ARM target support (Daniel Glockner) - allow unsigned char as default on ARM (Daniel...
[tinycc.git] / tcc.c
blob889380d29ce37f051225d96bb44ba15520878e58
1 /*
2 * TCC - Tiny C Compiler
3 *
4 * Copyright (c) 2001, 2002, 2003 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 #include <stdlib.h>
24 #include <stdio.h>
25 #include <stdarg.h>
26 #include <string.h>
27 #include <errno.h>
28 #include <math.h>
29 #include <unistd.h>
30 #include <signal.h>
31 #include <unistd.h>
32 #include <fcntl.h>
33 #include <setjmp.h>
34 #include <time.h>
35 #ifdef WIN32
36 #include <sys/timeb.h>
37 #endif
38 #ifndef WIN32
39 #include <sys/time.h>
40 #include <sys/ucontext.h>
41 #endif
42 #include "elf.h"
43 #include "stab.h"
44 #ifndef CONFIG_TCC_STATIC
45 #include <dlfcn.h>
46 #endif
48 #include "libtcc.h"
50 /* parser debug */
51 //#define PARSE_DEBUG
52 /* preprocessor debug */
53 //#define PP_DEBUG
54 /* include file debug */
55 //#define INC_DEBUG
57 //#define MEM_DEBUG
59 /* assembler debug */
60 //#define ASM_DEBUG
62 /* target selection */
63 //#define TCC_TARGET_I386 /* i386 code generator */
64 //#define TCC_TARGET_ARM /* ARMv4 code generator */
66 /* default target is I386 */
67 #if !defined(TCC_TARGET_I386) && !defined(TCC_TARGET_ARM)
68 #define TCC_TARGET_I386
69 #endif
71 #if !defined(WIN32) && !defined(TCC_UCLIBC) && !defined(TCC_TARGET_ARM)
72 #define CONFIG_TCC_BCHECK /* enable bound checking code */
73 #endif
75 /* define it to include assembler support */
76 #if !defined(TCC_TARGET_ARM)
77 #define CONFIG_TCC_ASM
78 #endif
80 /* path to find crt1.o, crti.o and crtn.o. Only needed when generating
81 executables or dlls */
82 #define CONFIG_TCC_CRT_PREFIX "/usr/lib"
84 #define INCLUDE_STACK_SIZE 32
85 #define IFDEF_STACK_SIZE 64
86 #define VSTACK_SIZE 64
87 #define STRING_MAX_SIZE 1024
89 #define TOK_HASH_SIZE 2048 /* must be a power of two */
90 #define TOK_ALLOC_INCR 512 /* must be a power of two */
91 #define TOK_STR_ALLOC_INCR_BITS 6
92 #define TOK_STR_ALLOC_INCR (1 << TOK_STR_ALLOC_INCR_BITS)
93 #define TOK_MAX_SIZE 4 /* token max size in int unit when stored in string */
95 /* token symbol management */
96 typedef struct TokenSym {
97 struct TokenSym *hash_next;
98 struct Sym *sym_define; /* direct pointer to define */
99 struct Sym *sym_label; /* direct pointer to label */
100 struct Sym *sym_struct; /* direct pointer to structure */
101 struct Sym *sym_identifier; /* direct pointer to identifier */
102 int tok; /* token number */
103 int len;
104 char str[1];
105 } TokenSym;
107 typedef struct CString {
108 int size; /* size in bytes */
109 void *data; /* either 'char *' or 'int *' */
110 int size_allocated;
111 void *data_allocated; /* if non NULL, data has been malloced */
112 } CString;
114 /* type definition */
115 typedef struct CType {
116 int t;
117 struct Sym *ref;
118 } CType;
120 /* constant value */
121 typedef union CValue {
122 long double ld;
123 double d;
124 float f;
125 int i;
126 unsigned int ui;
127 unsigned int ul; /* address (should be unsigned long on 64 bit cpu) */
128 long long ll;
129 unsigned long long ull;
130 struct CString *cstr;
131 void *ptr;
132 int tab[1];
133 } CValue;
135 /* value on stack */
136 typedef struct SValue {
137 CType type; /* type */
138 unsigned short r; /* register + flags */
139 unsigned short r2; /* second register, used for 'long long'
140 type. If not used, set to VT_CONST */
141 CValue c; /* constant, if VT_CONST */
142 struct Sym *sym; /* symbol, if (VT_SYM | VT_CONST) */
143 } SValue;
145 /* symbol management */
146 typedef struct Sym {
147 int v; /* symbol token */
148 int r; /* associated register */
149 int c; /* associated number */
150 CType type; /* associated type */
151 struct Sym *next; /* next related symbol */
152 struct Sym *prev; /* prev symbol in stack */
153 struct Sym *prev_tok; /* previous symbol for this token */
154 } Sym;
156 /* section definition */
157 /* XXX: use directly ELF structure for parameters ? */
158 /* special flag to indicate that the section should not be linked to
159 the other ones */
160 #define SHF_PRIVATE 0x80000000
162 typedef struct Section {
163 unsigned long data_offset; /* current data offset */
164 unsigned char *data; /* section data */
165 unsigned long data_allocated; /* used for realloc() handling */
166 int sh_name; /* elf section name (only used during output) */
167 int sh_num; /* elf section number */
168 int sh_type; /* elf section type */
169 int sh_flags; /* elf section flags */
170 int sh_info; /* elf section info */
171 int sh_addralign; /* elf section alignment */
172 int sh_entsize; /* elf entry size */
173 unsigned long sh_size; /* section size (only used during output) */
174 unsigned long sh_addr; /* address at which the section is relocated */
175 unsigned long sh_offset; /* address at which the section is relocated */
176 int nb_hashed_syms; /* used to resize the hash table */
177 struct Section *link; /* link to another section */
178 struct Section *reloc; /* corresponding section for relocation, if any */
179 struct Section *hash; /* hash table for symbols */
180 struct Section *next;
181 char name[1]; /* section name */
182 } Section;
184 typedef struct DLLReference {
185 int level;
186 char name[1];
187 } DLLReference;
189 /* GNUC attribute definition */
190 typedef struct AttributeDef {
191 int aligned;
192 Section *section;
193 unsigned char func_call; /* FUNC_CDECL or FUNC_STDCALL */
194 } AttributeDef;
196 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
197 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
198 #define SYM_FIRST_ANOM (1 << (31 - VT_STRUCT_SHIFT)) /* first anonymous sym */
200 /* stored in 'Sym.c' field */
201 #define FUNC_NEW 1 /* ansi function prototype */
202 #define FUNC_OLD 2 /* old function prototype */
203 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
205 /* stored in 'Sym.r' field */
206 #define FUNC_CDECL 0 /* standard c call */
207 #define FUNC_STDCALL 1 /* pascal c call */
209 /* field 'Sym.t' for macros */
210 #define MACRO_OBJ 0 /* object like macro */
211 #define MACRO_FUNC 1 /* function like macro */
213 /* field 'Sym.r' for C labels */
214 #define LABEL_DEFINED 0 /* label is defined */
215 #define LABEL_FORWARD 1 /* label is forward defined */
216 #define LABEL_DECLARED 2 /* label is declared but never used */
218 /* type_decl() types */
219 #define TYPE_ABSTRACT 1 /* type without variable */
220 #define TYPE_DIRECT 2 /* type with variable */
222 #define IO_BUF_SIZE 8192
224 typedef struct BufferedFile {
225 uint8_t *buf_ptr;
226 uint8_t *buf_end;
227 int fd;
228 int line_num; /* current line number - here to simplify code */
229 int ifndef_macro; /* #ifndef macro / #endif search */
230 int ifndef_macro_saved; /* saved ifndef_macro */
231 int *ifdef_stack_ptr; /* ifdef_stack value at the start of the file */
232 char inc_type; /* type of include */
233 char inc_filename[512]; /* filename specified by the user */
234 char filename[1024]; /* current filename - here to simplify code */
235 unsigned char buffer[IO_BUF_SIZE + 1]; /* extra size for CH_EOB char */
236 } BufferedFile;
238 #define CH_EOB '\\' /* end of buffer or '\0' char in file */
239 #define CH_EOF (-1) /* end of file */
241 /* parsing state (used to save parser state to reparse part of the
242 source several times) */
243 typedef struct ParseState {
244 int *macro_ptr;
245 int line_num;
246 int tok;
247 CValue tokc;
248 } ParseState;
250 /* used to record tokens */
251 typedef struct TokenString {
252 int *str;
253 int len;
254 int allocated_len;
255 int last_line_num;
256 } TokenString;
258 /* include file cache, used to find files faster and also to eliminate
259 inclusion if the include file is protected by #ifndef ... #endif */
260 typedef struct CachedInclude {
261 int ifndef_macro;
262 char type; /* '"' or '>' to give include type */
263 char filename[1]; /* path specified in #include */
264 } CachedInclude;
266 /* parser */
267 static struct BufferedFile *file;
268 static int ch, tok;
269 static CValue tokc;
270 static CString tokcstr; /* current parsed string, if any */
271 /* additional informations about token */
272 static int tok_flags;
273 #define TOK_FLAG_BOL 0x0001 /* beginning of line before */
274 #define TOK_FLAG_BOF 0x0002 /* beginning of file before */
275 #define TOK_FLAG_ENDIF 0x0004 /* a endif was found matching starting #ifdef */
277 static int *macro_ptr, *macro_ptr_allocated;
278 static int *unget_saved_macro_ptr;
279 static int unget_saved_buffer[TOK_MAX_SIZE + 1];
280 static int unget_buffer_enabled;
281 static int parse_flags;
282 #define PARSE_FLAG_PREPROCESS 0x0001 /* activate preprocessing */
283 #define PARSE_FLAG_TOK_NUM 0x0002 /* return numbers instead of TOK_PPNUM */
284 #define PARSE_FLAG_LINEFEED 0x0004 /* line feed is returned as a
285 token. line feed is also
286 returned at eof */
288 static Section *text_section, *data_section, *bss_section; /* predefined sections */
289 static Section *cur_text_section; /* current section where function code is
290 generated */
291 /* bound check related sections */
292 static Section *bounds_section; /* contains global data bound description */
293 static Section *lbounds_section; /* contains local data bound description */
294 /* symbol sections */
295 static Section *symtab_section, *strtab_section;
297 /* debug sections */
298 static Section *stab_section, *stabstr_section;
300 /* loc : local variable index
301 ind : output code index
302 rsym: return symbol
303 anon_sym: anonymous symbol index
305 static int rsym, anon_sym, ind, loc;
306 /* expression generation modifiers */
307 static int const_wanted; /* true if constant wanted */
308 static int nocode_wanted; /* true if no code generation wanted for an expression */
309 static int global_expr; /* true if compound literals must be allocated
310 globally (used during initializers parsing */
311 static CType func_vt; /* current function return type (used by return
312 instruction) */
313 static int func_vc;
314 static int last_line_num, last_ind, func_ind; /* debug last line number and pc */
315 static int tok_ident;
316 static TokenSym **table_ident;
317 static TokenSym *hash_ident[TOK_HASH_SIZE];
318 static char token_buf[STRING_MAX_SIZE + 1];
319 static char *funcname;
320 static Sym *global_stack, *local_stack;
321 static Sym *define_stack;
322 static Sym *global_label_stack, *local_label_stack;
324 static SValue vstack[VSTACK_SIZE], *vtop;
325 /* some predefined types */
326 static CType char_pointer_type, func_old_type, int_type;
327 /* true if isid(c) || isnum(c) */
328 static unsigned char isidnum_table[256];
330 /* compile with debug symbol (and use them if error during execution) */
331 static int do_debug = 0;
333 /* compile with built-in memory and bounds checker */
334 static int do_bounds_check = 0;
336 /* display benchmark infos */
337 #if !defined(LIBTCC)
338 static int do_bench = 0;
339 #endif
340 static int total_lines;
341 static int total_bytes;
343 /* use GNU C extensions */
344 static int gnu_ext = 1;
346 /* use Tiny C extensions */
347 static int tcc_ext = 1;
349 /* max number of callers shown if error */
350 static int num_callers = 6;
351 static const char **rt_bound_error_msg;
353 /* XXX: get rid of this ASAP */
354 static struct TCCState *tcc_state;
356 /* give the path of the tcc libraries */
357 static const char *tcc_lib_path = CONFIG_TCC_LIBDIR "/tcc";
359 struct TCCState {
360 int output_type;
362 BufferedFile **include_stack_ptr;
363 int *ifdef_stack_ptr;
365 /* include file handling */
366 char **include_paths;
367 int nb_include_paths;
368 char **sysinclude_paths;
369 int nb_sysinclude_paths;
370 CachedInclude **cached_includes;
371 int nb_cached_includes;
373 char **library_paths;
374 int nb_library_paths;
376 /* array of all loaded dlls (including those referenced by loaded
377 dlls) */
378 DLLReference **loaded_dlls;
379 int nb_loaded_dlls;
381 /* sections */
382 Section **sections;
383 int nb_sections; /* number of sections, including first dummy section */
385 /* got handling */
386 Section *got;
387 Section *plt;
388 unsigned long *got_offsets;
389 int nb_got_offsets;
390 /* give the correspondance from symtab indexes to dynsym indexes */
391 int *symtab_to_dynsym;
393 /* temporary dynamic symbol sections (for dll loading) */
394 Section *dynsymtab_section;
395 /* exported dynamic symbol section */
396 Section *dynsym;
398 int nostdinc; /* if true, no standard headers are added */
399 int nostdlib; /* if true, no standard libraries are added */
401 /* if true, static linking is performed */
402 int static_link;
404 /* if true, all symbols are exported */
405 int rdynamic;
407 /* if true, only link in referenced objects from archive */
408 int alacarte_link;
410 /* warning switches */
411 int warn_write_strings;
412 int warn_unsupported;
413 int warn_error;
414 int warn_none;
416 /* error handling */
417 void *error_opaque;
418 void (*error_func)(void *opaque, const char *msg);
419 int error_set_jmp_enabled;
420 jmp_buf error_jmp_buf;
421 int nb_errors;
423 /* tiny assembler state */
424 Sym *asm_labels;
426 /* see include_stack_ptr */
427 BufferedFile *include_stack[INCLUDE_STACK_SIZE];
429 /* see ifdef_stack_ptr */
430 int ifdef_stack[IFDEF_STACK_SIZE];
433 /* The current value can be: */
434 #define VT_VALMASK 0x00ff
435 #define VT_CONST 0x00f0 /* constant in vc
436 (must be first non register value) */
437 #define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */
438 #define VT_LOCAL 0x00f2 /* offset on stack */
439 #define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */
440 #define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */
441 #define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */
442 #define VT_LVAL 0x0100 /* var is an lvalue */
443 #define VT_SYM 0x0200 /* a symbol value is added */
444 #define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for
445 char/short stored in integer registers) */
446 #define VT_MUSTBOUND 0x0800 /* bound checking must be done before
447 dereferencing value */
448 #define VT_BOUNDED 0x8000 /* value is bounded. The address of the
449 bounding function call point is in vc */
450 #define VT_LVAL_BYTE 0x1000 /* lvalue is a byte */
451 #define VT_LVAL_SHORT 0x2000 /* lvalue is a short */
452 #define VT_LVAL_UNSIGNED 0x4000 /* lvalue is unsigned */
453 #define VT_LVAL_TYPE (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)
455 /* types */
456 #define VT_INT 0 /* integer type */
457 #define VT_BYTE 1 /* signed byte type */
458 #define VT_SHORT 2 /* short type */
459 #define VT_VOID 3 /* void type */
460 #define VT_PTR 4 /* pointer */
461 #define VT_ENUM 5 /* enum definition */
462 #define VT_FUNC 6 /* function type */
463 #define VT_STRUCT 7 /* struct/union definition */
464 #define VT_FLOAT 8 /* IEEE float */
465 #define VT_DOUBLE 9 /* IEEE double */
466 #define VT_LDOUBLE 10 /* IEEE long double */
467 #define VT_BOOL 11 /* ISOC99 boolean type */
468 #define VT_LLONG 12 /* 64 bit integer */
469 #define VT_LONG 13 /* long integer (NEVER USED as type, only
470 during parsing) */
471 #define VT_BTYPE 0x000f /* mask for basic type */
472 #define VT_UNSIGNED 0x0010 /* unsigned type */
473 #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
474 #define VT_BITFIELD 0x0040 /* bitfield modifier */
475 #define VT_CONSTANT 0x0800 /* const modifier */
476 #define VT_VOLATILE 0x1000 /* volatile modifier */
477 #define VT_SIGNED 0x2000 /* signed type */
479 /* storage */
480 #define VT_EXTERN 0x00000080 /* extern definition */
481 #define VT_STATIC 0x00000100 /* static variable */
482 #define VT_TYPEDEF 0x00000200 /* typedef definition */
483 #define VT_INLINE 0x00000400 /* inline definition */
485 #define VT_STRUCT_SHIFT 16 /* shift for bitfield shift values */
487 /* type mask (except storage) */
488 #define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE)
489 #define VT_TYPE (~(VT_STORAGE))
491 /* token values */
493 /* warning: the following compare tokens depend on i386 asm code */
494 #define TOK_ULT 0x92
495 #define TOK_UGE 0x93
496 #define TOK_EQ 0x94
497 #define TOK_NE 0x95
498 #define TOK_ULE 0x96
499 #define TOK_UGT 0x97
500 #define TOK_LT 0x9c
501 #define TOK_GE 0x9d
502 #define TOK_LE 0x9e
503 #define TOK_GT 0x9f
505 #define TOK_LAND 0xa0
506 #define TOK_LOR 0xa1
508 #define TOK_DEC 0xa2
509 #define TOK_MID 0xa3 /* inc/dec, to void constant */
510 #define TOK_INC 0xa4
511 #define TOK_UDIV 0xb0 /* unsigned division */
512 #define TOK_UMOD 0xb1 /* unsigned modulo */
513 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
514 #define TOK_CINT 0xb3 /* number in tokc */
515 #define TOK_CCHAR 0xb4 /* char constant in tokc */
516 #define TOK_STR 0xb5 /* pointer to string in tokc */
517 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
518 #define TOK_LCHAR 0xb7
519 #define TOK_LSTR 0xb8
520 #define TOK_CFLOAT 0xb9 /* float constant */
521 #define TOK_LINENUM 0xba /* line number info */
522 #define TOK_CDOUBLE 0xc0 /* double constant */
523 #define TOK_CLDOUBLE 0xc1 /* long double constant */
524 #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
525 #define TOK_ADDC1 0xc3 /* add with carry generation */
526 #define TOK_ADDC2 0xc4 /* add with carry use */
527 #define TOK_SUBC1 0xc5 /* add with carry generation */
528 #define TOK_SUBC2 0xc6 /* add with carry use */
529 #define TOK_CUINT 0xc8 /* unsigned int constant */
530 #define TOK_CLLONG 0xc9 /* long long constant */
531 #define TOK_CULLONG 0xca /* unsigned long long constant */
532 #define TOK_ARROW 0xcb
533 #define TOK_DOTS 0xcc /* three dots */
534 #define TOK_SHR 0xcd /* unsigned shift right */
535 #define TOK_PPNUM 0xce /* preprocessor number */
537 #define TOK_SHL 0x01 /* shift left */
538 #define TOK_SAR 0x02 /* signed shift right */
540 /* assignement operators : normal operator or 0x80 */
541 #define TOK_A_MOD 0xa5
542 #define TOK_A_AND 0xa6
543 #define TOK_A_MUL 0xaa
544 #define TOK_A_ADD 0xab
545 #define TOK_A_SUB 0xad
546 #define TOK_A_DIV 0xaf
547 #define TOK_A_XOR 0xde
548 #define TOK_A_OR 0xfc
549 #define TOK_A_SHL 0x81
550 #define TOK_A_SAR 0x82
552 #ifndef offsetof
553 #define offsetof(type, field) ((size_t) &((type *)0)->field)
554 #endif
556 #ifndef countof
557 #define countof(tab) (sizeof(tab) / sizeof((tab)[0]))
558 #endif
560 /* WARNING: the content of this string encodes token numbers */
561 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";
563 #define TOK_EOF (-1) /* end of file */
564 #define TOK_LINEFEED 10 /* line feed */
566 /* all identificators and strings have token above that */
567 #define TOK_IDENT 256
569 /* only used for i386 asm opcodes definitions */
570 #define DEF_ASM(x) DEF(TOK_ASM_ ## x, #x)
572 #define DEF_BWL(x) \
573 DEF(TOK_ASM_ ## x ## b, #x "b") \
574 DEF(TOK_ASM_ ## x ## w, #x "w") \
575 DEF(TOK_ASM_ ## x ## l, #x "l") \
576 DEF(TOK_ASM_ ## x, #x)
578 #define DEF_WL(x) \
579 DEF(TOK_ASM_ ## x ## w, #x "w") \
580 DEF(TOK_ASM_ ## x ## l, #x "l") \
581 DEF(TOK_ASM_ ## x, #x)
583 #define DEF_FP1(x) \
584 DEF(TOK_ASM_ ## f ## x ## s, "f" #x "s") \
585 DEF(TOK_ASM_ ## fi ## x ## l, "fi" #x "l") \
586 DEF(TOK_ASM_ ## f ## x ## l, "f" #x "l") \
587 DEF(TOK_ASM_ ## fi ## x ## s, "fi" #x "s")
589 #define DEF_FP(x) \
590 DEF(TOK_ASM_ ## f ## x, "f" #x ) \
591 DEF(TOK_ASM_ ## f ## x ## p, "f" #x "p") \
592 DEF_FP1(x)
594 #define DEF_ASMTEST(x) \
595 DEF_ASM(x ## o) \
596 DEF_ASM(x ## no) \
597 DEF_ASM(x ## b) \
598 DEF_ASM(x ## c) \
599 DEF_ASM(x ## nae) \
600 DEF_ASM(x ## nb) \
601 DEF_ASM(x ## nc) \
602 DEF_ASM(x ## ae) \
603 DEF_ASM(x ## e) \
604 DEF_ASM(x ## z) \
605 DEF_ASM(x ## ne) \
606 DEF_ASM(x ## nz) \
607 DEF_ASM(x ## be) \
608 DEF_ASM(x ## na) \
609 DEF_ASM(x ## nbe) \
610 DEF_ASM(x ## a) \
611 DEF_ASM(x ## s) \
612 DEF_ASM(x ## ns) \
613 DEF_ASM(x ## p) \
614 DEF_ASM(x ## pe) \
615 DEF_ASM(x ## np) \
616 DEF_ASM(x ## po) \
617 DEF_ASM(x ## l) \
618 DEF_ASM(x ## nge) \
619 DEF_ASM(x ## nl) \
620 DEF_ASM(x ## ge) \
621 DEF_ASM(x ## le) \
622 DEF_ASM(x ## ng) \
623 DEF_ASM(x ## nle) \
624 DEF_ASM(x ## g)
626 #define TOK_ASM_int TOK_INT
628 enum {
629 TOK_LAST = TOK_IDENT - 1,
630 #define DEF(id, str) id,
631 #include "tcctok.h"
632 #undef DEF
635 static const char tcc_keywords[] =
636 #define DEF(id, str) str "\0"
637 #include "tcctok.h"
638 #undef DEF
641 #define TOK_UIDENT TOK_DEFINE
643 #ifdef WIN32
644 #define snprintf _snprintf
645 #define vsnprintf _vsnprintf
646 #endif
648 #if defined(WIN32) || defined(TCC_UCLIBC) || defined(__FreeBSD__)
649 /* currently incorrect */
650 long double strtold(const char *nptr, char **endptr)
652 return (long double)strtod(nptr, endptr);
654 float strtof(const char *nptr, char **endptr)
656 return (float)strtod(nptr, endptr);
658 #else
659 /* XXX: need to define this to use them in non ISOC99 context */
660 extern float strtof (const char *__nptr, char **__endptr);
661 extern long double strtold (const char *__nptr, char **__endptr);
662 #endif
664 static char *pstrcpy(char *buf, int buf_size, const char *s);
665 static char *pstrcat(char *buf, int buf_size, const char *s);
667 static void next(void);
668 static void next_nomacro(void);
669 static void parse_expr_type(CType *type);
670 static void expr_type(CType *type);
671 static void unary_type(CType *type);
672 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
673 int case_reg, int is_expr);
674 static int expr_const(void);
675 static void expr_eq(void);
676 static void gexpr(void);
677 static void decl(int l);
678 static void decl_initializer(CType *type, Section *sec, unsigned long c,
679 int first, int size_only);
680 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
681 int has_init, int v, int scope);
682 int gv(int rc);
683 void gv2(int rc1, int rc2);
684 void move_reg(int r, int s);
685 void save_regs(int n);
686 void save_reg(int r);
687 void vpop(void);
688 void vswap(void);
689 void vdup(void);
690 int get_reg(int rc);
691 int get_reg_ex(int rc,int rc2);
693 static void macro_subst(TokenString *tok_str, Sym **nested_list,
694 const int *macro_str, int can_read_stream);
695 int save_reg_forced(int r);
696 void gen_op(int op);
697 void force_charshort_cast(int t);
698 static void gen_cast(CType *type);
699 void vstore(void);
700 static Sym *sym_find(int v);
701 static Sym *sym_push(int v, CType *type, int r, int c);
703 /* type handling */
704 static int type_size(CType *type, int *a);
705 static inline CType *pointed_type(CType *type);
706 static int pointed_size(CType *type);
707 static int lvalue_type(int t);
708 static int parse_btype(CType *type, AttributeDef *ad);
709 static void type_decl(CType *type, AttributeDef *ad, int *v, int td);
710 static int is_compatible_types(CType *type1, CType *type2);
712 int ieee_finite(double d);
713 void error(const char *fmt, ...);
714 void vpushi(int v);
715 void vrott(int n);
716 static void vpush_global_sym(CType *type, int v);
717 void vset(CType *type, int r, int v);
718 void type_to_str(char *buf, int buf_size,
719 CType *type, const char *varstr);
720 char *get_tok_str(int v, CValue *cv);
721 static Sym *get_sym_ref(CType *type, Section *sec,
722 unsigned long offset, unsigned long size);
723 static Sym *external_global_sym(int v, CType *type, int r);
725 /* section generation */
726 static void section_realloc(Section *sec, unsigned long new_size);
727 static void *section_ptr_add(Section *sec, unsigned long size);
728 static void put_extern_sym(Sym *sym, Section *section,
729 unsigned long value, unsigned long size);
730 static void greloc(Section *s, Sym *sym, unsigned long addr, int type);
731 static int put_elf_str(Section *s, const char *sym);
732 static int put_elf_sym(Section *s,
733 unsigned long value, unsigned long size,
734 int info, int other, int shndx, const char *name);
735 static int add_elf_sym(Section *s, unsigned long value, unsigned long size,
736 int info, int sh_num, const char *name);
737 static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
738 int type, int symbol);
739 static void put_stabs(const char *str, int type, int other, int desc,
740 unsigned long value);
741 static void put_stabs_r(const char *str, int type, int other, int desc,
742 unsigned long value, Section *sec, int sym_index);
743 static void put_stabn(int type, int other, int desc, int value);
744 static void put_stabd(int type, int other, int desc);
745 static int tcc_add_dll(TCCState *s, const char *filename, int flags);
747 #define AFF_PRINT_ERROR 0x0001 /* print error if file not found */
748 #define AFF_REFERENCED_DLL 0x0002 /* load a referenced dll from another dll */
749 static int tcc_add_file_internal(TCCState *s, const char *filename, int flags);
751 /* tccasm.c */
753 #ifdef CONFIG_TCC_ASM
755 typedef struct ExprValue {
756 uint32_t v;
757 Sym *sym;
758 } ExprValue;
760 #define MAX_ASM_OPERANDS 30
762 typedef struct ASMOperand {
763 int id; /* GCC 3 optionnal identifier (0 if number only supported */
764 char *constraint;
765 char asm_str[16]; /* computed asm string for operand */
766 SValue *vt; /* C value of the expression */
767 int ref_index; /* if >= 0, gives reference to a output constraint */
768 int priority; /* priority, used to assign registers */
769 int reg; /* if >= 0, register number used for this operand */
770 int is_llong; /* true if double register value */
771 } ASMOperand;
773 static void asm_expr(TCCState *s1, ExprValue *pe);
774 static int asm_int_expr(TCCState *s1);
775 static int find_constraint(ASMOperand *operands, int nb_operands,
776 const char *name, const char **pp);
778 static int tcc_assemble(TCCState *s1, int do_preprocess);
780 #endif
782 static void asm_instr(void);
784 /* true if float/double/long double type */
785 static inline int is_float(int t)
787 int bt;
788 bt = t & VT_BTYPE;
789 return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT;
792 #ifdef TCC_TARGET_I386
793 #include "i386-gen.c"
794 #endif
796 #ifdef TCC_TARGET_ARM
797 #include "arm-gen.c"
798 #endif
800 #ifdef CONFIG_TCC_STATIC
802 #define RTLD_LAZY 0x001
803 #define RTLD_NOW 0x002
804 #define RTLD_GLOBAL 0x100
805 #define RTLD_DEFAULT NULL
807 /* dummy function for profiling */
808 void *dlopen(const char *filename, int flag)
810 return NULL;
813 const char *dlerror(void)
815 return "error";
818 typedef struct TCCSyms {
819 char *str;
820 void *ptr;
821 } TCCSyms;
823 #define TCCSYM(a) { #a, &a, },
825 /* add the symbol you want here if no dynamic linking is done */
826 static TCCSyms tcc_syms[] = {
827 TCCSYM(printf)
828 TCCSYM(fprintf)
829 TCCSYM(fopen)
830 TCCSYM(fclose)
831 { NULL, NULL },
834 void *dlsym(void *handle, const char *symbol)
836 TCCSyms *p;
837 p = tcc_syms;
838 while (p->str != NULL) {
839 if (!strcmp(p->str, symbol))
840 return p->ptr;
841 p++;
843 return NULL;
846 #endif
848 /********************************************************/
850 /* we use our own 'finite' function to avoid potential problems with
851 non standard math libs */
852 /* XXX: endianness dependent */
853 int ieee_finite(double d)
855 int *p = (int *)&d;
856 return ((unsigned)((p[1] | 0x800fffff) + 1)) >> 31;
859 /* copy a string and truncate it. */
860 static char *pstrcpy(char *buf, int buf_size, const char *s)
862 char *q, *q_end;
863 int c;
865 if (buf_size > 0) {
866 q = buf;
867 q_end = buf + buf_size - 1;
868 while (q < q_end) {
869 c = *s++;
870 if (c == '\0')
871 break;
872 *q++ = c;
874 *q = '\0';
876 return buf;
879 /* strcat and truncate. */
880 static char *pstrcat(char *buf, int buf_size, const char *s)
882 int len;
883 len = strlen(buf);
884 if (len < buf_size)
885 pstrcpy(buf + len, buf_size - len, s);
886 return buf;
889 /* memory management */
890 #ifdef MEM_DEBUG
891 int mem_cur_size;
892 int mem_max_size;
893 #endif
895 static inline void tcc_free(void *ptr)
897 #ifdef MEM_DEBUG
898 mem_cur_size -= malloc_usable_size(ptr);
899 #endif
900 free(ptr);
903 static void *tcc_malloc(unsigned long size)
905 void *ptr;
906 ptr = malloc(size);
907 if (!ptr && size)
908 error("memory full");
909 #ifdef MEM_DEBUG
910 mem_cur_size += malloc_usable_size(ptr);
911 if (mem_cur_size > mem_max_size)
912 mem_max_size = mem_cur_size;
913 #endif
914 return ptr;
917 static void *tcc_mallocz(unsigned long size)
919 void *ptr;
920 ptr = tcc_malloc(size);
921 memset(ptr, 0, size);
922 return ptr;
925 static inline void *tcc_realloc(void *ptr, unsigned long size)
927 void *ptr1;
928 #ifdef MEM_DEBUG
929 mem_cur_size -= malloc_usable_size(ptr);
930 #endif
931 ptr1 = realloc(ptr, size);
932 #ifdef MEM_DEBUG
933 /* NOTE: count not correct if alloc error, but not critical */
934 mem_cur_size += malloc_usable_size(ptr1);
935 if (mem_cur_size > mem_max_size)
936 mem_max_size = mem_cur_size;
937 #endif
938 return ptr1;
941 static char *tcc_strdup(const char *str)
943 char *ptr;
944 ptr = tcc_malloc(strlen(str) + 1);
945 strcpy(ptr, str);
946 return ptr;
949 #define free(p) use_tcc_free(p)
950 #define malloc(s) use_tcc_malloc(s)
951 #define realloc(p, s) use_tcc_realloc(p, s)
953 static void dynarray_add(void ***ptab, int *nb_ptr, void *data)
955 int nb, nb_alloc;
956 void **pp;
958 nb = *nb_ptr;
959 pp = *ptab;
960 /* every power of two we double array size */
961 if ((nb & (nb - 1)) == 0) {
962 if (!nb)
963 nb_alloc = 1;
964 else
965 nb_alloc = nb * 2;
966 pp = tcc_realloc(pp, nb_alloc * sizeof(void *));
967 if (!pp)
968 error("memory full");
969 *ptab = pp;
971 pp[nb++] = data;
972 *nb_ptr = nb;
975 Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags)
977 Section *sec;
979 sec = tcc_mallocz(sizeof(Section) + strlen(name));
980 strcpy(sec->name, name);
981 sec->sh_type = sh_type;
982 sec->sh_flags = sh_flags;
983 switch(sh_type) {
984 case SHT_HASH:
985 case SHT_REL:
986 case SHT_DYNSYM:
987 case SHT_SYMTAB:
988 case SHT_DYNAMIC:
989 sec->sh_addralign = 4;
990 break;
991 case SHT_STRTAB:
992 sec->sh_addralign = 1;
993 break;
994 default:
995 sec->sh_addralign = 32; /* default conservative alignment */
996 break;
999 /* only add section if not private */
1000 if (!(sh_flags & SHF_PRIVATE)) {
1001 sec->sh_num = s1->nb_sections;
1002 dynarray_add((void ***)&s1->sections, &s1->nb_sections, sec);
1004 return sec;
1007 static void free_section(Section *s)
1009 tcc_free(s->data);
1010 tcc_free(s);
1013 /* realloc section and set its content to zero */
1014 static void section_realloc(Section *sec, unsigned long new_size)
1016 unsigned long size;
1017 unsigned char *data;
1019 size = sec->data_allocated;
1020 if (size == 0)
1021 size = 1;
1022 while (size < new_size)
1023 size = size * 2;
1024 data = tcc_realloc(sec->data, size);
1025 if (!data)
1026 error("memory full");
1027 memset(data + sec->data_allocated, 0, size - sec->data_allocated);
1028 sec->data = data;
1029 sec->data_allocated = size;
1032 /* reserve at least 'size' bytes in section 'sec' from
1033 sec->data_offset. */
1034 static void *section_ptr_add(Section *sec, unsigned long size)
1036 unsigned long offset, offset1;
1038 offset = sec->data_offset;
1039 offset1 = offset + size;
1040 if (offset1 > sec->data_allocated)
1041 section_realloc(sec, offset1);
1042 sec->data_offset = offset1;
1043 return sec->data + offset;
1046 /* return a reference to a section, and create it if it does not
1047 exists */
1048 Section *find_section(TCCState *s1, const char *name)
1050 Section *sec;
1051 int i;
1052 for(i = 1; i < s1->nb_sections; i++) {
1053 sec = s1->sections[i];
1054 if (!strcmp(name, sec->name))
1055 return sec;
1057 /* sections are created as PROGBITS */
1058 return new_section(s1, name, SHT_PROGBITS, SHF_ALLOC);
1061 /* update sym->c so that it points to an external symbol in section
1062 'section' with value 'value' */
1063 static void put_extern_sym(Sym *sym, Section *section,
1064 unsigned long value, unsigned long size)
1066 int sym_type, sym_bind, sh_num, info;
1067 Elf32_Sym *esym;
1068 const char *name;
1070 if (section)
1071 sh_num = section->sh_num;
1072 else
1073 sh_num = SHN_UNDEF;
1074 if (!sym->c) {
1075 if ((sym->type.t & VT_BTYPE) == VT_FUNC)
1076 sym_type = STT_FUNC;
1077 else
1078 sym_type = STT_OBJECT;
1079 if (sym->type.t & VT_STATIC)
1080 sym_bind = STB_LOCAL;
1081 else
1082 sym_bind = STB_GLOBAL;
1084 name = get_tok_str(sym->v, NULL);
1085 #ifdef CONFIG_TCC_BCHECK
1086 if (do_bounds_check) {
1087 char buf[32];
1089 /* XXX: avoid doing that for statics ? */
1090 /* if bound checking is activated, we change some function
1091 names by adding the "__bound" prefix */
1092 switch(sym->v) {
1093 #if 0
1094 /* XXX: we rely only on malloc hooks */
1095 case TOK_malloc:
1096 case TOK_free:
1097 case TOK_realloc:
1098 case TOK_memalign:
1099 case TOK_calloc:
1100 #endif
1101 case TOK_memcpy:
1102 case TOK_memmove:
1103 case TOK_memset:
1104 case TOK_strlen:
1105 case TOK_strcpy:
1106 strcpy(buf, "__bound_");
1107 strcat(buf, name);
1108 name = buf;
1109 break;
1112 #endif
1113 info = ELF32_ST_INFO(sym_bind, sym_type);
1114 sym->c = add_elf_sym(symtab_section, value, size, info, sh_num, name);
1115 } else {
1116 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
1117 esym->st_value = value;
1118 esym->st_size = size;
1119 esym->st_shndx = sh_num;
1123 /* add a new relocation entry to symbol 'sym' in section 's' */
1124 static void greloc(Section *s, Sym *sym, unsigned long offset, int type)
1126 if (!sym->c)
1127 put_extern_sym(sym, NULL, 0, 0);
1128 /* now we can add ELF relocation info */
1129 put_elf_reloc(symtab_section, s, offset, type, sym->c);
1132 static inline int isid(int c)
1134 return (c >= 'a' && c <= 'z') ||
1135 (c >= 'A' && c <= 'Z') ||
1136 c == '_';
1139 static inline int isnum(int c)
1141 return c >= '0' && c <= '9';
1144 static inline int isoct(int c)
1146 return c >= '0' && c <= '7';
1149 static inline int toup(int c)
1151 if (c >= 'a' && c <= 'z')
1152 return c - 'a' + 'A';
1153 else
1154 return c;
1157 static void strcat_vprintf(char *buf, int buf_size, const char *fmt, va_list ap)
1159 int len;
1160 len = strlen(buf);
1161 vsnprintf(buf + len, buf_size - len, fmt, ap);
1164 static void strcat_printf(char *buf, int buf_size, const char *fmt, ...)
1166 va_list ap;
1167 va_start(ap, fmt);
1168 strcat_vprintf(buf, buf_size, fmt, ap);
1169 va_end(ap);
1172 void error1(TCCState *s1, int is_warning, const char *fmt, va_list ap)
1174 char buf[2048];
1175 BufferedFile **f;
1177 buf[0] = '\0';
1178 if (file) {
1179 for(f = s1->include_stack; f < s1->include_stack_ptr; f++)
1180 strcat_printf(buf, sizeof(buf), "In file included from %s:%d:\n",
1181 (*f)->filename, (*f)->line_num);
1182 if (file->line_num > 0) {
1183 strcat_printf(buf, sizeof(buf),
1184 "%s:%d: ", file->filename, file->line_num);
1185 } else {
1186 strcat_printf(buf, sizeof(buf),
1187 "%s: ", file->filename);
1189 } else {
1190 strcat_printf(buf, sizeof(buf),
1191 "tcc: ");
1193 if (is_warning)
1194 strcat_printf(buf, sizeof(buf), "warning: ");
1195 strcat_vprintf(buf, sizeof(buf), fmt, ap);
1197 if (!s1->error_func) {
1198 /* default case: stderr */
1199 fprintf(stderr, "%s\n", buf);
1200 } else {
1201 s1->error_func(s1->error_opaque, buf);
1203 if (!is_warning || s1->warn_error)
1204 s1->nb_errors++;
1207 #ifdef LIBTCC
1208 void tcc_set_error_func(TCCState *s, void *error_opaque,
1209 void (*error_func)(void *opaque, const char *msg))
1211 s->error_opaque = error_opaque;
1212 s->error_func = error_func;
1214 #endif
1216 /* error without aborting current compilation */
1217 void error_noabort(const char *fmt, ...)
1219 TCCState *s1 = tcc_state;
1220 va_list ap;
1222 va_start(ap, fmt);
1223 error1(s1, 0, fmt, ap);
1224 va_end(ap);
1227 void error(const char *fmt, ...)
1229 TCCState *s1 = tcc_state;
1230 va_list ap;
1232 va_start(ap, fmt);
1233 error1(s1, 0, fmt, ap);
1234 va_end(ap);
1235 /* better than nothing: in some cases, we accept to handle errors */
1236 if (s1->error_set_jmp_enabled) {
1237 longjmp(s1->error_jmp_buf, 1);
1238 } else {
1239 /* XXX: eliminate this someday */
1240 exit(1);
1244 void expect(const char *msg)
1246 error("%s expected", msg);
1249 void warning(const char *fmt, ...)
1251 TCCState *s1 = tcc_state;
1252 va_list ap;
1254 if (s1->warn_none)
1255 return;
1257 va_start(ap, fmt);
1258 error1(s1, 1, fmt, ap);
1259 va_end(ap);
1262 void skip(int c)
1264 if (tok != c)
1265 error("'%c' expected", c);
1266 next();
1269 static void test_lvalue(void)
1271 if (!(vtop->r & VT_LVAL))
1272 expect("lvalue");
1275 /* allocate a new token */
1276 static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len)
1278 TokenSym *ts, **ptable;
1279 int i;
1281 if (tok_ident >= SYM_FIRST_ANOM)
1282 error("memory full");
1284 /* expand token table if needed */
1285 i = tok_ident - TOK_IDENT;
1286 if ((i % TOK_ALLOC_INCR) == 0) {
1287 ptable = tcc_realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *));
1288 if (!ptable)
1289 error("memory full");
1290 table_ident = ptable;
1293 ts = tcc_malloc(sizeof(TokenSym) + len);
1294 table_ident[i] = ts;
1295 ts->tok = tok_ident++;
1296 ts->sym_define = NULL;
1297 ts->sym_label = NULL;
1298 ts->sym_struct = NULL;
1299 ts->sym_identifier = NULL;
1300 ts->len = len;
1301 ts->hash_next = NULL;
1302 memcpy(ts->str, str, len);
1303 ts->str[len] = '\0';
1304 *pts = ts;
1305 return ts;
1308 #define TOK_HASH_INIT 1
1309 #define TOK_HASH_FUNC(h, c) ((h) * 263 + (c))
1311 /* find a token and add it if not found */
1312 static TokenSym *tok_alloc(const char *str, int len)
1314 TokenSym *ts, **pts;
1315 int i;
1316 unsigned int h;
1318 h = TOK_HASH_INIT;
1319 for(i=0;i<len;i++)
1320 h = TOK_HASH_FUNC(h, ((unsigned char *)str)[i]);
1321 h &= (TOK_HASH_SIZE - 1);
1323 pts = &hash_ident[h];
1324 for(;;) {
1325 ts = *pts;
1326 if (!ts)
1327 break;
1328 if (ts->len == len && !memcmp(ts->str, str, len))
1329 return ts;
1330 pts = &(ts->hash_next);
1332 return tok_alloc_new(pts, str, len);
1335 /* CString handling */
1337 static void cstr_realloc(CString *cstr, int new_size)
1339 int size;
1340 void *data;
1342 size = cstr->size_allocated;
1343 if (size == 0)
1344 size = 8; /* no need to allocate a too small first string */
1345 while (size < new_size)
1346 size = size * 2;
1347 data = tcc_realloc(cstr->data_allocated, size);
1348 if (!data)
1349 error("memory full");
1350 cstr->data_allocated = data;
1351 cstr->size_allocated = size;
1352 cstr->data = data;
1355 /* add a byte */
1356 static void cstr_ccat(CString *cstr, int ch)
1358 int size;
1359 size = cstr->size + 1;
1360 if (size > cstr->size_allocated)
1361 cstr_realloc(cstr, size);
1362 ((unsigned char *)cstr->data)[size - 1] = ch;
1363 cstr->size = size;
1366 static void cstr_cat(CString *cstr, const char *str)
1368 int c;
1369 for(;;) {
1370 c = *str;
1371 if (c == '\0')
1372 break;
1373 cstr_ccat(cstr, c);
1374 str++;
1378 /* add a wide char */
1379 static void cstr_wccat(CString *cstr, int ch)
1381 int size;
1382 size = cstr->size + sizeof(int);
1383 if (size > cstr->size_allocated)
1384 cstr_realloc(cstr, size);
1385 *(int *)(((unsigned char *)cstr->data) + size - sizeof(int)) = ch;
1386 cstr->size = size;
1389 static void cstr_new(CString *cstr)
1391 memset(cstr, 0, sizeof(CString));
1394 /* free string and reset it to NULL */
1395 static void cstr_free(CString *cstr)
1397 tcc_free(cstr->data_allocated);
1398 cstr_new(cstr);
1401 #define cstr_reset(cstr) cstr_free(cstr)
1403 static CString *cstr_dup(CString *cstr1)
1405 CString *cstr;
1406 int size;
1408 cstr = tcc_malloc(sizeof(CString));
1409 size = cstr1->size;
1410 cstr->size = size;
1411 cstr->size_allocated = size;
1412 cstr->data_allocated = tcc_malloc(size);
1413 cstr->data = cstr->data_allocated;
1414 memcpy(cstr->data_allocated, cstr1->data_allocated, size);
1415 return cstr;
1418 /* XXX: unicode ? */
1419 static void add_char(CString *cstr, int c)
1421 if (c == '\'' || c == '\"' || c == '\\') {
1422 /* XXX: could be more precise if char or string */
1423 cstr_ccat(cstr, '\\');
1425 if (c >= 32 && c <= 126) {
1426 cstr_ccat(cstr, c);
1427 } else {
1428 cstr_ccat(cstr, '\\');
1429 if (c == '\n') {
1430 cstr_ccat(cstr, 'n');
1431 } else {
1432 cstr_ccat(cstr, '0' + ((c >> 6) & 7));
1433 cstr_ccat(cstr, '0' + ((c >> 3) & 7));
1434 cstr_ccat(cstr, '0' + (c & 7));
1439 /* XXX: buffer overflow */
1440 /* XXX: float tokens */
1441 char *get_tok_str(int v, CValue *cv)
1443 static char buf[STRING_MAX_SIZE + 1];
1444 static CString cstr_buf;
1445 CString *cstr;
1446 unsigned char *q;
1447 char *p;
1448 int i, len;
1450 /* NOTE: to go faster, we give a fixed buffer for small strings */
1451 cstr_reset(&cstr_buf);
1452 cstr_buf.data = buf;
1453 cstr_buf.size_allocated = sizeof(buf);
1454 p = buf;
1456 switch(v) {
1457 case TOK_CINT:
1458 case TOK_CUINT:
1459 /* XXX: not quite exact, but only useful for testing */
1460 sprintf(p, "%u", cv->ui);
1461 break;
1462 case TOK_CLLONG:
1463 case TOK_CULLONG:
1464 /* XXX: not quite exact, but only useful for testing */
1465 sprintf(p, "%Lu", cv->ull);
1466 break;
1467 case TOK_CCHAR:
1468 case TOK_LCHAR:
1469 cstr_ccat(&cstr_buf, '\'');
1470 add_char(&cstr_buf, cv->i);
1471 cstr_ccat(&cstr_buf, '\'');
1472 cstr_ccat(&cstr_buf, '\0');
1473 break;
1474 case TOK_PPNUM:
1475 cstr = cv->cstr;
1476 len = cstr->size - 1;
1477 for(i=0;i<len;i++)
1478 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1479 cstr_ccat(&cstr_buf, '\0');
1480 break;
1481 case TOK_STR:
1482 case TOK_LSTR:
1483 cstr = cv->cstr;
1484 cstr_ccat(&cstr_buf, '\"');
1485 if (v == TOK_STR) {
1486 len = cstr->size - 1;
1487 for(i=0;i<len;i++)
1488 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1489 } else {
1490 len = (cstr->size / sizeof(int)) - 1;
1491 for(i=0;i<len;i++)
1492 add_char(&cstr_buf, ((int *)cstr->data)[i]);
1494 cstr_ccat(&cstr_buf, '\"');
1495 cstr_ccat(&cstr_buf, '\0');
1496 break;
1497 case TOK_LT:
1498 v = '<';
1499 goto addv;
1500 case TOK_GT:
1501 v = '>';
1502 goto addv;
1503 case TOK_A_SHL:
1504 return strcpy(p, "<<=");
1505 case TOK_A_SAR:
1506 return strcpy(p, ">>=");
1507 default:
1508 if (v < TOK_IDENT) {
1509 /* search in two bytes table */
1510 q = tok_two_chars;
1511 while (*q) {
1512 if (q[2] == v) {
1513 *p++ = q[0];
1514 *p++ = q[1];
1515 *p = '\0';
1516 return buf;
1518 q += 3;
1520 addv:
1521 *p++ = v;
1522 *p = '\0';
1523 } else if (v < tok_ident) {
1524 return table_ident[v - TOK_IDENT]->str;
1525 } else if (v >= SYM_FIRST_ANOM) {
1526 /* special name for anonymous symbol */
1527 sprintf(p, "L.%u", v - SYM_FIRST_ANOM);
1528 } else {
1529 /* should never happen */
1530 return NULL;
1532 break;
1534 return cstr_buf.data;
1537 /* push, without hashing */
1538 static Sym *sym_push2(Sym **ps, int v, int t, int c)
1540 Sym *s;
1541 s = tcc_malloc(sizeof(Sym));
1542 s->v = v;
1543 s->type.t = t;
1544 s->c = c;
1545 s->next = NULL;
1546 /* add in stack */
1547 s->prev = *ps;
1548 *ps = s;
1549 return s;
1552 /* find a symbol and return its associated structure. 's' is the top
1553 of the symbol stack */
1554 static Sym *sym_find2(Sym *s, int v)
1556 while (s) {
1557 if (s->v == v)
1558 return s;
1559 s = s->prev;
1561 return NULL;
1564 /* structure lookup */
1565 static inline Sym *struct_find(int v)
1567 v -= TOK_IDENT;
1568 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1569 return NULL;
1570 return table_ident[v]->sym_struct;
1573 /* find an identifier */
1574 static inline Sym *sym_find(int v)
1576 v -= TOK_IDENT;
1577 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1578 return NULL;
1579 return table_ident[v]->sym_identifier;
1582 /* push a given symbol on the symbol stack */
1583 static Sym *sym_push(int v, CType *type, int r, int c)
1585 Sym *s, **ps;
1586 TokenSym *ts;
1588 if (local_stack)
1589 ps = &local_stack;
1590 else
1591 ps = &global_stack;
1592 s = sym_push2(ps, v, type->t, c);
1593 s->type.ref = type->ref;
1594 s->r = r;
1595 /* don't record fields or anonymous symbols */
1596 /* XXX: simplify */
1597 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1598 /* record symbol in token array */
1599 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1600 if (v & SYM_STRUCT)
1601 ps = &ts->sym_struct;
1602 else
1603 ps = &ts->sym_identifier;
1604 s->prev_tok = *ps;
1605 *ps = s;
1607 return s;
1610 /* push a global identifier */
1611 static Sym *global_identifier_push(int v, int t, int c)
1613 Sym *s, **ps;
1614 s = sym_push2(&global_stack, v, t, c);
1615 /* don't record anonymous symbol */
1616 if (v < SYM_FIRST_ANOM) {
1617 ps = &table_ident[v - TOK_IDENT]->sym_identifier;
1618 /* modify the top most local identifier, so that
1619 sym_identifier will point to 's' when popped */
1620 while (*ps != NULL)
1621 ps = &(*ps)->prev_tok;
1622 s->prev_tok = NULL;
1623 *ps = s;
1625 return s;
1628 /* pop symbols until top reaches 'b' */
1629 static void sym_pop(Sym **ptop, Sym *b)
1631 Sym *s, *ss, **ps;
1632 TokenSym *ts;
1633 int v;
1635 s = *ptop;
1636 while(s != b) {
1637 ss = s->prev;
1638 v = s->v;
1639 /* remove symbol in token array */
1640 /* XXX: simplify */
1641 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1642 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1643 if (v & SYM_STRUCT)
1644 ps = &ts->sym_struct;
1645 else
1646 ps = &ts->sym_identifier;
1647 *ps = s->prev_tok;
1649 tcc_free(s);
1650 s = ss;
1652 *ptop = b;
1655 /* I/O layer */
1657 BufferedFile *tcc_open(TCCState *s1, const char *filename)
1659 int fd;
1660 BufferedFile *bf;
1662 fd = open(filename, O_RDONLY);
1663 if (fd < 0)
1664 return NULL;
1665 bf = tcc_malloc(sizeof(BufferedFile));
1666 if (!bf) {
1667 close(fd);
1668 return NULL;
1670 bf->fd = fd;
1671 bf->buf_ptr = bf->buffer;
1672 bf->buf_end = bf->buffer;
1673 bf->buffer[0] = CH_EOB; /* put eob symbol */
1674 pstrcpy(bf->filename, sizeof(bf->filename), filename);
1675 bf->line_num = 1;
1676 bf->ifndef_macro = 0;
1677 bf->ifdef_stack_ptr = s1->ifdef_stack_ptr;
1678 // printf("opening '%s'\n", filename);
1679 return bf;
1682 void tcc_close(BufferedFile *bf)
1684 total_lines += bf->line_num;
1685 close(bf->fd);
1686 tcc_free(bf);
1689 /* fill input buffer and peek next char */
1690 static int tcc_peekc_slow(BufferedFile *bf)
1692 int len;
1693 /* only tries to read if really end of buffer */
1694 if (bf->buf_ptr >= bf->buf_end) {
1695 if (bf->fd != -1) {
1696 #if defined(PARSE_DEBUG)
1697 len = 8;
1698 #else
1699 len = IO_BUF_SIZE;
1700 #endif
1701 len = read(bf->fd, bf->buffer, len);
1702 if (len < 0)
1703 len = 0;
1704 } else {
1705 len = 0;
1707 total_bytes += len;
1708 bf->buf_ptr = bf->buffer;
1709 bf->buf_end = bf->buffer + len;
1710 *bf->buf_end = CH_EOB;
1712 if (bf->buf_ptr < bf->buf_end) {
1713 return bf->buf_ptr[0];
1714 } else {
1715 bf->buf_ptr = bf->buf_end;
1716 return CH_EOF;
1720 /* return the current character, handling end of block if necessary
1721 (but not stray) */
1722 static int handle_eob(void)
1724 return tcc_peekc_slow(file);
1727 /* read next char from current input file and handle end of input buffer */
1728 static inline void inp(void)
1730 ch = *(++(file->buf_ptr));
1731 /* end of buffer/file handling */
1732 if (ch == CH_EOB)
1733 ch = handle_eob();
1736 /* handle '\[\r]\n' */
1737 static void handle_stray(void)
1739 while (ch == '\\') {
1740 inp();
1741 if (ch == '\n') {
1742 file->line_num++;
1743 inp();
1744 } else if (ch == '\r') {
1745 inp();
1746 if (ch != '\n')
1747 goto fail;
1748 file->line_num++;
1749 inp();
1750 } else {
1751 fail:
1752 error("stray '\\' in program");
1757 /* skip the stray and handle the \\n case. Output an error if
1758 incorrect char after the stray */
1759 static int handle_stray1(uint8_t *p)
1761 int c;
1763 if (p >= file->buf_end) {
1764 file->buf_ptr = p;
1765 c = handle_eob();
1766 p = file->buf_ptr;
1767 if (c == '\\')
1768 goto parse_stray;
1769 } else {
1770 parse_stray:
1771 file->buf_ptr = p;
1772 ch = *p;
1773 handle_stray();
1774 p = file->buf_ptr;
1775 c = *p;
1777 return c;
1780 /* handle just the EOB case, but not stray */
1781 #define PEEKC_EOB(c, p)\
1783 p++;\
1784 c = *p;\
1785 if (c == '\\') {\
1786 file->buf_ptr = p;\
1787 c = handle_eob();\
1788 p = file->buf_ptr;\
1792 /* handle the complicated stray case */
1793 #define PEEKC(c, p)\
1795 p++;\
1796 c = *p;\
1797 if (c == '\\') {\
1798 c = handle_stray1(p);\
1799 p = file->buf_ptr;\
1803 /* input with '\[\r]\n' handling. Note that this function cannot
1804 handle other characters after '\', so you cannot call it inside
1805 strings or comments */
1806 static void minp(void)
1808 inp();
1809 if (ch == '\\')
1810 handle_stray();
1814 /* single line C++ comments */
1815 static uint8_t *parse_line_comment(uint8_t *p)
1817 int c;
1819 p++;
1820 for(;;) {
1821 c = *p;
1822 if (c == '\n' || c == CH_EOF) {
1823 break;
1824 } else if (c == '\\') {
1825 PEEKC_EOB(c, p);
1826 if (c == '\n') {
1827 file->line_num++;
1828 PEEKC_EOB(c, p);
1829 } else if (c == '\r') {
1830 PEEKC_EOB(c, p);
1831 if (c == '\n') {
1832 file->line_num++;
1833 PEEKC_EOB(c, p);
1836 } else {
1837 p++;
1840 return p;
1843 /* C comments */
1844 static uint8_t *parse_comment(uint8_t *p)
1846 int c;
1848 p++;
1849 for(;;) {
1850 /* fast skip loop */
1851 for(;;) {
1852 c = *p;
1853 if (c == '\n' || c == '*' || c == '\\')
1854 break;
1855 p++;
1856 c = *p;
1857 if (c == '\n' || c == '*' || c == '\\')
1858 break;
1859 p++;
1861 /* now we can handle all the cases */
1862 if (c == '\n') {
1863 file->line_num++;
1864 p++;
1865 } else if (c == '*') {
1866 p++;
1867 for(;;) {
1868 c = *p;
1869 if (c == '*') {
1870 p++;
1871 } else if (c == '/') {
1872 goto end_of_comment;
1873 } else if (c == '\\') {
1874 file->buf_ptr = p;
1875 c = handle_eob();
1876 p = file->buf_ptr;
1877 if (c == '\\') {
1878 /* skip '\[\r]\n', otherwise just skip the stray */
1879 while (c == '\\') {
1880 PEEKC_EOB(c, p);
1881 if (c == '\n') {
1882 file->line_num++;
1883 PEEKC_EOB(c, p);
1884 } else if (c == '\r') {
1885 PEEKC_EOB(c, p);
1886 if (c == '\n') {
1887 file->line_num++;
1888 PEEKC_EOB(c, p);
1890 } else {
1891 goto after_star;
1895 } else {
1896 break;
1899 after_star: ;
1900 } else {
1901 /* stray, eob or eof */
1902 file->buf_ptr = p;
1903 c = handle_eob();
1904 p = file->buf_ptr;
1905 if (c == CH_EOF) {
1906 error("unexpected end of file in comment");
1907 } else if (c == '\\') {
1908 p++;
1912 end_of_comment:
1913 p++;
1914 return p;
1917 #define cinp minp
1919 /* space exlcuding newline */
1920 static inline int is_space(int ch)
1922 return ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f' || ch == '\r';
1925 static inline void skip_spaces(void)
1927 while (is_space(ch))
1928 cinp();
1931 /* parse a string without interpreting escapes */
1932 static uint8_t *parse_pp_string(uint8_t *p,
1933 int sep, CString *str)
1935 int c;
1936 p++;
1937 for(;;) {
1938 c = *p;
1939 if (c == sep) {
1940 break;
1941 } else if (c == '\\') {
1942 file->buf_ptr = p;
1943 c = handle_eob();
1944 p = file->buf_ptr;
1945 if (c == CH_EOF) {
1946 unterminated_string:
1947 /* XXX: indicate line number of start of string */
1948 error("missing terminating %c character", sep);
1949 } else if (c == '\\') {
1950 /* escape : just skip \[\r]\n */
1951 PEEKC_EOB(c, p);
1952 if (c == '\n') {
1953 file->line_num++;
1954 p++;
1955 } else if (c == '\r') {
1956 PEEKC_EOB(c, p);
1957 if (c != '\n')
1958 expect("'\n' after '\r'");
1959 file->line_num++;
1960 p++;
1961 } else if (c == CH_EOF) {
1962 goto unterminated_string;
1963 } else {
1964 if (str) {
1965 cstr_ccat(str, '\\');
1966 cstr_ccat(str, c);
1968 p++;
1971 } else if (c == '\n') {
1972 file->line_num++;
1973 goto add_char;
1974 } else if (c == '\r') {
1975 PEEKC_EOB(c, p);
1976 if (c != '\n') {
1977 cstr_ccat(str, '\r');
1978 } else {
1979 file->line_num++;
1980 goto add_char;
1982 } else {
1983 add_char:
1984 if (str)
1985 cstr_ccat(str, c);
1986 p++;
1989 p++;
1990 return p;
1993 /* skip block of text until #else, #elif or #endif. skip also pairs of
1994 #if/#endif */
1995 void preprocess_skip(void)
1997 int a, start_of_line, c;
1998 uint8_t *p;
2000 p = file->buf_ptr;
2001 start_of_line = 1;
2002 a = 0;
2003 for(;;) {
2004 redo_no_start:
2005 c = *p;
2006 switch(c) {
2007 case ' ':
2008 case '\t':
2009 case '\f':
2010 case '\v':
2011 case '\r':
2012 p++;
2013 goto redo_no_start;
2014 case '\n':
2015 start_of_line = 1;
2016 file->line_num++;
2017 p++;
2018 goto redo_no_start;
2019 case '\\':
2020 file->buf_ptr = p;
2021 c = handle_eob();
2022 if (c == CH_EOF) {
2023 expect("#endif");
2024 } else if (c == '\\') {
2025 /* XXX: incorrect: should not give an error */
2026 ch = file->buf_ptr[0];
2027 handle_stray();
2029 p = file->buf_ptr;
2030 goto redo_no_start;
2031 /* skip strings */
2032 case '\"':
2033 case '\'':
2034 p = parse_pp_string(p, c, NULL);
2035 break;
2036 /* skip comments */
2037 case '/':
2038 file->buf_ptr = p;
2039 ch = *p;
2040 minp();
2041 p = file->buf_ptr;
2042 if (ch == '*') {
2043 p = parse_comment(p);
2044 } else if (ch == '/') {
2045 p = parse_line_comment(p);
2047 break;
2049 case '#':
2050 p++;
2051 if (start_of_line) {
2052 file->buf_ptr = p;
2053 next_nomacro();
2054 p = file->buf_ptr;
2055 if (a == 0 &&
2056 (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
2057 goto the_end;
2058 if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
2059 a++;
2060 else if (tok == TOK_ENDIF)
2061 a--;
2063 break;
2064 default:
2065 p++;
2066 break;
2068 start_of_line = 0;
2070 the_end: ;
2071 file->buf_ptr = p;
2074 /* ParseState handling */
2076 /* XXX: currently, no include file info is stored. Thus, we cannot display
2077 accurate messages if the function or data definition spans multiple
2078 files */
2080 /* save current parse state in 's' */
2081 void save_parse_state(ParseState *s)
2083 s->line_num = file->line_num;
2084 s->macro_ptr = macro_ptr;
2085 s->tok = tok;
2086 s->tokc = tokc;
2089 /* restore parse state from 's' */
2090 void restore_parse_state(ParseState *s)
2092 file->line_num = s->line_num;
2093 macro_ptr = s->macro_ptr;
2094 tok = s->tok;
2095 tokc = s->tokc;
2098 /* return the number of additional 'ints' necessary to store the
2099 token */
2100 static inline int tok_ext_size(int t)
2102 switch(t) {
2103 /* 4 bytes */
2104 case TOK_CINT:
2105 case TOK_CUINT:
2106 case TOK_CCHAR:
2107 case TOK_LCHAR:
2108 case TOK_STR:
2109 case TOK_LSTR:
2110 case TOK_CFLOAT:
2111 case TOK_LINENUM:
2112 case TOK_PPNUM:
2113 return 1;
2114 case TOK_CDOUBLE:
2115 case TOK_CLLONG:
2116 case TOK_CULLONG:
2117 return 2;
2118 case TOK_CLDOUBLE:
2119 return LDOUBLE_SIZE / 4;
2120 default:
2121 return 0;
2125 /* token string handling */
2127 static inline void tok_str_new(TokenString *s)
2129 s->str = NULL;
2130 s->len = 0;
2131 s->allocated_len = 0;
2132 s->last_line_num = -1;
2135 static void tok_str_free(int *str)
2137 const int *p;
2138 CString *cstr;
2139 int t;
2141 p = str;
2142 for(;;) {
2143 t = *p;
2144 /* NOTE: we test zero separately so that GCC can generate a
2145 table for the following switch */
2146 if (t == 0)
2147 break;
2148 switch(t) {
2149 case TOK_CINT:
2150 case TOK_CUINT:
2151 case TOK_CCHAR:
2152 case TOK_LCHAR:
2153 case TOK_CFLOAT:
2154 case TOK_LINENUM:
2155 p += 2;
2156 break;
2157 case TOK_PPNUM:
2158 case TOK_STR:
2159 case TOK_LSTR:
2160 /* XXX: use a macro to be portable on 64 bit ? */
2161 cstr = (CString *)p[1];
2162 cstr_free(cstr);
2163 tcc_free(cstr);
2164 p += 2;
2165 break;
2166 case TOK_CDOUBLE:
2167 case TOK_CLLONG:
2168 case TOK_CULLONG:
2169 p += 3;
2170 break;
2171 case TOK_CLDOUBLE:
2172 p += 1 + (LDOUBLE_SIZE / 4);
2173 break;
2174 default:
2175 p++;
2176 break;
2179 tcc_free(str);
2182 static int *tok_str_realloc(TokenString *s)
2184 int *str, len;
2186 len = s->allocated_len + TOK_STR_ALLOC_INCR;
2187 str = tcc_realloc(s->str, len * sizeof(int));
2188 if (!str)
2189 error("memory full");
2190 s->allocated_len = len;
2191 s->str = str;
2192 return str;
2195 static void tok_str_add(TokenString *s, int t)
2197 int len, *str;
2199 len = s->len;
2200 str = s->str;
2201 if (len >= s->allocated_len)
2202 str = tok_str_realloc(s);
2203 str[len++] = t;
2204 s->len = len;
2207 static void tok_str_add2(TokenString *s, int t, CValue *cv)
2209 int len, *str;
2211 len = s->len;
2212 str = s->str;
2214 /* allocate space for worst case */
2215 if (len + TOK_MAX_SIZE > s->allocated_len)
2216 str = tok_str_realloc(s);
2217 str[len++] = t;
2218 switch(t) {
2219 case TOK_CINT:
2220 case TOK_CUINT:
2221 case TOK_CCHAR:
2222 case TOK_LCHAR:
2223 case TOK_CFLOAT:
2224 case TOK_LINENUM:
2225 str[len++] = cv->tab[0];
2226 break;
2227 case TOK_PPNUM:
2228 case TOK_STR:
2229 case TOK_LSTR:
2230 str[len++] = (int)cstr_dup(cv->cstr);
2231 break;
2232 case TOK_CDOUBLE:
2233 case TOK_CLLONG:
2234 case TOK_CULLONG:
2235 #if LDOUBLE_SIZE == 8
2236 case TOK_CLDOUBLE:
2237 #endif
2238 str[len++] = cv->tab[0];
2239 str[len++] = cv->tab[1];
2240 break;
2241 #if LDOUBLE_SIZE == 12
2242 case TOK_CLDOUBLE:
2243 str[len++] = cv->tab[0];
2244 str[len++] = cv->tab[1];
2245 str[len++] = cv->tab[2];
2246 #elif LDOUBLE_SIZE != 8
2247 #error add long double size support
2248 #endif
2249 break;
2250 default:
2251 break;
2253 s->len = len;
2256 /* add the current parse token in token string 's' */
2257 static void tok_str_add_tok(TokenString *s)
2259 CValue cval;
2261 /* save line number info */
2262 if (file->line_num != s->last_line_num) {
2263 s->last_line_num = file->line_num;
2264 cval.i = s->last_line_num;
2265 tok_str_add2(s, TOK_LINENUM, &cval);
2267 tok_str_add2(s, tok, &tokc);
2270 #if LDOUBLE_SIZE == 12
2271 #define LDOUBLE_GET(p, cv) \
2272 cv.tab[0] = p[0]; \
2273 cv.tab[1] = p[1]; \
2274 cv.tab[2] = p[2];
2275 #elif LDOUBLE_SIZE == 8
2276 #define LDOUBLE_GET(p, cv) \
2277 cv.tab[0] = p[0]; \
2278 cv.tab[1] = p[1];
2279 #else
2280 #error add long double size support
2281 #endif
2284 /* get a token from an integer array and increment pointer
2285 accordingly. we code it as a macro to avoid pointer aliasing. */
2286 #define TOK_GET(t, p, cv) \
2288 t = *p++; \
2289 switch(t) { \
2290 case TOK_CINT: \
2291 case TOK_CUINT: \
2292 case TOK_CCHAR: \
2293 case TOK_LCHAR: \
2294 case TOK_CFLOAT: \
2295 case TOK_LINENUM: \
2296 case TOK_STR: \
2297 case TOK_LSTR: \
2298 case TOK_PPNUM: \
2299 cv.tab[0] = *p++; \
2300 break; \
2301 case TOK_CDOUBLE: \
2302 case TOK_CLLONG: \
2303 case TOK_CULLONG: \
2304 cv.tab[0] = p[0]; \
2305 cv.tab[1] = p[1]; \
2306 p += 2; \
2307 break; \
2308 case TOK_CLDOUBLE: \
2309 LDOUBLE_GET(p, cv); \
2310 p += LDOUBLE_SIZE / 4; \
2311 break; \
2312 default: \
2313 break; \
2317 /* defines handling */
2318 static inline void define_push(int v, int macro_type, int *str, Sym *first_arg)
2320 Sym *s;
2322 s = sym_push2(&define_stack, v, macro_type, (int)str);
2323 s->next = first_arg;
2324 table_ident[v - TOK_IDENT]->sym_define = s;
2327 /* undefined a define symbol. Its name is just set to zero */
2328 static void define_undef(Sym *s)
2330 int v;
2331 v = s->v;
2332 if (v >= TOK_IDENT && v < tok_ident)
2333 table_ident[v - TOK_IDENT]->sym_define = NULL;
2334 s->v = 0;
2337 static inline Sym *define_find(int v)
2339 v -= TOK_IDENT;
2340 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2341 return NULL;
2342 return table_ident[v]->sym_define;
2345 /* free define stack until top reaches 'b' */
2346 static void free_defines(Sym *b)
2348 Sym *top, *top1;
2349 int v;
2351 top = define_stack;
2352 while (top != b) {
2353 top1 = top->prev;
2354 /* do not free args or predefined defines */
2355 if (top->c)
2356 tok_str_free((int *)top->c);
2357 v = top->v;
2358 if (v >= TOK_IDENT && v < tok_ident)
2359 table_ident[v - TOK_IDENT]->sym_define = NULL;
2360 tcc_free(top);
2361 top = top1;
2363 define_stack = b;
2366 /* label lookup */
2367 static Sym *label_find(int v)
2369 v -= TOK_IDENT;
2370 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2371 return NULL;
2372 return table_ident[v]->sym_label;
2375 static Sym *label_push(Sym **ptop, int v, int flags)
2377 Sym *s, **ps;
2378 s = sym_push2(ptop, v, 0, 0);
2379 s->r = flags;
2380 ps = &table_ident[v - TOK_IDENT]->sym_label;
2381 if (ptop == &global_label_stack) {
2382 /* modify the top most local identifier, so that
2383 sym_identifier will point to 's' when popped */
2384 while (*ps != NULL)
2385 ps = &(*ps)->prev_tok;
2387 s->prev_tok = *ps;
2388 *ps = s;
2389 return s;
2392 /* pop labels until element last is reached. Look if any labels are
2393 undefined. Define symbols if '&&label' was used. */
2394 static void label_pop(Sym **ptop, Sym *slast)
2396 Sym *s, *s1;
2397 for(s = *ptop; s != slast; s = s1) {
2398 s1 = s->prev;
2399 if (s->r == LABEL_DECLARED) {
2400 warning("label '%s' declared but not used", get_tok_str(s->v, NULL));
2401 } else if (s->r == LABEL_FORWARD) {
2402 error("label '%s' used but not defined",
2403 get_tok_str(s->v, NULL));
2404 } else {
2405 if (s->c) {
2406 /* define corresponding symbol. A size of
2407 1 is put. */
2408 put_extern_sym(s, cur_text_section, (long)s->next, 1);
2411 /* remove label */
2412 table_ident[s->v - TOK_IDENT]->sym_label = s->prev_tok;
2413 tcc_free(s);
2415 *ptop = slast;
2418 /* eval an expression for #if/#elif */
2419 static int expr_preprocess(void)
2421 int c, t;
2422 TokenString str;
2424 tok_str_new(&str);
2425 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2426 next(); /* do macro subst */
2427 if (tok == TOK_DEFINED) {
2428 next_nomacro();
2429 t = tok;
2430 if (t == '(')
2431 next_nomacro();
2432 c = define_find(tok) != 0;
2433 if (t == '(')
2434 next_nomacro();
2435 tok = TOK_CINT;
2436 tokc.i = c;
2437 } else if (tok >= TOK_IDENT) {
2438 /* if undefined macro */
2439 tok = TOK_CINT;
2440 tokc.i = 0;
2442 tok_str_add_tok(&str);
2444 tok_str_add(&str, -1); /* simulate end of file */
2445 tok_str_add(&str, 0);
2446 /* now evaluate C constant expression */
2447 macro_ptr = str.str;
2448 next();
2449 c = expr_const();
2450 macro_ptr = NULL;
2451 tok_str_free(str.str);
2452 return c != 0;
2455 #if defined(PARSE_DEBUG) || defined(PP_DEBUG)
2456 static void tok_print(int *str)
2458 int t;
2459 CValue cval;
2461 while (1) {
2462 TOK_GET(t, str, cval);
2463 if (!t)
2464 break;
2465 printf(" %s", get_tok_str(t, &cval));
2467 printf("\n");
2469 #endif
2471 /* parse after #define */
2472 static void parse_define(void)
2474 Sym *s, *first, **ps;
2475 int v, t, varg, is_vaargs, c;
2476 TokenString str;
2478 v = tok;
2479 if (v < TOK_IDENT)
2480 error("invalid macro name '%s'", get_tok_str(tok, &tokc));
2481 /* XXX: should check if same macro (ANSI) */
2482 first = NULL;
2483 t = MACRO_OBJ;
2484 /* '(' must be just after macro definition for MACRO_FUNC */
2485 c = file->buf_ptr[0];
2486 if (c == '\\')
2487 c = handle_stray1(file->buf_ptr);
2488 if (c == '(') {
2489 next_nomacro();
2490 next_nomacro();
2491 ps = &first;
2492 while (tok != ')') {
2493 varg = tok;
2494 next_nomacro();
2495 is_vaargs = 0;
2496 if (varg == TOK_DOTS) {
2497 varg = TOK___VA_ARGS__;
2498 is_vaargs = 1;
2499 } else if (tok == TOK_DOTS && gnu_ext) {
2500 is_vaargs = 1;
2501 next_nomacro();
2503 if (varg < TOK_IDENT)
2504 error("badly punctuated parameter list");
2505 s = sym_push2(&define_stack, varg | SYM_FIELD, is_vaargs, 0);
2506 *ps = s;
2507 ps = &s->next;
2508 if (tok != ',')
2509 break;
2510 next_nomacro();
2512 t = MACRO_FUNC;
2514 tok_str_new(&str);
2515 next_nomacro();
2516 /* EOF testing necessary for '-D' handling */
2517 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2518 tok_str_add2(&str, tok, &tokc);
2519 next_nomacro();
2521 tok_str_add(&str, 0);
2522 #ifdef PP_DEBUG
2523 printf("define %s %d: ", get_tok_str(v, NULL), t);
2524 tok_print(str.str);
2525 #endif
2526 define_push(v, t, str.str, first);
2529 /* XXX: use a token or a hash table to accelerate matching ? */
2530 static CachedInclude *search_cached_include(TCCState *s1,
2531 int type, const char *filename)
2533 CachedInclude *e;
2534 int i;
2536 for(i = 0;i < s1->nb_cached_includes; i++) {
2537 e = s1->cached_includes[i];
2538 if (e->type == type && !strcmp(e->filename, filename))
2539 return e;
2541 return NULL;
2544 static inline void add_cached_include(TCCState *s1, int type,
2545 const char *filename, int ifndef_macro)
2547 CachedInclude *e;
2549 if (search_cached_include(s1, type, filename))
2550 return;
2551 #ifdef INC_DEBUG
2552 printf("adding cached '%s' %s\n", filename, get_tok_str(ifndef_macro, NULL));
2553 #endif
2554 e = tcc_malloc(sizeof(CachedInclude) + strlen(filename));
2555 if (!e)
2556 return;
2557 e->type = type;
2558 strcpy(e->filename, filename);
2559 e->ifndef_macro = ifndef_macro;
2560 dynarray_add((void ***)&s1->cached_includes, &s1->nb_cached_includes, e);
2563 /* is_bof is true if first non space token at beginning of file */
2564 static void preprocess(int is_bof)
2566 TCCState *s1 = tcc_state;
2567 int size, i, c, n, saved_parse_flags;
2568 char buf[1024], *q, *p;
2569 char buf1[1024];
2570 BufferedFile *f;
2571 Sym *s;
2572 CachedInclude *e;
2574 saved_parse_flags = parse_flags;
2575 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM |
2576 PARSE_FLAG_LINEFEED;
2577 next_nomacro();
2578 redo:
2579 switch(tok) {
2580 case TOK_DEFINE:
2581 next_nomacro();
2582 parse_define();
2583 break;
2584 case TOK_UNDEF:
2585 next_nomacro();
2586 s = define_find(tok);
2587 /* undefine symbol by putting an invalid name */
2588 if (s)
2589 define_undef(s);
2590 break;
2591 case TOK_INCLUDE:
2592 ch = file->buf_ptr[0];
2593 /* XXX: incorrect if comments : use next_nomacro with a special mode */
2594 skip_spaces();
2595 if (ch == '<') {
2596 c = '>';
2597 goto read_name;
2598 } else if (ch == '\"') {
2599 c = ch;
2600 read_name:
2601 /* XXX: better stray handling */
2602 minp();
2603 q = buf;
2604 while (ch != c && ch != '\n' && ch != CH_EOF) {
2605 if ((q - buf) < sizeof(buf) - 1)
2606 *q++ = ch;
2607 minp();
2609 *q = '\0';
2610 minp();
2611 #if 0
2612 /* eat all spaces and comments after include */
2613 /* XXX: slightly incorrect */
2614 while (ch1 != '\n' && ch1 != CH_EOF)
2615 inp();
2616 #endif
2617 } else {
2618 /* computed #include : either we have only strings or
2619 we have anything enclosed in '<>' */
2620 next();
2621 buf[0] = '\0';
2622 if (tok == TOK_STR) {
2623 while (tok != TOK_LINEFEED) {
2624 if (tok != TOK_STR) {
2625 include_syntax:
2626 error("'#include' expects \"FILENAME\" or <FILENAME>");
2628 pstrcat(buf, sizeof(buf), (char *)tokc.cstr->data);
2629 next();
2631 c = '\"';
2632 } else {
2633 int len;
2634 while (tok != TOK_LINEFEED) {
2635 pstrcat(buf, sizeof(buf), get_tok_str(tok, &tokc));
2636 next();
2638 len = strlen(buf);
2639 /* check syntax and remove '<>' */
2640 if (len < 2 || buf[0] != '<' || buf[len - 1] != '>')
2641 goto include_syntax;
2642 memmove(buf, buf + 1, len - 2);
2643 buf[len - 2] = '\0';
2644 c = '>';
2648 e = search_cached_include(s1, c, buf);
2649 if (e && define_find(e->ifndef_macro)) {
2650 /* no need to parse the include because the 'ifndef macro'
2651 is defined */
2652 #ifdef INC_DEBUG
2653 printf("%s: skipping %s\n", file->filename, buf);
2654 #endif
2655 } else {
2656 if (c == '\"') {
2657 /* first search in current dir if "header.h" */
2658 size = 0;
2659 p = strrchr(file->filename, '/');
2660 if (p)
2661 size = p + 1 - file->filename;
2662 if (size > sizeof(buf1) - 1)
2663 size = sizeof(buf1) - 1;
2664 memcpy(buf1, file->filename, size);
2665 buf1[size] = '\0';
2666 pstrcat(buf1, sizeof(buf1), buf);
2667 f = tcc_open(s1, buf1);
2668 if (f)
2669 goto found;
2671 if (s1->include_stack_ptr >= s1->include_stack + INCLUDE_STACK_SIZE)
2672 error("#include recursion too deep");
2673 /* now search in all the include paths */
2674 n = s1->nb_include_paths + s1->nb_sysinclude_paths;
2675 for(i = 0; i < n; i++) {
2676 const char *path;
2677 if (i < s1->nb_include_paths)
2678 path = s1->include_paths[i];
2679 else
2680 path = s1->sysinclude_paths[i - s1->nb_include_paths];
2681 pstrcpy(buf1, sizeof(buf1), path);
2682 pstrcat(buf1, sizeof(buf1), "/");
2683 pstrcat(buf1, sizeof(buf1), buf);
2684 f = tcc_open(s1, buf1);
2685 if (f)
2686 goto found;
2688 error("include file '%s' not found", buf);
2689 f = NULL;
2690 found:
2691 #ifdef INC_DEBUG
2692 printf("%s: including %s\n", file->filename, buf1);
2693 #endif
2694 f->inc_type = c;
2695 pstrcpy(f->inc_filename, sizeof(f->inc_filename), buf);
2696 /* push current file in stack */
2697 /* XXX: fix current line init */
2698 *s1->include_stack_ptr++ = file;
2699 file = f;
2700 /* add include file debug info */
2701 if (do_debug) {
2702 put_stabs(file->filename, N_BINCL, 0, 0, 0);
2704 tok_flags |= TOK_FLAG_BOF | TOK_FLAG_BOL;
2705 ch = file->buf_ptr[0];
2706 goto the_end;
2708 break;
2709 case TOK_IFNDEF:
2710 c = 1;
2711 goto do_ifdef;
2712 case TOK_IF:
2713 c = expr_preprocess();
2714 goto do_if;
2715 case TOK_IFDEF:
2716 c = 0;
2717 do_ifdef:
2718 next_nomacro();
2719 if (tok < TOK_IDENT)
2720 error("invalid argument for '#if%sdef'", c ? "n" : "");
2721 if (is_bof) {
2722 if (c) {
2723 #ifdef INC_DEBUG
2724 printf("#ifndef %s\n", get_tok_str(tok, NULL));
2725 #endif
2726 file->ifndef_macro = tok;
2729 c = (define_find(tok) != 0) ^ c;
2730 do_if:
2731 if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE)
2732 error("memory full");
2733 *s1->ifdef_stack_ptr++ = c;
2734 goto test_skip;
2735 case TOK_ELSE:
2736 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
2737 error("#else without matching #if");
2738 if (s1->ifdef_stack_ptr[-1] & 2)
2739 error("#else after #else");
2740 c = (s1->ifdef_stack_ptr[-1] ^= 3);
2741 goto test_skip;
2742 case TOK_ELIF:
2743 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
2744 error("#elif without matching #if");
2745 c = s1->ifdef_stack_ptr[-1];
2746 if (c > 1)
2747 error("#elif after #else");
2748 /* last #if/#elif expression was true: we skip */
2749 if (c == 1)
2750 goto skip;
2751 c = expr_preprocess();
2752 s1->ifdef_stack_ptr[-1] = c;
2753 test_skip:
2754 if (!(c & 1)) {
2755 skip:
2756 preprocess_skip();
2757 is_bof = 0;
2758 goto redo;
2760 break;
2761 case TOK_ENDIF:
2762 if (s1->ifdef_stack_ptr <= file->ifdef_stack_ptr)
2763 error("#endif without matching #if");
2764 s1->ifdef_stack_ptr--;
2765 /* '#ifndef macro' was at the start of file. Now we check if
2766 an '#endif' is exactly at the end of file */
2767 if (file->ifndef_macro &&
2768 s1->ifdef_stack_ptr == file->ifdef_stack_ptr) {
2769 file->ifndef_macro_saved = file->ifndef_macro;
2770 /* need to set to zero to avoid false matches if another
2771 #ifndef at middle of file */
2772 file->ifndef_macro = 0;
2773 while (tok != TOK_LINEFEED)
2774 next_nomacro();
2775 tok_flags |= TOK_FLAG_ENDIF;
2776 goto the_end;
2778 break;
2779 case TOK_LINE:
2780 next();
2781 if (tok != TOK_CINT)
2782 error("#line");
2783 file->line_num = tokc.i - 1; /* the line number will be incremented after */
2784 next();
2785 if (tok != TOK_LINEFEED) {
2786 if (tok != TOK_STR)
2787 error("#line");
2788 pstrcpy(file->filename, sizeof(file->filename),
2789 (char *)tokc.cstr->data);
2791 break;
2792 case TOK_ERROR:
2793 case TOK_WARNING:
2794 c = tok;
2795 ch = file->buf_ptr[0];
2796 skip_spaces();
2797 q = buf;
2798 while (ch != '\n' && ch != CH_EOF) {
2799 if ((q - buf) < sizeof(buf) - 1)
2800 *q++ = ch;
2801 minp();
2803 *q = '\0';
2804 if (c == TOK_ERROR)
2805 error("#error %s", buf);
2806 else
2807 warning("#warning %s", buf);
2808 break;
2809 case TOK_PRAGMA:
2810 /* ignored */
2811 break;
2812 default:
2813 if (tok == TOK_LINEFEED || tok == '!' || tok == TOK_CINT) {
2814 /* '!' is ignored to allow C scripts. numbers are ignored
2815 to emulate cpp behaviour */
2816 } else {
2817 error("invalid preprocessing directive #%s", get_tok_str(tok, &tokc));
2819 break;
2821 /* ignore other preprocess commands or #! for C scripts */
2822 while (tok != TOK_LINEFEED)
2823 next_nomacro();
2824 the_end:
2825 parse_flags = saved_parse_flags;
2828 /* evaluate escape codes in a string. */
2829 static void parse_escape_string(CString *outstr, const uint8_t *buf, int is_long)
2831 int c, n;
2832 const uint8_t *p;
2834 p = buf;
2835 for(;;) {
2836 c = *p;
2837 if (c == '\0')
2838 break;
2839 if (c == '\\') {
2840 p++;
2841 /* escape */
2842 c = *p;
2843 switch(c) {
2844 case '0': case '1': case '2': case '3':
2845 case '4': case '5': case '6': case '7':
2846 /* at most three octal digits */
2847 n = c - '0';
2848 p++;
2849 c = *p;
2850 if (isoct(c)) {
2851 n = n * 8 + c - '0';
2852 p++;
2853 c = *p;
2854 if (isoct(c)) {
2855 n = n * 8 + c - '0';
2856 p++;
2859 c = n;
2860 goto add_char_nonext;
2861 case 'x':
2862 p++;
2863 n = 0;
2864 for(;;) {
2865 c = *p;
2866 if (c >= 'a' && c <= 'f')
2867 c = c - 'a' + 10;
2868 else if (c >= 'A' && c <= 'F')
2869 c = c - 'A' + 10;
2870 else if (isnum(c))
2871 c = c - '0';
2872 else
2873 break;
2874 n = n * 16 + c;
2875 p++;
2877 c = n;
2878 goto add_char_nonext;
2879 case 'a':
2880 c = '\a';
2881 break;
2882 case 'b':
2883 c = '\b';
2884 break;
2885 case 'f':
2886 c = '\f';
2887 break;
2888 case 'n':
2889 c = '\n';
2890 break;
2891 case 'r':
2892 c = '\r';
2893 break;
2894 case 't':
2895 c = '\t';
2896 break;
2897 case 'v':
2898 c = '\v';
2899 break;
2900 case 'e':
2901 if (!gnu_ext)
2902 goto invalid_escape;
2903 c = 27;
2904 break;
2905 case '\'':
2906 case '\"':
2907 case '\\':
2908 case '?':
2909 break;
2910 default:
2911 invalid_escape:
2912 if (c >= '!' && c <= '~')
2913 warning("unknown escape sequence: \'\\%c\'", c);
2914 else
2915 warning("unknown escape sequence: \'\\x%x\'", c);
2916 break;
2919 p++;
2920 add_char_nonext:
2921 if (!is_long)
2922 cstr_ccat(outstr, c);
2923 else
2924 cstr_wccat(outstr, c);
2926 /* add a trailing '\0' */
2927 if (!is_long)
2928 cstr_ccat(outstr, '\0');
2929 else
2930 cstr_wccat(outstr, '\0');
2933 /* we use 64 bit numbers */
2934 #define BN_SIZE 2
2936 /* bn = (bn << shift) | or_val */
2937 void bn_lshift(unsigned int *bn, int shift, int or_val)
2939 int i;
2940 unsigned int v;
2941 for(i=0;i<BN_SIZE;i++) {
2942 v = bn[i];
2943 bn[i] = (v << shift) | or_val;
2944 or_val = v >> (32 - shift);
2948 void bn_zero(unsigned int *bn)
2950 int i;
2951 for(i=0;i<BN_SIZE;i++) {
2952 bn[i] = 0;
2956 /* parse number in null terminated string 'p' and return it in the
2957 current token */
2958 void parse_number(const char *p)
2960 int b, t, shift, frac_bits, s, exp_val, ch;
2961 char *q;
2962 unsigned int bn[BN_SIZE];
2963 double d;
2965 /* number */
2966 q = token_buf;
2967 ch = *p++;
2968 t = ch;
2969 ch = *p++;
2970 *q++ = t;
2971 b = 10;
2972 if (t == '.') {
2973 goto float_frac_parse;
2974 } else if (t == '0') {
2975 if (ch == 'x' || ch == 'X') {
2976 q--;
2977 ch = *p++;
2978 b = 16;
2979 } else if (tcc_ext && (ch == 'b' || ch == 'B')) {
2980 q--;
2981 ch = *p++;
2982 b = 2;
2985 /* parse all digits. cannot check octal numbers at this stage
2986 because of floating point constants */
2987 while (1) {
2988 if (ch >= 'a' && ch <= 'f')
2989 t = ch - 'a' + 10;
2990 else if (ch >= 'A' && ch <= 'F')
2991 t = ch - 'A' + 10;
2992 else if (isnum(ch))
2993 t = ch - '0';
2994 else
2995 break;
2996 if (t >= b)
2997 break;
2998 if (q >= token_buf + STRING_MAX_SIZE) {
2999 num_too_long:
3000 error("number too long");
3002 *q++ = ch;
3003 ch = *p++;
3005 if (ch == '.' ||
3006 ((ch == 'e' || ch == 'E') && b == 10) ||
3007 ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
3008 if (b != 10) {
3009 /* NOTE: strtox should support that for hexa numbers, but
3010 non ISOC99 libcs do not support it, so we prefer to do
3011 it by hand */
3012 /* hexadecimal or binary floats */
3013 /* XXX: handle overflows */
3014 *q = '\0';
3015 if (b == 16)
3016 shift = 4;
3017 else
3018 shift = 2;
3019 bn_zero(bn);
3020 q = token_buf;
3021 while (1) {
3022 t = *q++;
3023 if (t == '\0') {
3024 break;
3025 } else if (t >= 'a') {
3026 t = t - 'a' + 10;
3027 } else if (t >= 'A') {
3028 t = t - 'A' + 10;
3029 } else {
3030 t = t - '0';
3032 bn_lshift(bn, shift, t);
3034 frac_bits = 0;
3035 if (ch == '.') {
3036 ch = *p++;
3037 while (1) {
3038 t = ch;
3039 if (t >= 'a' && t <= 'f') {
3040 t = t - 'a' + 10;
3041 } else if (t >= 'A' && t <= 'F') {
3042 t = t - 'A' + 10;
3043 } else if (t >= '0' && t <= '9') {
3044 t = t - '0';
3045 } else {
3046 break;
3048 if (t >= b)
3049 error("invalid digit");
3050 bn_lshift(bn, shift, t);
3051 frac_bits += shift;
3052 ch = *p++;
3055 if (ch != 'p' && ch != 'P')
3056 expect("exponent");
3057 ch = *p++;
3058 s = 1;
3059 exp_val = 0;
3060 if (ch == '+') {
3061 ch = *p++;
3062 } else if (ch == '-') {
3063 s = -1;
3064 ch = *p++;
3066 if (ch < '0' || ch > '9')
3067 expect("exponent digits");
3068 while (ch >= '0' && ch <= '9') {
3069 exp_val = exp_val * 10 + ch - '0';
3070 ch = *p++;
3072 exp_val = exp_val * s;
3074 /* now we can generate the number */
3075 /* XXX: should patch directly float number */
3076 d = (double)bn[1] * 4294967296.0 + (double)bn[0];
3077 d = ldexp(d, exp_val - frac_bits);
3078 t = toup(ch);
3079 if (t == 'F') {
3080 ch = *p++;
3081 tok = TOK_CFLOAT;
3082 /* float : should handle overflow */
3083 tokc.f = (float)d;
3084 } else if (t == 'L') {
3085 ch = *p++;
3086 tok = TOK_CLDOUBLE;
3087 /* XXX: not large enough */
3088 tokc.ld = (long double)d;
3089 } else {
3090 tok = TOK_CDOUBLE;
3091 tokc.d = d;
3093 } else {
3094 /* decimal floats */
3095 if (ch == '.') {
3096 if (q >= token_buf + STRING_MAX_SIZE)
3097 goto num_too_long;
3098 *q++ = ch;
3099 ch = *p++;
3100 float_frac_parse:
3101 while (ch >= '0' && ch <= '9') {
3102 if (q >= token_buf + STRING_MAX_SIZE)
3103 goto num_too_long;
3104 *q++ = ch;
3105 ch = *p++;
3108 if (ch == 'e' || ch == 'E') {
3109 if (q >= token_buf + STRING_MAX_SIZE)
3110 goto num_too_long;
3111 *q++ = ch;
3112 ch = *p++;
3113 if (ch == '-' || ch == '+') {
3114 if (q >= token_buf + STRING_MAX_SIZE)
3115 goto num_too_long;
3116 *q++ = ch;
3117 ch = *p++;
3119 if (ch < '0' || ch > '9')
3120 expect("exponent digits");
3121 while (ch >= '0' && ch <= '9') {
3122 if (q >= token_buf + STRING_MAX_SIZE)
3123 goto num_too_long;
3124 *q++ = ch;
3125 ch = *p++;
3128 *q = '\0';
3129 t = toup(ch);
3130 errno = 0;
3131 if (t == 'F') {
3132 ch = *p++;
3133 tok = TOK_CFLOAT;
3134 tokc.f = strtof(token_buf, NULL);
3135 } else if (t == 'L') {
3136 ch = *p++;
3137 tok = TOK_CLDOUBLE;
3138 tokc.ld = strtold(token_buf, NULL);
3139 } else {
3140 tok = TOK_CDOUBLE;
3141 tokc.d = strtod(token_buf, NULL);
3144 } else {
3145 unsigned long long n, n1;
3146 int lcount, ucount;
3148 /* integer number */
3149 *q = '\0';
3150 q = token_buf;
3151 if (b == 10 && *q == '0') {
3152 b = 8;
3153 q++;
3155 n = 0;
3156 while(1) {
3157 t = *q++;
3158 /* no need for checks except for base 10 / 8 errors */
3159 if (t == '\0') {
3160 break;
3161 } else if (t >= 'a') {
3162 t = t - 'a' + 10;
3163 } else if (t >= 'A') {
3164 t = t - 'A' + 10;
3165 } else {
3166 t = t - '0';
3167 if (t >= b)
3168 error("invalid digit");
3170 n1 = n;
3171 n = n * b + t;
3172 /* detect overflow */
3173 /* XXX: this test is not reliable */
3174 if (n < n1)
3175 error("integer constant overflow");
3178 /* XXX: not exactly ANSI compliant */
3179 if ((n & 0xffffffff00000000LL) != 0) {
3180 if ((n >> 63) != 0)
3181 tok = TOK_CULLONG;
3182 else
3183 tok = TOK_CLLONG;
3184 } else if (n > 0x7fffffff) {
3185 tok = TOK_CUINT;
3186 } else {
3187 tok = TOK_CINT;
3189 lcount = 0;
3190 ucount = 0;
3191 for(;;) {
3192 t = toup(ch);
3193 if (t == 'L') {
3194 if (lcount >= 2)
3195 error("three 'l's in integer constant");
3196 lcount++;
3197 if (lcount == 2) {
3198 if (tok == TOK_CINT)
3199 tok = TOK_CLLONG;
3200 else if (tok == TOK_CUINT)
3201 tok = TOK_CULLONG;
3203 ch = *p++;
3204 } else if (t == 'U') {
3205 if (ucount >= 1)
3206 error("two 'u's in integer constant");
3207 ucount++;
3208 if (tok == TOK_CINT)
3209 tok = TOK_CUINT;
3210 else if (tok == TOK_CLLONG)
3211 tok = TOK_CULLONG;
3212 ch = *p++;
3213 } else {
3214 break;
3217 if (tok == TOK_CINT || tok == TOK_CUINT)
3218 tokc.ui = n;
3219 else
3220 tokc.ull = n;
3225 #define PARSE2(c1, tok1, c2, tok2) \
3226 case c1: \
3227 PEEKC(c, p); \
3228 if (c == c2) { \
3229 p++; \
3230 tok = tok2; \
3231 } else { \
3232 tok = tok1; \
3234 break;
3236 /* return next token without macro substitution */
3237 static inline void next_nomacro1(void)
3239 int t, c, is_long;
3240 TokenSym *ts;
3241 uint8_t *p, *p1;
3242 unsigned int h;
3244 p = file->buf_ptr;
3245 redo_no_start:
3246 c = *p;
3247 switch(c) {
3248 case ' ':
3249 case '\t':
3250 case '\f':
3251 case '\v':
3252 case '\r':
3253 p++;
3254 goto redo_no_start;
3256 case '\\':
3257 /* first look if it is in fact an end of buffer */
3258 if (p >= file->buf_end) {
3259 file->buf_ptr = p;
3260 handle_eob();
3261 p = file->buf_ptr;
3262 if (p >= file->buf_end)
3263 goto parse_eof;
3264 else
3265 goto redo_no_start;
3266 } else {
3267 file->buf_ptr = p;
3268 ch = *p;
3269 handle_stray();
3270 p = file->buf_ptr;
3271 goto redo_no_start;
3273 parse_eof:
3275 TCCState *s1 = tcc_state;
3276 if (parse_flags & PARSE_FLAG_LINEFEED) {
3277 tok = TOK_LINEFEED;
3278 } else if (s1->include_stack_ptr == s1->include_stack ||
3279 !(parse_flags & PARSE_FLAG_PREPROCESS)) {
3280 /* no include left : end of file. */
3281 tok = TOK_EOF;
3282 } else {
3283 /* pop include file */
3285 /* test if previous '#endif' was after a #ifdef at
3286 start of file */
3287 if (tok_flags & TOK_FLAG_ENDIF) {
3288 #ifdef INC_DEBUG
3289 printf("#endif %s\n", get_tok_str(file->ifndef_macro_saved, NULL));
3290 #endif
3291 add_cached_include(s1, file->inc_type, file->inc_filename,
3292 file->ifndef_macro_saved);
3295 /* add end of include file debug info */
3296 if (do_debug) {
3297 put_stabd(N_EINCL, 0, 0);
3299 /* pop include stack */
3300 tcc_close(file);
3301 s1->include_stack_ptr--;
3302 file = *s1->include_stack_ptr;
3303 p = file->buf_ptr;
3304 goto redo_no_start;
3307 break;
3309 case '\n':
3310 if (parse_flags & PARSE_FLAG_LINEFEED) {
3311 tok = TOK_LINEFEED;
3312 } else {
3313 file->line_num++;
3314 tok_flags |= TOK_FLAG_BOL;
3315 p++;
3316 goto redo_no_start;
3318 break;
3320 case '#':
3321 /* XXX: simplify */
3322 PEEKC(c, p);
3323 if ((tok_flags & TOK_FLAG_BOL) &&
3324 (parse_flags & PARSE_FLAG_PREPROCESS)) {
3325 file->buf_ptr = p;
3326 preprocess(tok_flags & TOK_FLAG_BOF);
3327 p = file->buf_ptr;
3328 goto redo_no_start;
3329 } else {
3330 if (c == '#') {
3331 p++;
3332 tok = TOK_TWOSHARPS;
3333 } else {
3334 tok = '#';
3337 break;
3339 case 'a': case 'b': case 'c': case 'd':
3340 case 'e': case 'f': case 'g': case 'h':
3341 case 'i': case 'j': case 'k': case 'l':
3342 case 'm': case 'n': case 'o': case 'p':
3343 case 'q': case 'r': case 's': case 't':
3344 case 'u': case 'v': case 'w': case 'x':
3345 case 'y': case 'z':
3346 case 'A': case 'B': case 'C': case 'D':
3347 case 'E': case 'F': case 'G': case 'H':
3348 case 'I': case 'J': case 'K':
3349 case 'M': case 'N': case 'O': case 'P':
3350 case 'Q': case 'R': case 'S': case 'T':
3351 case 'U': case 'V': case 'W': case 'X':
3352 case 'Y': case 'Z':
3353 case '_':
3354 parse_ident_fast:
3355 p1 = p;
3356 h = TOK_HASH_INIT;
3357 h = TOK_HASH_FUNC(h, c);
3358 p++;
3359 for(;;) {
3360 c = *p;
3361 if (!isidnum_table[c])
3362 break;
3363 h = TOK_HASH_FUNC(h, c);
3364 p++;
3366 if (c != '\\') {
3367 TokenSym **pts;
3368 int len;
3370 /* fast case : no stray found, so we have the full token
3371 and we have already hashed it */
3372 len = p - p1;
3373 h &= (TOK_HASH_SIZE - 1);
3374 pts = &hash_ident[h];
3375 for(;;) {
3376 ts = *pts;
3377 if (!ts)
3378 break;
3379 if (ts->len == len && !memcmp(ts->str, p1, len))
3380 goto token_found;
3381 pts = &(ts->hash_next);
3383 ts = tok_alloc_new(pts, p1, len);
3384 token_found: ;
3385 } else {
3386 /* slower case */
3387 cstr_reset(&tokcstr);
3389 while (p1 < p) {
3390 cstr_ccat(&tokcstr, *p1);
3391 p1++;
3393 p--;
3394 PEEKC(c, p);
3395 parse_ident_slow:
3396 while (isidnum_table[c]) {
3397 cstr_ccat(&tokcstr, c);
3398 PEEKC(c, p);
3400 ts = tok_alloc(tokcstr.data, tokcstr.size);
3402 tok = ts->tok;
3403 break;
3404 case 'L':
3405 t = p[1];
3406 if (t != '\\' && t != '\'' && t != '\"') {
3407 /* fast case */
3408 goto parse_ident_fast;
3409 } else {
3410 PEEKC(c, p);
3411 if (c == '\'' || c == '\"') {
3412 is_long = 1;
3413 goto str_const;
3414 } else {
3415 cstr_reset(&tokcstr);
3416 cstr_ccat(&tokcstr, 'L');
3417 goto parse_ident_slow;
3420 break;
3421 case '0': case '1': case '2': case '3':
3422 case '4': case '5': case '6': case '7':
3423 case '8': case '9':
3425 cstr_reset(&tokcstr);
3426 /* after the first digit, accept digits, alpha, '.' or sign if
3427 prefixed by 'eEpP' */
3428 parse_num:
3429 for(;;) {
3430 t = c;
3431 cstr_ccat(&tokcstr, c);
3432 PEEKC(c, p);
3433 if (!(isnum(c) || isid(c) || c == '.' ||
3434 ((c == '+' || c == '-') &&
3435 (t == 'e' || t == 'E' || t == 'p' || t == 'P'))))
3436 break;
3438 /* We add a trailing '\0' to ease parsing */
3439 cstr_ccat(&tokcstr, '\0');
3440 tokc.cstr = &tokcstr;
3441 tok = TOK_PPNUM;
3442 break;
3443 case '.':
3444 /* special dot handling because it can also start a number */
3445 PEEKC(c, p);
3446 if (isnum(c)) {
3447 cstr_reset(&tokcstr);
3448 cstr_ccat(&tokcstr, '.');
3449 goto parse_num;
3450 } else if (c == '.') {
3451 PEEKC(c, p);
3452 if (c != '.')
3453 expect("'.'");
3454 PEEKC(c, p);
3455 tok = TOK_DOTS;
3456 } else {
3457 tok = '.';
3459 break;
3460 case '\'':
3461 case '\"':
3462 is_long = 0;
3463 str_const:
3465 CString str;
3466 int sep;
3468 sep = c;
3470 /* parse the string */
3471 cstr_new(&str);
3472 p = parse_pp_string(p, sep, &str);
3473 cstr_ccat(&str, '\0');
3475 /* eval the escape (should be done as TOK_PPNUM) */
3476 cstr_reset(&tokcstr);
3477 parse_escape_string(&tokcstr, str.data, is_long);
3478 cstr_free(&str);
3480 if (sep == '\'') {
3481 int char_size;
3482 /* XXX: make it portable */
3483 if (!is_long)
3484 char_size = 1;
3485 else
3486 char_size = sizeof(int);
3487 if (tokcstr.size <= char_size)
3488 error("empty character constant");
3489 if (tokcstr.size > 2 * char_size)
3490 warning("multi-character character constant");
3491 if (!is_long) {
3492 tokc.i = *(int8_t *)tokcstr.data;
3493 tok = TOK_CCHAR;
3494 } else {
3495 tokc.i = *(int *)tokcstr.data;
3496 tok = TOK_LCHAR;
3498 } else {
3499 tokc.cstr = &tokcstr;
3500 if (!is_long)
3501 tok = TOK_STR;
3502 else
3503 tok = TOK_LSTR;
3506 break;
3508 case '<':
3509 PEEKC(c, p);
3510 if (c == '=') {
3511 p++;
3512 tok = TOK_LE;
3513 } else if (c == '<') {
3514 PEEKC(c, p);
3515 if (c == '=') {
3516 p++;
3517 tok = TOK_A_SHL;
3518 } else {
3519 tok = TOK_SHL;
3521 } else {
3522 tok = TOK_LT;
3524 break;
3526 case '>':
3527 PEEKC(c, p);
3528 if (c == '=') {
3529 p++;
3530 tok = TOK_GE;
3531 } else if (c == '>') {
3532 PEEKC(c, p);
3533 if (c == '=') {
3534 p++;
3535 tok = TOK_A_SAR;
3536 } else {
3537 tok = TOK_SAR;
3539 } else {
3540 tok = TOK_GT;
3542 break;
3544 case '&':
3545 PEEKC(c, p);
3546 if (c == '&') {
3547 p++;
3548 tok = TOK_LAND;
3549 } else if (c == '=') {
3550 p++;
3551 tok = TOK_A_AND;
3552 } else {
3553 tok = '&';
3555 break;
3557 case '|':
3558 PEEKC(c, p);
3559 if (c == '|') {
3560 p++;
3561 tok = TOK_LOR;
3562 } else if (c == '=') {
3563 p++;
3564 tok = TOK_A_OR;
3565 } else {
3566 tok = '|';
3568 break;
3570 case '+':
3571 PEEKC(c, p);
3572 if (c == '+') {
3573 p++;
3574 tok = TOK_INC;
3575 } else if (c == '=') {
3576 p++;
3577 tok = TOK_A_ADD;
3578 } else {
3579 tok = '+';
3581 break;
3583 case '-':
3584 PEEKC(c, p);
3585 if (c == '-') {
3586 p++;
3587 tok = TOK_DEC;
3588 } else if (c == '=') {
3589 p++;
3590 tok = TOK_A_SUB;
3591 } else if (c == '>') {
3592 p++;
3593 tok = TOK_ARROW;
3594 } else {
3595 tok = '-';
3597 break;
3599 PARSE2('!', '!', '=', TOK_NE)
3600 PARSE2('=', '=', '=', TOK_EQ)
3601 PARSE2('*', '*', '=', TOK_A_MUL)
3602 PARSE2('%', '%', '=', TOK_A_MOD)
3603 PARSE2('^', '^', '=', TOK_A_XOR)
3605 /* comments or operator */
3606 case '/':
3607 PEEKC(c, p);
3608 if (c == '*') {
3609 p = parse_comment(p);
3610 goto redo_no_start;
3611 } else if (c == '/') {
3612 p = parse_line_comment(p);
3613 goto redo_no_start;
3614 } else if (c == '=') {
3615 p++;
3616 tok = TOK_A_DIV;
3617 } else {
3618 tok = '/';
3620 break;
3622 /* simple tokens */
3623 case '(':
3624 case ')':
3625 case '[':
3626 case ']':
3627 case '{':
3628 case '}':
3629 case ',':
3630 case ';':
3631 case ':':
3632 case '?':
3633 case '~':
3634 case '$': /* only used in assembler */
3635 tok = c;
3636 p++;
3637 break;
3638 default:
3639 error("unrecognized character \\x%02x", c);
3640 break;
3642 file->buf_ptr = p;
3643 tok_flags = 0;
3644 #if defined(PARSE_DEBUG)
3645 printf("token = %s\n", get_tok_str(tok, &tokc));
3646 #endif
3649 /* return next token without macro substitution. Can read input from
3650 macro_ptr buffer */
3651 static void next_nomacro(void)
3653 if (macro_ptr) {
3654 redo:
3655 tok = *macro_ptr;
3656 if (tok) {
3657 TOK_GET(tok, macro_ptr, tokc);
3658 if (tok == TOK_LINENUM) {
3659 file->line_num = tokc.i;
3660 goto redo;
3663 } else {
3664 next_nomacro1();
3668 /* substitute args in macro_str and return allocated string */
3669 static int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
3671 int *st, last_tok, t, notfirst;
3672 Sym *s;
3673 CValue cval;
3674 TokenString str;
3675 CString cstr;
3677 tok_str_new(&str);
3678 last_tok = 0;
3679 while(1) {
3680 TOK_GET(t, macro_str, cval);
3681 if (!t)
3682 break;
3683 if (t == '#') {
3684 /* stringize */
3685 TOK_GET(t, macro_str, cval);
3686 if (!t)
3687 break;
3688 s = sym_find2(args, t);
3689 if (s) {
3690 cstr_new(&cstr);
3691 st = (int *)s->c;
3692 notfirst = 0;
3693 while (*st) {
3694 if (notfirst)
3695 cstr_ccat(&cstr, ' ');
3696 TOK_GET(t, st, cval);
3697 cstr_cat(&cstr, get_tok_str(t, &cval));
3698 notfirst = 1;
3700 cstr_ccat(&cstr, '\0');
3701 #ifdef PP_DEBUG
3702 printf("stringize: %s\n", (char *)cstr.data);
3703 #endif
3704 /* add string */
3705 cval.cstr = &cstr;
3706 tok_str_add2(&str, TOK_STR, &cval);
3707 cstr_free(&cstr);
3708 } else {
3709 tok_str_add2(&str, t, &cval);
3711 } else if (t >= TOK_IDENT) {
3712 s = sym_find2(args, t);
3713 if (s) {
3714 st = (int *)s->c;
3715 /* if '##' is present before or after, no arg substitution */
3716 if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) {
3717 /* special case for var arg macros : ## eats the
3718 ',' if empty VA_ARGS variable. */
3719 /* XXX: test of the ',' is not 100%
3720 reliable. should fix it to avoid security
3721 problems */
3722 if (gnu_ext && s->type.t &&
3723 last_tok == TOK_TWOSHARPS &&
3724 str.len >= 2 && str.str[str.len - 2] == ',') {
3725 if (*st == 0) {
3726 /* suppress ',' '##' */
3727 str.len -= 2;
3728 } else {
3729 /* suppress '##' and add variable */
3730 str.len--;
3731 goto add_var;
3733 } else {
3734 int t1;
3735 add_var:
3736 for(;;) {
3737 TOK_GET(t1, st, cval);
3738 if (!t1)
3739 break;
3740 tok_str_add2(&str, t1, &cval);
3743 } else {
3744 /* NOTE: the stream cannot be read when macro
3745 substituing an argument */
3746 macro_subst(&str, nested_list, st, 0);
3748 } else {
3749 tok_str_add(&str, t);
3751 } else {
3752 tok_str_add2(&str, t, &cval);
3754 last_tok = t;
3756 tok_str_add(&str, 0);
3757 return str.str;
3760 static char const ab_month_name[12][4] =
3762 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
3763 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
3766 /* do macro substitution of current token with macro 's' and add
3767 result to (tok_str,tok_len). 'nested_list' is the list of all
3768 macros we got inside to avoid recursing. Return non zero if no
3769 substitution needs to be done */
3770 static int macro_subst_tok(TokenString *tok_str,
3771 Sym **nested_list, Sym *s, int can_read_stream)
3773 Sym *args, *sa, *sa1;
3774 int mstr_allocated, parlevel, *mstr, t;
3775 TokenString str;
3776 char *cstrval;
3777 CValue cval;
3778 CString cstr;
3780 /* if symbol is a macro, prepare substitution */
3782 /* special macros */
3783 if (tok == TOK___LINE__) {
3784 cval.i = file->line_num;
3785 tok_str_add2(tok_str, TOK_CINT, &cval);
3786 } else if (tok == TOK___FILE__) {
3787 cstrval = file->filename;
3788 goto add_cstr;
3789 tok_str_add2(tok_str, TOK_STR, &cval);
3790 } else if (tok == TOK___DATE__ || tok == TOK___TIME__) {
3791 time_t ti;
3792 struct tm *tm;
3793 char buf[64];
3795 time(&ti);
3796 tm = localtime(&ti);
3797 if (tok == TOK___DATE__) {
3798 snprintf(buf, sizeof(buf), "%s %2d %d",
3799 ab_month_name[tm->tm_mon], tm->tm_mday, tm->tm_year + 1900);
3800 } else {
3801 snprintf(buf, sizeof(buf), "%02d:%02d:%02d",
3802 tm->tm_hour, tm->tm_min, tm->tm_sec);
3804 cstrval = buf;
3805 add_cstr:
3806 cstr_new(&cstr);
3807 cstr_cat(&cstr, cstrval);
3808 cstr_ccat(&cstr, '\0');
3809 cval.cstr = &cstr;
3810 tok_str_add2(tok_str, TOK_STR, &cval);
3811 cstr_free(&cstr);
3812 } else {
3813 mstr = (int *)s->c;
3814 mstr_allocated = 0;
3815 if (s->type.t == MACRO_FUNC) {
3816 /* NOTE: we do not use next_nomacro to avoid eating the
3817 next token. XXX: find better solution */
3818 if (macro_ptr) {
3819 t = *macro_ptr;
3820 if (t == 0 && can_read_stream) {
3821 /* end of macro stream: we must look at the token
3822 after in the file */
3823 macro_ptr = NULL;
3824 goto parse_stream;
3826 } else {
3827 parse_stream:
3828 /* XXX: incorrect with comments */
3829 ch = file->buf_ptr[0];
3830 while (is_space(ch) || ch == '\n')
3831 cinp();
3832 t = ch;
3834 if (t != '(') /* no macro subst */
3835 return -1;
3837 /* argument macro */
3838 next_nomacro();
3839 next_nomacro();
3840 args = NULL;
3841 sa = s->next;
3842 /* NOTE: empty args are allowed, except if no args */
3843 for(;;) {
3844 /* handle '()' case */
3845 if (!args && !sa && tok == ')')
3846 break;
3847 if (!sa)
3848 error("macro '%s' used with too many args",
3849 get_tok_str(s->v, 0));
3850 tok_str_new(&str);
3851 parlevel = 0;
3852 /* NOTE: non zero sa->t indicates VA_ARGS */
3853 while ((parlevel > 0 ||
3854 (tok != ')' &&
3855 (tok != ',' || sa->type.t))) &&
3856 tok != -1) {
3857 if (tok == '(')
3858 parlevel++;
3859 else if (tok == ')')
3860 parlevel--;
3861 tok_str_add2(&str, tok, &tokc);
3862 next_nomacro();
3864 tok_str_add(&str, 0);
3865 sym_push2(&args, sa->v & ~SYM_FIELD, sa->type.t, (int)str.str);
3866 sa = sa->next;
3867 if (tok == ')') {
3868 /* special case for gcc var args: add an empty
3869 var arg argument if it is omitted */
3870 if (sa && sa->type.t && gnu_ext)
3871 continue;
3872 else
3873 break;
3875 if (tok != ',')
3876 expect(",");
3877 next_nomacro();
3879 if (sa) {
3880 error("macro '%s' used with too few args",
3881 get_tok_str(s->v, 0));
3884 /* now subst each arg */
3885 mstr = macro_arg_subst(nested_list, mstr, args);
3886 /* free memory */
3887 sa = args;
3888 while (sa) {
3889 sa1 = sa->prev;
3890 tok_str_free((int *)sa->c);
3891 tcc_free(sa);
3892 sa = sa1;
3894 mstr_allocated = 1;
3896 sym_push2(nested_list, s->v, 0, 0);
3897 macro_subst(tok_str, nested_list, mstr, 1);
3898 /* pop nested defined symbol */
3899 sa1 = *nested_list;
3900 *nested_list = sa1->prev;
3901 tcc_free(sa1);
3902 if (mstr_allocated)
3903 tok_str_free(mstr);
3905 return 0;
3908 /* handle the '##' operator. Return NULL if no '##' seen. Otherwise
3909 return the resulting string (which must be freed). */
3910 static inline int *macro_twosharps(const int *macro_str)
3912 TokenSym *ts;
3913 const int *macro_ptr1, *start_macro_ptr, *ptr, *saved_macro_ptr;
3914 int t;
3915 const char *p1, *p2;
3916 CValue cval;
3917 TokenString macro_str1;
3918 CString cstr;
3920 start_macro_ptr = macro_str;
3921 /* we search the first '##' */
3922 for(;;) {
3923 macro_ptr1 = macro_str;
3924 TOK_GET(t, macro_str, cval);
3925 /* nothing more to do if end of string */
3926 if (t == 0)
3927 return NULL;
3928 if (*macro_str == TOK_TWOSHARPS)
3929 break;
3932 /* we saw '##', so we need more processing to handle it */
3933 cstr_new(&cstr);
3934 tok_str_new(&macro_str1);
3935 tok = t;
3936 tokc = cval;
3938 /* add all tokens seen so far */
3939 for(ptr = start_macro_ptr; ptr < macro_ptr1;) {
3940 TOK_GET(t, ptr, cval);
3941 tok_str_add2(&macro_str1, t, &cval);
3943 saved_macro_ptr = macro_ptr;
3944 /* XXX: get rid of the use of macro_ptr here */
3945 macro_ptr = (int *)macro_str;
3946 for(;;) {
3947 while (*macro_ptr == TOK_TWOSHARPS) {
3948 macro_ptr++;
3949 macro_ptr1 = macro_ptr;
3950 t = *macro_ptr;
3951 if (t) {
3952 TOK_GET(t, macro_ptr, cval);
3953 /* We concatenate the two tokens if we have an
3954 identifier or a preprocessing number */
3955 cstr_reset(&cstr);
3956 p1 = get_tok_str(tok, &tokc);
3957 cstr_cat(&cstr, p1);
3958 p2 = get_tok_str(t, &cval);
3959 cstr_cat(&cstr, p2);
3960 cstr_ccat(&cstr, '\0');
3962 if ((tok >= TOK_IDENT || tok == TOK_PPNUM) &&
3963 (t >= TOK_IDENT || t == TOK_PPNUM)) {
3964 if (tok == TOK_PPNUM) {
3965 /* if number, then create a number token */
3966 /* NOTE: no need to allocate because
3967 tok_str_add2() does it */
3968 tokc.cstr = &cstr;
3969 } else {
3970 /* if identifier, we must do a test to
3971 validate we have a correct identifier */
3972 if (t == TOK_PPNUM) {
3973 const char *p;
3974 int c;
3976 p = p2;
3977 for(;;) {
3978 c = *p;
3979 if (c == '\0')
3980 break;
3981 p++;
3982 if (!isnum(c) && !isid(c))
3983 goto error_pasting;
3986 ts = tok_alloc(cstr.data, strlen(cstr.data));
3987 tok = ts->tok; /* modify current token */
3989 } else {
3990 const char *str = cstr.data;
3991 const unsigned char *q;
3993 /* we look for a valid token */
3994 /* XXX: do more extensive checks */
3995 if (!strcmp(str, ">>=")) {
3996 tok = TOK_A_SAR;
3997 } else if (!strcmp(str, "<<=")) {
3998 tok = TOK_A_SHL;
3999 } else if (strlen(str) == 2) {
4000 /* search in two bytes table */
4001 q = tok_two_chars;
4002 for(;;) {
4003 if (!*q)
4004 goto error_pasting;
4005 if (q[0] == str[0] && q[1] == str[1])
4006 break;
4007 q += 3;
4009 tok = q[2];
4010 } else {
4011 error_pasting:
4012 /* NOTE: because get_tok_str use a static buffer,
4013 we must save it */
4014 cstr_reset(&cstr);
4015 p1 = get_tok_str(tok, &tokc);
4016 cstr_cat(&cstr, p1);
4017 cstr_ccat(&cstr, '\0');
4018 p2 = get_tok_str(t, &cval);
4019 warning("pasting \"%s\" and \"%s\" does not give a valid preprocessing token", cstr.data, p2);
4020 /* cannot merge tokens: just add them separately */
4021 tok_str_add2(&macro_str1, tok, &tokc);
4022 /* XXX: free associated memory ? */
4023 tok = t;
4024 tokc = cval;
4029 tok_str_add2(&macro_str1, tok, &tokc);
4030 next_nomacro();
4031 if (tok == 0)
4032 break;
4034 macro_ptr = (int *)saved_macro_ptr;
4035 cstr_free(&cstr);
4036 tok_str_add(&macro_str1, 0);
4037 return macro_str1.str;
4041 /* do macro substitution of macro_str and add result to
4042 (tok_str,tok_len). 'nested_list' is the list of all macros we got
4043 inside to avoid recursing. */
4044 static void macro_subst(TokenString *tok_str, Sym **nested_list,
4045 const int *macro_str, int can_read_stream)
4047 Sym *s;
4048 int *saved_macro_ptr, *macro_str1;
4049 const int *ptr;
4050 int t, ret;
4051 CValue cval;
4053 /* first scan for '##' operator handling */
4054 ptr = macro_str;
4055 macro_str1 = macro_twosharps(ptr);
4056 if (macro_str1)
4057 ptr = macro_str1;
4058 while (1) {
4059 /* NOTE: ptr == NULL can only happen if tokens are read from
4060 file stream due to a macro function call */
4061 if (ptr == NULL)
4062 break;
4063 TOK_GET(t, ptr, cval);
4064 if (t == 0)
4065 break;
4066 s = define_find(t);
4067 if (s != NULL) {
4068 /* if nested substitution, do nothing */
4069 if (sym_find2(*nested_list, t))
4070 goto no_subst;
4071 saved_macro_ptr = macro_ptr;
4072 macro_ptr = (int *)ptr;
4073 tok = t;
4074 ret = macro_subst_tok(tok_str, nested_list, s, can_read_stream);
4075 ptr = (int *)macro_ptr;
4076 macro_ptr = saved_macro_ptr;
4077 if (ret != 0)
4078 goto no_subst;
4079 } else {
4080 no_subst:
4081 tok_str_add2(tok_str, t, &cval);
4084 if (macro_str1)
4085 tok_str_free(macro_str1);
4088 /* return next token with macro substitution */
4089 static void next(void)
4091 Sym *nested_list, *s;
4092 TokenString str;
4094 redo:
4095 next_nomacro();
4096 if (!macro_ptr) {
4097 /* if not reading from macro substituted string, then try
4098 to substitute macros */
4099 if (tok >= TOK_IDENT &&
4100 (parse_flags & PARSE_FLAG_PREPROCESS)) {
4101 s = define_find(tok);
4102 if (s) {
4103 /* we have a macro: we try to substitute */
4104 tok_str_new(&str);
4105 nested_list = NULL;
4106 if (macro_subst_tok(&str, &nested_list, s, 1) == 0) {
4107 /* substitution done, NOTE: maybe empty */
4108 tok_str_add(&str, 0);
4109 macro_ptr = str.str;
4110 macro_ptr_allocated = str.str;
4111 goto redo;
4115 } else {
4116 if (tok == 0) {
4117 /* end of macro or end of unget buffer */
4118 if (unget_buffer_enabled) {
4119 macro_ptr = unget_saved_macro_ptr;
4120 unget_buffer_enabled = 0;
4121 } else {
4122 /* end of macro string: free it */
4123 tok_str_free(macro_ptr_allocated);
4124 macro_ptr = NULL;
4126 goto redo;
4130 /* convert preprocessor tokens into C tokens */
4131 if (tok == TOK_PPNUM &&
4132 (parse_flags & PARSE_FLAG_TOK_NUM)) {
4133 parse_number((char *)tokc.cstr->data);
4137 /* push back current token and set current token to 'last_tok'. Only
4138 identifier case handled for labels. */
4139 static inline void unget_tok(int last_tok)
4141 int i, n;
4142 int *q;
4143 unget_saved_macro_ptr = macro_ptr;
4144 unget_buffer_enabled = 1;
4145 q = unget_saved_buffer;
4146 macro_ptr = q;
4147 *q++ = tok;
4148 n = tok_ext_size(tok) - 1;
4149 for(i=0;i<n;i++)
4150 *q++ = tokc.tab[i];
4151 *q = 0; /* end of token string */
4152 tok = last_tok;
4156 void swap(int *p, int *q)
4158 int t;
4159 t = *p;
4160 *p = *q;
4161 *q = t;
4164 void vsetc(CType *type, int r, CValue *vc)
4166 int v;
4168 if (vtop >= vstack + VSTACK_SIZE)
4169 error("memory full");
4170 /* cannot let cpu flags if other instruction are generated. Also
4171 avoid leaving VT_JMP anywhere except on the top of the stack
4172 because it would complicate the code generator. */
4173 if (vtop >= vstack) {
4174 v = vtop->r & VT_VALMASK;
4175 if (v == VT_CMP || (v & ~1) == VT_JMP)
4176 gv(RC_INT);
4178 vtop++;
4179 vtop->type = *type;
4180 vtop->r = r;
4181 vtop->r2 = VT_CONST;
4182 vtop->c = *vc;
4185 /* push integer constant */
4186 void vpushi(int v)
4188 CValue cval;
4189 cval.i = v;
4190 vsetc(&int_type, VT_CONST, &cval);
4193 /* Return a static symbol pointing to a section */
4194 static Sym *get_sym_ref(CType *type, Section *sec,
4195 unsigned long offset, unsigned long size)
4197 int v;
4198 Sym *sym;
4200 v = anon_sym++;
4201 sym = global_identifier_push(v, type->t | VT_STATIC, 0);
4202 sym->type.ref = type->ref;
4203 sym->r = VT_CONST | VT_SYM;
4204 put_extern_sym(sym, sec, offset, size);
4205 return sym;
4208 /* push a reference to a section offset by adding a dummy symbol */
4209 static void vpush_ref(CType *type, Section *sec, unsigned long offset, unsigned long size)
4211 CValue cval;
4213 cval.ul = 0;
4214 vsetc(type, VT_CONST | VT_SYM, &cval);
4215 vtop->sym = get_sym_ref(type, sec, offset, size);
4218 /* define a new external reference to a symbol 'v' of type 'u' */
4219 static Sym *external_global_sym(int v, CType *type, int r)
4221 Sym *s;
4223 s = sym_find(v);
4224 if (!s) {
4225 /* push forward reference */
4226 s = global_identifier_push(v, type->t | VT_EXTERN, 0);
4227 s->type.ref = type->ref;
4228 s->r = r | VT_CONST | VT_SYM;
4230 return s;
4233 /* define a new external reference to a symbol 'v' of type 'u' */
4234 static Sym *external_sym(int v, CType *type, int r)
4236 Sym *s;
4238 s = sym_find(v);
4239 if (!s) {
4240 /* push forward reference */
4241 s = sym_push(v, type, r | VT_CONST | VT_SYM, 0);
4242 s->type.t |= VT_EXTERN;
4243 } else {
4244 if (!is_compatible_types(&s->type, type))
4245 error("incompatible types for redefinition of '%s'",
4246 get_tok_str(v, NULL));
4248 return s;
4251 /* push a reference to global symbol v */
4252 static void vpush_global_sym(CType *type, int v)
4254 Sym *sym;
4255 CValue cval;
4257 sym = external_global_sym(v, type, 0);
4258 cval.ul = 0;
4259 vsetc(type, VT_CONST | VT_SYM, &cval);
4260 vtop->sym = sym;
4263 void vset(CType *type, int r, int v)
4265 CValue cval;
4267 cval.i = v;
4268 vsetc(type, r, &cval);
4271 void vseti(int r, int v)
4273 CType type;
4274 type.t = VT_INT;
4275 vset(&type, r, v);
4278 void vswap(void)
4280 SValue tmp;
4282 tmp = vtop[0];
4283 vtop[0] = vtop[-1];
4284 vtop[-1] = tmp;
4287 void vpushv(SValue *v)
4289 if (vtop >= vstack + VSTACK_SIZE)
4290 error("memory full");
4291 vtop++;
4292 *vtop = *v;
4295 void vdup(void)
4297 vpushv(vtop);
4300 /* save r to the memory stack, and mark it as being free */
4301 void save_reg(int r)
4303 int l, saved, size, align;
4304 SValue *p, sv;
4305 CType *type;
4307 /* modify all stack values */
4308 saved = 0;
4309 l = 0;
4310 for(p=vstack;p<=vtop;p++) {
4311 if ((p->r & VT_VALMASK) == r ||
4312 (p->r2 & VT_VALMASK) == r) {
4313 /* must save value on stack if not already done */
4314 if (!saved) {
4315 /* NOTE: must reload 'r' because r might be equal to r2 */
4316 r = p->r & VT_VALMASK;
4317 /* store register in the stack */
4318 type = &p->type;
4319 if ((p->r & VT_LVAL) ||
4320 (!is_float(type->t) && (type->t & VT_BTYPE) != VT_LLONG))
4321 type = &int_type;
4322 size = type_size(type, &align);
4323 loc = (loc - size) & -align;
4324 sv.type.t = type->t;
4325 sv.r = VT_LOCAL | VT_LVAL;
4326 sv.c.ul = loc;
4327 store(r, &sv);
4328 #ifdef TCC_TARGET_I386
4329 /* x86 specific: need to pop fp register ST0 if saved */
4330 if (r == TREG_ST0) {
4331 o(0xd9dd); /* fstp %st(1) */
4333 #endif
4334 /* special long long case */
4335 if ((type->t & VT_BTYPE) == VT_LLONG) {
4336 sv.c.ul += 4;
4337 store(p->r2, &sv);
4339 l = loc;
4340 saved = 1;
4342 /* mark that stack entry as being saved on the stack */
4343 if (p->r & VT_LVAL) {
4344 /* also clear the bounded flag because the
4345 relocation address of the function was stored in
4346 p->c.ul */
4347 p->r = (p->r & ~(VT_VALMASK | VT_BOUNDED)) | VT_LLOCAL;
4348 } else {
4349 p->r = lvalue_type(p->type.t) | VT_LOCAL;
4351 p->r2 = VT_CONST;
4352 p->c.ul = l;
4357 /* find a register of class 'rc2' with at most one reference on stack.
4358 * If none, call get_reg(rc) */
4359 int get_reg_ex(int rc, int rc2)
4361 int r;
4362 SValue *p;
4364 for(r=0;r<NB_REGS;r++) {
4365 if (reg_classes[r] & rc2) {
4366 int n;
4367 n=0;
4368 for(p = vstack; p <= vtop; p++) {
4369 if ((p->r & VT_VALMASK) == r ||
4370 (p->r2 & VT_VALMASK) == r)
4371 n++;
4373 if (n <= 1)
4374 return r;
4377 return get_reg(rc);
4380 /* find a free register of class 'rc'. If none, save one register */
4381 int get_reg(int rc)
4383 int r;
4384 SValue *p;
4386 /* find a free register */
4387 for(r=0;r<NB_REGS;r++) {
4388 if (reg_classes[r] & rc) {
4389 for(p=vstack;p<=vtop;p++) {
4390 if ((p->r & VT_VALMASK) == r ||
4391 (p->r2 & VT_VALMASK) == r)
4392 goto notfound;
4394 return r;
4396 notfound: ;
4399 /* no register left : free the first one on the stack (VERY
4400 IMPORTANT to start from the bottom to ensure that we don't
4401 spill registers used in gen_opi()) */
4402 for(p=vstack;p<=vtop;p++) {
4403 r = p->r & VT_VALMASK;
4404 if (r < VT_CONST && (reg_classes[r] & rc))
4405 goto save_found;
4406 /* also look at second register (if long long) */
4407 r = p->r2 & VT_VALMASK;
4408 if (r < VT_CONST && (reg_classes[r] & rc)) {
4409 save_found:
4410 save_reg(r);
4411 return r;
4414 /* Should never comes here */
4415 return -1;
4418 /* save registers up to (vtop - n) stack entry */
4419 void save_regs(int n)
4421 int r;
4422 SValue *p, *p1;
4423 p1 = vtop - n;
4424 for(p = vstack;p <= p1; p++) {
4425 r = p->r & VT_VALMASK;
4426 if (r < VT_CONST) {
4427 save_reg(r);
4432 /* move register 's' to 'r', and flush previous value of r to memory
4433 if needed */
4434 void move_reg(int r, int s)
4436 SValue sv;
4438 if (r != s) {
4439 save_reg(r);
4440 sv.type.t = VT_INT;
4441 sv.r = s;
4442 sv.c.ul = 0;
4443 load(r, &sv);
4447 /* get address of vtop (vtop MUST BE an lvalue) */
4448 void gaddrof(void)
4450 vtop->r &= ~VT_LVAL;
4451 /* tricky: if saved lvalue, then we can go back to lvalue */
4452 if ((vtop->r & VT_VALMASK) == VT_LLOCAL)
4453 vtop->r = (vtop->r & ~(VT_VALMASK | VT_LVAL_TYPE)) | VT_LOCAL | VT_LVAL;
4456 #ifdef CONFIG_TCC_BCHECK
4457 /* generate lvalue bound code */
4458 void gbound(void)
4460 int lval_type;
4461 CType type1;
4463 vtop->r &= ~VT_MUSTBOUND;
4464 /* if lvalue, then use checking code before dereferencing */
4465 if (vtop->r & VT_LVAL) {
4466 /* if not VT_BOUNDED value, then make one */
4467 if (!(vtop->r & VT_BOUNDED)) {
4468 lval_type = vtop->r & (VT_LVAL_TYPE | VT_LVAL);
4469 /* must save type because we must set it to int to get pointer */
4470 type1 = vtop->type;
4471 vtop->type.t = VT_INT;
4472 gaddrof();
4473 vpushi(0);
4474 gen_bounded_ptr_add();
4475 vtop->r |= lval_type;
4476 vtop->type = type1;
4478 /* then check for dereferencing */
4479 gen_bounded_ptr_deref();
4482 #endif
4484 /* store vtop a register belonging to class 'rc'. lvalues are
4485 converted to values. Cannot be used if cannot be converted to
4486 register value (such as structures). */
4487 int gv(int rc)
4489 int r, r2, rc2, bit_pos, bit_size, size, align, i;
4490 unsigned long long ll;
4492 /* NOTE: get_reg can modify vstack[] */
4493 if (vtop->type.t & VT_BITFIELD) {
4494 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
4495 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
4496 /* remove bit field info to avoid loops */
4497 vtop->type.t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
4498 /* generate shifts */
4499 vpushi(32 - (bit_pos + bit_size));
4500 gen_op(TOK_SHL);
4501 vpushi(32 - bit_size);
4502 /* NOTE: transformed to SHR if unsigned */
4503 gen_op(TOK_SAR);
4504 r = gv(rc);
4505 } else {
4506 if (is_float(vtop->type.t) &&
4507 (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4508 Sym *sym;
4509 int *ptr;
4510 unsigned long offset;
4512 /* XXX: unify with initializers handling ? */
4513 /* CPUs usually cannot use float constants, so we store them
4514 generically in data segment */
4515 size = type_size(&vtop->type, &align);
4516 offset = (data_section->data_offset + align - 1) & -align;
4517 data_section->data_offset = offset;
4518 /* XXX: not portable yet */
4519 ptr = section_ptr_add(data_section, size);
4520 size = size >> 2;
4521 for(i=0;i<size;i++)
4522 ptr[i] = vtop->c.tab[i];
4523 sym = get_sym_ref(&vtop->type, data_section, offset, size << 2);
4524 vtop->r |= VT_LVAL | VT_SYM;
4525 vtop->sym = sym;
4526 vtop->c.ul = 0;
4528 #ifdef CONFIG_TCC_BCHECK
4529 if (vtop->r & VT_MUSTBOUND)
4530 gbound();
4531 #endif
4533 r = vtop->r & VT_VALMASK;
4534 /* need to reload if:
4535 - constant
4536 - lvalue (need to dereference pointer)
4537 - already a register, but not in the right class */
4538 if (r >= VT_CONST ||
4539 (vtop->r & VT_LVAL) ||
4540 !(reg_classes[r] & rc) ||
4541 ((vtop->type.t & VT_BTYPE) == VT_LLONG &&
4542 !(reg_classes[vtop->r2] & rc))) {
4543 r = get_reg(rc);
4544 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
4545 /* two register type load : expand to two words
4546 temporarily */
4547 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4548 /* load constant */
4549 ll = vtop->c.ull;
4550 vtop->c.ui = ll; /* first word */
4551 load(r, vtop);
4552 vtop->r = r; /* save register value */
4553 vpushi(ll >> 32); /* second word */
4554 } else if (r >= VT_CONST ||
4555 (vtop->r & VT_LVAL)) {
4556 /* load from memory */
4557 load(r, vtop);
4558 vdup();
4559 vtop[-1].r = r; /* save register value */
4560 /* increment pointer to get second word */
4561 vtop->type.t = VT_INT;
4562 gaddrof();
4563 vpushi(4);
4564 gen_op('+');
4565 vtop->r |= VT_LVAL;
4566 } else {
4567 /* move registers */
4568 load(r, vtop);
4569 vdup();
4570 vtop[-1].r = r; /* save register value */
4571 vtop->r = vtop[-1].r2;
4573 /* allocate second register */
4574 rc2 = RC_INT;
4575 if (rc == RC_IRET)
4576 rc2 = RC_LRET;
4577 r2 = get_reg(rc2);
4578 load(r2, vtop);
4579 vpop();
4580 /* write second register */
4581 vtop->r2 = r2;
4582 } else if ((vtop->r & VT_LVAL) && !is_float(vtop->type.t)) {
4583 int t1, t;
4584 /* lvalue of scalar type : need to use lvalue type
4585 because of possible cast */
4586 t = vtop->type.t;
4587 t1 = t;
4588 /* compute memory access type */
4589 if (vtop->r & VT_LVAL_BYTE)
4590 t = VT_BYTE;
4591 else if (vtop->r & VT_LVAL_SHORT)
4592 t = VT_SHORT;
4593 if (vtop->r & VT_LVAL_UNSIGNED)
4594 t |= VT_UNSIGNED;
4595 vtop->type.t = t;
4596 load(r, vtop);
4597 /* restore wanted type */
4598 vtop->type.t = t1;
4599 } else {
4600 /* one register type load */
4601 load(r, vtop);
4604 vtop->r = r;
4606 return r;
4609 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
4610 void gv2(int rc1, int rc2)
4612 int v;
4614 /* generate more generic register first. But VT_JMP or VT_CMP
4615 values must be generated first in all cases to avoid possible
4616 reload errors */
4617 v = vtop[0].r & VT_VALMASK;
4618 if (v != VT_CMP && (v & ~1) != VT_JMP && rc1 <= rc2) {
4619 vswap();
4620 gv(rc1);
4621 vswap();
4622 gv(rc2);
4623 /* test if reload is needed for first register */
4624 if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
4625 vswap();
4626 gv(rc1);
4627 vswap();
4629 } else {
4630 gv(rc2);
4631 vswap();
4632 gv(rc1);
4633 vswap();
4634 /* test if reload is needed for first register */
4635 if ((vtop[0].r & VT_VALMASK) >= VT_CONST) {
4636 gv(rc2);
4641 /* expand long long on stack in two int registers */
4642 void lexpand(void)
4644 int u;
4646 u = vtop->type.t & VT_UNSIGNED;
4647 gv(RC_INT);
4648 vdup();
4649 vtop[0].r = vtop[-1].r2;
4650 vtop[0].r2 = VT_CONST;
4651 vtop[-1].r2 = VT_CONST;
4652 vtop[0].type.t = VT_INT | u;
4653 vtop[-1].type.t = VT_INT | u;
4656 /* build a long long from two ints */
4657 void lbuild(int t)
4659 gv2(RC_INT, RC_INT);
4660 vtop[-1].r2 = vtop[0].r;
4661 vtop[-1].type.t = t;
4662 vpop();
4665 /* rotate n first stack elements to the bottom
4666 I1 ... In -> I2 ... In I1 [top is right]
4668 void vrotb(int n)
4670 int i;
4671 SValue tmp;
4673 tmp = vtop[-n + 1];
4674 for(i=-n+1;i!=0;i++)
4675 vtop[i] = vtop[i+1];
4676 vtop[0] = tmp;
4679 /* rotate n first stack elements to the top
4680 I1 ... In -> In I1 ... I(n-1) [top is right]
4682 void vrott(int n)
4684 int i;
4685 SValue tmp;
4687 tmp = vtop[0];
4688 for(i = 0;i < n - 1; i++)
4689 vtop[-i] = vtop[-i - 1];
4690 vtop[-n + 1] = tmp;
4693 /* pop stack value */
4694 void vpop(void)
4696 int v;
4697 v = vtop->r & VT_VALMASK;
4698 #ifdef TCC_TARGET_I386
4699 /* for x86, we need to pop the FP stack */
4700 if (v == TREG_ST0 && !nocode_wanted) {
4701 o(0xd9dd); /* fstp %st(1) */
4702 } else
4703 #endif
4704 if (v == VT_JMP || v == VT_JMPI) {
4705 /* need to put correct jump if && or || without test */
4706 gsym(vtop->c.ul);
4708 vtop--;
4711 /* convert stack entry to register and duplicate its value in another
4712 register */
4713 void gv_dup(void)
4715 int rc, t, r, r1;
4716 SValue sv;
4718 t = vtop->type.t;
4719 if ((t & VT_BTYPE) == VT_LLONG) {
4720 lexpand();
4721 gv_dup();
4722 vswap();
4723 vrotb(3);
4724 gv_dup();
4725 vrotb(4);
4726 /* stack: H L L1 H1 */
4727 lbuild(t);
4728 vrotb(3);
4729 vrotb(3);
4730 vswap();
4731 lbuild(t);
4732 vswap();
4733 } else {
4734 /* duplicate value */
4735 rc = RC_INT;
4736 sv.type.t = VT_INT;
4737 if (is_float(t)) {
4738 rc = RC_FLOAT;
4739 sv.type.t = t;
4741 r = gv(rc);
4742 r1 = get_reg(rc);
4743 sv.r = r;
4744 sv.c.ul = 0;
4745 load(r1, &sv); /* move r to r1 */
4746 vdup();
4747 /* duplicates value */
4748 vtop->r = r1;
4752 /* generate CPU independent (unsigned) long long operations */
4753 void gen_opl(int op)
4755 int t, a, b, op1, c, i;
4756 int func;
4757 SValue tmp;
4759 switch(op) {
4760 case '/':
4761 case TOK_PDIV:
4762 func = TOK___divdi3;
4763 goto gen_func;
4764 case TOK_UDIV:
4765 func = TOK___udivdi3;
4766 goto gen_func;
4767 case '%':
4768 func = TOK___moddi3;
4769 goto gen_func;
4770 case TOK_UMOD:
4771 func = TOK___umoddi3;
4772 gen_func:
4773 /* call generic long long function */
4774 vpush_global_sym(&func_old_type, func);
4775 vrott(3);
4776 gfunc_call(2);
4777 vpushi(0);
4778 vtop->r = REG_IRET;
4779 vtop->r2 = REG_LRET;
4780 break;
4781 case '^':
4782 case '&':
4783 case '|':
4784 case '*':
4785 case '+':
4786 case '-':
4787 t = vtop->type.t;
4788 vswap();
4789 lexpand();
4790 vrotb(3);
4791 lexpand();
4792 /* stack: L1 H1 L2 H2 */
4793 tmp = vtop[0];
4794 vtop[0] = vtop[-3];
4795 vtop[-3] = tmp;
4796 tmp = vtop[-2];
4797 vtop[-2] = vtop[-3];
4798 vtop[-3] = tmp;
4799 vswap();
4800 /* stack: H1 H2 L1 L2 */
4801 if (op == '*') {
4802 vpushv(vtop - 1);
4803 vpushv(vtop - 1);
4804 gen_op(TOK_UMULL);
4805 lexpand();
4806 /* stack: H1 H2 L1 L2 ML MH */
4807 for(i=0;i<4;i++)
4808 vrotb(6);
4809 /* stack: ML MH H1 H2 L1 L2 */
4810 tmp = vtop[0];
4811 vtop[0] = vtop[-2];
4812 vtop[-2] = tmp;
4813 /* stack: ML MH H1 L2 H2 L1 */
4814 gen_op('*');
4815 vrotb(3);
4816 vrotb(3);
4817 gen_op('*');
4818 /* stack: ML MH M1 M2 */
4819 gen_op('+');
4820 gen_op('+');
4821 } else if (op == '+' || op == '-') {
4822 /* XXX: add non carry method too (for MIPS or alpha) */
4823 if (op == '+')
4824 op1 = TOK_ADDC1;
4825 else
4826 op1 = TOK_SUBC1;
4827 gen_op(op1);
4828 /* stack: H1 H2 (L1 op L2) */
4829 vrotb(3);
4830 vrotb(3);
4831 gen_op(op1 + 1); /* TOK_xxxC2 */
4832 } else {
4833 gen_op(op);
4834 /* stack: H1 H2 (L1 op L2) */
4835 vrotb(3);
4836 vrotb(3);
4837 /* stack: (L1 op L2) H1 H2 */
4838 gen_op(op);
4839 /* stack: (L1 op L2) (H1 op H2) */
4841 /* stack: L H */
4842 lbuild(t);
4843 break;
4844 case TOK_SAR:
4845 case TOK_SHR:
4846 case TOK_SHL:
4847 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
4848 t = vtop[-1].type.t;
4849 vswap();
4850 lexpand();
4851 vrotb(3);
4852 /* stack: L H shift */
4853 c = (int)vtop->c.i;
4854 /* constant: simpler */
4855 /* NOTE: all comments are for SHL. the other cases are
4856 done by swaping words */
4857 vpop();
4858 if (op != TOK_SHL)
4859 vswap();
4860 if (c >= 32) {
4861 /* stack: L H */
4862 vpop();
4863 if (c > 32) {
4864 vpushi(c - 32);
4865 gen_op(op);
4867 if (op != TOK_SAR) {
4868 vpushi(0);
4869 } else {
4870 gv_dup();
4871 vpushi(31);
4872 gen_op(TOK_SAR);
4874 vswap();
4875 } else {
4876 vswap();
4877 gv_dup();
4878 /* stack: H L L */
4879 vpushi(c);
4880 gen_op(op);
4881 vswap();
4882 vpushi(32 - c);
4883 if (op == TOK_SHL)
4884 gen_op(TOK_SHR);
4885 else
4886 gen_op(TOK_SHL);
4887 vrotb(3);
4888 /* stack: L L H */
4889 vpushi(c);
4890 if (op == TOK_SHL)
4891 gen_op(TOK_SHL);
4892 else
4893 gen_op(TOK_SHR);
4894 gen_op('|');
4896 if (op != TOK_SHL)
4897 vswap();
4898 lbuild(t);
4899 } else {
4900 /* XXX: should provide a faster fallback on x86 ? */
4901 switch(op) {
4902 case TOK_SAR:
4903 func = TOK___sardi3;
4904 goto gen_func;
4905 case TOK_SHR:
4906 func = TOK___shrdi3;
4907 goto gen_func;
4908 case TOK_SHL:
4909 func = TOK___shldi3;
4910 goto gen_func;
4913 break;
4914 default:
4915 /* compare operations */
4916 t = vtop->type.t;
4917 vswap();
4918 lexpand();
4919 vrotb(3);
4920 lexpand();
4921 /* stack: L1 H1 L2 H2 */
4922 tmp = vtop[-1];
4923 vtop[-1] = vtop[-2];
4924 vtop[-2] = tmp;
4925 /* stack: L1 L2 H1 H2 */
4926 /* compare high */
4927 op1 = op;
4928 /* when values are equal, we need to compare low words. since
4929 the jump is inverted, we invert the test too. */
4930 if (op1 == TOK_LT)
4931 op1 = TOK_LE;
4932 else if (op1 == TOK_GT)
4933 op1 = TOK_GE;
4934 else if (op1 == TOK_ULT)
4935 op1 = TOK_ULE;
4936 else if (op1 == TOK_UGT)
4937 op1 = TOK_UGE;
4938 a = 0;
4939 b = 0;
4940 gen_op(op1);
4941 if (op1 != TOK_NE) {
4942 a = gtst(1, 0);
4944 if (op != TOK_EQ) {
4945 /* generate non equal test */
4946 /* XXX: NOT PORTABLE yet */
4947 if (a == 0) {
4948 b = gtst(0, 0);
4949 } else {
4950 #if defined(TCC_TARGET_I386)
4951 b = psym(0x850f, 0);
4952 #elif defined(TCC_TARGET_ARM)
4953 b = ind;
4954 o(0x1A000000 | encbranch(ind, 0, 1));
4955 #else
4956 #error not supported
4957 #endif
4960 /* compare low. Always unsigned */
4961 op1 = op;
4962 if (op1 == TOK_LT)
4963 op1 = TOK_ULT;
4964 else if (op1 == TOK_LE)
4965 op1 = TOK_ULE;
4966 else if (op1 == TOK_GT)
4967 op1 = TOK_UGT;
4968 else if (op1 == TOK_GE)
4969 op1 = TOK_UGE;
4970 gen_op(op1);
4971 a = gtst(1, a);
4972 gsym(b);
4973 vseti(VT_JMPI, a);
4974 break;
4978 /* handle integer constant optimizations and various machine
4979 independent opt */
4980 void gen_opic(int op)
4982 int fc, c1, c2, n;
4983 SValue *v1, *v2;
4985 v1 = vtop - 1;
4986 v2 = vtop;
4987 /* currently, we cannot do computations with forward symbols */
4988 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
4989 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
4990 if (c1 && c2) {
4991 fc = v2->c.i;
4992 switch(op) {
4993 case '+': v1->c.i += fc; break;
4994 case '-': v1->c.i -= fc; break;
4995 case '&': v1->c.i &= fc; break;
4996 case '^': v1->c.i ^= fc; break;
4997 case '|': v1->c.i |= fc; break;
4998 case '*': v1->c.i *= fc; break;
5000 case TOK_PDIV:
5001 case '/':
5002 case '%':
5003 case TOK_UDIV:
5004 case TOK_UMOD:
5005 /* if division by zero, generate explicit division */
5006 if (fc == 0) {
5007 if (const_wanted)
5008 error("division by zero in constant");
5009 goto general_case;
5011 switch(op) {
5012 default: v1->c.i /= fc; break;
5013 case '%': v1->c.i %= fc; break;
5014 case TOK_UDIV: v1->c.i = (unsigned)v1->c.i / fc; break;
5015 case TOK_UMOD: v1->c.i = (unsigned)v1->c.i % fc; break;
5017 break;
5018 case TOK_SHL: v1->c.i <<= fc; break;
5019 case TOK_SHR: v1->c.i = (unsigned)v1->c.i >> fc; break;
5020 case TOK_SAR: v1->c.i >>= fc; break;
5021 /* tests */
5022 case TOK_ULT: v1->c.i = (unsigned)v1->c.i < (unsigned)fc; break;
5023 case TOK_UGE: v1->c.i = (unsigned)v1->c.i >= (unsigned)fc; break;
5024 case TOK_EQ: v1->c.i = v1->c.i == fc; break;
5025 case TOK_NE: v1->c.i = v1->c.i != fc; break;
5026 case TOK_ULE: v1->c.i = (unsigned)v1->c.i <= (unsigned)fc; break;
5027 case TOK_UGT: v1->c.i = (unsigned)v1->c.i > (unsigned)fc; break;
5028 case TOK_LT: v1->c.i = v1->c.i < fc; break;
5029 case TOK_GE: v1->c.i = v1->c.i >= fc; break;
5030 case TOK_LE: v1->c.i = v1->c.i <= fc; break;
5031 case TOK_GT: v1->c.i = v1->c.i > fc; break;
5032 /* logical */
5033 case TOK_LAND: v1->c.i = v1->c.i && fc; break;
5034 case TOK_LOR: v1->c.i = v1->c.i || fc; break;
5035 default:
5036 goto general_case;
5038 vtop--;
5039 } else {
5040 /* if commutative ops, put c2 as constant */
5041 if (c1 && (op == '+' || op == '&' || op == '^' ||
5042 op == '|' || op == '*')) {
5043 vswap();
5044 swap(&c1, &c2);
5046 fc = vtop->c.i;
5047 if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
5048 op == TOK_PDIV) &&
5049 fc == 1) ||
5050 ((op == '+' || op == '-' || op == '|' || op == '^' ||
5051 op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
5052 fc == 0) ||
5053 (op == '&' &&
5054 fc == -1))) {
5055 /* nothing to do */
5056 vtop--;
5057 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
5058 /* try to use shifts instead of muls or divs */
5059 if (fc > 0 && (fc & (fc - 1)) == 0) {
5060 n = -1;
5061 while (fc) {
5062 fc >>= 1;
5063 n++;
5065 vtop->c.i = n;
5066 if (op == '*')
5067 op = TOK_SHL;
5068 else if (op == TOK_PDIV)
5069 op = TOK_SAR;
5070 else
5071 op = TOK_SHR;
5073 goto general_case;
5074 } else if (c2 && (op == '+' || op == '-') &&
5075 (vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) ==
5076 (VT_CONST | VT_SYM)) {
5077 /* symbol + constant case */
5078 if (op == '-')
5079 fc = -fc;
5080 vtop--;
5081 vtop->c.i += fc;
5082 } else {
5083 general_case:
5084 if (!nocode_wanted) {
5085 /* call low level op generator */
5086 gen_opi(op);
5087 } else {
5088 vtop--;
5094 /* generate a floating point operation with constant propagation */
5095 void gen_opif(int op)
5097 int c1, c2;
5098 SValue *v1, *v2;
5099 long double f1, f2;
5101 v1 = vtop - 1;
5102 v2 = vtop;
5103 /* currently, we cannot do computations with forward symbols */
5104 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5105 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5106 if (c1 && c2) {
5107 if (v1->type.t == VT_FLOAT) {
5108 f1 = v1->c.f;
5109 f2 = v2->c.f;
5110 } else if (v1->type.t == VT_DOUBLE) {
5111 f1 = v1->c.d;
5112 f2 = v2->c.d;
5113 } else {
5114 f1 = v1->c.ld;
5115 f2 = v2->c.ld;
5118 /* NOTE: we only do constant propagation if finite number (not
5119 NaN or infinity) (ANSI spec) */
5120 if (!ieee_finite(f1) || !ieee_finite(f2))
5121 goto general_case;
5123 switch(op) {
5124 case '+': f1 += f2; break;
5125 case '-': f1 -= f2; break;
5126 case '*': f1 *= f2; break;
5127 case '/':
5128 if (f2 == 0.0) {
5129 if (const_wanted)
5130 error("division by zero in constant");
5131 goto general_case;
5133 f1 /= f2;
5134 break;
5135 /* XXX: also handles tests ? */
5136 default:
5137 goto general_case;
5139 /* XXX: overflow test ? */
5140 if (v1->type.t == VT_FLOAT) {
5141 v1->c.f = f1;
5142 } else if (v1->type.t == VT_DOUBLE) {
5143 v1->c.d = f1;
5144 } else {
5145 v1->c.ld = f1;
5147 vtop--;
5148 } else {
5149 general_case:
5150 if (!nocode_wanted) {
5151 gen_opf(op);
5152 } else {
5153 vtop--;
5158 static int pointed_size(CType *type)
5160 int align;
5161 return type_size(pointed_type(type), &align);
5164 static inline int is_null_pointer(SValue *p)
5166 if ((p->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
5167 return 0;
5168 return ((p->type.t & VT_BTYPE) == VT_INT && p->c.i == 0) ||
5169 ((p->type.t & VT_BTYPE) == VT_LLONG && p->c.ll == 0);
5172 static inline int is_integer_btype(int bt)
5174 return (bt == VT_BYTE || bt == VT_SHORT ||
5175 bt == VT_INT || bt == VT_LLONG);
5178 /* check types for comparison or substraction of pointers */
5179 static void check_comparison_pointer_types(SValue *p1, SValue *p2, int op)
5181 CType *type1, *type2, tmp_type1, tmp_type2;
5182 int bt1, bt2;
5184 /* null pointers are accepted for all comparisons as gcc */
5185 if (is_null_pointer(p1) || is_null_pointer(p2))
5186 return;
5187 type1 = &p1->type;
5188 type2 = &p2->type;
5189 bt1 = type1->t & VT_BTYPE;
5190 bt2 = type2->t & VT_BTYPE;
5191 /* accept comparison between pointer and integer with a warning */
5192 if ((is_integer_btype(bt1) || is_integer_btype(bt2)) && op != '-') {
5193 warning("comparison between pointer and integer");
5194 return;
5197 /* both must be pointers or implicit function pointers */
5198 if (bt1 == VT_PTR) {
5199 type1 = pointed_type(type1);
5200 } else if (bt1 != VT_FUNC)
5201 goto invalid_operands;
5203 if (bt2 == VT_PTR) {
5204 type2 = pointed_type(type2);
5205 } else if (bt2 != VT_FUNC) {
5206 invalid_operands:
5207 error("invalid operands to binary %s", get_tok_str(op, NULL));
5209 if ((type1->t & VT_BTYPE) == VT_VOID ||
5210 (type2->t & VT_BTYPE) == VT_VOID)
5211 return;
5212 tmp_type1 = *type1;
5213 tmp_type2 = *type2;
5214 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5215 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5216 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
5217 /* gcc-like error if '-' is used */
5218 if (op == '-')
5219 goto invalid_operands;
5220 else
5221 warning("comparison of distinct pointer types lacks a cast");
5225 /* generic gen_op: handles types problems */
5226 void gen_op(int op)
5228 int u, t1, t2, bt1, bt2, t;
5229 CType type1;
5231 t1 = vtop[-1].type.t;
5232 t2 = vtop[0].type.t;
5233 bt1 = t1 & VT_BTYPE;
5234 bt2 = t2 & VT_BTYPE;
5236 if (bt1 == VT_PTR || bt2 == VT_PTR) {
5237 /* at least one operand is a pointer */
5238 /* relationnal op: must be both pointers */
5239 if (op >= TOK_ULT && op <= TOK_GT) {
5240 check_comparison_pointer_types(vtop - 1, vtop, op);
5241 /* pointers are handled are unsigned */
5242 t = VT_INT | VT_UNSIGNED;
5243 goto std_op;
5245 /* if both pointers, then it must be the '-' op */
5246 if (bt1 == VT_PTR && bt2 == VT_PTR) {
5247 if (op != '-')
5248 error("cannot use pointers here");
5249 check_comparison_pointer_types(vtop - 1, vtop, op);
5250 /* XXX: check that types are compatible */
5251 u = pointed_size(&vtop[-1].type);
5252 gen_opic(op);
5253 /* set to integer type */
5254 vtop->type.t = VT_INT;
5255 vpushi(u);
5256 gen_op(TOK_PDIV);
5257 } else {
5258 /* exactly one pointer : must be '+' or '-'. */
5259 if (op != '-' && op != '+')
5260 error("cannot use pointers here");
5261 /* Put pointer as first operand */
5262 if (bt2 == VT_PTR) {
5263 vswap();
5264 swap(&t1, &t2);
5266 type1 = vtop[-1].type;
5267 /* XXX: cast to int ? (long long case) */
5268 vpushi(pointed_size(&vtop[-1].type));
5269 gen_op('*');
5270 #ifdef CONFIG_TCC_BCHECK
5271 /* if evaluating constant expression, no code should be
5272 generated, so no bound check */
5273 if (do_bounds_check && !const_wanted) {
5274 /* if bounded pointers, we generate a special code to
5275 test bounds */
5276 if (op == '-') {
5277 vpushi(0);
5278 vswap();
5279 gen_op('-');
5281 gen_bounded_ptr_add();
5282 } else
5283 #endif
5285 gen_opic(op);
5287 /* put again type if gen_opic() swaped operands */
5288 vtop->type = type1;
5290 } else if (is_float(bt1) || is_float(bt2)) {
5291 /* compute bigger type and do implicit casts */
5292 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
5293 t = VT_LDOUBLE;
5294 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
5295 t = VT_DOUBLE;
5296 } else {
5297 t = VT_FLOAT;
5299 /* floats can only be used for a few operations */
5300 if (op != '+' && op != '-' && op != '*' && op != '/' &&
5301 (op < TOK_ULT || op > TOK_GT))
5302 error("invalid operands for binary operation");
5303 goto std_op;
5304 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
5305 /* cast to biggest op */
5306 t = VT_LLONG;
5307 /* convert to unsigned if it does not fit in a long long */
5308 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
5309 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
5310 t |= VT_UNSIGNED;
5311 goto std_op;
5312 } else {
5313 /* integer operations */
5314 t = VT_INT;
5315 /* convert to unsigned if it does not fit in an integer */
5316 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
5317 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
5318 t |= VT_UNSIGNED;
5319 std_op:
5320 /* XXX: currently, some unsigned operations are explicit, so
5321 we modify them here */
5322 if (t & VT_UNSIGNED) {
5323 if (op == TOK_SAR)
5324 op = TOK_SHR;
5325 else if (op == '/')
5326 op = TOK_UDIV;
5327 else if (op == '%')
5328 op = TOK_UMOD;
5329 else if (op == TOK_LT)
5330 op = TOK_ULT;
5331 else if (op == TOK_GT)
5332 op = TOK_UGT;
5333 else if (op == TOK_LE)
5334 op = TOK_ULE;
5335 else if (op == TOK_GE)
5336 op = TOK_UGE;
5338 vswap();
5339 type1.t = t;
5340 gen_cast(&type1);
5341 vswap();
5342 /* special case for shifts and long long: we keep the shift as
5343 an integer */
5344 if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL)
5345 type1.t = VT_INT;
5346 gen_cast(&type1);
5347 if (is_float(t))
5348 gen_opif(op);
5349 else if ((t & VT_BTYPE) == VT_LLONG)
5350 gen_opl(op);
5351 else
5352 gen_opic(op);
5353 if (op >= TOK_ULT && op <= TOK_GT) {
5354 /* relationnal op: the result is an int */
5355 vtop->type.t = VT_INT;
5356 } else {
5357 vtop->type.t = t;
5362 /* generic itof for unsigned long long case */
5363 void gen_cvt_itof1(int t)
5365 if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
5366 (VT_LLONG | VT_UNSIGNED)) {
5368 if (t == VT_FLOAT)
5369 vpush_global_sym(&func_old_type, TOK___ulltof);
5370 else if (t == VT_DOUBLE)
5371 vpush_global_sym(&func_old_type, TOK___ulltod);
5372 else
5373 vpush_global_sym(&func_old_type, TOK___ulltold);
5374 vrott(2);
5375 gfunc_call(1);
5376 vpushi(0);
5377 vtop->r = REG_FRET;
5378 } else {
5379 gen_cvt_itof(t);
5383 /* generic ftoi for unsigned long long case */
5384 void gen_cvt_ftoi1(int t)
5386 int st;
5388 if (t == (VT_LLONG | VT_UNSIGNED)) {
5389 /* not handled natively */
5390 st = vtop->type.t & VT_BTYPE;
5391 if (st == VT_FLOAT)
5392 vpush_global_sym(&func_old_type, TOK___fixunssfdi);
5393 else if (st == VT_DOUBLE)
5394 vpush_global_sym(&func_old_type, TOK___fixunsdfdi);
5395 else
5396 vpush_global_sym(&func_old_type, TOK___fixunsxfdi);
5397 vrott(2);
5398 gfunc_call(1);
5399 vpushi(0);
5400 vtop->r = REG_IRET;
5401 vtop->r2 = REG_LRET;
5402 } else {
5403 gen_cvt_ftoi(t);
5407 /* force char or short cast */
5408 void force_charshort_cast(int t)
5410 int bits, dbt;
5411 dbt = t & VT_BTYPE;
5412 /* XXX: add optimization if lvalue : just change type and offset */
5413 if (dbt == VT_BYTE)
5414 bits = 8;
5415 else
5416 bits = 16;
5417 if (t & VT_UNSIGNED) {
5418 vpushi((1 << bits) - 1);
5419 gen_op('&');
5420 } else {
5421 bits = 32 - bits;
5422 vpushi(bits);
5423 gen_op(TOK_SHL);
5424 vpushi(bits);
5425 gen_op(TOK_SAR);
5429 /* cast 'vtop' to 'type' */
5430 static void gen_cast(CType *type)
5432 int sbt, dbt, sf, df, c;
5434 /* special delayed cast for char/short */
5435 /* XXX: in some cases (multiple cascaded casts), it may still
5436 be incorrect */
5437 if (vtop->r & VT_MUSTCAST) {
5438 vtop->r &= ~VT_MUSTCAST;
5439 force_charshort_cast(vtop->type.t);
5442 dbt = type->t & (VT_BTYPE | VT_UNSIGNED);
5443 sbt = vtop->type.t & (VT_BTYPE | VT_UNSIGNED);
5445 if (sbt != dbt && !nocode_wanted) {
5446 sf = is_float(sbt);
5447 df = is_float(dbt);
5448 c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5449 if (sf && df) {
5450 /* convert from fp to fp */
5451 if (c) {
5452 /* constant case: we can do it now */
5453 /* XXX: in ISOC, cannot do it if error in convert */
5454 if (dbt == VT_FLOAT && sbt == VT_DOUBLE)
5455 vtop->c.f = (float)vtop->c.d;
5456 else if (dbt == VT_FLOAT && sbt == VT_LDOUBLE)
5457 vtop->c.f = (float)vtop->c.ld;
5458 else if (dbt == VT_DOUBLE && sbt == VT_FLOAT)
5459 vtop->c.d = (double)vtop->c.f;
5460 else if (dbt == VT_DOUBLE && sbt == VT_LDOUBLE)
5461 vtop->c.d = (double)vtop->c.ld;
5462 else if (dbt == VT_LDOUBLE && sbt == VT_FLOAT)
5463 vtop->c.ld = (long double)vtop->c.f;
5464 else if (dbt == VT_LDOUBLE && sbt == VT_DOUBLE)
5465 vtop->c.ld = (long double)vtop->c.d;
5466 } else {
5467 /* non constant case: generate code */
5468 gen_cvt_ftof(dbt);
5470 } else if (df) {
5471 /* convert int to fp */
5472 if (c) {
5473 switch(sbt) {
5474 case VT_LLONG | VT_UNSIGNED:
5475 case VT_LLONG:
5476 /* XXX: add const cases for long long */
5477 goto do_itof;
5478 case VT_INT | VT_UNSIGNED:
5479 switch(dbt) {
5480 case VT_FLOAT: vtop->c.f = (float)vtop->c.ui; break;
5481 case VT_DOUBLE: vtop->c.d = (double)vtop->c.ui; break;
5482 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.ui; break;
5484 break;
5485 default:
5486 switch(dbt) {
5487 case VT_FLOAT: vtop->c.f = (float)vtop->c.i; break;
5488 case VT_DOUBLE: vtop->c.d = (double)vtop->c.i; break;
5489 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.i; break;
5491 break;
5493 } else {
5494 do_itof:
5495 #if !defined(TCC_TARGET_ARM)
5496 gen_cvt_itof1(dbt);
5497 #else
5498 gen_cvt_itof(dbt);
5499 #endif
5501 } else if (sf) {
5502 /* convert fp to int */
5503 /* we handle char/short/etc... with generic code */
5504 if (dbt != (VT_INT | VT_UNSIGNED) &&
5505 dbt != (VT_LLONG | VT_UNSIGNED) &&
5506 dbt != VT_LLONG)
5507 dbt = VT_INT;
5508 if (c) {
5509 switch(dbt) {
5510 case VT_LLONG | VT_UNSIGNED:
5511 case VT_LLONG:
5512 /* XXX: add const cases for long long */
5513 goto do_ftoi;
5514 case VT_INT | VT_UNSIGNED:
5515 switch(sbt) {
5516 case VT_FLOAT: vtop->c.ui = (unsigned int)vtop->c.d; break;
5517 case VT_DOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
5518 case VT_LDOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
5520 break;
5521 default:
5522 /* int case */
5523 switch(sbt) {
5524 case VT_FLOAT: vtop->c.i = (int)vtop->c.d; break;
5525 case VT_DOUBLE: vtop->c.i = (int)vtop->c.d; break;
5526 case VT_LDOUBLE: vtop->c.i = (int)vtop->c.d; break;
5528 break;
5530 } else {
5531 do_ftoi:
5532 gen_cvt_ftoi1(dbt);
5534 if (dbt == VT_INT && (type->t & (VT_BTYPE | VT_UNSIGNED)) != dbt) {
5535 /* additional cast for char/short/bool... */
5536 vtop->type.t = dbt;
5537 gen_cast(type);
5539 } else if ((dbt & VT_BTYPE) == VT_LLONG) {
5540 if ((sbt & VT_BTYPE) != VT_LLONG) {
5541 /* scalar to long long */
5542 if (c) {
5543 if (sbt == (VT_INT | VT_UNSIGNED))
5544 vtop->c.ll = vtop->c.ui;
5545 else
5546 vtop->c.ll = vtop->c.i;
5547 } else {
5548 /* machine independent conversion */
5549 gv(RC_INT);
5550 /* generate high word */
5551 if (sbt == (VT_INT | VT_UNSIGNED)) {
5552 vpushi(0);
5553 gv(RC_INT);
5554 } else {
5555 gv_dup();
5556 vpushi(31);
5557 gen_op(TOK_SAR);
5559 /* patch second register */
5560 vtop[-1].r2 = vtop->r;
5561 vpop();
5564 } else if (dbt == VT_BOOL) {
5565 /* scalar to bool */
5566 vpushi(0);
5567 gen_op(TOK_NE);
5568 } else if ((dbt & VT_BTYPE) == VT_BYTE ||
5569 (dbt & VT_BTYPE) == VT_SHORT) {
5570 force_charshort_cast(dbt);
5571 } else if ((dbt & VT_BTYPE) == VT_INT) {
5572 /* scalar to int */
5573 if (sbt == VT_LLONG) {
5574 /* from long long: just take low order word */
5575 lexpand();
5576 vpop();
5578 /* if lvalue and single word type, nothing to do because
5579 the lvalue already contains the real type size (see
5580 VT_LVAL_xxx constants) */
5583 vtop->type = *type;
5586 /* return type size. Put alignment at 'a' */
5587 static int type_size(CType *type, int *a)
5589 Sym *s;
5590 int bt;
5592 bt = type->t & VT_BTYPE;
5593 if (bt == VT_STRUCT) {
5594 /* struct/union */
5595 s = type->ref;
5596 *a = s->r;
5597 return s->c;
5598 } else if (bt == VT_PTR) {
5599 if (type->t & VT_ARRAY) {
5600 s = type->ref;
5601 return type_size(&s->type, a) * s->c;
5602 } else {
5603 *a = PTR_SIZE;
5604 return PTR_SIZE;
5606 } else if (bt == VT_LDOUBLE) {
5607 *a = LDOUBLE_ALIGN;
5608 return LDOUBLE_SIZE;
5609 } else if (bt == VT_DOUBLE || bt == VT_LLONG) {
5610 *a = 4; /* XXX: i386 specific */
5611 return 8;
5612 } else if (bt == VT_INT || bt == VT_ENUM || bt == VT_FLOAT) {
5613 *a = 4;
5614 return 4;
5615 } else if (bt == VT_SHORT) {
5616 *a = 2;
5617 return 2;
5618 } else {
5619 /* char, void, function, _Bool */
5620 *a = 1;
5621 return 1;
5625 /* return the pointed type of t */
5626 static inline CType *pointed_type(CType *type)
5628 return &type->ref->type;
5631 /* modify type so that its it is a pointer to type. */
5632 static void mk_pointer(CType *type)
5634 Sym *s;
5635 s = sym_push(SYM_FIELD, type, 0, -1);
5636 type->t = VT_PTR | (type->t & ~VT_TYPE);
5637 type->ref = s;
5640 /* compare function types. OLD functions match any new functions */
5641 static int is_compatible_func(CType *type1, CType *type2)
5643 Sym *s1, *s2;
5645 s1 = type1->ref;
5646 s2 = type2->ref;
5647 if (!is_compatible_types(&s1->type, &s2->type))
5648 return 0;
5649 /* XXX: not complete */
5650 if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
5651 return 1;
5652 if (s1->c != s2->c)
5653 return 0;
5654 while (s1 != NULL) {
5655 if (s2 == NULL)
5656 return 0;
5657 if (!is_compatible_types(&s1->type, &s2->type))
5658 return 0;
5659 s1 = s1->next;
5660 s2 = s2->next;
5662 if (s2)
5663 return 0;
5664 return 1;
5667 /* return true if type1 and type2 are exactly the same (including
5668 qualifiers).
5670 - enums are not checked as gcc __builtin_types_compatible_p ()
5672 static int is_compatible_types(CType *type1, CType *type2)
5674 int bt1, t1, t2;
5676 t1 = type1->t & VT_TYPE;
5677 t2 = type2->t & VT_TYPE;
5678 /* XXX: bitfields ? */
5679 if (t1 != t2)
5680 return 0;
5681 /* test more complicated cases */
5682 bt1 = t1 & VT_BTYPE;
5683 if (bt1 == VT_PTR) {
5684 type1 = pointed_type(type1);
5685 type2 = pointed_type(type2);
5686 return is_compatible_types(type1, type2);
5687 } else if (bt1 == VT_STRUCT) {
5688 return (type1->ref == type2->ref);
5689 } else if (bt1 == VT_FUNC) {
5690 return is_compatible_func(type1, type2);
5691 } else {
5692 return 1;
5696 /* print a type. If 'varstr' is not NULL, then the variable is also
5697 printed in the type */
5698 /* XXX: union */
5699 /* XXX: add array and function pointers */
5700 void type_to_str(char *buf, int buf_size,
5701 CType *type, const char *varstr)
5703 int bt, v, t;
5704 Sym *s, *sa;
5705 char buf1[256];
5706 const char *tstr;
5708 t = type->t & VT_TYPE;
5709 bt = t & VT_BTYPE;
5710 buf[0] = '\0';
5711 if (t & VT_CONSTANT)
5712 pstrcat(buf, buf_size, "const ");
5713 if (t & VT_VOLATILE)
5714 pstrcat(buf, buf_size, "volatile ");
5715 if (t & VT_UNSIGNED)
5716 pstrcat(buf, buf_size, "unsigned ");
5717 switch(bt) {
5718 case VT_VOID:
5719 tstr = "void";
5720 goto add_tstr;
5721 case VT_BOOL:
5722 tstr = "_Bool";
5723 goto add_tstr;
5724 case VT_BYTE:
5725 tstr = "char";
5726 goto add_tstr;
5727 case VT_SHORT:
5728 tstr = "short";
5729 goto add_tstr;
5730 case VT_INT:
5731 tstr = "int";
5732 goto add_tstr;
5733 case VT_LONG:
5734 tstr = "long";
5735 goto add_tstr;
5736 case VT_LLONG:
5737 tstr = "long long";
5738 goto add_tstr;
5739 case VT_FLOAT:
5740 tstr = "float";
5741 goto add_tstr;
5742 case VT_DOUBLE:
5743 tstr = "double";
5744 goto add_tstr;
5745 case VT_LDOUBLE:
5746 tstr = "long double";
5747 add_tstr:
5748 pstrcat(buf, buf_size, tstr);
5749 break;
5750 case VT_ENUM:
5751 case VT_STRUCT:
5752 if (bt == VT_STRUCT)
5753 tstr = "struct ";
5754 else
5755 tstr = "enum ";
5756 pstrcat(buf, buf_size, tstr);
5757 v = type->ref->v & ~SYM_STRUCT;
5758 if (v >= SYM_FIRST_ANOM)
5759 pstrcat(buf, buf_size, "<anonymous>");
5760 else
5761 pstrcat(buf, buf_size, get_tok_str(v, NULL));
5762 break;
5763 case VT_FUNC:
5764 s = type->ref;
5765 type_to_str(buf, buf_size, &s->type, varstr);
5766 pstrcat(buf, buf_size, "(");
5767 sa = s->next;
5768 while (sa != NULL) {
5769 type_to_str(buf1, sizeof(buf1), &sa->type, NULL);
5770 pstrcat(buf, buf_size, buf1);
5771 sa = sa->next;
5772 if (sa)
5773 pstrcat(buf, buf_size, ", ");
5775 pstrcat(buf, buf_size, ")");
5776 goto no_var;
5777 case VT_PTR:
5778 s = type->ref;
5779 pstrcpy(buf1, sizeof(buf1), "*");
5780 if (varstr)
5781 pstrcat(buf1, sizeof(buf1), varstr);
5782 type_to_str(buf, buf_size, &s->type, buf1);
5783 goto no_var;
5785 if (varstr) {
5786 pstrcat(buf, buf_size, " ");
5787 pstrcat(buf, buf_size, varstr);
5789 no_var: ;
5792 /* verify type compatibility to store vtop in 'dt' type, and generate
5793 casts if needed. */
5794 static void gen_assign_cast(CType *dt)
5796 CType *st, *type1, *type2, tmp_type1, tmp_type2;
5797 char buf1[256], buf2[256];
5798 int dbt, sbt;
5800 st = &vtop->type; /* source type */
5801 dbt = dt->t & VT_BTYPE;
5802 sbt = st->t & VT_BTYPE;
5803 if (dt->t & VT_CONSTANT)
5804 warning("assignment of read-only location");
5805 switch(dbt) {
5806 case VT_PTR:
5807 /* special cases for pointers */
5808 /* '0' can also be a pointer */
5809 if (is_null_pointer(vtop))
5810 goto type_ok;
5811 /* accept implicit pointer to integer cast with warning */
5812 if (is_integer_btype(sbt)) {
5813 warning("assignment makes pointer from integer without a cast");
5814 goto type_ok;
5816 type1 = pointed_type(dt);
5817 /* a function is implicitely a function pointer */
5818 if (sbt == VT_FUNC) {
5819 if ((type1->t & VT_BTYPE) != VT_VOID &&
5820 !is_compatible_types(pointed_type(dt), st))
5821 goto error;
5822 else
5823 goto type_ok;
5825 if (sbt != VT_PTR)
5826 goto error;
5827 type2 = pointed_type(st);
5828 if ((type1->t & VT_BTYPE) == VT_VOID ||
5829 (type2->t & VT_BTYPE) == VT_VOID) {
5830 /* void * can match anything */
5831 } else {
5832 /* exact type match, except for unsigned */
5833 tmp_type1 = *type1;
5834 tmp_type2 = *type2;
5835 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5836 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5837 if (!is_compatible_types(&tmp_type1, &tmp_type2))
5838 goto error;
5840 /* check const and volatile */
5841 if ((!(type1->t & VT_CONSTANT) && (type2->t & VT_CONSTANT)) ||
5842 (!(type1->t & VT_VOLATILE) && (type2->t & VT_VOLATILE)))
5843 warning("assignment discards qualifiers from pointer target type");
5844 break;
5845 case VT_BYTE:
5846 case VT_SHORT:
5847 case VT_INT:
5848 case VT_LLONG:
5849 if (sbt == VT_PTR || sbt == VT_FUNC) {
5850 warning("assignment makes integer from pointer without a cast");
5852 /* XXX: more tests */
5853 break;
5854 case VT_STRUCT:
5855 if (!is_compatible_types(dt, st)) {
5856 error:
5857 type_to_str(buf1, sizeof(buf1), st, NULL);
5858 type_to_str(buf2, sizeof(buf2), dt, NULL);
5859 error("cannot cast '%s' to '%s'", buf1, buf2);
5861 break;
5863 type_ok:
5864 gen_cast(dt);
5867 /* store vtop in lvalue pushed on stack */
5868 void vstore(void)
5870 int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
5872 ft = vtop[-1].type.t;
5873 sbt = vtop->type.t & VT_BTYPE;
5874 dbt = ft & VT_BTYPE;
5875 if (((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
5876 (sbt == VT_INT && dbt == VT_SHORT)) {
5877 /* optimize char/short casts */
5878 delayed_cast = VT_MUSTCAST;
5879 vtop->type.t = ft & VT_TYPE;
5880 /* XXX: factorize */
5881 if (ft & VT_CONSTANT)
5882 warning("assignment of read-only location");
5883 } else {
5884 delayed_cast = 0;
5885 gen_assign_cast(&vtop[-1].type);
5888 if (sbt == VT_STRUCT) {
5889 /* if structure, only generate pointer */
5890 /* structure assignment : generate memcpy */
5891 /* XXX: optimize if small size */
5892 if (!nocode_wanted) {
5893 size = type_size(&vtop->type, &align);
5895 vpush_global_sym(&func_old_type, TOK_memcpy);
5897 /* destination */
5898 vpushv(vtop - 2);
5899 vtop->type.t = VT_INT;
5900 gaddrof();
5901 /* source */
5902 vpushv(vtop - 2);
5903 vtop->type.t = VT_INT;
5904 gaddrof();
5905 /* type size */
5906 vpushi(size);
5907 gfunc_call(3);
5909 vswap();
5910 vpop();
5911 } else {
5912 vswap();
5913 vpop();
5915 /* leave source on stack */
5916 } else if (ft & VT_BITFIELD) {
5917 /* bitfield store handling */
5918 bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
5919 bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
5920 /* remove bit field info to avoid loops */
5921 vtop[-1].type.t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
5923 /* duplicate destination */
5924 vdup();
5925 vtop[-1] = vtop[-2];
5927 /* mask and shift source */
5928 vpushi((1 << bit_size) - 1);
5929 gen_op('&');
5930 vpushi(bit_pos);
5931 gen_op(TOK_SHL);
5932 /* load destination, mask and or with source */
5933 vswap();
5934 vpushi(~(((1 << bit_size) - 1) << bit_pos));
5935 gen_op('&');
5936 gen_op('|');
5937 /* store result */
5938 vstore();
5939 } else {
5940 #ifdef CONFIG_TCC_BCHECK
5941 /* bound check case */
5942 if (vtop[-1].r & VT_MUSTBOUND) {
5943 vswap();
5944 gbound();
5945 vswap();
5947 #endif
5948 if (!nocode_wanted) {
5949 rc = RC_INT;
5950 if (is_float(ft))
5951 rc = RC_FLOAT;
5952 r = gv(rc); /* generate value */
5953 /* if lvalue was saved on stack, must read it */
5954 if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
5955 SValue sv;
5956 t = get_reg(RC_INT);
5957 sv.type.t = VT_INT;
5958 sv.r = VT_LOCAL | VT_LVAL;
5959 sv.c.ul = vtop[-1].c.ul;
5960 load(t, &sv);
5961 vtop[-1].r = t | VT_LVAL;
5963 store(r, vtop - 1);
5964 /* two word case handling : store second register at word + 4 */
5965 if ((ft & VT_BTYPE) == VT_LLONG) {
5966 vswap();
5967 /* convert to int to increment easily */
5968 vtop->type.t = VT_INT;
5969 gaddrof();
5970 vpushi(4);
5971 gen_op('+');
5972 vtop->r |= VT_LVAL;
5973 vswap();
5974 /* XXX: it works because r2 is spilled last ! */
5975 store(vtop->r2, vtop - 1);
5978 vswap();
5979 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
5980 vtop->r |= delayed_cast;
5984 /* post defines POST/PRE add. c is the token ++ or -- */
5985 void inc(int post, int c)
5987 test_lvalue();
5988 vdup(); /* save lvalue */
5989 if (post) {
5990 gv_dup(); /* duplicate value */
5991 vrotb(3);
5992 vrotb(3);
5994 /* add constant */
5995 vpushi(c - TOK_MID);
5996 gen_op('+');
5997 vstore(); /* store value */
5998 if (post)
5999 vpop(); /* if post op, return saved value */
6002 /* Parse GNUC __attribute__ extension. Currently, the following
6003 extensions are recognized:
6004 - aligned(n) : set data/function alignment.
6005 - section(x) : generate data/code in this section.
6006 - unused : currently ignored, but may be used someday.
6008 static void parse_attribute(AttributeDef *ad)
6010 int t, n;
6012 while (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) {
6013 next();
6014 skip('(');
6015 skip('(');
6016 while (tok != ')') {
6017 if (tok < TOK_IDENT)
6018 expect("attribute name");
6019 t = tok;
6020 next();
6021 switch(t) {
6022 case TOK_SECTION1:
6023 case TOK_SECTION2:
6024 skip('(');
6025 if (tok != TOK_STR)
6026 expect("section name");
6027 ad->section = find_section(tcc_state, (char *)tokc.cstr->data);
6028 next();
6029 skip(')');
6030 break;
6031 case TOK_ALIGNED1:
6032 case TOK_ALIGNED2:
6033 if (tok == '(') {
6034 next();
6035 n = expr_const();
6036 if (n <= 0 || (n & (n - 1)) != 0)
6037 error("alignment must be a positive power of two");
6038 skip(')');
6039 } else {
6040 n = MAX_ALIGN;
6042 ad->aligned = n;
6043 break;
6044 case TOK_UNUSED1:
6045 case TOK_UNUSED2:
6046 /* currently, no need to handle it because tcc does not
6047 track unused objects */
6048 break;
6049 case TOK_NORETURN1:
6050 case TOK_NORETURN2:
6051 /* currently, no need to handle it because tcc does not
6052 track unused objects */
6053 break;
6054 case TOK_CDECL1:
6055 case TOK_CDECL2:
6056 case TOK_CDECL3:
6057 ad->func_call = FUNC_CDECL;
6058 break;
6059 case TOK_STDCALL1:
6060 case TOK_STDCALL2:
6061 case TOK_STDCALL3:
6062 ad->func_call = FUNC_STDCALL;
6063 break;
6064 default:
6065 if (tcc_state->warn_unsupported)
6066 warning("'%s' attribute ignored", get_tok_str(t, NULL));
6067 /* skip parameters */
6068 /* XXX: skip parenthesis too */
6069 if (tok == '(') {
6070 next();
6071 while (tok != ')' && tok != -1)
6072 next();
6073 next();
6075 break;
6077 if (tok != ',')
6078 break;
6079 next();
6081 skip(')');
6082 skip(')');
6086 /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
6087 static void struct_decl(CType *type, int u)
6089 int a, v, size, align, maxalign, c, offset;
6090 int bit_size, bit_pos, bsize, bt, lbit_pos;
6091 Sym *s, *ss, **ps;
6092 AttributeDef ad;
6093 CType type1, btype;
6095 a = tok; /* save decl type */
6096 next();
6097 if (tok != '{') {
6098 v = tok;
6099 next();
6100 /* struct already defined ? return it */
6101 if (v < TOK_IDENT)
6102 expect("struct/union/enum name");
6103 s = struct_find(v);
6104 if (s) {
6105 if (s->type.t != a)
6106 error("invalid type");
6107 goto do_decl;
6109 } else {
6110 v = anon_sym++;
6112 type1.t = a;
6113 /* we put an undefined size for struct/union */
6114 s = sym_push(v | SYM_STRUCT, &type1, 0, -1);
6115 s->r = 0; /* default alignment is zero as gcc */
6116 /* put struct/union/enum name in type */
6117 do_decl:
6118 type->t = u;
6119 type->ref = s;
6121 if (tok == '{') {
6122 next();
6123 if (s->c != -1)
6124 error("struct/union/enum already defined");
6125 /* cannot be empty */
6126 c = 0;
6127 /* non empty enums are not allowed */
6128 if (a == TOK_ENUM) {
6129 for(;;) {
6130 v = tok;
6131 if (v < TOK_UIDENT)
6132 expect("identifier");
6133 next();
6134 if (tok == '=') {
6135 next();
6136 c = expr_const();
6138 /* enum symbols have static storage */
6139 ss = sym_push(v, &int_type, VT_CONST, c);
6140 ss->type.t |= VT_STATIC;
6141 if (tok != ',')
6142 break;
6143 next();
6144 c++;
6145 /* NOTE: we accept a trailing comma */
6146 if (tok == '}')
6147 break;
6149 skip('}');
6150 } else {
6151 maxalign = 1;
6152 ps = &s->next;
6153 bit_pos = 0;
6154 offset = 0;
6155 while (tok != '}') {
6156 parse_btype(&btype, &ad);
6157 while (1) {
6158 bit_size = -1;
6159 v = 0;
6160 type1 = btype;
6161 if (tok != ':') {
6162 type_decl(&type1, &ad, &v, TYPE_DIRECT);
6163 if ((type1.t & VT_BTYPE) == VT_FUNC ||
6164 (type1.t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN | VT_INLINE)))
6165 error("invalid type for '%s'",
6166 get_tok_str(v, NULL));
6168 if (tok == ':') {
6169 next();
6170 bit_size = expr_const();
6171 /* XXX: handle v = 0 case for messages */
6172 if (bit_size < 0)
6173 error("negative width in bit-field '%s'",
6174 get_tok_str(v, NULL));
6175 if (v && bit_size == 0)
6176 error("zero width for bit-field '%s'",
6177 get_tok_str(v, NULL));
6179 size = type_size(&type1, &align);
6180 lbit_pos = 0;
6181 if (bit_size >= 0) {
6182 bt = type1.t & VT_BTYPE;
6183 if (bt != VT_INT &&
6184 bt != VT_BYTE &&
6185 bt != VT_SHORT &&
6186 bt != VT_ENUM)
6187 error("bitfields must have scalar type");
6188 bsize = size * 8;
6189 if (bit_size > bsize) {
6190 error("width of '%s' exceeds its type",
6191 get_tok_str(v, NULL));
6192 } else if (bit_size == bsize) {
6193 /* no need for bit fields */
6194 bit_pos = 0;
6195 } else if (bit_size == 0) {
6196 /* XXX: what to do if only padding in a
6197 structure ? */
6198 /* zero size: means to pad */
6199 if (bit_pos > 0)
6200 bit_pos = bsize;
6201 } else {
6202 /* we do not have enough room ? */
6203 if ((bit_pos + bit_size) > bsize)
6204 bit_pos = 0;
6205 lbit_pos = bit_pos;
6206 /* XXX: handle LSB first */
6207 type1.t |= VT_BITFIELD |
6208 (bit_pos << VT_STRUCT_SHIFT) |
6209 (bit_size << (VT_STRUCT_SHIFT + 6));
6210 bit_pos += bit_size;
6212 } else {
6213 bit_pos = 0;
6215 if (v) {
6216 /* add new memory data only if starting
6217 bit field */
6218 if (lbit_pos == 0) {
6219 if (a == TOK_STRUCT) {
6220 c = (c + align - 1) & -align;
6221 offset = c;
6222 c += size;
6223 } else {
6224 offset = 0;
6225 if (size > c)
6226 c = size;
6228 if (align > maxalign)
6229 maxalign = align;
6231 #if 0
6232 printf("add field %s offset=%d",
6233 get_tok_str(v, NULL), offset);
6234 if (type1.t & VT_BITFIELD) {
6235 printf(" pos=%d size=%d",
6236 (type1.t >> VT_STRUCT_SHIFT) & 0x3f,
6237 (type1.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
6239 printf("\n");
6240 #endif
6241 ss = sym_push(v | SYM_FIELD, &type1, 0, offset);
6242 *ps = ss;
6243 ps = &ss->next;
6245 if (tok == ';' || tok == TOK_EOF)
6246 break;
6247 skip(',');
6249 skip(';');
6251 skip('}');
6252 /* store size and alignment */
6253 s->c = (c + maxalign - 1) & -maxalign;
6254 s->r = maxalign;
6259 /* return 0 if no type declaration. otherwise, return the basic type
6260 and skip it.
6262 static int parse_btype(CType *type, AttributeDef *ad)
6264 int t, u, type_found, typespec_found;
6265 Sym *s;
6266 CType type1;
6268 memset(ad, 0, sizeof(AttributeDef));
6269 type_found = 0;
6270 typespec_found = 0;
6271 t = 0;
6272 while(1) {
6273 switch(tok) {
6274 case TOK_EXTENSION:
6275 /* currently, we really ignore extension */
6276 next();
6277 continue;
6279 /* basic types */
6280 case TOK_CHAR:
6281 u = VT_BYTE;
6282 basic_type:
6283 next();
6284 basic_type1:
6285 if ((t & VT_BTYPE) != 0)
6286 error("too many basic types");
6287 t |= u;
6288 typespec_found = 1;
6289 break;
6290 case TOK_VOID:
6291 u = VT_VOID;
6292 goto basic_type;
6293 case TOK_SHORT:
6294 u = VT_SHORT;
6295 goto basic_type;
6296 case TOK_INT:
6297 next();
6298 typespec_found = 1;
6299 break;
6300 case TOK_LONG:
6301 next();
6302 if ((t & VT_BTYPE) == VT_DOUBLE) {
6303 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6304 } else if ((t & VT_BTYPE) == VT_LONG) {
6305 t = (t & ~VT_BTYPE) | VT_LLONG;
6306 } else {
6307 u = VT_LONG;
6308 goto basic_type1;
6310 break;
6311 case TOK_BOOL:
6312 u = VT_BOOL;
6313 goto basic_type;
6314 case TOK_FLOAT:
6315 u = VT_FLOAT;
6316 goto basic_type;
6317 case TOK_DOUBLE:
6318 next();
6319 if ((t & VT_BTYPE) == VT_LONG) {
6320 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6321 } else {
6322 u = VT_DOUBLE;
6323 goto basic_type1;
6325 break;
6326 case TOK_ENUM:
6327 struct_decl(&type1, VT_ENUM);
6328 basic_type2:
6329 u = type1.t;
6330 type->ref = type1.ref;
6331 goto basic_type1;
6332 case TOK_STRUCT:
6333 case TOK_UNION:
6334 struct_decl(&type1, VT_STRUCT);
6335 goto basic_type2;
6337 /* type modifiers */
6338 case TOK_CONST1:
6339 case TOK_CONST2:
6340 case TOK_CONST3:
6341 t |= VT_CONSTANT;
6342 next();
6343 break;
6344 case TOK_VOLATILE1:
6345 case TOK_VOLATILE2:
6346 case TOK_VOLATILE3:
6347 t |= VT_VOLATILE;
6348 next();
6349 break;
6350 case TOK_SIGNED1:
6351 case TOK_SIGNED2:
6352 case TOK_SIGNED3:
6353 typespec_found = 1;
6354 t |= VT_SIGNED;
6355 next();
6356 break;
6357 case TOK_REGISTER:
6358 case TOK_AUTO:
6359 case TOK_RESTRICT1:
6360 case TOK_RESTRICT2:
6361 case TOK_RESTRICT3:
6362 next();
6363 break;
6364 case TOK_UNSIGNED:
6365 t |= VT_UNSIGNED;
6366 next();
6367 typespec_found = 1;
6368 break;
6370 /* storage */
6371 case TOK_EXTERN:
6372 t |= VT_EXTERN;
6373 next();
6374 break;
6375 case TOK_STATIC:
6376 t |= VT_STATIC;
6377 next();
6378 break;
6379 case TOK_TYPEDEF:
6380 t |= VT_TYPEDEF;
6381 next();
6382 break;
6383 case TOK_INLINE1:
6384 case TOK_INLINE2:
6385 case TOK_INLINE3:
6386 t |= VT_INLINE;
6387 next();
6388 break;
6390 /* GNUC attribute */
6391 case TOK_ATTRIBUTE1:
6392 case TOK_ATTRIBUTE2:
6393 parse_attribute(ad);
6394 break;
6395 /* GNUC typeof */
6396 case TOK_TYPEOF1:
6397 case TOK_TYPEOF2:
6398 case TOK_TYPEOF3:
6399 next();
6400 parse_expr_type(&type1);
6401 goto basic_type2;
6402 default:
6403 if (typespec_found)
6404 goto the_end;
6405 s = sym_find(tok);
6406 if (!s || !(s->type.t & VT_TYPEDEF))
6407 goto the_end;
6408 t |= (s->type.t & ~VT_TYPEDEF);
6409 type->ref = s->type.ref;
6410 next();
6411 break;
6413 type_found = 1;
6415 the_end:
6416 if ((t & (VT_SIGNED|VT_UNSIGNED)) == (VT_SIGNED|VT_UNSIGNED))
6417 error("signed and unsigned modifier");
6418 #ifdef CHAR_IS_UNSIGNED
6419 if ((t & (VT_SIGNED|VT_UNSIGNED|VT_BTYPE)) == VT_BYTE)
6420 t |= VT_UNSIGNED;
6421 #endif
6422 t &= ~VT_SIGNED;
6424 /* long is never used as type */
6425 if ((t & VT_BTYPE) == VT_LONG)
6426 t = (t & ~VT_BTYPE) | VT_INT;
6427 type->t = t;
6428 return type_found;
6431 /* convert a function parameter type (array to pointer and function to
6432 function pointer) */
6433 static inline void convert_parameter_type(CType *pt)
6435 /* array must be transformed to pointer according to ANSI C */
6436 pt->t &= ~VT_ARRAY;
6437 if ((pt->t & VT_BTYPE) == VT_FUNC) {
6438 mk_pointer(pt);
6442 static void post_type(CType *type, AttributeDef *ad)
6444 int n, l, t1;
6445 Sym **plast, *s, *first;
6446 AttributeDef ad1;
6447 CType pt;
6449 if (tok == '(') {
6450 /* function declaration */
6451 next();
6452 l = 0;
6453 first = NULL;
6454 plast = &first;
6455 while (tok != ')') {
6456 /* read param name and compute offset */
6457 if (l != FUNC_OLD) {
6458 if (!parse_btype(&pt, &ad1)) {
6459 if (l) {
6460 error("invalid type");
6461 } else {
6462 l = FUNC_OLD;
6463 goto old_proto;
6466 l = FUNC_NEW;
6467 if ((pt.t & VT_BTYPE) == VT_VOID && tok == ')')
6468 break;
6469 type_decl(&pt, &ad1, &n, TYPE_DIRECT | TYPE_ABSTRACT);
6470 if ((pt.t & VT_BTYPE) == VT_VOID)
6471 error("parameter declared as void");
6472 } else {
6473 old_proto:
6474 n = tok;
6475 pt.t = VT_INT;
6476 next();
6478 convert_parameter_type(&pt);
6479 s = sym_push(n | SYM_FIELD, &pt, 0, 0);
6480 *plast = s;
6481 plast = &s->next;
6482 if (tok == ',') {
6483 next();
6484 if (l == FUNC_NEW && tok == TOK_DOTS) {
6485 l = FUNC_ELLIPSIS;
6486 next();
6487 break;
6491 /* if no parameters, then old type prototype */
6492 if (l == 0)
6493 l = FUNC_OLD;
6494 skip(')');
6495 t1 = type->t & VT_STORAGE;
6496 /* NOTE: const is ignored in returned type as it has a special
6497 meaning in gcc / C++ */
6498 type->t &= ~(VT_STORAGE | VT_CONSTANT);
6499 post_type(type, ad);
6500 /* we push a anonymous symbol which will contain the function prototype */
6501 s = sym_push(SYM_FIELD, type, ad->func_call, l);
6502 s->next = first;
6503 type->t = t1 | VT_FUNC;
6504 type->ref = s;
6505 } else if (tok == '[') {
6506 /* array definition */
6507 next();
6508 n = -1;
6509 if (tok != ']') {
6510 n = expr_const();
6511 if (n < 0)
6512 error("invalid array size");
6514 skip(']');
6515 /* parse next post type */
6516 t1 = type->t & VT_STORAGE;
6517 type->t &= ~VT_STORAGE;
6518 post_type(type, ad);
6520 /* we push a anonymous symbol which will contain the array
6521 element type */
6522 s = sym_push(SYM_FIELD, type, 0, n);
6523 type->t = t1 | VT_ARRAY | VT_PTR;
6524 type->ref = s;
6528 /* Parse a type declaration (except basic type), and return the type
6529 in 'type'. 'td' is a bitmask indicating which kind of type decl is
6530 expected. 'type' should contain the basic type. 'ad' is the
6531 attribute definition of the basic type. It can be modified by
6532 type_decl().
6534 static void type_decl(CType *type, AttributeDef *ad, int *v, int td)
6536 Sym *s;
6537 CType type1, *type2;
6538 int qualifiers;
6540 while (tok == '*') {
6541 qualifiers = 0;
6542 redo:
6543 next();
6544 switch(tok) {
6545 case TOK_CONST1:
6546 case TOK_CONST2:
6547 case TOK_CONST3:
6548 qualifiers |= VT_CONSTANT;
6549 goto redo;
6550 case TOK_VOLATILE1:
6551 case TOK_VOLATILE2:
6552 case TOK_VOLATILE3:
6553 qualifiers |= VT_VOLATILE;
6554 goto redo;
6555 case TOK_RESTRICT1:
6556 case TOK_RESTRICT2:
6557 case TOK_RESTRICT3:
6558 goto redo;
6560 mk_pointer(type);
6561 type->t |= qualifiers;
6564 /* XXX: clarify attribute handling */
6565 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6566 parse_attribute(ad);
6568 /* recursive type */
6569 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
6570 type1.t = 0; /* XXX: same as int */
6571 if (tok == '(') {
6572 next();
6573 /* XXX: this is not correct to modify 'ad' at this point, but
6574 the syntax is not clear */
6575 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6576 parse_attribute(ad);
6577 type_decl(&type1, ad, v, td);
6578 skip(')');
6579 } else {
6580 /* type identifier */
6581 if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
6582 *v = tok;
6583 next();
6584 } else {
6585 if (!(td & TYPE_ABSTRACT))
6586 expect("identifier");
6587 *v = 0;
6590 post_type(type, ad);
6591 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6592 parse_attribute(ad);
6593 if (!type1.t)
6594 return;
6595 /* append type at the end of type1 */
6596 type2 = &type1;
6597 for(;;) {
6598 s = type2->ref;
6599 type2 = &s->type;
6600 if (!type2->t) {
6601 *type2 = *type;
6602 break;
6605 *type = type1;
6608 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
6609 static int lvalue_type(int t)
6611 int bt, r;
6612 r = VT_LVAL;
6613 bt = t & VT_BTYPE;
6614 if (bt == VT_BYTE || bt == VT_BOOL)
6615 r |= VT_LVAL_BYTE;
6616 else if (bt == VT_SHORT)
6617 r |= VT_LVAL_SHORT;
6618 else
6619 return r;
6620 if (t & VT_UNSIGNED)
6621 r |= VT_LVAL_UNSIGNED;
6622 return r;
6625 /* indirection with full error checking and bound check */
6626 static void indir(void)
6628 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
6629 expect("pointer");
6630 if ((vtop->r & VT_LVAL) && !nocode_wanted)
6631 gv(RC_INT);
6632 vtop->type = *pointed_type(&vtop->type);
6633 /* an array is never an lvalue */
6634 if (!(vtop->type.t & VT_ARRAY)) {
6635 vtop->r |= lvalue_type(vtop->type.t);
6636 /* if bound checking, the referenced pointer must be checked */
6637 if (do_bounds_check)
6638 vtop->r |= VT_MUSTBOUND;
6642 /* pass a parameter to a function and do type checking and casting */
6643 static void gfunc_param_typed(Sym *func, Sym *arg)
6645 int func_type;
6646 CType type;
6648 func_type = func->c;
6649 if (func_type == FUNC_OLD ||
6650 (func_type == FUNC_ELLIPSIS && arg == NULL)) {
6651 /* default casting : only need to convert float to double */
6652 if ((vtop->type.t & VT_BTYPE) == VT_FLOAT) {
6653 type.t = VT_DOUBLE;
6654 gen_cast(&type);
6656 } else if (arg == NULL) {
6657 error("too many arguments to function");
6658 } else {
6659 type = arg->type;
6660 type.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
6661 gen_assign_cast(&type);
6665 /* parse an expression of the form '(type)' or '(expr)' and return its
6666 type */
6667 static void parse_expr_type(CType *type)
6669 int n;
6670 AttributeDef ad;
6672 skip('(');
6673 if (parse_btype(type, &ad)) {
6674 type_decl(type, &ad, &n, TYPE_ABSTRACT);
6675 } else {
6676 expr_type(type);
6678 skip(')');
6681 static void parse_type(CType *type)
6683 AttributeDef ad;
6684 int n;
6686 if (!parse_btype(type, &ad)) {
6687 expect("type");
6689 type_decl(type, &ad, &n, TYPE_ABSTRACT);
6692 static void vpush_tokc(int t)
6694 CType type;
6695 type.t = t;
6696 vsetc(&type, VT_CONST, &tokc);
6699 static void unary(void)
6701 int n, t, align, size, r;
6702 CType type;
6703 Sym *s;
6704 AttributeDef ad;
6706 /* XXX: GCC 2.95.3 does not generate a table although it should be
6707 better here */
6708 tok_next:
6709 switch(tok) {
6710 case TOK_EXTENSION:
6711 next();
6712 goto tok_next;
6713 case TOK_CINT:
6714 case TOK_CCHAR:
6715 case TOK_LCHAR:
6716 vpushi(tokc.i);
6717 next();
6718 break;
6719 case TOK_CUINT:
6720 vpush_tokc(VT_INT | VT_UNSIGNED);
6721 next();
6722 break;
6723 case TOK_CLLONG:
6724 vpush_tokc(VT_LLONG);
6725 next();
6726 break;
6727 case TOK_CULLONG:
6728 vpush_tokc(VT_LLONG | VT_UNSIGNED);
6729 next();
6730 break;
6731 case TOK_CFLOAT:
6732 vpush_tokc(VT_FLOAT);
6733 next();
6734 break;
6735 case TOK_CDOUBLE:
6736 vpush_tokc(VT_DOUBLE);
6737 next();
6738 break;
6739 case TOK_CLDOUBLE:
6740 vpush_tokc(VT_LDOUBLE);
6741 next();
6742 break;
6743 case TOK___FUNCTION__:
6744 if (!gnu_ext)
6745 goto tok_identifier;
6746 /* fall thru */
6747 case TOK___FUNC__:
6749 void *ptr;
6750 int len;
6751 /* special function name identifier */
6752 len = strlen(funcname) + 1;
6753 /* generate char[len] type */
6754 type.t = VT_BYTE;
6755 mk_pointer(&type);
6756 type.t |= VT_ARRAY;
6757 type.ref->c = len;
6758 vpush_ref(&type, data_section, data_section->data_offset, len);
6759 ptr = section_ptr_add(data_section, len);
6760 memcpy(ptr, funcname, len);
6761 next();
6763 break;
6764 case TOK_LSTR:
6765 t = VT_INT;
6766 goto str_init;
6767 case TOK_STR:
6768 /* string parsing */
6769 t = VT_BYTE;
6770 str_init:
6771 if (tcc_state->warn_write_strings)
6772 t |= VT_CONSTANT;
6773 type.t = t;
6774 mk_pointer(&type);
6775 type.t |= VT_ARRAY;
6776 memset(&ad, 0, sizeof(AttributeDef));
6777 decl_initializer_alloc(&type, &ad, VT_CONST, 2, 0, 0);
6778 break;
6779 case '(':
6780 next();
6781 /* cast ? */
6782 if (parse_btype(&type, &ad)) {
6783 type_decl(&type, &ad, &n, TYPE_ABSTRACT);
6784 skip(')');
6785 /* check ISOC99 compound literal */
6786 if (tok == '{') {
6787 /* data is allocated locally by default */
6788 if (global_expr)
6789 r = VT_CONST;
6790 else
6791 r = VT_LOCAL;
6792 /* all except arrays are lvalues */
6793 if (!(type.t & VT_ARRAY))
6794 r |= lvalue_type(type.t);
6795 memset(&ad, 0, sizeof(AttributeDef));
6796 decl_initializer_alloc(&type, &ad, r, 1, 0, 0);
6797 } else {
6798 unary();
6799 gen_cast(&type);
6801 } else if (tok == '{') {
6802 /* save all registers */
6803 save_regs(0);
6804 /* statement expression : we do not accept break/continue
6805 inside as GCC does */
6806 block(NULL, NULL, NULL, NULL, 0, 1);
6807 skip(')');
6808 } else {
6809 gexpr();
6810 skip(')');
6812 break;
6813 case '*':
6814 next();
6815 unary();
6816 indir();
6817 break;
6818 case '&':
6819 next();
6820 unary();
6821 /* functions names must be treated as function pointers,
6822 except for unary '&' and sizeof. Since we consider that
6823 functions are not lvalues, we only have to handle it
6824 there and in function calls. */
6825 /* arrays can also be used although they are not lvalues */
6826 if ((vtop->type.t & VT_BTYPE) != VT_FUNC &&
6827 !(vtop->type.t & VT_ARRAY))
6828 test_lvalue();
6829 mk_pointer(&vtop->type);
6830 gaddrof();
6831 break;
6832 case '!':
6833 next();
6834 unary();
6835 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST)
6836 vtop->c.i = !vtop->c.i;
6837 else if ((vtop->r & VT_VALMASK) == VT_CMP)
6838 vtop->c.i = vtop->c.i ^ 1;
6839 else
6840 vseti(VT_JMP, gtst(1, 0));
6841 break;
6842 case '~':
6843 next();
6844 unary();
6845 vpushi(-1);
6846 gen_op('^');
6847 break;
6848 case '+':
6849 next();
6850 /* in order to force cast, we add zero */
6851 unary();
6852 if ((vtop->type.t & VT_BTYPE) == VT_PTR)
6853 error("pointer not accepted for unary plus");
6854 vpushi(0);
6855 gen_op('+');
6856 break;
6857 case TOK_SIZEOF:
6858 case TOK_ALIGNOF1:
6859 case TOK_ALIGNOF2:
6860 t = tok;
6861 next();
6862 if (tok == '(') {
6863 parse_expr_type(&type);
6864 } else {
6865 unary_type(&type);
6867 size = type_size(&type, &align);
6868 if (t == TOK_SIZEOF) {
6869 if (size < 0)
6870 error("sizeof applied to an incomplete type");
6871 vpushi(size);
6872 } else {
6873 vpushi(align);
6875 break;
6877 case TOK_builtin_types_compatible_p:
6879 CType type1, type2;
6880 next();
6881 skip('(');
6882 parse_type(&type1);
6883 skip(',');
6884 parse_type(&type2);
6885 skip(')');
6886 type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
6887 type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
6888 vpushi(is_compatible_types(&type1, &type2));
6890 break;
6891 case TOK_builtin_constant_p:
6893 int saved_nocode_wanted, res;
6894 next();
6895 skip('(');
6896 saved_nocode_wanted = nocode_wanted;
6897 nocode_wanted = 1;
6898 gexpr();
6899 res = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
6900 vpop();
6901 nocode_wanted = saved_nocode_wanted;
6902 skip(')');
6903 vpushi(res);
6905 break;
6906 case TOK_INC:
6907 case TOK_DEC:
6908 t = tok;
6909 next();
6910 unary();
6911 inc(0, t);
6912 break;
6913 case '-':
6914 next();
6915 vpushi(0);
6916 unary();
6917 gen_op('-');
6918 break;
6919 case TOK_LAND:
6920 if (!gnu_ext)
6921 goto tok_identifier;
6922 next();
6923 /* allow to take the address of a label */
6924 if (tok < TOK_UIDENT)
6925 expect("label identifier");
6926 s = label_find(tok);
6927 if (!s) {
6928 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
6929 } else {
6930 if (s->r == LABEL_DECLARED)
6931 s->r = LABEL_FORWARD;
6933 if (!s->type.t) {
6934 s->type.t = VT_VOID;
6935 mk_pointer(&s->type);
6936 s->type.t |= VT_STATIC;
6938 vset(&s->type, VT_CONST | VT_SYM, 0);
6939 vtop->sym = s;
6940 next();
6941 break;
6942 default:
6943 tok_identifier:
6944 t = tok;
6945 next();
6946 if (t < TOK_UIDENT)
6947 expect("identifier");
6948 s = sym_find(t);
6949 if (!s) {
6950 if (tok != '(')
6951 error("'%s' undeclared", get_tok_str(t, NULL));
6952 /* for simple function calls, we tolerate undeclared
6953 external reference to int() function */
6954 s = external_global_sym(t, &func_old_type, 0);
6956 vset(&s->type, s->r, s->c);
6957 /* if forward reference, we must point to s */
6958 if (vtop->r & VT_SYM) {
6959 vtop->sym = s;
6960 vtop->c.ul = 0;
6962 break;
6965 /* post operations */
6966 while (1) {
6967 if (tok == TOK_INC || tok == TOK_DEC) {
6968 inc(1, tok);
6969 next();
6970 } else if (tok == '.' || tok == TOK_ARROW) {
6971 /* field */
6972 if (tok == TOK_ARROW)
6973 indir();
6974 test_lvalue();
6975 gaddrof();
6976 next();
6977 /* expect pointer on structure */
6978 if ((vtop->type.t & VT_BTYPE) != VT_STRUCT)
6979 expect("struct or union");
6980 s = vtop->type.ref;
6981 /* find field */
6982 tok |= SYM_FIELD;
6983 while ((s = s->next) != NULL) {
6984 if (s->v == tok)
6985 break;
6987 if (!s)
6988 error("field not found");
6989 /* add field offset to pointer */
6990 vtop->type = char_pointer_type; /* change type to 'char *' */
6991 vpushi(s->c);
6992 gen_op('+');
6993 /* change type to field type, and set to lvalue */
6994 vtop->type = s->type;
6995 /* an array is never an lvalue */
6996 if (!(vtop->type.t & VT_ARRAY)) {
6997 vtop->r |= lvalue_type(vtop->type.t);
6998 /* if bound checking, the referenced pointer must be checked */
6999 if (do_bounds_check)
7000 vtop->r |= VT_MUSTBOUND;
7002 next();
7003 } else if (tok == '[') {
7004 next();
7005 gexpr();
7006 gen_op('+');
7007 indir();
7008 skip(']');
7009 } else if (tok == '(') {
7010 SValue ret;
7011 Sym *sa;
7012 int nb_args;
7014 /* function call */
7015 if ((vtop->type.t & VT_BTYPE) != VT_FUNC) {
7016 /* pointer test (no array accepted) */
7017 if ((vtop->type.t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
7018 vtop->type = *pointed_type(&vtop->type);
7019 if ((vtop->type.t & VT_BTYPE) != VT_FUNC)
7020 goto error_func;
7021 } else {
7022 error_func:
7023 expect("function pointer");
7025 } else {
7026 vtop->r &= ~VT_LVAL; /* no lvalue */
7028 /* get return type */
7029 s = vtop->type.ref;
7030 next();
7031 sa = s->next; /* first parameter */
7032 nb_args = 0;
7033 /* compute first implicit argument if a structure is returned */
7034 if ((s->type.t & VT_BTYPE) == VT_STRUCT) {
7035 /* get some space for the returned structure */
7036 size = type_size(&s->type, &align);
7037 loc = (loc - size) & -align;
7038 ret.type = s->type;
7039 ret.r = VT_LOCAL | VT_LVAL;
7040 /* pass it as 'int' to avoid structure arg passing
7041 problems */
7042 vseti(VT_LOCAL, loc);
7043 ret.c = vtop->c;
7044 nb_args++;
7045 } else {
7046 ret.type = s->type;
7047 ret.r2 = VT_CONST;
7048 /* return in register */
7049 if (is_float(ret.type.t)) {
7050 ret.r = REG_FRET;
7051 } else {
7052 if ((ret.type.t & VT_BTYPE) == VT_LLONG)
7053 ret.r2 = REG_LRET;
7054 ret.r = REG_IRET;
7056 ret.c.i = 0;
7058 if (tok != ')') {
7059 for(;;) {
7060 expr_eq();
7061 gfunc_param_typed(s, sa);
7062 nb_args++;
7063 if (sa)
7064 sa = sa->next;
7065 if (tok == ')')
7066 break;
7067 skip(',');
7070 if (sa)
7071 error("too few arguments to function");
7072 skip(')');
7073 if (!nocode_wanted) {
7074 gfunc_call(nb_args);
7075 } else {
7076 vtop -= (nb_args + 1);
7078 /* return value */
7079 vsetc(&ret.type, ret.r, &ret.c);
7080 vtop->r2 = ret.r2;
7081 } else {
7082 break;
7087 static void uneq(void)
7089 int t;
7091 unary();
7092 if (tok == '=' ||
7093 (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
7094 tok == TOK_A_XOR || tok == TOK_A_OR ||
7095 tok == TOK_A_SHL || tok == TOK_A_SAR) {
7096 test_lvalue();
7097 t = tok;
7098 next();
7099 if (t == '=') {
7100 expr_eq();
7101 } else {
7102 vdup();
7103 expr_eq();
7104 gen_op(t & 0x7f);
7106 vstore();
7110 static void expr_prod(void)
7112 int t;
7114 uneq();
7115 while (tok == '*' || tok == '/' || tok == '%') {
7116 t = tok;
7117 next();
7118 uneq();
7119 gen_op(t);
7123 static void expr_sum(void)
7125 int t;
7127 expr_prod();
7128 while (tok == '+' || tok == '-') {
7129 t = tok;
7130 next();
7131 expr_prod();
7132 gen_op(t);
7136 static void expr_shift(void)
7138 int t;
7140 expr_sum();
7141 while (tok == TOK_SHL || tok == TOK_SAR) {
7142 t = tok;
7143 next();
7144 expr_sum();
7145 gen_op(t);
7149 static void expr_cmp(void)
7151 int t;
7153 expr_shift();
7154 while ((tok >= TOK_ULE && tok <= TOK_GT) ||
7155 tok == TOK_ULT || tok == TOK_UGE) {
7156 t = tok;
7157 next();
7158 expr_shift();
7159 gen_op(t);
7163 static void expr_cmpeq(void)
7165 int t;
7167 expr_cmp();
7168 while (tok == TOK_EQ || tok == TOK_NE) {
7169 t = tok;
7170 next();
7171 expr_cmp();
7172 gen_op(t);
7176 static void expr_and(void)
7178 expr_cmpeq();
7179 while (tok == '&') {
7180 next();
7181 expr_cmpeq();
7182 gen_op('&');
7186 static void expr_xor(void)
7188 expr_and();
7189 while (tok == '^') {
7190 next();
7191 expr_and();
7192 gen_op('^');
7196 static void expr_or(void)
7198 expr_xor();
7199 while (tok == '|') {
7200 next();
7201 expr_xor();
7202 gen_op('|');
7206 /* XXX: fix this mess */
7207 static void expr_land_const(void)
7209 expr_or();
7210 while (tok == TOK_LAND) {
7211 next();
7212 expr_or();
7213 gen_op(TOK_LAND);
7217 /* XXX: fix this mess */
7218 static void expr_lor_const(void)
7220 expr_land_const();
7221 while (tok == TOK_LOR) {
7222 next();
7223 expr_land_const();
7224 gen_op(TOK_LOR);
7228 /* only used if non constant */
7229 static void expr_land(void)
7231 int t;
7233 expr_or();
7234 if (tok == TOK_LAND) {
7235 t = 0;
7236 for(;;) {
7237 t = gtst(1, t);
7238 if (tok != TOK_LAND) {
7239 vseti(VT_JMPI, t);
7240 break;
7242 next();
7243 expr_or();
7248 static void expr_lor(void)
7250 int t;
7252 expr_land();
7253 if (tok == TOK_LOR) {
7254 t = 0;
7255 for(;;) {
7256 t = gtst(0, t);
7257 if (tok != TOK_LOR) {
7258 vseti(VT_JMP, t);
7259 break;
7261 next();
7262 expr_land();
7267 /* XXX: better constant handling */
7268 static void expr_eq(void)
7270 int tt, u, r1, r2, rc, t1, t2, bt1, bt2;
7271 SValue sv;
7272 CType type, type1, type2;
7274 if (const_wanted) {
7275 int c1, c;
7276 expr_lor_const();
7277 if (tok == '?') {
7278 c = vtop->c.i;
7279 vpop();
7280 next();
7281 if (tok == ':' && gnu_ext) {
7282 c1 = c;
7283 } else {
7284 gexpr();
7285 c1 = vtop->c.i;
7286 vpop();
7288 skip(':');
7289 expr_eq();
7290 if (c)
7291 vtop->c.i = c1;
7293 } else {
7294 expr_lor();
7295 if (tok == '?') {
7296 next();
7297 if (vtop != vstack) {
7298 /* needed to avoid having different registers saved in
7299 each branch */
7300 if (is_float(vtop->type.t))
7301 rc = RC_FLOAT;
7302 else
7303 rc = RC_INT;
7304 gv(rc);
7305 save_regs(1);
7307 if (tok == ':' && gnu_ext) {
7308 gv_dup();
7309 tt = gtst(1, 0);
7310 } else {
7311 tt = gtst(1, 0);
7312 gexpr();
7314 type1 = vtop->type;
7315 sv = *vtop; /* save value to handle it later */
7316 vtop--; /* no vpop so that FP stack is not flushed */
7317 skip(':');
7318 u = gjmp(0);
7319 gsym(tt);
7320 expr_eq();
7321 type2 = vtop->type;
7323 t1 = type1.t;
7324 bt1 = t1 & VT_BTYPE;
7325 t2 = type2.t;
7326 bt2 = t2 & VT_BTYPE;
7327 /* cast operands to correct type according to ISOC rules */
7328 if (is_float(bt1) || is_float(bt2)) {
7329 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
7330 type.t = VT_LDOUBLE;
7331 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
7332 type.t = VT_DOUBLE;
7333 } else {
7334 type.t = VT_FLOAT;
7336 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
7337 /* cast to biggest op */
7338 type.t = VT_LLONG;
7339 /* convert to unsigned if it does not fit in a long long */
7340 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
7341 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
7342 type.t |= VT_UNSIGNED;
7343 } else if (bt1 == VT_PTR || bt2 == VT_PTR) {
7344 /* XXX: test pointer compatibility */
7345 type = type1;
7346 } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
7347 /* XXX: test structure compatibility */
7348 type = type1;
7349 } else if (bt1 == VT_VOID || bt2 == VT_VOID) {
7350 /* NOTE: as an extension, we accept void on only one side */
7351 type.t = VT_VOID;
7352 } else {
7353 /* integer operations */
7354 type.t = VT_INT;
7355 /* convert to unsigned if it does not fit in an integer */
7356 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
7357 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
7358 type.t |= VT_UNSIGNED;
7361 /* now we convert second operand */
7362 gen_cast(&type);
7363 rc = RC_INT;
7364 if (is_float(type.t)) {
7365 rc = RC_FLOAT;
7366 } else if ((type.t & VT_BTYPE) == VT_LLONG) {
7367 /* for long longs, we use fixed registers to avoid having
7368 to handle a complicated move */
7369 rc = RC_IRET;
7372 r2 = gv(rc);
7373 /* this is horrible, but we must also convert first
7374 operand */
7375 tt = gjmp(0);
7376 gsym(u);
7377 /* put again first value and cast it */
7378 *vtop = sv;
7379 gen_cast(&type);
7380 r1 = gv(rc);
7381 move_reg(r2, r1);
7382 vtop->r = r2;
7383 gsym(tt);
7388 static void gexpr(void)
7390 while (1) {
7391 expr_eq();
7392 if (tok != ',')
7393 break;
7394 vpop();
7395 next();
7399 /* parse an expression and return its type without any side effect. */
7400 static void expr_type(CType *type)
7402 int saved_nocode_wanted;
7404 saved_nocode_wanted = nocode_wanted;
7405 nocode_wanted = 1;
7406 gexpr();
7407 *type = vtop->type;
7408 vpop();
7409 nocode_wanted = saved_nocode_wanted;
7412 /* parse a unary expression and return its type without any side
7413 effect. */
7414 static void unary_type(CType *type)
7416 int a;
7418 a = nocode_wanted;
7419 nocode_wanted = 1;
7420 unary();
7421 *type = vtop->type;
7422 vpop();
7423 nocode_wanted = a;
7426 /* parse a constant expression and return value in vtop. */
7427 static void expr_const1(void)
7429 int a;
7430 a = const_wanted;
7431 const_wanted = 1;
7432 expr_eq();
7433 const_wanted = a;
7436 /* parse an integer constant and return its value. */
7437 static int expr_const(void)
7439 int c;
7440 expr_const1();
7441 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
7442 expect("constant expression");
7443 c = vtop->c.i;
7444 vpop();
7445 return c;
7448 /* return the label token if current token is a label, otherwise
7449 return zero */
7450 static int is_label(void)
7452 int last_tok;
7454 /* fast test first */
7455 if (tok < TOK_UIDENT)
7456 return 0;
7457 /* no need to save tokc because tok is an identifier */
7458 last_tok = tok;
7459 next();
7460 if (tok == ':') {
7461 next();
7462 return last_tok;
7463 } else {
7464 unget_tok(last_tok);
7465 return 0;
7469 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
7470 int case_reg, int is_expr)
7472 int a, b, c, d;
7473 Sym *s;
7475 /* generate line number info */
7476 if (do_debug &&
7477 (last_line_num != file->line_num || last_ind != ind)) {
7478 put_stabn(N_SLINE, 0, file->line_num, ind - func_ind);
7479 last_ind = ind;
7480 last_line_num = file->line_num;
7483 if (is_expr) {
7484 /* default return value is (void) */
7485 vpushi(0);
7486 vtop->type.t = VT_VOID;
7489 if (tok == TOK_IF) {
7490 /* if test */
7491 next();
7492 skip('(');
7493 gexpr();
7494 skip(')');
7495 a = gtst(1, 0);
7496 block(bsym, csym, case_sym, def_sym, case_reg, 0);
7497 c = tok;
7498 if (c == TOK_ELSE) {
7499 next();
7500 d = gjmp(0);
7501 gsym(a);
7502 block(bsym, csym, case_sym, def_sym, case_reg, 0);
7503 gsym(d); /* patch else jmp */
7504 } else
7505 gsym(a);
7506 } else if (tok == TOK_WHILE) {
7507 next();
7508 d = ind;
7509 skip('(');
7510 gexpr();
7511 skip(')');
7512 a = gtst(1, 0);
7513 b = 0;
7514 block(&a, &b, case_sym, def_sym, case_reg, 0);
7515 gjmp_addr(d);
7516 gsym(a);
7517 gsym_addr(b, d);
7518 } else if (tok == '{') {
7519 Sym *llabel;
7521 next();
7522 /* record local declaration stack position */
7523 s = local_stack;
7524 llabel = local_label_stack;
7525 /* handle local labels declarations */
7526 if (tok == TOK_LABEL) {
7527 next();
7528 for(;;) {
7529 if (tok < TOK_UIDENT)
7530 expect("label identifier");
7531 label_push(&local_label_stack, tok, LABEL_DECLARED);
7532 next();
7533 if (tok == ',') {
7534 next();
7535 } else {
7536 skip(';');
7537 break;
7541 while (tok != '}') {
7542 decl(VT_LOCAL);
7543 if (tok != '}') {
7544 if (is_expr)
7545 vpop();
7546 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
7549 /* pop locally defined labels */
7550 label_pop(&local_label_stack, llabel);
7551 /* pop locally defined symbols */
7552 sym_pop(&local_stack, s);
7553 next();
7554 } else if (tok == TOK_RETURN) {
7555 next();
7556 if (tok != ';') {
7557 gexpr();
7558 gen_assign_cast(&func_vt);
7559 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
7560 CType type;
7561 /* if returning structure, must copy it to implicit
7562 first pointer arg location */
7563 type = func_vt;
7564 mk_pointer(&type);
7565 vset(&type, VT_LOCAL | VT_LVAL, func_vc);
7566 indir();
7567 vswap();
7568 /* copy structure value to pointer */
7569 vstore();
7570 } else if (is_float(func_vt.t)) {
7571 gv(RC_FRET);
7572 } else {
7573 gv(RC_IRET);
7575 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
7577 skip(';');
7578 rsym = gjmp(rsym); /* jmp */
7579 } else if (tok == TOK_BREAK) {
7580 /* compute jump */
7581 if (!bsym)
7582 error("cannot break");
7583 *bsym = gjmp(*bsym);
7584 next();
7585 skip(';');
7586 } else if (tok == TOK_CONTINUE) {
7587 /* compute jump */
7588 if (!csym)
7589 error("cannot continue");
7590 *csym = gjmp(*csym);
7591 next();
7592 skip(';');
7593 } else if (tok == TOK_FOR) {
7594 int e;
7595 next();
7596 skip('(');
7597 if (tok != ';') {
7598 gexpr();
7599 vpop();
7601 skip(';');
7602 d = ind;
7603 c = ind;
7604 a = 0;
7605 b = 0;
7606 if (tok != ';') {
7607 gexpr();
7608 a = gtst(1, 0);
7610 skip(';');
7611 if (tok != ')') {
7612 e = gjmp(0);
7613 c = ind;
7614 gexpr();
7615 vpop();
7616 gjmp_addr(d);
7617 gsym(e);
7619 skip(')');
7620 block(&a, &b, case_sym, def_sym, case_reg, 0);
7621 gjmp_addr(c);
7622 gsym(a);
7623 gsym_addr(b, c);
7624 } else
7625 if (tok == TOK_DO) {
7626 next();
7627 a = 0;
7628 b = 0;
7629 d = ind;
7630 block(&a, &b, case_sym, def_sym, case_reg, 0);
7631 skip(TOK_WHILE);
7632 skip('(');
7633 gsym(b);
7634 gexpr();
7635 c = gtst(0, 0);
7636 gsym_addr(c, d);
7637 skip(')');
7638 gsym(a);
7639 skip(';');
7640 } else
7641 if (tok == TOK_SWITCH) {
7642 next();
7643 skip('(');
7644 gexpr();
7645 /* XXX: other types than integer */
7646 case_reg = gv(RC_INT);
7647 vpop();
7648 skip(')');
7649 a = 0;
7650 b = gjmp(0); /* jump to first case */
7651 c = 0;
7652 block(&a, csym, &b, &c, case_reg, 0);
7653 /* if no default, jmp after switch */
7654 if (c == 0)
7655 c = ind;
7656 /* default label */
7657 gsym_addr(b, c);
7658 /* break label */
7659 gsym(a);
7660 } else
7661 if (tok == TOK_CASE) {
7662 int v1, v2;
7663 if (!case_sym)
7664 expect("switch");
7665 next();
7666 v1 = expr_const();
7667 v2 = v1;
7668 if (gnu_ext && tok == TOK_DOTS) {
7669 next();
7670 v2 = expr_const();
7671 if (v2 < v1)
7672 warning("empty case range");
7674 /* since a case is like a label, we must skip it with a jmp */
7675 b = gjmp(0);
7676 gsym(*case_sym);
7677 vseti(case_reg, 0);
7678 vpushi(v1);
7679 if (v1 == v2) {
7680 gen_op(TOK_EQ);
7681 *case_sym = gtst(1, 0);
7682 } else {
7683 gen_op(TOK_GE);
7684 *case_sym = gtst(1, 0);
7685 vseti(case_reg, 0);
7686 vpushi(v2);
7687 gen_op(TOK_LE);
7688 *case_sym = gtst(1, *case_sym);
7690 gsym(b);
7691 skip(':');
7692 is_expr = 0;
7693 goto block_after_label;
7694 } else
7695 if (tok == TOK_DEFAULT) {
7696 next();
7697 skip(':');
7698 if (!def_sym)
7699 expect("switch");
7700 if (*def_sym)
7701 error("too many 'default'");
7702 *def_sym = ind;
7703 is_expr = 0;
7704 goto block_after_label;
7705 } else
7706 if (tok == TOK_GOTO) {
7707 next();
7708 if (tok == '*' && gnu_ext) {
7709 /* computed goto */
7710 next();
7711 gexpr();
7712 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
7713 expect("pointer");
7714 ggoto();
7715 } else if (tok >= TOK_UIDENT) {
7716 s = label_find(tok);
7717 /* put forward definition if needed */
7718 if (!s) {
7719 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
7720 } else {
7721 if (s->r == LABEL_DECLARED)
7722 s->r = LABEL_FORWARD;
7724 /* label already defined */
7725 if (s->r & LABEL_FORWARD)
7726 s->next = (void *)gjmp((long)s->next);
7727 else
7728 gjmp_addr((long)s->next);
7729 next();
7730 } else {
7731 expect("label identifier");
7733 skip(';');
7734 } else if (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3) {
7735 asm_instr();
7736 } else {
7737 b = is_label();
7738 if (b) {
7739 /* label case */
7740 s = label_find(b);
7741 if (s) {
7742 if (s->r == LABEL_DEFINED)
7743 error("duplicate label '%s'", get_tok_str(s->v, NULL));
7744 gsym((long)s->next);
7745 s->r = LABEL_DEFINED;
7746 } else {
7747 s = label_push(&global_label_stack, b, LABEL_DEFINED);
7749 s->next = (void *)ind;
7750 /* we accept this, but it is a mistake */
7751 block_after_label:
7752 if (tok == '}') {
7753 warning("deprecated use of label at end of compound statement");
7754 } else {
7755 if (is_expr)
7756 vpop();
7757 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
7759 } else {
7760 /* expression case */
7761 if (tok != ';') {
7762 if (is_expr) {
7763 vpop();
7764 gexpr();
7765 } else {
7766 gexpr();
7767 vpop();
7770 skip(';');
7775 /* t is the array or struct type. c is the array or struct
7776 address. cur_index/cur_field is the pointer to the current
7777 value. 'size_only' is true if only size info is needed (only used
7778 in arrays) */
7779 static void decl_designator(CType *type, Section *sec, unsigned long c,
7780 int *cur_index, Sym **cur_field,
7781 int size_only)
7783 Sym *s, *f;
7784 int notfirst, index, index_last, align, l, nb_elems, elem_size;
7785 CType type1;
7787 notfirst = 0;
7788 elem_size = 0;
7789 nb_elems = 1;
7790 if (gnu_ext && (l = is_label()) != 0)
7791 goto struct_field;
7792 while (tok == '[' || tok == '.') {
7793 if (tok == '[') {
7794 if (!(type->t & VT_ARRAY))
7795 expect("array type");
7796 s = type->ref;
7797 next();
7798 index = expr_const();
7799 if (index < 0 || (s->c >= 0 && index >= s->c))
7800 expect("invalid index");
7801 if (tok == TOK_DOTS && gnu_ext) {
7802 next();
7803 index_last = expr_const();
7804 if (index_last < 0 ||
7805 (s->c >= 0 && index_last >= s->c) ||
7806 index_last < index)
7807 expect("invalid index");
7808 } else {
7809 index_last = index;
7811 skip(']');
7812 if (!notfirst)
7813 *cur_index = index_last;
7814 type = pointed_type(type);
7815 elem_size = type_size(type, &align);
7816 c += index * elem_size;
7817 /* NOTE: we only support ranges for last designator */
7818 nb_elems = index_last - index + 1;
7819 if (nb_elems != 1) {
7820 notfirst = 1;
7821 break;
7823 } else {
7824 next();
7825 l = tok;
7826 next();
7827 struct_field:
7828 if ((type->t & VT_BTYPE) != VT_STRUCT)
7829 expect("struct/union type");
7830 s = type->ref;
7831 l |= SYM_FIELD;
7832 f = s->next;
7833 while (f) {
7834 if (f->v == l)
7835 break;
7836 f = f->next;
7838 if (!f)
7839 expect("field");
7840 if (!notfirst)
7841 *cur_field = f;
7842 /* XXX: fix this mess by using explicit storage field */
7843 type1 = f->type;
7844 type1.t |= (type->t & ~VT_TYPE);
7845 type = &type1;
7846 c += f->c;
7848 notfirst = 1;
7850 if (notfirst) {
7851 if (tok == '=') {
7852 next();
7853 } else {
7854 if (!gnu_ext)
7855 expect("=");
7857 } else {
7858 if (type->t & VT_ARRAY) {
7859 index = *cur_index;
7860 type = pointed_type(type);
7861 c += index * type_size(type, &align);
7862 } else {
7863 f = *cur_field;
7864 if (!f)
7865 error("too many field init");
7866 /* XXX: fix this mess by using explicit storage field */
7867 type1 = f->type;
7868 type1.t |= (type->t & ~VT_TYPE);
7869 type = &type1;
7870 c += f->c;
7873 decl_initializer(type, sec, c, 0, size_only);
7875 /* XXX: make it more general */
7876 if (!size_only && nb_elems > 1) {
7877 unsigned long c_end;
7878 uint8_t *src, *dst;
7879 int i;
7881 if (!sec)
7882 error("range init not supported yet for dynamic storage");
7883 c_end = c + nb_elems * elem_size;
7884 if (c_end > sec->data_allocated)
7885 section_realloc(sec, c_end);
7886 src = sec->data + c;
7887 dst = src;
7888 for(i = 1; i < nb_elems; i++) {
7889 dst += elem_size;
7890 memcpy(dst, src, elem_size);
7895 #define EXPR_VAL 0
7896 #define EXPR_CONST 1
7897 #define EXPR_ANY 2
7899 /* store a value or an expression directly in global data or in local array */
7900 static void init_putv(CType *type, Section *sec, unsigned long c,
7901 int v, int expr_type)
7903 int saved_global_expr, bt, bit_pos, bit_size;
7904 void *ptr;
7905 unsigned long long bit_mask;
7906 CType dtype;
7908 switch(expr_type) {
7909 case EXPR_VAL:
7910 vpushi(v);
7911 break;
7912 case EXPR_CONST:
7913 /* compound literals must be allocated globally in this case */
7914 saved_global_expr = global_expr;
7915 global_expr = 1;
7916 expr_const1();
7917 global_expr = saved_global_expr;
7918 /* NOTE: symbols are accepted */
7919 if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST)
7920 error("initializer element is not constant");
7921 break;
7922 case EXPR_ANY:
7923 expr_eq();
7924 break;
7927 dtype = *type;
7928 dtype.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
7930 if (sec) {
7931 /* XXX: not portable */
7932 /* XXX: generate error if incorrect relocation */
7933 gen_assign_cast(&dtype);
7934 bt = type->t & VT_BTYPE;
7935 ptr = sec->data + c;
7936 /* XXX: make code faster ? */
7937 if (!(type->t & VT_BITFIELD)) {
7938 bit_pos = 0;
7939 bit_size = 32;
7940 bit_mask = -1LL;
7941 } else {
7942 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
7943 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
7944 bit_mask = (1LL << bit_size) - 1;
7946 if ((vtop->r & VT_SYM) &&
7947 (bt == VT_BYTE ||
7948 bt == VT_SHORT ||
7949 bt == VT_DOUBLE ||
7950 bt == VT_LDOUBLE ||
7951 bt == VT_LLONG ||
7952 (bt == VT_INT && bit_size != 32)))
7953 error("initializer element is not computable at load time");
7954 switch(bt) {
7955 case VT_BYTE:
7956 *(char *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
7957 break;
7958 case VT_SHORT:
7959 *(short *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
7960 break;
7961 case VT_DOUBLE:
7962 *(double *)ptr = vtop->c.d;
7963 break;
7964 case VT_LDOUBLE:
7965 *(long double *)ptr = vtop->c.ld;
7966 break;
7967 case VT_LLONG:
7968 *(long long *)ptr |= (vtop->c.ll & bit_mask) << bit_pos;
7969 break;
7970 default:
7971 if (vtop->r & VT_SYM) {
7972 greloc(sec, vtop->sym, c, R_DATA_32);
7974 *(int *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
7975 break;
7977 vtop--;
7978 } else {
7979 vset(&dtype, VT_LOCAL, c);
7980 vswap();
7981 vstore();
7982 vpop();
7986 /* put zeros for variable based init */
7987 static void init_putz(CType *t, Section *sec, unsigned long c, int size)
7989 if (sec) {
7990 /* nothing to do because globals are already set to zero */
7991 } else {
7992 vpush_global_sym(&func_old_type, TOK_memset);
7993 vseti(VT_LOCAL, c);
7994 vpushi(0);
7995 vpushi(size);
7996 gfunc_call(3);
8000 /* 't' contains the type and storage info. 'c' is the offset of the
8001 object in section 'sec'. If 'sec' is NULL, it means stack based
8002 allocation. 'first' is true if array '{' must be read (multi
8003 dimension implicit array init handling). 'size_only' is true if
8004 size only evaluation is wanted (only for arrays). */
8005 static void decl_initializer(CType *type, Section *sec, unsigned long c,
8006 int first, int size_only)
8008 int index, array_length, n, no_oblock, nb, parlevel, i;
8009 int size1, align1, expr_type;
8010 Sym *s, *f;
8011 CType *t1;
8013 if (type->t & VT_ARRAY) {
8014 s = type->ref;
8015 n = s->c;
8016 array_length = 0;
8017 t1 = pointed_type(type);
8018 size1 = type_size(t1, &align1);
8020 no_oblock = 1;
8021 if ((first && tok != TOK_LSTR && tok != TOK_STR) ||
8022 tok == '{') {
8023 skip('{');
8024 no_oblock = 0;
8027 /* only parse strings here if correct type (otherwise: handle
8028 them as ((w)char *) expressions */
8029 if ((tok == TOK_LSTR &&
8030 (t1->t & VT_BTYPE) == VT_INT) ||
8031 (tok == TOK_STR &&
8032 (t1->t & VT_BTYPE) == VT_BYTE)) {
8033 while (tok == TOK_STR || tok == TOK_LSTR) {
8034 int cstr_len, ch;
8035 CString *cstr;
8037 cstr = tokc.cstr;
8038 /* compute maximum number of chars wanted */
8039 if (tok == TOK_STR)
8040 cstr_len = cstr->size;
8041 else
8042 cstr_len = cstr->size / sizeof(int);
8043 cstr_len--;
8044 nb = cstr_len;
8045 if (n >= 0 && nb > (n - array_length))
8046 nb = n - array_length;
8047 if (!size_only) {
8048 if (cstr_len > nb)
8049 warning("initializer-string for array is too long");
8050 /* in order to go faster for common case (char
8051 string in global variable, we handle it
8052 specifically */
8053 if (sec && tok == TOK_STR && size1 == 1) {
8054 memcpy(sec->data + c + array_length, cstr->data, nb);
8055 } else {
8056 for(i=0;i<nb;i++) {
8057 if (tok == TOK_STR)
8058 ch = ((unsigned char *)cstr->data)[i];
8059 else
8060 ch = ((int *)cstr->data)[i];
8061 init_putv(t1, sec, c + (array_length + i) * size1,
8062 ch, EXPR_VAL);
8066 array_length += nb;
8067 next();
8069 /* only add trailing zero if enough storage (no
8070 warning in this case since it is standard) */
8071 if (n < 0 || array_length < n) {
8072 if (!size_only) {
8073 init_putv(t1, sec, c + (array_length * size1), 0, EXPR_VAL);
8075 array_length++;
8077 } else {
8078 index = 0;
8079 while (tok != '}') {
8080 decl_designator(type, sec, c, &index, NULL, size_only);
8081 if (n >= 0 && index >= n)
8082 error("index too large");
8083 /* must put zero in holes (note that doing it that way
8084 ensures that it even works with designators) */
8085 if (!size_only && array_length < index) {
8086 init_putz(t1, sec, c + array_length * size1,
8087 (index - array_length) * size1);
8089 index++;
8090 if (index > array_length)
8091 array_length = index;
8092 /* special test for multi dimensional arrays (may not
8093 be strictly correct if designators are used at the
8094 same time) */
8095 if (index >= n && no_oblock)
8096 break;
8097 if (tok == '}')
8098 break;
8099 skip(',');
8102 if (!no_oblock)
8103 skip('}');
8104 /* put zeros at the end */
8105 if (!size_only && n >= 0 && array_length < n) {
8106 init_putz(t1, sec, c + array_length * size1,
8107 (n - array_length) * size1);
8109 /* patch type size if needed */
8110 if (n < 0)
8111 s->c = array_length;
8112 } else if ((type->t & VT_BTYPE) == VT_STRUCT &&
8113 (sec || !first || tok == '{')) {
8114 int par_count;
8116 /* NOTE: the previous test is a specific case for automatic
8117 struct/union init */
8118 /* XXX: union needs only one init */
8120 /* XXX: this test is incorrect for local initializers
8121 beginning with ( without {. It would be much more difficult
8122 to do it correctly (ideally, the expression parser should
8123 be used in all cases) */
8124 par_count = 0;
8125 if (tok == '(') {
8126 AttributeDef ad1;
8127 CType type1;
8128 next();
8129 while (tok == '(') {
8130 par_count++;
8131 next();
8133 if (!parse_btype(&type1, &ad1))
8134 expect("cast");
8135 type_decl(&type1, &ad1, &n, TYPE_ABSTRACT);
8136 #if 0
8137 if (!is_assignable_types(type, &type1))
8138 error("invalid type for cast");
8139 #endif
8140 skip(')');
8142 no_oblock = 1;
8143 if (first || tok == '{') {
8144 skip('{');
8145 no_oblock = 0;
8147 s = type->ref;
8148 f = s->next;
8149 array_length = 0;
8150 index = 0;
8151 n = s->c;
8152 while (tok != '}') {
8153 decl_designator(type, sec, c, NULL, &f, size_only);
8154 index = f->c;
8155 if (!size_only && array_length < index) {
8156 init_putz(type, sec, c + array_length,
8157 index - array_length);
8159 index = index + type_size(&f->type, &align1);
8160 if (index > array_length)
8161 array_length = index;
8162 f = f->next;
8163 if (no_oblock && f == NULL)
8164 break;
8165 if (tok == '}')
8166 break;
8167 skip(',');
8169 /* put zeros at the end */
8170 if (!size_only && array_length < n) {
8171 init_putz(type, sec, c + array_length,
8172 n - array_length);
8174 if (!no_oblock)
8175 skip('}');
8176 while (par_count) {
8177 skip(')');
8178 par_count--;
8180 } else if (tok == '{') {
8181 next();
8182 decl_initializer(type, sec, c, first, size_only);
8183 skip('}');
8184 } else if (size_only) {
8185 /* just skip expression */
8186 parlevel = 0;
8187 while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
8188 tok != -1) {
8189 if (tok == '(')
8190 parlevel++;
8191 else if (tok == ')')
8192 parlevel--;
8193 next();
8195 } else {
8196 /* currently, we always use constant expression for globals
8197 (may change for scripting case) */
8198 expr_type = EXPR_CONST;
8199 if (!sec)
8200 expr_type = EXPR_ANY;
8201 init_putv(type, sec, c, 0, expr_type);
8205 /* parse an initializer for type 't' if 'has_init' is non zero, and
8206 allocate space in local or global data space ('r' is either
8207 VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
8208 variable 'v' of scope 'scope' is declared before initializers are
8209 parsed. If 'v' is zero, then a reference to the new object is put
8210 in the value stack. If 'has_init' is 2, a special parsing is done
8211 to handle string constants. */
8212 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
8213 int has_init, int v, int scope)
8215 int size, align, addr, data_offset;
8216 int level;
8217 ParseState saved_parse_state;
8218 TokenString init_str;
8219 Section *sec;
8221 size = type_size(type, &align);
8222 /* If unknown size, we must evaluate it before
8223 evaluating initializers because
8224 initializers can generate global data too
8225 (e.g. string pointers or ISOC99 compound
8226 literals). It also simplifies local
8227 initializers handling */
8228 tok_str_new(&init_str);
8229 if (size < 0) {
8230 if (!has_init)
8231 error("unknown type size");
8232 /* get all init string */
8233 if (has_init == 2) {
8234 /* only get strings */
8235 while (tok == TOK_STR || tok == TOK_LSTR) {
8236 tok_str_add_tok(&init_str);
8237 next();
8239 } else {
8240 level = 0;
8241 while (level > 0 || (tok != ',' && tok != ';')) {
8242 if (tok < 0)
8243 error("unexpected end of file in initializer");
8244 tok_str_add_tok(&init_str);
8245 if (tok == '{')
8246 level++;
8247 else if (tok == '}') {
8248 if (level == 0)
8249 break;
8250 level--;
8252 next();
8255 tok_str_add(&init_str, -1);
8256 tok_str_add(&init_str, 0);
8258 /* compute size */
8259 save_parse_state(&saved_parse_state);
8261 macro_ptr = init_str.str;
8262 next();
8263 decl_initializer(type, NULL, 0, 1, 1);
8264 /* prepare second initializer parsing */
8265 macro_ptr = init_str.str;
8266 next();
8268 /* if still unknown size, error */
8269 size = type_size(type, &align);
8270 if (size < 0)
8271 error("unknown type size");
8273 /* take into account specified alignment if bigger */
8274 if (ad->aligned > align)
8275 align = ad->aligned;
8276 if ((r & VT_VALMASK) == VT_LOCAL) {
8277 sec = NULL;
8278 if (do_bounds_check && (type->t & VT_ARRAY))
8279 loc--;
8280 loc = (loc - size) & -align;
8281 addr = loc;
8282 /* handles bounds */
8283 /* XXX: currently, since we do only one pass, we cannot track
8284 '&' operators, so we add only arrays */
8285 if (do_bounds_check && (type->t & VT_ARRAY)) {
8286 unsigned long *bounds_ptr;
8287 /* add padding between regions */
8288 loc--;
8289 /* then add local bound info */
8290 bounds_ptr = section_ptr_add(lbounds_section, 2 * sizeof(unsigned long));
8291 bounds_ptr[0] = addr;
8292 bounds_ptr[1] = size;
8294 if (v) {
8295 /* local variable */
8296 sym_push(v, type, r, addr);
8297 } else {
8298 /* push local reference */
8299 vset(type, r, addr);
8301 } else {
8302 Sym *sym;
8304 sym = NULL;
8305 if (v && scope == VT_CONST) {
8306 /* see if the symbol was already defined */
8307 sym = sym_find(v);
8308 if (sym) {
8309 if (!is_compatible_types(&sym->type, type))
8310 error("incompatible types for redefinition of '%s'",
8311 get_tok_str(v, NULL));
8312 if (sym->type.t & VT_EXTERN) {
8313 /* if the variable is extern, it was not allocated */
8314 sym->type.t &= ~VT_EXTERN;
8315 } else {
8316 /* we accept several definitions of the same
8317 global variable. this is tricky, because we
8318 must play with the SHN_COMMON type of the symbol */
8319 /* XXX: should check if the variable was already
8320 initialized. It is incorrect to initialized it
8321 twice */
8322 /* no init data, we won't add more to the symbol */
8323 if (!has_init)
8324 goto no_alloc;
8329 /* allocate symbol in corresponding section */
8330 sec = ad->section;
8331 if (!sec) {
8332 if (has_init)
8333 sec = data_section;
8335 if (sec) {
8336 data_offset = sec->data_offset;
8337 data_offset = (data_offset + align - 1) & -align;
8338 addr = data_offset;
8339 /* very important to increment global pointer at this time
8340 because initializers themselves can create new initializers */
8341 data_offset += size;
8342 /* add padding if bound check */
8343 if (do_bounds_check)
8344 data_offset++;
8345 sec->data_offset = data_offset;
8346 /* allocate section space to put the data */
8347 if (sec->sh_type != SHT_NOBITS &&
8348 data_offset > sec->data_allocated)
8349 section_realloc(sec, data_offset);
8350 } else {
8351 addr = 0; /* avoid warning */
8354 if (v) {
8355 if (scope == VT_CONST) {
8356 if (!sym)
8357 goto do_def;
8358 } else {
8359 do_def:
8360 sym = sym_push(v, type, r | VT_SYM, 0);
8362 /* update symbol definition */
8363 if (sec) {
8364 put_extern_sym(sym, sec, addr, size);
8365 } else {
8366 Elf32_Sym *esym;
8367 /* put a common area */
8368 put_extern_sym(sym, NULL, align, size);
8369 /* XXX: find a nicer way */
8370 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
8371 esym->st_shndx = SHN_COMMON;
8373 } else {
8374 CValue cval;
8376 /* push global reference */
8377 sym = get_sym_ref(type, sec, addr, size);
8378 cval.ul = 0;
8379 vsetc(type, VT_CONST | VT_SYM, &cval);
8380 vtop->sym = sym;
8383 /* handles bounds now because the symbol must be defined
8384 before for the relocation */
8385 if (do_bounds_check) {
8386 unsigned long *bounds_ptr;
8388 greloc(bounds_section, sym, bounds_section->data_offset, R_DATA_32);
8389 /* then add global bound info */
8390 bounds_ptr = section_ptr_add(bounds_section, 2 * sizeof(long));
8391 bounds_ptr[0] = 0; /* relocated */
8392 bounds_ptr[1] = size;
8395 if (has_init) {
8396 decl_initializer(type, sec, addr, 1, 0);
8397 /* restore parse state if needed */
8398 if (init_str.str) {
8399 tok_str_free(init_str.str);
8400 restore_parse_state(&saved_parse_state);
8403 no_alloc: ;
8406 void put_func_debug(Sym *sym)
8408 char buf[512];
8410 /* stabs info */
8411 /* XXX: we put here a dummy type */
8412 snprintf(buf, sizeof(buf), "%s:%c1",
8413 funcname, sym->type.t & VT_STATIC ? 'f' : 'F');
8414 put_stabs_r(buf, N_FUN, 0, file->line_num, 0,
8415 cur_text_section, sym->c);
8416 last_ind = 0;
8417 last_line_num = 0;
8420 /* not finished : try to put some local vars in registers */
8421 //#define CONFIG_REG_VARS
8423 #ifdef CONFIG_REG_VARS
8424 void add_var_ref(int t)
8426 printf("%s:%d: &%s\n",
8427 file->filename, file->line_num,
8428 get_tok_str(t, NULL));
8431 /* first pass on a function with heuristic to extract variable usage
8432 and pointer references to local variables for register allocation */
8433 void analyse_function(void)
8435 int level, t;
8437 for(;;) {
8438 if (tok == -1)
8439 break;
8440 /* any symbol coming after '&' is considered as being a
8441 variable whose reference is taken. It is highly unaccurate
8442 but it is difficult to do better without a complete parse */
8443 if (tok == '&') {
8444 next();
8445 /* if '& number', then no need to examine next tokens */
8446 if (tok == TOK_CINT ||
8447 tok == TOK_CUINT ||
8448 tok == TOK_CLLONG ||
8449 tok == TOK_CULLONG) {
8450 continue;
8451 } else if (tok >= TOK_UIDENT) {
8452 /* if '& ident [' or '& ident ->', then ident address
8453 is not needed */
8454 t = tok;
8455 next();
8456 if (tok != '[' && tok != TOK_ARROW)
8457 add_var_ref(t);
8458 } else {
8459 level = 0;
8460 while (tok != '}' && tok != ';' &&
8461 !((tok == ',' || tok == ')') && level == 0)) {
8462 if (tok >= TOK_UIDENT) {
8463 add_var_ref(tok);
8464 } else if (tok == '(') {
8465 level++;
8466 } else if (tok == ')') {
8467 level--;
8469 next();
8472 } else {
8473 next();
8477 #endif
8479 /* parse an old style function declaration list */
8480 /* XXX: check multiple parameter */
8481 static void func_decl_list(Sym *func_sym)
8483 AttributeDef ad;
8484 int v;
8485 Sym *s;
8486 CType btype, type;
8488 /* parse each declaration */
8489 while (tok != '{' && tok != ';' && tok != ',' && tok != TOK_EOF) {
8490 if (!parse_btype(&btype, &ad))
8491 expect("declaration list");
8492 if (((btype.t & VT_BTYPE) == VT_ENUM ||
8493 (btype.t & VT_BTYPE) == VT_STRUCT) &&
8494 tok == ';') {
8495 /* we accept no variable after */
8496 } else {
8497 for(;;) {
8498 type = btype;
8499 type_decl(&type, &ad, &v, TYPE_DIRECT);
8500 /* find parameter in function parameter list */
8501 s = func_sym->next;
8502 while (s != NULL) {
8503 if ((s->v & ~SYM_FIELD) == v)
8504 goto found;
8505 s = s->next;
8507 error("declaration for parameter '%s' but no such parameter",
8508 get_tok_str(v, NULL));
8509 found:
8510 /* check that no storage specifier except 'register' was given */
8511 if (type.t & VT_STORAGE)
8512 error("storage class specified for '%s'", get_tok_str(v, NULL));
8513 convert_parameter_type(&type);
8514 /* we can add the type (NOTE: it could be local to the function) */
8515 s->type = type;
8516 /* accept other parameters */
8517 if (tok == ',')
8518 next();
8519 else
8520 break;
8523 skip(';');
8527 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
8528 static void decl(int l)
8530 int v, has_init, r;
8531 CType type, btype;
8532 Sym *sym;
8533 AttributeDef ad;
8535 while (1) {
8536 if (!parse_btype(&btype, &ad)) {
8537 /* skip redundant ';' */
8538 /* XXX: find more elegant solution */
8539 if (tok == ';') {
8540 next();
8541 continue;
8543 /* special test for old K&R protos without explicit int
8544 type. Only accepted when defining global data */
8545 if (l == VT_LOCAL || tok < TOK_DEFINE)
8546 break;
8547 btype.t = VT_INT;
8549 if (((btype.t & VT_BTYPE) == VT_ENUM ||
8550 (btype.t & VT_BTYPE) == VT_STRUCT) &&
8551 tok == ';') {
8552 /* we accept no variable after */
8553 next();
8554 continue;
8556 while (1) { /* iterate thru each declaration */
8557 type = btype;
8558 type_decl(&type, &ad, &v, TYPE_DIRECT);
8559 #if 0
8561 char buf[500];
8562 type_to_str(buf, sizeof(buf), t, get_tok_str(v, NULL));
8563 printf("type = '%s'\n", buf);
8565 #endif
8566 if ((type.t & VT_BTYPE) == VT_FUNC) {
8567 /* if old style function prototype, we accept a
8568 declaration list */
8569 sym = type.ref;
8570 if (sym->c == FUNC_OLD)
8571 func_decl_list(sym);
8574 if (tok == '{') {
8575 #ifdef CONFIG_REG_VARS
8576 TokenString func_str;
8577 ParseState saved_parse_state;
8578 int block_level;
8579 #endif
8581 if (l == VT_LOCAL)
8582 error("cannot use local functions");
8583 if (!(type.t & VT_FUNC))
8584 expect("function definition");
8586 /* reject abstract declarators in function definition */
8587 sym = type.ref;
8588 while ((sym = sym->next) != NULL)
8589 if (!(sym->v & ~SYM_FIELD))
8590 expect("identifier");
8592 /* XXX: cannot do better now: convert extern line to static inline */
8593 if ((type.t & (VT_EXTERN | VT_INLINE)) == (VT_EXTERN | VT_INLINE))
8594 type.t = (type.t & ~VT_EXTERN) | VT_STATIC;
8596 #ifdef CONFIG_REG_VARS
8597 /* parse all function code and record it */
8599 tok_str_new(&func_str);
8601 block_level = 0;
8602 for(;;) {
8603 int t;
8604 if (tok == -1)
8605 error("unexpected end of file");
8606 tok_str_add_tok(&func_str);
8607 t = tok;
8608 next();
8609 if (t == '{') {
8610 block_level++;
8611 } else if (t == '}') {
8612 block_level--;
8613 if (block_level == 0)
8614 break;
8617 tok_str_add(&func_str, -1);
8618 tok_str_add(&func_str, 0);
8620 save_parse_state(&saved_parse_state);
8622 macro_ptr = func_str.str;
8623 next();
8624 analyse_function();
8625 #endif
8627 /* compute text section */
8628 cur_text_section = ad.section;
8629 if (!cur_text_section)
8630 cur_text_section = text_section;
8631 ind = cur_text_section->data_offset;
8632 funcname = get_tok_str(v, NULL);
8633 sym = sym_find(v);
8634 if (sym) {
8635 /* if symbol is already defined, then put complete type */
8636 sym->type = type;
8637 } else {
8638 /* put function symbol */
8639 sym = global_identifier_push(v, type.t, 0);
8640 sym->type.ref = type.ref;
8642 /* NOTE: we patch the symbol size later */
8643 put_extern_sym(sym, cur_text_section, ind, 0);
8644 func_ind = ind;
8645 sym->r = VT_SYM | VT_CONST;
8646 /* put debug symbol */
8647 if (do_debug)
8648 put_func_debug(sym);
8649 /* push a dummy symbol to enable local sym storage */
8650 sym_push2(&local_stack, SYM_FIELD, 0, 0);
8651 gfunc_prolog(&type);
8652 loc = 0;
8653 rsym = 0;
8654 #ifdef CONFIG_REG_VARS
8655 macro_ptr = func_str.str;
8656 next();
8657 #endif
8658 block(NULL, NULL, NULL, NULL, 0, 0);
8659 gsym(rsym);
8660 gfunc_epilog();
8661 cur_text_section->data_offset = ind;
8662 label_pop(&global_label_stack, NULL);
8663 sym_pop(&local_stack, NULL); /* reset local stack */
8664 /* end of function */
8665 /* patch symbol size */
8666 ((Elf32_Sym *)symtab_section->data)[sym->c].st_size =
8667 ind - func_ind;
8668 if (do_debug) {
8669 put_stabn(N_FUN, 0, 0, ind - func_ind);
8671 funcname = ""; /* for safety */
8672 func_vt.t = VT_VOID; /* for safety */
8673 ind = 0; /* for safety */
8675 #ifdef CONFIG_REG_VARS
8676 tok_str_free(func_str.str);
8677 restore_parse_state(&saved_parse_state);
8678 #endif
8679 break;
8680 } else {
8681 if (btype.t & VT_TYPEDEF) {
8682 /* save typedefed type */
8683 /* XXX: test storage specifiers ? */
8684 sym = sym_push(v, &type, 0, 0);
8685 sym->type.t |= VT_TYPEDEF;
8686 } else if ((type.t & VT_BTYPE) == VT_FUNC) {
8687 /* external function definition */
8688 external_sym(v, &type, 0);
8689 } else {
8690 /* not lvalue if array */
8691 r = 0;
8692 if (!(type.t & VT_ARRAY))
8693 r |= lvalue_type(type.t);
8694 has_init = (tok == '=');
8695 if ((btype.t & VT_EXTERN) ||
8696 ((type.t & VT_ARRAY) && (type.t & VT_STATIC) &&
8697 !has_init && l == VT_CONST && type.ref->c < 0)) {
8698 /* external variable */
8699 /* NOTE: as GCC, uninitialized global static
8700 arrays of null size are considered as
8701 extern */
8702 external_sym(v, &type, r);
8703 } else {
8704 if (type.t & VT_STATIC)
8705 r |= VT_CONST;
8706 else
8707 r |= l;
8708 if (has_init)
8709 next();
8710 decl_initializer_alloc(&type, &ad, r,
8711 has_init, v, l);
8714 if (tok != ',') {
8715 skip(';');
8716 break;
8718 next();
8724 /* better than nothing, but needs extension to handle '-E' option
8725 correctly too */
8726 static void preprocess_init(TCCState *s1)
8728 s1->include_stack_ptr = s1->include_stack;
8729 /* XXX: move that before to avoid having to initialize
8730 file->ifdef_stack_ptr ? */
8731 s1->ifdef_stack_ptr = s1->ifdef_stack;
8732 file->ifdef_stack_ptr = s1->ifdef_stack_ptr;
8734 /* XXX: not ANSI compliant: bound checking says error */
8735 vtop = vstack - 1;
8738 /* compile the C file opened in 'file'. Return non zero if errors. */
8739 static int tcc_compile(TCCState *s1)
8741 Sym *define_start;
8742 char buf[512];
8743 volatile int section_sym;
8745 #ifdef INC_DEBUG
8746 printf("%s: **** new file\n", file->filename);
8747 #endif
8748 preprocess_init(s1);
8750 funcname = "";
8751 anon_sym = SYM_FIRST_ANOM;
8753 /* file info: full path + filename */
8754 section_sym = 0; /* avoid warning */
8755 if (do_debug) {
8756 section_sym = put_elf_sym(symtab_section, 0, 0,
8757 ELF32_ST_INFO(STB_LOCAL, STT_SECTION), 0,
8758 text_section->sh_num, NULL);
8759 getcwd(buf, sizeof(buf));
8760 pstrcat(buf, sizeof(buf), "/");
8761 put_stabs_r(buf, N_SO, 0, 0,
8762 text_section->data_offset, text_section, section_sym);
8763 put_stabs_r(file->filename, N_SO, 0, 0,
8764 text_section->data_offset, text_section, section_sym);
8766 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
8767 symbols can be safely used */
8768 put_elf_sym(symtab_section, 0, 0,
8769 ELF32_ST_INFO(STB_LOCAL, STT_FILE), 0,
8770 SHN_ABS, file->filename);
8772 /* define some often used types */
8773 int_type.t = VT_INT;
8775 char_pointer_type.t = VT_BYTE;
8776 mk_pointer(&char_pointer_type);
8778 func_old_type.t = VT_FUNC;
8779 func_old_type.ref = sym_push(SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD);
8781 #if 0
8782 /* define 'void *alloca(unsigned int)' builtin function */
8784 Sym *s1;
8786 p = anon_sym++;
8787 sym = sym_push(p, mk_pointer(VT_VOID), FUNC_CDECL, FUNC_NEW);
8788 s1 = sym_push(SYM_FIELD, VT_UNSIGNED | VT_INT, 0, 0);
8789 s1->next = NULL;
8790 sym->next = s1;
8791 sym_push(TOK_alloca, VT_FUNC | (p << VT_STRUCT_SHIFT), VT_CONST, 0);
8793 #endif
8795 define_start = define_stack;
8797 if (setjmp(s1->error_jmp_buf) == 0) {
8798 s1->nb_errors = 0;
8799 s1->error_set_jmp_enabled = 1;
8801 ch = file->buf_ptr[0];
8802 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
8803 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM;
8804 next();
8805 decl(VT_CONST);
8806 if (tok != TOK_EOF)
8807 expect("declaration");
8809 /* end of translation unit info */
8810 if (do_debug) {
8811 put_stabs_r(NULL, N_SO, 0, 0,
8812 text_section->data_offset, text_section, section_sym);
8815 s1->error_set_jmp_enabled = 0;
8817 /* reset define stack, but leave -Dsymbols (may be incorrect if
8818 they are undefined) */
8819 free_defines(define_start);
8821 sym_pop(&global_stack, NULL);
8823 return s1->nb_errors != 0 ? -1 : 0;
8826 #ifdef LIBTCC
8827 int tcc_compile_string(TCCState *s, const char *str)
8829 BufferedFile bf1, *bf = &bf1;
8830 int ret, len;
8831 char *buf;
8833 /* init file structure */
8834 bf->fd = -1;
8835 /* XXX: avoid copying */
8836 len = strlen(str);
8837 buf = tcc_malloc(len + 1);
8838 if (!buf)
8839 return -1;
8840 memcpy(buf, str, len);
8841 buf[len] = CH_EOB;
8842 bf->buf_ptr = buf;
8843 bf->buf_end = buf + len;
8844 pstrcpy(bf->filename, sizeof(bf->filename), "<string>");
8845 bf->line_num = 1;
8846 file = bf;
8848 ret = tcc_compile(s);
8850 tcc_free(buf);
8852 /* currently, no need to close */
8853 return ret;
8855 #endif
8857 /* define a preprocessor symbol. A value can also be provided with the '=' operator */
8858 void tcc_define_symbol(TCCState *s1, const char *sym, const char *value)
8860 BufferedFile bf1, *bf = &bf1;
8862 pstrcpy(bf->buffer, IO_BUF_SIZE, sym);
8863 pstrcat(bf->buffer, IO_BUF_SIZE, " ");
8864 /* default value */
8865 if (!value)
8866 value = "1";
8867 pstrcat(bf->buffer, IO_BUF_SIZE, value);
8869 /* init file structure */
8870 bf->fd = -1;
8871 bf->buf_ptr = bf->buffer;
8872 bf->buf_end = bf->buffer + strlen(bf->buffer);
8873 *bf->buf_end = CH_EOB;
8874 bf->filename[0] = '\0';
8875 bf->line_num = 1;
8876 file = bf;
8878 s1->include_stack_ptr = s1->include_stack;
8880 /* parse with define parser */
8881 ch = file->buf_ptr[0];
8882 next_nomacro();
8883 parse_define();
8884 file = NULL;
8887 /* undefine a preprocessor symbol */
8888 void tcc_undefine_symbol(TCCState *s1, const char *sym)
8890 TokenSym *ts;
8891 Sym *s;
8892 ts = tok_alloc(sym, strlen(sym));
8893 s = define_find(ts->tok);
8894 /* undefine symbol by putting an invalid name */
8895 if (s)
8896 define_undef(s);
8899 #ifdef CONFIG_TCC_ASM
8901 #ifdef TCC_TARGET_I386
8902 #include "i386-asm.c"
8903 #endif
8904 #include "tccasm.c"
8906 #else
8907 static void asm_instr(void)
8909 error("inline asm() not supported");
8911 #endif
8913 #include "tccelf.c"
8915 /* print the position in the source file of PC value 'pc' by reading
8916 the stabs debug information */
8917 static void rt_printline(unsigned long wanted_pc)
8919 Stab_Sym *sym, *sym_end;
8920 char func_name[128], last_func_name[128];
8921 unsigned long func_addr, last_pc, pc;
8922 const char *incl_files[INCLUDE_STACK_SIZE];
8923 int incl_index, len, last_line_num, i;
8924 const char *str, *p;
8926 fprintf(stderr, "0x%08lx:", wanted_pc);
8928 func_name[0] = '\0';
8929 func_addr = 0;
8930 incl_index = 0;
8931 last_func_name[0] = '\0';
8932 last_pc = 0xffffffff;
8933 last_line_num = 1;
8934 sym = (Stab_Sym *)stab_section->data + 1;
8935 sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset);
8936 while (sym < sym_end) {
8937 switch(sym->n_type) {
8938 /* function start or end */
8939 case N_FUN:
8940 if (sym->n_strx == 0) {
8941 /* we test if between last line and end of function */
8942 pc = sym->n_value + func_addr;
8943 if (wanted_pc >= last_pc && wanted_pc < pc)
8944 goto found;
8945 func_name[0] = '\0';
8946 func_addr = 0;
8947 } else {
8948 str = stabstr_section->data + sym->n_strx;
8949 p = strchr(str, ':');
8950 if (!p) {
8951 pstrcpy(func_name, sizeof(func_name), str);
8952 } else {
8953 len = p - str;
8954 if (len > sizeof(func_name) - 1)
8955 len = sizeof(func_name) - 1;
8956 memcpy(func_name, str, len);
8957 func_name[len] = '\0';
8959 func_addr = sym->n_value;
8961 break;
8962 /* line number info */
8963 case N_SLINE:
8964 pc = sym->n_value + func_addr;
8965 if (wanted_pc >= last_pc && wanted_pc < pc)
8966 goto found;
8967 last_pc = pc;
8968 last_line_num = sym->n_desc;
8969 /* XXX: slow! */
8970 strcpy(last_func_name, func_name);
8971 break;
8972 /* include files */
8973 case N_BINCL:
8974 str = stabstr_section->data + sym->n_strx;
8975 add_incl:
8976 if (incl_index < INCLUDE_STACK_SIZE) {
8977 incl_files[incl_index++] = str;
8979 break;
8980 case N_EINCL:
8981 if (incl_index > 1)
8982 incl_index--;
8983 break;
8984 case N_SO:
8985 if (sym->n_strx == 0) {
8986 incl_index = 0; /* end of translation unit */
8987 } else {
8988 str = stabstr_section->data + sym->n_strx;
8989 /* do not add path */
8990 len = strlen(str);
8991 if (len > 0 && str[len - 1] != '/')
8992 goto add_incl;
8994 break;
8996 sym++;
8999 /* second pass: we try symtab symbols (no line number info) */
9000 incl_index = 0;
9002 Elf32_Sym *sym, *sym_end;
9003 int type;
9005 sym_end = (Elf32_Sym *)(symtab_section->data + symtab_section->data_offset);
9006 for(sym = (Elf32_Sym *)symtab_section->data + 1;
9007 sym < sym_end;
9008 sym++) {
9009 type = ELF32_ST_TYPE(sym->st_info);
9010 if (type == STT_FUNC) {
9011 if (wanted_pc >= sym->st_value &&
9012 wanted_pc < sym->st_value + sym->st_size) {
9013 pstrcpy(last_func_name, sizeof(last_func_name),
9014 strtab_section->data + sym->st_name);
9015 goto found;
9020 /* did not find any info: */
9021 fprintf(stderr, " ???\n");
9022 return;
9023 found:
9024 if (last_func_name[0] != '\0') {
9025 fprintf(stderr, " %s()", last_func_name);
9027 if (incl_index > 0) {
9028 fprintf(stderr, " (%s:%d",
9029 incl_files[incl_index - 1], last_line_num);
9030 for(i = incl_index - 2; i >= 0; i--)
9031 fprintf(stderr, ", included from %s", incl_files[i]);
9032 fprintf(stderr, ")");
9034 fprintf(stderr, "\n");
9037 #ifndef WIN32
9039 #ifdef __i386__
9041 /* fix for glibc 2.1 */
9042 #ifndef REG_EIP
9043 #define REG_EIP EIP
9044 #define REG_EBP EBP
9045 #endif
9047 /* return the PC at frame level 'level'. Return non zero if not found */
9048 static int rt_get_caller_pc(unsigned long *paddr,
9049 ucontext_t *uc, int level)
9051 unsigned long fp;
9052 int i;
9054 if (level == 0) {
9055 #ifdef __FreeBSD__
9056 *paddr = uc->uc_mcontext.mc_eip;
9057 #else
9058 *paddr = uc->uc_mcontext.gregs[REG_EIP];
9059 #endif
9060 return 0;
9061 } else {
9062 #ifdef __FreeBSD__
9063 fp = uc->uc_mcontext.mc_ebp;
9064 #else
9065 fp = uc->uc_mcontext.gregs[REG_EBP];
9066 #endif
9067 for(i=1;i<level;i++) {
9068 /* XXX: check address validity with program info */
9069 if (fp <= 0x1000 || fp >= 0xc0000000)
9070 return -1;
9071 fp = ((unsigned long *)fp)[0];
9073 *paddr = ((unsigned long *)fp)[1];
9074 return 0;
9077 #else
9079 #warning add arch specific rt_get_caller_pc()
9081 static int rt_get_caller_pc(unsigned long *paddr,
9082 ucontext_t *uc, int level)
9084 return -1;
9086 #endif
9088 /* emit a run time error at position 'pc' */
9089 void rt_error(ucontext_t *uc, const char *fmt, ...)
9091 va_list ap;
9092 unsigned long pc;
9093 int i;
9095 va_start(ap, fmt);
9096 fprintf(stderr, "Runtime error: ");
9097 vfprintf(stderr, fmt, ap);
9098 fprintf(stderr, "\n");
9099 for(i=0;i<num_callers;i++) {
9100 if (rt_get_caller_pc(&pc, uc, i) < 0)
9101 break;
9102 if (i == 0)
9103 fprintf(stderr, "at ");
9104 else
9105 fprintf(stderr, "by ");
9106 rt_printline(pc);
9108 exit(255);
9109 va_end(ap);
9112 /* signal handler for fatal errors */
9113 static void sig_error(int signum, siginfo_t *siginf, void *puc)
9115 ucontext_t *uc = puc;
9117 switch(signum) {
9118 case SIGFPE:
9119 switch(siginf->si_code) {
9120 case FPE_INTDIV:
9121 case FPE_FLTDIV:
9122 rt_error(uc, "division by zero");
9123 break;
9124 default:
9125 rt_error(uc, "floating point exception");
9126 break;
9128 break;
9129 case SIGBUS:
9130 case SIGSEGV:
9131 if (rt_bound_error_msg && *rt_bound_error_msg)
9132 rt_error(uc, *rt_bound_error_msg);
9133 else
9134 rt_error(uc, "dereferencing invalid pointer");
9135 break;
9136 case SIGILL:
9137 rt_error(uc, "illegal instruction");
9138 break;
9139 case SIGABRT:
9140 rt_error(uc, "abort() called");
9141 break;
9142 default:
9143 rt_error(uc, "caught signal %d", signum);
9144 break;
9146 exit(255);
9148 #endif
9150 /* do all relocations (needed before using tcc_get_symbol()) */
9151 int tcc_relocate(TCCState *s1)
9153 Section *s;
9154 int i;
9156 s1->nb_errors = 0;
9158 tcc_add_runtime(s1);
9160 build_got_entries(s1);
9162 relocate_common_syms();
9164 /* compute relocation address : section are relocated in place. We
9165 also alloc the bss space */
9166 for(i = 1; i < s1->nb_sections; i++) {
9167 s = s1->sections[i];
9168 if (s->sh_flags & SHF_ALLOC) {
9169 if (s->sh_type == SHT_NOBITS)
9170 s->data = tcc_mallocz(s->data_offset);
9171 s->sh_addr = (unsigned long)s->data;
9175 relocate_syms(s1, 1);
9177 if (s1->nb_errors != 0)
9178 return -1;
9180 /* relocate each section */
9181 for(i = 1; i < s1->nb_sections; i++) {
9182 s = s1->sections[i];
9183 if (s->reloc)
9184 relocate_section(s1, s);
9186 return 0;
9189 /* launch the compiled program with the given arguments */
9190 int tcc_run(TCCState *s1, int argc, char **argv)
9192 int (*prog_main)(int, char **);
9194 if (tcc_relocate(s1) < 0)
9195 return -1;
9197 prog_main = tcc_get_symbol_err(s1, "main");
9199 if (do_debug) {
9200 #ifdef WIN32
9201 error("debug mode currently not available for Windows");
9202 #else
9203 struct sigaction sigact;
9204 /* install TCC signal handlers to print debug info on fatal
9205 runtime errors */
9206 sigact.sa_flags = SA_SIGINFO | SA_RESETHAND;
9207 sigact.sa_sigaction = sig_error;
9208 sigemptyset(&sigact.sa_mask);
9209 sigaction(SIGFPE, &sigact, NULL);
9210 sigaction(SIGILL, &sigact, NULL);
9211 sigaction(SIGSEGV, &sigact, NULL);
9212 sigaction(SIGBUS, &sigact, NULL);
9213 sigaction(SIGABRT, &sigact, NULL);
9214 #endif
9217 #ifdef CONFIG_TCC_BCHECK
9218 if (do_bounds_check) {
9219 void (*bound_init)(void);
9221 /* set error function */
9222 rt_bound_error_msg = (void *)tcc_get_symbol_err(s1,
9223 "__bound_error_msg");
9225 /* XXX: use .init section so that it also work in binary ? */
9226 bound_init = (void *)tcc_get_symbol_err(s1, "__bound_init");
9227 bound_init();
9229 #endif
9230 return (*prog_main)(argc, argv);
9233 TCCState *tcc_new(void)
9235 const char *p, *r;
9236 TCCState *s;
9237 TokenSym *ts;
9238 int i, c;
9240 s = tcc_mallocz(sizeof(TCCState));
9241 if (!s)
9242 return NULL;
9243 tcc_state = s;
9244 s->output_type = TCC_OUTPUT_MEMORY;
9246 /* init isid table */
9247 for(i=0;i<256;i++)
9248 isidnum_table[i] = isid(i) || isnum(i);
9250 /* add all tokens */
9251 table_ident = NULL;
9252 memset(hash_ident, 0, TOK_HASH_SIZE * sizeof(TokenSym *));
9254 tok_ident = TOK_IDENT;
9255 p = tcc_keywords;
9256 while (*p) {
9257 r = p;
9258 for(;;) {
9259 c = *r++;
9260 if (c == '\0')
9261 break;
9263 ts = tok_alloc(p, r - p - 1);
9264 p = r;
9267 /* we add dummy defines for some special macros to speed up tests
9268 and to have working defined() */
9269 define_push(TOK___LINE__, MACRO_OBJ, NULL, NULL);
9270 define_push(TOK___FILE__, MACRO_OBJ, NULL, NULL);
9271 define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL);
9272 define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL);
9274 /* standard defines */
9275 tcc_define_symbol(s, "__STDC__", NULL);
9276 #if defined(TCC_TARGET_I386)
9277 tcc_define_symbol(s, "__i386__", NULL);
9278 #endif
9279 #if defined(TCC_TARGET_ARM)
9280 tcc_define_symbol(s, "__ARM_ARCH_4__", NULL);
9281 tcc_define_symbol(s, "__arm_elf__", NULL);
9282 tcc_define_symbol(s, "__arm_elf", NULL);
9283 tcc_define_symbol(s, "arm_elf", NULL);
9284 tcc_define_symbol(s, "__arm__", NULL);
9285 tcc_define_symbol(s, "__arm", NULL);
9286 tcc_define_symbol(s, "arm", NULL);
9287 tcc_define_symbol(s, "__APCS_32__", NULL);
9288 #endif
9289 #ifdef CHAR_IS_UNSIGNED
9290 tcc_define_symbol(s, "__CHAR_UNSIGNED__", NULL);
9291 #endif
9292 #if defined(linux)
9293 tcc_define_symbol(s, "__linux__", NULL);
9294 tcc_define_symbol(s, "linux", NULL);
9295 #endif
9296 /* tiny C specific defines */
9297 tcc_define_symbol(s, "__TINYC__", NULL);
9299 /* tiny C & gcc defines */
9300 tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned int");
9301 tcc_define_symbol(s, "__PTRDIFF_TYPE__", "int");
9302 tcc_define_symbol(s, "__WCHAR_TYPE__", "int");
9304 /* default library paths */
9305 tcc_add_library_path(s, "/usr/local/lib");
9306 tcc_add_library_path(s, "/usr/lib");
9307 tcc_add_library_path(s, "/lib");
9309 /* no section zero */
9310 dynarray_add((void ***)&s->sections, &s->nb_sections, NULL);
9312 /* create standard sections */
9313 text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
9314 data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
9315 bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
9317 /* symbols are always generated for linking stage */
9318 symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0,
9319 ".strtab",
9320 ".hashtab", SHF_PRIVATE);
9321 strtab_section = symtab_section->link;
9323 /* private symbol table for dynamic symbols */
9324 s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE,
9325 ".dynstrtab",
9326 ".dynhashtab", SHF_PRIVATE);
9327 s->alacarte_link = 1;
9328 return s;
9331 void tcc_delete(TCCState *s1)
9333 int i, n;
9335 /* free -D defines */
9336 free_defines(NULL);
9338 /* free tokens */
9339 n = tok_ident - TOK_IDENT;
9340 for(i = 0; i < n; i++)
9341 tcc_free(table_ident[i]);
9342 tcc_free(table_ident);
9344 /* free all sections */
9346 free_section(symtab_section->hash);
9348 free_section(s1->dynsymtab_section->hash);
9349 free_section(s1->dynsymtab_section->link);
9350 free_section(s1->dynsymtab_section);
9352 for(i = 1; i < s1->nb_sections; i++)
9353 free_section(s1->sections[i]);
9354 tcc_free(s1->sections);
9356 /* free loaded dlls array */
9357 for(i = 0; i < s1->nb_loaded_dlls; i++)
9358 tcc_free(s1->loaded_dlls[i]);
9359 tcc_free(s1->loaded_dlls);
9361 /* library paths */
9362 for(i = 0; i < s1->nb_library_paths; i++)
9363 tcc_free(s1->library_paths[i]);
9364 tcc_free(s1->library_paths);
9366 /* cached includes */
9367 for(i = 0; i < s1->nb_cached_includes; i++)
9368 tcc_free(s1->cached_includes[i]);
9369 tcc_free(s1->cached_includes);
9371 for(i = 0; i < s1->nb_include_paths; i++)
9372 tcc_free(s1->include_paths[i]);
9373 tcc_free(s1->include_paths);
9375 for(i = 0; i < s1->nb_sysinclude_paths; i++)
9376 tcc_free(s1->sysinclude_paths[i]);
9377 tcc_free(s1->sysinclude_paths);
9379 tcc_free(s1);
9382 int tcc_add_include_path(TCCState *s1, const char *pathname)
9384 char *pathname1;
9386 pathname1 = tcc_strdup(pathname);
9387 dynarray_add((void ***)&s1->include_paths, &s1->nb_include_paths, pathname1);
9388 return 0;
9391 int tcc_add_sysinclude_path(TCCState *s1, const char *pathname)
9393 char *pathname1;
9395 pathname1 = tcc_strdup(pathname);
9396 dynarray_add((void ***)&s1->sysinclude_paths, &s1->nb_sysinclude_paths, pathname1);
9397 return 0;
9400 static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
9402 const char *ext, *filename1;
9403 Elf32_Ehdr ehdr;
9404 int fd, ret;
9405 BufferedFile *saved_file;
9407 /* find source file type with extension */
9408 filename1 = strrchr(filename, '/');
9409 if (filename1)
9410 filename1++;
9411 else
9412 filename1 = filename;
9413 ext = strrchr(filename1, '.');
9414 if (ext)
9415 ext++;
9417 /* open the file */
9418 saved_file = file;
9419 file = tcc_open(s1, filename);
9420 if (!file) {
9421 if (flags & AFF_PRINT_ERROR) {
9422 error_noabort("file '%s' not found", filename);
9424 ret = -1;
9425 goto fail1;
9428 if (!ext || !strcmp(ext, "c")) {
9429 /* C file assumed */
9430 ret = tcc_compile(s1);
9431 } else
9432 #ifdef CONFIG_TCC_ASM
9433 if (!strcmp(ext, "S")) {
9434 /* preprocessed assembler */
9435 ret = tcc_assemble(s1, 1);
9436 } else if (!strcmp(ext, "s")) {
9437 /* non preprocessed assembler */
9438 ret = tcc_assemble(s1, 0);
9439 } else
9440 #endif
9442 fd = file->fd;
9443 /* assume executable format: auto guess file type */
9444 ret = read(fd, &ehdr, sizeof(ehdr));
9445 lseek(fd, 0, SEEK_SET);
9446 if (ret <= 0) {
9447 error_noabort("could not read header");
9448 goto fail;
9449 } else if (ret != sizeof(ehdr)) {
9450 goto try_load_script;
9453 if (ehdr.e_ident[0] == ELFMAG0 &&
9454 ehdr.e_ident[1] == ELFMAG1 &&
9455 ehdr.e_ident[2] == ELFMAG2 &&
9456 ehdr.e_ident[3] == ELFMAG3) {
9457 file->line_num = 0; /* do not display line number if error */
9458 if (ehdr.e_type == ET_REL) {
9459 ret = tcc_load_object_file(s1, fd, 0);
9460 } else if (ehdr.e_type == ET_DYN) {
9461 if (s1->output_type == TCC_OUTPUT_MEMORY) {
9462 void *h;
9463 h = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY);
9464 if (h)
9465 ret = 0;
9466 else
9467 ret = -1;
9468 } else {
9469 ret = tcc_load_dll(s1, fd, filename,
9470 (flags & AFF_REFERENCED_DLL) != 0);
9472 } else {
9473 error_noabort("unrecognized ELF file");
9474 goto fail;
9476 } else if (memcmp((char *)&ehdr, ARMAG, 8) == 0) {
9477 file->line_num = 0; /* do not display line number if error */
9478 ret = tcc_load_archive(s1, fd);
9479 } else {
9480 /* as GNU ld, consider it is an ld script if not recognized */
9481 try_load_script:
9482 ret = tcc_load_ldscript(s1);
9483 if (ret < 0) {
9484 error_noabort("unrecognized file type");
9485 goto fail;
9489 the_end:
9490 tcc_close(file);
9491 fail1:
9492 file = saved_file;
9493 return ret;
9494 fail:
9495 ret = -1;
9496 goto the_end;
9499 int tcc_add_file(TCCState *s, const char *filename)
9501 return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR);
9504 int tcc_add_library_path(TCCState *s, const char *pathname)
9506 char *pathname1;
9508 pathname1 = tcc_strdup(pathname);
9509 dynarray_add((void ***)&s->library_paths, &s->nb_library_paths, pathname1);
9510 return 0;
9513 /* find and load a dll. Return non zero if not found */
9514 /* XXX: add '-rpath' option support ? */
9515 static int tcc_add_dll(TCCState *s, const char *filename, int flags)
9517 char buf[1024];
9518 int i;
9520 for(i = 0; i < s->nb_library_paths; i++) {
9521 snprintf(buf, sizeof(buf), "%s/%s",
9522 s->library_paths[i], filename);
9523 if (tcc_add_file_internal(s, buf, flags) == 0)
9524 return 0;
9526 return -1;
9529 /* the library name is the same as the argument of the '-l' option */
9530 int tcc_add_library(TCCState *s, const char *libraryname)
9532 char buf[1024];
9533 int i;
9535 /* first we look for the dynamic library if not static linking */
9536 if (!s->static_link) {
9537 snprintf(buf, sizeof(buf), "lib%s.so", libraryname);
9538 if (tcc_add_dll(s, buf, 0) == 0)
9539 return 0;
9542 /* then we look for the static library */
9543 for(i = 0; i < s->nb_library_paths; i++) {
9544 snprintf(buf, sizeof(buf), "%s/lib%s.a",
9545 s->library_paths[i], libraryname);
9546 if (tcc_add_file_internal(s, buf, 0) == 0)
9547 return 0;
9549 return -1;
9552 int tcc_add_symbol(TCCState *s, const char *name, unsigned long val)
9554 add_elf_sym(symtab_section, val, 0,
9555 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE),
9556 SHN_ABS, name);
9557 return 0;
9560 int tcc_set_output_type(TCCState *s, int output_type)
9562 char buf[1024];
9564 s->output_type = output_type;
9566 if (!s->nostdinc) {
9567 /* default include paths */
9568 /* XXX: reverse order needed if -isystem support */
9569 tcc_add_sysinclude_path(s, "/usr/local/include");
9570 tcc_add_sysinclude_path(s, "/usr/include");
9571 snprintf(buf, sizeof(buf), "%s/include", tcc_lib_path);
9572 tcc_add_sysinclude_path(s, buf);
9575 /* if bound checking, then add corresponding sections */
9576 #ifdef CONFIG_TCC_BCHECK
9577 if (do_bounds_check) {
9578 /* define symbol */
9579 tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL);
9580 /* create bounds sections */
9581 bounds_section = new_section(s, ".bounds",
9582 SHT_PROGBITS, SHF_ALLOC);
9583 lbounds_section = new_section(s, ".lbounds",
9584 SHT_PROGBITS, SHF_ALLOC);
9586 #endif
9588 /* add debug sections */
9589 if (do_debug) {
9590 /* stab symbols */
9591 stab_section = new_section(s, ".stab", SHT_PROGBITS, 0);
9592 stab_section->sh_entsize = sizeof(Stab_Sym);
9593 stabstr_section = new_section(s, ".stabstr", SHT_STRTAB, 0);
9594 put_elf_str(stabstr_section, "");
9595 stab_section->link = stabstr_section;
9596 /* put first entry */
9597 put_stabs("", 0, 0, 0, 0);
9600 /* add libc crt1/crti objects */
9601 if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) &&
9602 !s->nostdlib) {
9603 if (output_type != TCC_OUTPUT_DLL)
9604 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crt1.o");
9605 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crti.o");
9607 return 0;
9610 #define WD_ALL 0x0001 /* warning is activated when using -Wall */
9612 typedef struct WarningDef {
9613 int offset;
9614 int flags;
9615 const char *name;
9616 } WarningDef;
9618 static const WarningDef warning_defs[] = {
9619 { offsetof(TCCState, warn_unsupported), 0, "unsupported" },
9620 { offsetof(TCCState, warn_write_strings), 0, "write-strings" },
9621 { offsetof(TCCState, warn_error), 0, "error" },
9624 /* set/reset a warning */
9625 int tcc_set_warning(TCCState *s, const char *warning_name, int value)
9627 int i;
9628 const WarningDef *p;
9629 if (!strcmp(warning_name, "all")) {
9630 for(i = 0, p = warning_defs; i < countof(warning_defs); i++, p++) {
9631 if (p->flags & WD_ALL)
9632 *(int *)((uint8_t *)s + p->offset) = 1;
9634 } else {
9635 for(i = 0, p = warning_defs; i < countof(warning_defs); i++, p++) {
9636 if (!strcmp(warning_name, p->name))
9637 goto found;
9639 return -1;
9640 found:
9641 *(int *)((uint8_t *)s + p->offset) = value;
9643 return 0;
9646 #if !defined(LIBTCC)
9648 /* extract the basename of a file */
9649 static const char *tcc_basename(const char *name)
9651 const char *p;
9652 p = strrchr(name, '/');
9653 #ifdef WIN32
9654 if (!p)
9655 p = strrchr(name, '\\');
9656 #endif
9657 if (!p)
9658 p = name;
9659 else
9660 p++;
9661 return p;
9664 static int64_t getclock_us(void)
9666 #ifdef WIN32
9667 struct _timeb tb;
9668 _ftime(&tb);
9669 return (tb.time * 1000LL + tb.millitm) * 1000LL;
9670 #else
9671 struct timeval tv;
9672 gettimeofday(&tv, NULL);
9673 return tv.tv_sec * 1000000LL + tv.tv_usec;
9674 #endif
9677 void help(void)
9679 printf("tcc version " TCC_VERSION " - Tiny C Compiler - Copyright (C) 2001-2003 Fabrice Bellard\n"
9680 "usage: tcc [-v] [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
9681 " [-Wwarn] [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-static]\n"
9682 " [infile1 infile2...] [-run infile args...]\n"
9683 "\n"
9684 "General options:\n"
9685 " -v display current version\n"
9686 " -c compile only - generate an object file\n"
9687 " -o outfile set output filename\n"
9688 " -Bdir set tcc internal library path\n"
9689 " -bench output compilation statistics\n"
9690 " -run run compiled source\n"
9691 " -Wwarning set or reset (with 'no-' prefix) 'warning'\n"
9692 " -w disable all warnings\n"
9693 "Preprocessor options:\n"
9694 " -Idir add include path 'dir'\n"
9695 " -Dsym[=val] define 'sym' with value 'val'\n"
9696 " -Usym undefine 'sym'\n"
9697 "Linker options:\n"
9698 " -Ldir add library path 'dir'\n"
9699 " -llib link with dynamic or static library 'lib'\n"
9700 " -shared generate a shared library\n"
9701 " -static static linking\n"
9702 " -rdynamic export all global symbols to dynamic linker\n"
9703 " -r relocatable output\n"
9704 "Debugger options:\n"
9705 " -g generate runtime debug info\n"
9706 #ifdef CONFIG_TCC_BCHECK
9707 " -b compile with built-in memory and bounds checker (implies -g)\n"
9708 #endif
9709 " -bt N show N callers in stack traces\n"
9713 #define TCC_OPTION_HAS_ARG 0x0001
9714 #define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
9716 typedef struct TCCOption {
9717 const char *name;
9718 uint16_t index;
9719 uint16_t flags;
9720 } TCCOption;
9722 enum {
9723 TCC_OPTION_HELP,
9724 TCC_OPTION_I,
9725 TCC_OPTION_D,
9726 TCC_OPTION_U,
9727 TCC_OPTION_L,
9728 TCC_OPTION_B,
9729 TCC_OPTION_l,
9730 TCC_OPTION_bench,
9731 TCC_OPTION_bt,
9732 TCC_OPTION_b,
9733 TCC_OPTION_g,
9734 TCC_OPTION_c,
9735 TCC_OPTION_static,
9736 TCC_OPTION_shared,
9737 TCC_OPTION_o,
9738 TCC_OPTION_r,
9739 TCC_OPTION_W,
9740 TCC_OPTION_O,
9741 TCC_OPTION_m,
9742 TCC_OPTION_f,
9743 TCC_OPTION_nostdinc,
9744 TCC_OPTION_nostdlib,
9745 TCC_OPTION_print_search_dirs,
9746 TCC_OPTION_rdynamic,
9747 TCC_OPTION_run,
9748 TCC_OPTION_v,
9749 TCC_OPTION_w,
9752 static const TCCOption tcc_options[] = {
9753 { "h", TCC_OPTION_HELP, 0 },
9754 { "?", TCC_OPTION_HELP, 0 },
9755 { "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG },
9756 { "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG },
9757 { "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG },
9758 { "L", TCC_OPTION_L, TCC_OPTION_HAS_ARG },
9759 { "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG },
9760 { "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
9761 { "bench", TCC_OPTION_bench, 0 },
9762 { "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG },
9763 #ifdef CONFIG_TCC_BCHECK
9764 { "b", TCC_OPTION_b, 0 },
9765 #endif
9766 { "g", TCC_OPTION_g, 0 },
9767 { "c", TCC_OPTION_c, 0 },
9768 { "static", TCC_OPTION_static, 0 },
9769 { "shared", TCC_OPTION_shared, 0 },
9770 { "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG },
9771 { "run", TCC_OPTION_run, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
9772 { "rdynamic", TCC_OPTION_rdynamic, 0 },
9773 { "r", TCC_OPTION_r, 0 },
9774 { "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
9775 { "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
9776 { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG },
9777 { "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
9778 { "nostdinc", TCC_OPTION_nostdinc, 0 },
9779 { "nostdlib", TCC_OPTION_nostdlib, 0 },
9780 { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 },
9781 { "v", TCC_OPTION_v, 0 },
9782 { "w", TCC_OPTION_w, 0 },
9783 { NULL },
9786 /* convert 'str' into an array of space separated strings */
9787 static int expand_args(char ***pargv, const char *str)
9789 const char *s1;
9790 char **argv, *arg;
9791 int argc, len;
9793 argc = 0;
9794 argv = NULL;
9795 for(;;) {
9796 while (is_space(*str))
9797 str++;
9798 if (*str == '\0')
9799 break;
9800 s1 = str;
9801 while (*str != '\0' && !is_space(*str))
9802 str++;
9803 len = str - s1;
9804 arg = tcc_malloc(len + 1);
9805 memcpy(arg, s1, len);
9806 arg[len] = '\0';
9807 dynarray_add((void ***)&argv, &argc, arg);
9809 *pargv = argv;
9810 return argc;
9813 static char **files;
9814 static int nb_files, nb_libraries;
9815 static int multiple_files;
9816 static int print_search_dirs;
9817 static int output_type;
9818 static int reloc_output;
9819 static const char *outfile;
9821 int parse_args(TCCState *s, int argc, char **argv)
9823 int optind;
9824 const TCCOption *popt;
9825 const char *optarg, *p1, *r1;
9826 char *r;
9828 optind = 0;
9829 while (1) {
9830 if (optind >= argc) {
9831 if (nb_files == 0 && !print_search_dirs)
9832 goto show_help;
9833 else
9834 break;
9836 r = argv[optind++];
9837 if (r[0] != '-') {
9838 /* add a new file */
9839 dynarray_add((void ***)&files, &nb_files, r);
9840 if (!multiple_files) {
9841 optind--;
9842 /* argv[0] will be this file */
9843 break;
9845 } else {
9846 /* find option in table (match only the first chars */
9847 popt = tcc_options;
9848 for(;;) {
9849 p1 = popt->name;
9850 if (p1 == NULL)
9851 error("invalid option -- '%s'", r);
9852 r1 = r + 1;
9853 for(;;) {
9854 if (*p1 == '\0')
9855 goto option_found;
9856 if (*r1 != *p1)
9857 break;
9858 p1++;
9859 r1++;
9861 popt++;
9863 option_found:
9864 if (popt->flags & TCC_OPTION_HAS_ARG) {
9865 if (*r1 != '\0' || (popt->flags & TCC_OPTION_NOSEP)) {
9866 optarg = r1;
9867 } else {
9868 if (optind >= argc)
9869 error("argument to '%s' is missing", r);
9870 optarg = argv[optind++];
9872 } else {
9873 if (*r1 != '\0')
9874 goto show_help;
9875 optarg = NULL;
9878 switch(popt->index) {
9879 case TCC_OPTION_HELP:
9880 show_help:
9881 help();
9882 exit(1);
9883 case TCC_OPTION_I:
9884 if (tcc_add_include_path(s, optarg) < 0)
9885 error("too many include paths");
9886 break;
9887 case TCC_OPTION_D:
9889 char *sym, *value;
9890 sym = (char *)optarg;
9891 value = strchr(sym, '=');
9892 if (value) {
9893 *value = '\0';
9894 value++;
9896 tcc_define_symbol(s, sym, value);
9898 break;
9899 case TCC_OPTION_U:
9900 tcc_undefine_symbol(s, optarg);
9901 break;
9902 case TCC_OPTION_L:
9903 tcc_add_library_path(s, optarg);
9904 break;
9905 case TCC_OPTION_B:
9906 /* set tcc utilities path (mainly for tcc development) */
9907 tcc_lib_path = optarg;
9908 break;
9909 case TCC_OPTION_l:
9910 dynarray_add((void ***)&files, &nb_files, r);
9911 nb_libraries++;
9912 break;
9913 case TCC_OPTION_bench:
9914 do_bench = 1;
9915 break;
9916 case TCC_OPTION_bt:
9917 num_callers = atoi(optarg);
9918 break;
9919 #ifdef CONFIG_TCC_BCHECK
9920 case TCC_OPTION_b:
9921 do_bounds_check = 1;
9922 do_debug = 1;
9923 break;
9924 #endif
9925 case TCC_OPTION_g:
9926 do_debug = 1;
9927 break;
9928 case TCC_OPTION_c:
9929 multiple_files = 1;
9930 output_type = TCC_OUTPUT_OBJ;
9931 break;
9932 case TCC_OPTION_static:
9933 s->static_link = 1;
9934 break;
9935 case TCC_OPTION_shared:
9936 output_type = TCC_OUTPUT_DLL;
9937 break;
9938 case TCC_OPTION_o:
9939 multiple_files = 1;
9940 outfile = optarg;
9941 break;
9942 case TCC_OPTION_r:
9943 /* generate a .o merging several output files */
9944 reloc_output = 1;
9945 output_type = TCC_OUTPUT_OBJ;
9946 break;
9947 case TCC_OPTION_nostdinc:
9948 s->nostdinc = 1;
9949 break;
9950 case TCC_OPTION_nostdlib:
9951 s->nostdlib = 1;
9952 break;
9953 case TCC_OPTION_print_search_dirs:
9954 print_search_dirs = 1;
9955 break;
9956 case TCC_OPTION_run:
9958 int argc1;
9959 char **argv1;
9960 argc1 = expand_args(&argv1, optarg);
9961 if (argc1 > 0) {
9962 parse_args(s, argc1, argv1);
9964 multiple_files = 0;
9965 output_type = TCC_OUTPUT_MEMORY;
9967 break;
9968 case TCC_OPTION_v:
9969 printf("tcc version %s\n", TCC_VERSION);
9970 exit(0);
9971 case TCC_OPTION_W:
9973 const char *p = optarg;
9974 int value;
9975 value = 1;
9976 if (p[0] == 'n' && p[1] == 'o' && p[2] == '-') {
9977 p += 2;
9978 value = 0;
9980 if (tcc_set_warning(s, p, value) < 0 && s->warn_unsupported)
9981 goto unsupported_option;
9983 break;
9984 case TCC_OPTION_w:
9985 s->warn_none = 1;
9986 break;
9987 case TCC_OPTION_rdynamic:
9988 s->rdynamic = 1;
9989 break;
9990 default:
9991 if (s->warn_unsupported) {
9992 unsupported_option:
9993 warning("unsupported option '%s'", r);
9995 break;
9999 return optind;
10002 int main(int argc, char **argv)
10004 int i;
10005 TCCState *s;
10006 int nb_objfiles, ret, optind;
10007 char objfilename[1024];
10008 int64_t start_time = 0;
10010 s = tcc_new();
10011 output_type = TCC_OUTPUT_EXE;
10012 outfile = NULL;
10013 multiple_files = 1;
10014 files = NULL;
10015 nb_files = 0;
10016 nb_libraries = 0;
10017 reloc_output = 0;
10018 print_search_dirs = 0;
10020 optind = parse_args(s, argc - 1, argv + 1) + 1;
10022 if (print_search_dirs) {
10023 /* enough for Linux kernel */
10024 printf("install: %s/\n", tcc_lib_path);
10025 return 0;
10028 nb_objfiles = nb_files - nb_libraries;
10030 /* if outfile provided without other options, we output an
10031 executable */
10032 if (outfile && output_type == TCC_OUTPUT_MEMORY)
10033 output_type = TCC_OUTPUT_EXE;
10035 /* check -c consistency : only single file handled. XXX: checks file type */
10036 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
10037 /* accepts only a single input file */
10038 if (nb_objfiles != 1)
10039 error("cannot specify multiple files with -c");
10040 if (nb_libraries != 0)
10041 error("cannot specify libraries with -c");
10044 /* compute default outfile name */
10045 if (output_type != TCC_OUTPUT_MEMORY && !outfile) {
10046 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
10047 char *ext;
10048 /* strip path */
10049 pstrcpy(objfilename, sizeof(objfilename) - 1,
10050 tcc_basename(files[0]));
10051 /* add .o extension */
10052 ext = strrchr(objfilename, '.');
10053 if (!ext)
10054 goto default_outfile;
10055 strcpy(ext + 1, "o");
10056 } else {
10057 default_outfile:
10058 pstrcpy(objfilename, sizeof(objfilename), "a.out");
10060 outfile = objfilename;
10063 if (do_bench) {
10064 start_time = getclock_us();
10067 tcc_set_output_type(s, output_type);
10069 /* compile or add each files or library */
10070 for(i = 0;i < nb_files; i++) {
10071 const char *filename;
10073 filename = files[i];
10074 if (filename[0] == '-') {
10075 if (tcc_add_library(s, filename + 2) < 0)
10076 error("cannot find %s", filename);
10077 } else {
10078 if (tcc_add_file(s, filename) < 0) {
10079 ret = 1;
10080 goto the_end;
10085 /* free all files */
10086 tcc_free(files);
10088 if (do_bench) {
10089 double total_time;
10090 total_time = (double)(getclock_us() - start_time) / 1000000.0;
10091 if (total_time < 0.001)
10092 total_time = 0.001;
10093 if (total_bytes < 1)
10094 total_bytes = 1;
10095 printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
10096 tok_ident - TOK_IDENT, total_lines, total_bytes,
10097 total_time, (int)(total_lines / total_time),
10098 total_bytes / total_time / 1000000.0);
10101 if (s->output_type != TCC_OUTPUT_MEMORY) {
10102 tcc_output_file(s, outfile);
10103 ret = 0;
10104 } else {
10105 ret = tcc_run(s, argc - optind, argv + optind);
10107 the_end:
10108 /* XXX: cannot do it with bound checking because of the malloc hooks */
10109 if (!do_bounds_check)
10110 tcc_delete(s);
10112 #ifdef MEM_DEBUG
10113 if (do_bench) {
10114 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size, mem_max_size);
10116 #endif
10117 return ret;
10120 #endif