build of cross compilers is optional - win32 merge
[tinycc/miki.git] / tcc.c
blob85bf503799070be138a5392cda330fae85a10117
1 /*
2 * TCC - Tiny C Compiler
3 *
4 * Copyright (c) 2001-2004 Fabrice Bellard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #define _GNU_SOURCE
21 #include "config.h"
23 #ifdef CONFIG_TCCBOOT
25 #include "tccboot.h"
26 #define CONFIG_TCC_STATIC
28 #else
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <stdarg.h>
33 #include <string.h>
34 #include <errno.h>
35 #include <math.h>
36 #include <unistd.h>
37 #include <signal.h>
38 #include <fcntl.h>
39 #include <setjmp.h>
40 #include <time.h>
41 #ifdef WIN32
42 #include <sys/timeb.h>
43 #endif
44 #ifndef WIN32
45 #include <sys/time.h>
46 #include <sys/ucontext.h>
47 #endif
49 #endif /* !CONFIG_TCCBOOT */
51 #include "elf.h"
52 #include "stab.h"
54 #ifndef O_BINARY
55 #define O_BINARY 0
56 #endif
58 #include "libtcc.h"
60 /* parser debug */
61 //#define PARSE_DEBUG
62 /* preprocessor debug */
63 //#define PP_DEBUG
64 /* include file debug */
65 //#define INC_DEBUG
67 //#define MEM_DEBUG
69 /* assembler debug */
70 //#define ASM_DEBUG
72 /* target selection */
73 //#define TCC_TARGET_I386 /* i386 code generator */
74 //#define TCC_TARGET_ARM /* ARMv4 code generator */
75 //#define TCC_TARGET_C67 /* TMS320C67xx code generator */
77 /* default target is I386 */
78 #if !defined(TCC_TARGET_I386) && !defined(TCC_TARGET_ARM) && \
79 !defined(TCC_TARGET_C67)
80 #define TCC_TARGET_I386
81 #endif
83 #if !defined(WIN32) && !defined(TCC_UCLIBC) && !defined(TCC_TARGET_ARM) && \
84 !defined(TCC_TARGET_C67)
85 #define CONFIG_TCC_BCHECK /* enable bound checking code */
86 #endif
88 #if defined(WIN32) && !defined(TCC_TARGET_PE)
89 #define CONFIG_TCC_STATIC
90 #endif
92 /* define it to include assembler support */
93 #if !defined(TCC_TARGET_ARM) && !defined(TCC_TARGET_C67)
94 #define CONFIG_TCC_ASM
95 #endif
97 /* object format selection */
98 #if defined(TCC_TARGET_C67)
99 #define TCC_TARGET_COFF
100 #endif
102 #define FALSE 0
103 #define false 0
104 #define TRUE 1
105 #define true 1
106 typedef int BOOL;
108 /* path to find crt1.o, crti.o and crtn.o. Only needed when generating
109 executables or dlls */
110 #define CONFIG_TCC_CRT_PREFIX "/usr/lib"
112 #define INCLUDE_STACK_SIZE 32
113 #define IFDEF_STACK_SIZE 64
114 #define VSTACK_SIZE 256
115 #define STRING_MAX_SIZE 1024
116 #define PACK_STACK_SIZE 8
118 #define TOK_HASH_SIZE 8192 /* must be a power of two */
119 #define TOK_ALLOC_INCR 512 /* must be a power of two */
120 #define TOK_MAX_SIZE 4 /* token max size in int unit when stored in string */
122 /* token symbol management */
123 typedef struct TokenSym {
124 struct TokenSym *hash_next;
125 struct Sym *sym_define; /* direct pointer to define */
126 struct Sym *sym_label; /* direct pointer to label */
127 struct Sym *sym_struct; /* direct pointer to structure */
128 struct Sym *sym_identifier; /* direct pointer to identifier */
129 int tok; /* token number */
130 int len;
131 char str[1];
132 } TokenSym;
134 typedef struct CString {
135 int size; /* size in bytes */
136 void *data; /* either 'char *' or 'int *' */
137 int size_allocated;
138 void *data_allocated; /* if non NULL, data has been malloced */
139 } CString;
141 /* type definition */
142 typedef struct CType {
143 int t;
144 struct Sym *ref;
145 } CType;
147 /* constant value */
148 typedef union CValue {
149 long double ld;
150 double d;
151 float f;
152 int i;
153 unsigned int ui;
154 unsigned int ul; /* address (should be unsigned long on 64 bit cpu) */
155 long long ll;
156 unsigned long long ull;
157 struct CString *cstr;
158 void *ptr;
159 int tab[1];
160 } CValue;
162 /* value on stack */
163 typedef struct SValue {
164 CType type; /* type */
165 unsigned short r; /* register + flags */
166 unsigned short r2; /* second register, used for 'long long'
167 type. If not used, set to VT_CONST */
168 CValue c; /* constant, if VT_CONST */
169 struct Sym *sym; /* symbol, if (VT_SYM | VT_CONST) */
170 } SValue;
172 /* symbol management */
173 typedef struct Sym {
174 int v; /* symbol token */
175 int r; /* associated register */
176 int c; /* associated number */
177 CType type; /* associated type */
178 struct Sym *next; /* next related symbol */
179 struct Sym *prev; /* prev symbol in stack */
180 struct Sym *prev_tok; /* previous symbol for this token */
181 } Sym;
183 /* section definition */
184 /* XXX: use directly ELF structure for parameters ? */
185 /* special flag to indicate that the section should not be linked to
186 the other ones */
187 #define SHF_PRIVATE 0x80000000
189 typedef struct Section {
190 unsigned long data_offset; /* current data offset */
191 unsigned char *data; /* section data */
192 unsigned long data_allocated; /* used for realloc() handling */
193 int sh_name; /* elf section name (only used during output) */
194 int sh_num; /* elf section number */
195 int sh_type; /* elf section type */
196 int sh_flags; /* elf section flags */
197 int sh_info; /* elf section info */
198 int sh_addralign; /* elf section alignment */
199 int sh_entsize; /* elf entry size */
200 unsigned long sh_size; /* section size (only used during output) */
201 unsigned long sh_addr; /* address at which the section is relocated */
202 unsigned long sh_offset; /* address at which the section is relocated */
203 int nb_hashed_syms; /* used to resize the hash table */
204 struct Section *link; /* link to another section */
205 struct Section *reloc; /* corresponding section for relocation, if any */
206 struct Section *hash; /* hash table for symbols */
207 struct Section *next;
208 char name[1]; /* section name */
209 } Section;
211 typedef struct DLLReference {
212 int level;
213 char name[1];
214 } DLLReference;
216 /* GNUC attribute definition */
217 typedef struct AttributeDef {
218 int aligned;
219 int packed;
220 Section *section;
221 unsigned char func_call; /* FUNC_CDECL, FUNC_STDCALL, FUNC_FASTCALLx */
222 unsigned char dllexport;
223 } AttributeDef;
225 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
226 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
227 #define SYM_FIRST_ANOM 0x10000000 /* first anonymous sym */
229 /* stored in 'Sym.c' field */
230 #define FUNC_NEW 1 /* ansi function prototype */
231 #define FUNC_OLD 2 /* old function prototype */
232 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
234 /* stored in 'Sym.r' field */
235 #define FUNC_CDECL 0 /* standard c call */
236 #define FUNC_STDCALL 1 /* pascal c call */
237 #define FUNC_FASTCALL1 2 /* first param in %eax */
238 #define FUNC_FASTCALL2 3 /* first parameters in %eax, %edx */
239 #define FUNC_FASTCALL3 4 /* first parameter in %eax, %edx, %ecx */
241 /* field 'Sym.t' for macros */
242 #define MACRO_OBJ 0 /* object like macro */
243 #define MACRO_FUNC 1 /* function like macro */
245 /* field 'Sym.r' for C labels */
246 #define LABEL_DEFINED 0 /* label is defined */
247 #define LABEL_FORWARD 1 /* label is forward defined */
248 #define LABEL_DECLARED 2 /* label is declared but never used */
250 /* type_decl() types */
251 #define TYPE_ABSTRACT 1 /* type without variable */
252 #define TYPE_DIRECT 2 /* type with variable */
254 #define IO_BUF_SIZE 8192
256 typedef struct BufferedFile {
257 uint8_t *buf_ptr;
258 uint8_t *buf_end;
259 int fd;
260 int line_num; /* current line number - here to simplify code */
261 int ifndef_macro; /* #ifndef macro / #endif search */
262 int ifndef_macro_saved; /* saved ifndef_macro */
263 int *ifdef_stack_ptr; /* ifdef_stack value at the start of the file */
264 char inc_type; /* type of include */
265 char inc_filename[512]; /* filename specified by the user */
266 char filename[1024]; /* current filename - here to simplify code */
267 unsigned char buffer[IO_BUF_SIZE + 1]; /* extra size for CH_EOB char */
268 } BufferedFile;
270 #define CH_EOB '\\' /* end of buffer or '\0' char in file */
271 #define CH_EOF (-1) /* end of file */
273 /* parsing state (used to save parser state to reparse part of the
274 source several times) */
275 typedef struct ParseState {
276 int *macro_ptr;
277 int line_num;
278 int tok;
279 CValue tokc;
280 } ParseState;
282 /* used to record tokens */
283 typedef struct TokenString {
284 int *str;
285 int len;
286 int allocated_len;
287 int last_line_num;
288 } TokenString;
290 /* include file cache, used to find files faster and also to eliminate
291 inclusion if the include file is protected by #ifndef ... #endif */
292 typedef struct CachedInclude {
293 int ifndef_macro;
294 int hash_next; /* -1 if none */
295 char type; /* '"' or '>' to give include type */
296 char filename[1]; /* path specified in #include */
297 } CachedInclude;
299 #define CACHED_INCLUDES_HASH_SIZE 512
301 /* parser */
302 static struct BufferedFile *file;
303 static int ch, tok;
304 static CValue tokc;
305 static CString tokcstr; /* current parsed string, if any */
306 /* additional informations about token */
307 static int tok_flags;
308 #define TOK_FLAG_BOL 0x0001 /* beginning of line before */
309 #define TOK_FLAG_BOF 0x0002 /* beginning of file before */
310 #define TOK_FLAG_ENDIF 0x0004 /* a endif was found matching starting #ifdef */
312 static int *macro_ptr, *macro_ptr_allocated;
313 static int *unget_saved_macro_ptr;
314 static int unget_saved_buffer[TOK_MAX_SIZE + 1];
315 static int unget_buffer_enabled;
316 static int parse_flags;
317 #define PARSE_FLAG_PREPROCESS 0x0001 /* activate preprocessing */
318 #define PARSE_FLAG_TOK_NUM 0x0002 /* return numbers instead of TOK_PPNUM */
319 #define PARSE_FLAG_LINEFEED 0x0004 /* line feed is returned as a
320 token. line feed is also
321 returned at eof */
322 #define PARSE_FLAG_ASM_COMMENTS 0x0008 /* '#' can be used for line comment */
324 static Section *text_section, *data_section, *bss_section; /* predefined sections */
325 static Section *cur_text_section; /* current section where function code is
326 generated */
327 #ifdef CONFIG_TCC_ASM
328 static Section *last_text_section; /* to handle .previous asm directive */
329 #endif
330 /* bound check related sections */
331 static Section *bounds_section; /* contains global data bound description */
332 static Section *lbounds_section; /* contains local data bound description */
333 /* symbol sections */
334 static Section *symtab_section, *strtab_section;
336 /* debug sections */
337 static Section *stab_section, *stabstr_section;
339 /* loc : local variable index
340 ind : output code index
341 rsym: return symbol
342 anon_sym: anonymous symbol index
344 static int rsym, anon_sym, ind, loc;
345 /* expression generation modifiers */
346 static int const_wanted; /* true if constant wanted */
347 static int nocode_wanted; /* true if no code generation wanted for an expression */
348 static int global_expr; /* true if compound literals must be allocated
349 globally (used during initializers parsing */
350 static CType func_vt; /* current function return type (used by return
351 instruction) */
352 static int func_vc;
353 static int last_line_num, last_ind, func_ind; /* debug last line number and pc */
354 static int tok_ident;
355 static TokenSym **table_ident;
356 static TokenSym *hash_ident[TOK_HASH_SIZE];
357 static char token_buf[STRING_MAX_SIZE + 1];
358 static char *funcname;
359 static Sym *global_stack, *local_stack;
360 static Sym *define_stack;
361 static Sym *global_label_stack, *local_label_stack;
362 /* symbol allocator */
363 #define SYM_POOL_NB (8192 / sizeof(Sym))
364 static Sym *sym_free_first;
366 static SValue vstack[VSTACK_SIZE], *vtop;
367 /* some predefined types */
368 static CType char_pointer_type, func_old_type, int_type;
369 /* true if isid(c) || isnum(c) */
370 static unsigned char isidnum_table[256];
372 /* compile with debug symbol (and use them if error during execution) */
373 static int do_debug = 0;
375 /* compile with built-in memory and bounds checker */
376 static int do_bounds_check = 0;
378 /* display benchmark infos */
379 #if !defined(LIBTCC)
380 static int do_bench = 0;
381 #endif
382 static int total_lines;
383 static int total_bytes;
385 /* use GNU C extensions */
386 static int gnu_ext = 1;
388 /* use Tiny C extensions */
389 static int tcc_ext = 1;
391 /* max number of callers shown if error */
392 static int num_callers = 6;
393 static const char **rt_bound_error_msg;
395 /* XXX: get rid of this ASAP */
396 static struct TCCState *tcc_state;
398 /* give the path of the tcc libraries */
399 static const char *tcc_lib_path = CONFIG_TCCDIR;
401 struct TCCState {
402 int output_type;
404 BufferedFile **include_stack_ptr;
405 int *ifdef_stack_ptr;
407 /* include file handling */
408 char **include_paths;
409 int nb_include_paths;
410 char **sysinclude_paths;
411 int nb_sysinclude_paths;
412 CachedInclude **cached_includes;
413 int nb_cached_includes;
415 char **library_paths;
416 int nb_library_paths;
418 /* array of all loaded dlls (including those referenced by loaded
419 dlls) */
420 DLLReference **loaded_dlls;
421 int nb_loaded_dlls;
423 /* sections */
424 Section **sections;
425 int nb_sections; /* number of sections, including first dummy section */
427 /* got handling */
428 Section *got;
429 Section *plt;
430 unsigned long *got_offsets;
431 int nb_got_offsets;
432 /* give the correspondance from symtab indexes to dynsym indexes */
433 int *symtab_to_dynsym;
435 /* temporary dynamic symbol sections (for dll loading) */
436 Section *dynsymtab_section;
437 /* exported dynamic symbol section */
438 Section *dynsym;
440 int nostdinc; /* if true, no standard headers are added */
441 int nostdlib; /* if true, no standard libraries are added */
443 int nocommon; /* if true, do not use common symbols for .bss data */
445 /* if true, static linking is performed */
446 int static_link;
448 /* if true, all symbols are exported */
449 int rdynamic;
451 /* if true, only link in referenced objects from archive */
452 int alacarte_link;
454 /* address of text section */
455 unsigned long text_addr;
456 int has_text_addr;
458 /* output format, see TCC_OUTPUT_FORMAT_xxx */
459 int output_format;
461 /* C language options */
462 int char_is_unsigned;
464 /* warning switches */
465 int warn_write_strings;
466 int warn_unsupported;
467 int warn_error;
468 int warn_none;
469 int warn_implicit_function_declaration;
471 /* error handling */
472 void *error_opaque;
473 void (*error_func)(void *opaque, const char *msg);
474 int error_set_jmp_enabled;
475 jmp_buf error_jmp_buf;
476 int nb_errors;
478 /* tiny assembler state */
479 Sym *asm_labels;
481 /* see include_stack_ptr */
482 BufferedFile *include_stack[INCLUDE_STACK_SIZE];
484 /* see ifdef_stack_ptr */
485 int ifdef_stack[IFDEF_STACK_SIZE];
487 /* see cached_includes */
488 int cached_includes_hash[CACHED_INCLUDES_HASH_SIZE];
490 /* pack stack */
491 int pack_stack[PACK_STACK_SIZE];
492 int *pack_stack_ptr;
495 /* The current value can be: */
496 #define VT_VALMASK 0x00ff
497 #define VT_CONST 0x00f0 /* constant in vc
498 (must be first non register value) */
499 #define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */
500 #define VT_LOCAL 0x00f2 /* offset on stack */
501 #define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */
502 #define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */
503 #define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */
504 #define VT_LVAL 0x0100 /* var is an lvalue */
505 #define VT_SYM 0x0200 /* a symbol value is added */
506 #define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for
507 char/short stored in integer registers) */
508 #define VT_MUSTBOUND 0x0800 /* bound checking must be done before
509 dereferencing value */
510 #define VT_BOUNDED 0x8000 /* value is bounded. The address of the
511 bounding function call point is in vc */
512 #define VT_LVAL_BYTE 0x1000 /* lvalue is a byte */
513 #define VT_LVAL_SHORT 0x2000 /* lvalue is a short */
514 #define VT_LVAL_UNSIGNED 0x4000 /* lvalue is unsigned */
515 #define VT_LVAL_TYPE (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)
517 /* types */
518 #define VT_INT 0 /* integer type */
519 #define VT_BYTE 1 /* signed byte type */
520 #define VT_SHORT 2 /* short type */
521 #define VT_VOID 3 /* void type */
522 #define VT_PTR 4 /* pointer */
523 #define VT_ENUM 5 /* enum definition */
524 #define VT_FUNC 6 /* function type */
525 #define VT_STRUCT 7 /* struct/union definition */
526 #define VT_FLOAT 8 /* IEEE float */
527 #define VT_DOUBLE 9 /* IEEE double */
528 #define VT_LDOUBLE 10 /* IEEE long double */
529 #define VT_BOOL 11 /* ISOC99 boolean type */
530 #define VT_LLONG 12 /* 64 bit integer */
531 #define VT_LONG 13 /* long integer (NEVER USED as type, only
532 during parsing) */
533 #define VT_BTYPE 0x000f /* mask for basic type */
534 #define VT_UNSIGNED 0x0010 /* unsigned type */
535 #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
536 #define VT_BITFIELD 0x0040 /* bitfield modifier */
537 #define VT_CONSTANT 0x0800 /* const modifier */
538 #define VT_VOLATILE 0x1000 /* volatile modifier */
539 #define VT_SIGNED 0x2000 /* signed type */
541 /* storage */
542 #define VT_EXTERN 0x00000080 /* extern definition */
543 #define VT_STATIC 0x00000100 /* static variable */
544 #define VT_TYPEDEF 0x00000200 /* typedef definition */
545 #define VT_INLINE 0x00000400 /* inline definition */
547 #define VT_STRUCT_SHIFT 16 /* shift for bitfield shift values */
549 /* type mask (except storage) */
550 #define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE)
551 #define VT_TYPE (~(VT_STORAGE))
553 /* token values */
555 /* warning: the following compare tokens depend on i386 asm code */
556 #define TOK_ULT 0x92
557 #define TOK_UGE 0x93
558 #define TOK_EQ 0x94
559 #define TOK_NE 0x95
560 #define TOK_ULE 0x96
561 #define TOK_UGT 0x97
562 #define TOK_LT 0x9c
563 #define TOK_GE 0x9d
564 #define TOK_LE 0x9e
565 #define TOK_GT 0x9f
567 #define TOK_LAND 0xa0
568 #define TOK_LOR 0xa1
570 #define TOK_DEC 0xa2
571 #define TOK_MID 0xa3 /* inc/dec, to void constant */
572 #define TOK_INC 0xa4
573 #define TOK_UDIV 0xb0 /* unsigned division */
574 #define TOK_UMOD 0xb1 /* unsigned modulo */
575 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
576 #define TOK_CINT 0xb3 /* number in tokc */
577 #define TOK_CCHAR 0xb4 /* char constant in tokc */
578 #define TOK_STR 0xb5 /* pointer to string in tokc */
579 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
580 #define TOK_LCHAR 0xb7
581 #define TOK_LSTR 0xb8
582 #define TOK_CFLOAT 0xb9 /* float constant */
583 #define TOK_LINENUM 0xba /* line number info */
584 #define TOK_CDOUBLE 0xc0 /* double constant */
585 #define TOK_CLDOUBLE 0xc1 /* long double constant */
586 #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
587 #define TOK_ADDC1 0xc3 /* add with carry generation */
588 #define TOK_ADDC2 0xc4 /* add with carry use */
589 #define TOK_SUBC1 0xc5 /* add with carry generation */
590 #define TOK_SUBC2 0xc6 /* add with carry use */
591 #define TOK_CUINT 0xc8 /* unsigned int constant */
592 #define TOK_CLLONG 0xc9 /* long long constant */
593 #define TOK_CULLONG 0xca /* unsigned long long constant */
594 #define TOK_ARROW 0xcb
595 #define TOK_DOTS 0xcc /* three dots */
596 #define TOK_SHR 0xcd /* unsigned shift right */
597 #define TOK_PPNUM 0xce /* preprocessor number */
599 #define TOK_SHL 0x01 /* shift left */
600 #define TOK_SAR 0x02 /* signed shift right */
602 /* assignement operators : normal operator or 0x80 */
603 #define TOK_A_MOD 0xa5
604 #define TOK_A_AND 0xa6
605 #define TOK_A_MUL 0xaa
606 #define TOK_A_ADD 0xab
607 #define TOK_A_SUB 0xad
608 #define TOK_A_DIV 0xaf
609 #define TOK_A_XOR 0xde
610 #define TOK_A_OR 0xfc
611 #define TOK_A_SHL 0x81
612 #define TOK_A_SAR 0x82
614 #ifndef offsetof
615 #define offsetof(type, field) ((size_t) &((type *)0)->field)
616 #endif
618 #ifndef countof
619 #define countof(tab) (sizeof(tab) / sizeof((tab)[0]))
620 #endif
622 /* WARNING: the content of this string encodes token numbers */
623 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";
625 #define TOK_EOF (-1) /* end of file */
626 #define TOK_LINEFEED 10 /* line feed */
628 /* all identificators and strings have token above that */
629 #define TOK_IDENT 256
631 /* only used for i386 asm opcodes definitions */
632 #define DEF_ASM(x) DEF(TOK_ASM_ ## x, #x)
634 #define DEF_BWL(x) \
635 DEF(TOK_ASM_ ## x ## b, #x "b") \
636 DEF(TOK_ASM_ ## x ## w, #x "w") \
637 DEF(TOK_ASM_ ## x ## l, #x "l") \
638 DEF(TOK_ASM_ ## x, #x)
640 #define DEF_WL(x) \
641 DEF(TOK_ASM_ ## x ## w, #x "w") \
642 DEF(TOK_ASM_ ## x ## l, #x "l") \
643 DEF(TOK_ASM_ ## x, #x)
645 #define DEF_FP1(x) \
646 DEF(TOK_ASM_ ## f ## x ## s, "f" #x "s") \
647 DEF(TOK_ASM_ ## fi ## x ## l, "fi" #x "l") \
648 DEF(TOK_ASM_ ## f ## x ## l, "f" #x "l") \
649 DEF(TOK_ASM_ ## fi ## x ## s, "fi" #x "s")
651 #define DEF_FP(x) \
652 DEF(TOK_ASM_ ## f ## x, "f" #x ) \
653 DEF(TOK_ASM_ ## f ## x ## p, "f" #x "p") \
654 DEF_FP1(x)
656 #define DEF_ASMTEST(x) \
657 DEF_ASM(x ## o) \
658 DEF_ASM(x ## no) \
659 DEF_ASM(x ## b) \
660 DEF_ASM(x ## c) \
661 DEF_ASM(x ## nae) \
662 DEF_ASM(x ## nb) \
663 DEF_ASM(x ## nc) \
664 DEF_ASM(x ## ae) \
665 DEF_ASM(x ## e) \
666 DEF_ASM(x ## z) \
667 DEF_ASM(x ## ne) \
668 DEF_ASM(x ## nz) \
669 DEF_ASM(x ## be) \
670 DEF_ASM(x ## na) \
671 DEF_ASM(x ## nbe) \
672 DEF_ASM(x ## a) \
673 DEF_ASM(x ## s) \
674 DEF_ASM(x ## ns) \
675 DEF_ASM(x ## p) \
676 DEF_ASM(x ## pe) \
677 DEF_ASM(x ## np) \
678 DEF_ASM(x ## po) \
679 DEF_ASM(x ## l) \
680 DEF_ASM(x ## nge) \
681 DEF_ASM(x ## nl) \
682 DEF_ASM(x ## ge) \
683 DEF_ASM(x ## le) \
684 DEF_ASM(x ## ng) \
685 DEF_ASM(x ## nle) \
686 DEF_ASM(x ## g)
688 #define TOK_ASM_int TOK_INT
690 enum tcc_token {
691 TOK_LAST = TOK_IDENT - 1,
692 #define DEF(id, str) id,
693 #include "tcctok.h"
694 #undef DEF
697 static const char tcc_keywords[] =
698 #define DEF(id, str) str "\0"
699 #include "tcctok.h"
700 #undef DEF
703 #define TOK_UIDENT TOK_DEFINE
705 #ifdef WIN32
706 int __stdcall GetModuleFileNameA(void *, char *, int);
707 void *__stdcall GetProcAddress(void *, const char *);
708 void *__stdcall GetModuleHandleA(const char *);
709 void *__stdcall LoadLibraryA(const char *);
710 int __stdcall FreeConsole(void);
712 #define snprintf _snprintf
713 #define vsnprintf _vsnprintf
714 #endif
716 #if defined(WIN32) || defined(TCC_UCLIBC) || defined(__FreeBSD__)
717 /* currently incorrect */
718 long double strtold(const char *nptr, char **endptr)
720 return (long double)strtod(nptr, endptr);
722 float strtof(const char *nptr, char **endptr)
724 return (float)strtod(nptr, endptr);
726 #else
727 /* XXX: need to define this to use them in non ISOC99 context */
728 extern float strtof (const char *__nptr, char **__endptr);
729 extern long double strtold (const char *__nptr, char **__endptr);
730 #endif
732 static char *pstrcpy(char *buf, int buf_size, const char *s);
733 static char *pstrcat(char *buf, int buf_size, const char *s);
734 static const char *tcc_basename(const char *name);
736 static void next(void);
737 static void next_nomacro(void);
738 static void parse_expr_type(CType *type);
739 static void expr_type(CType *type);
740 static void unary_type(CType *type);
741 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
742 int case_reg, int is_expr);
743 static int expr_const(void);
744 static void expr_eq(void);
745 static void gexpr(void);
746 static void gen_inline_functions(void);
747 static void decl(int l);
748 static void decl_initializer(CType *type, Section *sec, unsigned long c,
749 int first, int size_only);
750 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
751 int has_init, int v, int scope);
752 int gv(int rc);
753 void gv2(int rc1, int rc2);
754 void move_reg(int r, int s);
755 void save_regs(int n);
756 void save_reg(int r);
757 void vpop(void);
758 void vswap(void);
759 void vdup(void);
760 int get_reg(int rc);
761 int get_reg_ex(int rc,int rc2);
763 static void macro_subst(TokenString *tok_str, Sym **nested_list,
764 const int *macro_str, int can_read_stream);
765 void gen_op(int op);
766 void force_charshort_cast(int t);
767 static void gen_cast(CType *type);
768 void vstore(void);
769 static Sym *sym_find(int v);
770 static Sym *sym_push(int v, CType *type, int r, int c);
772 /* type handling */
773 static int type_size(CType *type, int *a);
774 static inline CType *pointed_type(CType *type);
775 static int pointed_size(CType *type);
776 static int lvalue_type(int t);
777 static int parse_btype(CType *type, AttributeDef *ad);
778 static void type_decl(CType *type, AttributeDef *ad, int *v, int td);
779 static int is_compatible_types(CType *type1, CType *type2);
781 int ieee_finite(double d);
782 void error(const char *fmt, ...);
783 void vpushi(int v);
784 void vrott(int n);
785 void vnrott(int n);
786 void lexpand_nr(void);
787 static void vpush_global_sym(CType *type, int v);
788 void vset(CType *type, int r, int v);
789 void type_to_str(char *buf, int buf_size,
790 CType *type, const char *varstr);
791 char *get_tok_str(int v, CValue *cv);
792 static Sym *get_sym_ref(CType *type, Section *sec,
793 unsigned long offset, unsigned long size);
794 static Sym *external_global_sym(int v, CType *type, int r);
796 /* section generation */
797 static void section_realloc(Section *sec, unsigned long new_size);
798 static void *section_ptr_add(Section *sec, unsigned long size);
799 static void put_extern_sym(Sym *sym, Section *section,
800 unsigned long value, unsigned long size);
801 static void greloc(Section *s, Sym *sym, unsigned long addr, int type);
802 static int put_elf_str(Section *s, const char *sym);
803 static int put_elf_sym(Section *s,
804 unsigned long value, unsigned long size,
805 int info, int other, int shndx, const char *name);
806 static int add_elf_sym(Section *s, unsigned long value, unsigned long size,
807 int info, int other, int sh_num, const char *name);
808 static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
809 int type, int symbol);
810 static void put_stabs(const char *str, int type, int other, int desc,
811 unsigned long value);
812 static void put_stabs_r(const char *str, int type, int other, int desc,
813 unsigned long value, Section *sec, int sym_index);
814 static void put_stabn(int type, int other, int desc, int value);
815 static void put_stabd(int type, int other, int desc);
816 static int tcc_add_dll(TCCState *s, const char *filename, int flags);
818 #define AFF_PRINT_ERROR 0x0001 /* print error if file not found */
819 #define AFF_REFERENCED_DLL 0x0002 /* load a referenced dll from another dll */
820 static int tcc_add_file_internal(TCCState *s, const char *filename, int flags);
822 /* tcccoff.c */
823 int tcc_output_coff(TCCState *s1, FILE *f);
825 /* tccpe.c */
826 void *resolve_sym(TCCState *s1, const char *sym, int type);
827 int pe_load_def_file(struct TCCState *s1, FILE *fp);
828 void pe_setup_paths(struct TCCState *s1, int *p_output_type, const char **p_outfile, char *first_file);
829 unsigned long pe_add_runtime(struct TCCState *s1);
830 int tcc_output_pe(struct TCCState *s1, const char *filename);
832 /* tccasm.c */
834 #ifdef CONFIG_TCC_ASM
836 typedef struct ExprValue {
837 uint32_t v;
838 Sym *sym;
839 } ExprValue;
841 #define MAX_ASM_OPERANDS 30
843 typedef struct ASMOperand {
844 int id; /* GCC 3 optionnal identifier (0 if number only supported */
845 char *constraint;
846 char asm_str[16]; /* computed asm string for operand */
847 SValue *vt; /* C value of the expression */
848 int ref_index; /* if >= 0, gives reference to a output constraint */
849 int input_index; /* if >= 0, gives reference to an input constraint */
850 int priority; /* priority, used to assign registers */
851 int reg; /* if >= 0, register number used for this operand */
852 int is_llong; /* true if double register value */
853 int is_memory; /* true if memory operand */
854 int is_rw; /* for '+' modifier */
855 } ASMOperand;
857 static void asm_expr(TCCState *s1, ExprValue *pe);
858 static int asm_int_expr(TCCState *s1);
859 static int find_constraint(ASMOperand *operands, int nb_operands,
860 const char *name, const char **pp);
862 static int tcc_assemble(TCCState *s1, int do_preprocess);
864 #endif
866 static void asm_instr(void);
867 static void asm_global_instr(void);
869 /* true if float/double/long double type */
870 static inline int is_float(int t)
872 int bt;
873 bt = t & VT_BTYPE;
874 return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT;
877 #ifdef TCC_TARGET_I386
878 #include "i386-gen.c"
879 #endif
881 #ifdef TCC_TARGET_ARM
882 #include "arm-gen.c"
883 #endif
885 #ifdef TCC_TARGET_C67
886 #include "c67-gen.c"
887 #endif
889 #ifdef CONFIG_TCC_STATIC
891 #define RTLD_LAZY 0x001
892 #define RTLD_NOW 0x002
893 #define RTLD_GLOBAL 0x100
894 #define RTLD_DEFAULT NULL
896 /* dummy function for profiling */
897 void *dlopen(const char *filename, int flag)
899 return NULL;
902 const char *dlerror(void)
904 return "error";
907 typedef struct TCCSyms {
908 char *str;
909 void *ptr;
910 } TCCSyms;
912 #define TCCSYM(a) { #a, &a, },
914 /* add the symbol you want here if no dynamic linking is done */
915 static TCCSyms tcc_syms[] = {
916 #if !defined(CONFIG_TCCBOOT)
917 TCCSYM(printf)
918 TCCSYM(fprintf)
919 TCCSYM(fopen)
920 TCCSYM(fclose)
921 #endif
922 { NULL, NULL },
925 void *resolve_sym(TCCState *s1, const char *symbol, int type)
927 TCCSyms *p;
928 p = tcc_syms;
929 while (p->str != NULL) {
930 if (!strcmp(p->str, symbol))
931 return p->ptr;
932 p++;
934 return NULL;
937 #elif !defined(WIN32)
939 #include <dlfcn.h>
941 void *resolve_sym(TCCState *s1, const char *sym, int type)
943 return dlsym(RTLD_DEFAULT, sym);
946 #endif
948 /********************************************************/
950 /* we use our own 'finite' function to avoid potential problems with
951 non standard math libs */
952 /* XXX: endianness dependent */
953 int ieee_finite(double d)
955 int *p = (int *)&d;
956 return ((unsigned)((p[1] | 0x800fffff) + 1)) >> 31;
959 /* copy a string and truncate it. */
960 static char *pstrcpy(char *buf, int buf_size, const char *s)
962 char *q, *q_end;
963 int c;
965 if (buf_size > 0) {
966 q = buf;
967 q_end = buf + buf_size - 1;
968 while (q < q_end) {
969 c = *s++;
970 if (c == '\0')
971 break;
972 *q++ = c;
974 *q = '\0';
976 return buf;
979 /* strcat and truncate. */
980 static char *pstrcat(char *buf, int buf_size, const char *s)
982 int len;
983 len = strlen(buf);
984 if (len < buf_size)
985 pstrcpy(buf + len, buf_size - len, s);
986 return buf;
989 static int strstart(const char *str, const char *val, const char **ptr)
991 const char *p, *q;
992 p = str;
993 q = val;
994 while (*q != '\0') {
995 if (*p != *q)
996 return 0;
997 p++;
998 q++;
1000 if (ptr)
1001 *ptr = p;
1002 return 1;
1005 /* memory management */
1006 #ifdef MEM_DEBUG
1007 int mem_cur_size;
1008 int mem_max_size;
1009 #endif
1011 static inline void tcc_free(void *ptr)
1013 #ifdef MEM_DEBUG
1014 mem_cur_size -= malloc_usable_size(ptr);
1015 #endif
1016 free(ptr);
1019 static void *tcc_malloc(unsigned long size)
1021 void *ptr;
1022 ptr = malloc(size);
1023 if (!ptr && size)
1024 error("memory full");
1025 #ifdef MEM_DEBUG
1026 mem_cur_size += malloc_usable_size(ptr);
1027 if (mem_cur_size > mem_max_size)
1028 mem_max_size = mem_cur_size;
1029 #endif
1030 return ptr;
1033 static void *tcc_mallocz(unsigned long size)
1035 void *ptr;
1036 ptr = tcc_malloc(size);
1037 memset(ptr, 0, size);
1038 return ptr;
1041 static inline void *tcc_realloc(void *ptr, unsigned long size)
1043 void *ptr1;
1044 #ifdef MEM_DEBUG
1045 mem_cur_size -= malloc_usable_size(ptr);
1046 #endif
1047 ptr1 = realloc(ptr, size);
1048 #ifdef MEM_DEBUG
1049 /* NOTE: count not correct if alloc error, but not critical */
1050 mem_cur_size += malloc_usable_size(ptr1);
1051 if (mem_cur_size > mem_max_size)
1052 mem_max_size = mem_cur_size;
1053 #endif
1054 return ptr1;
1057 static char *tcc_strdup(const char *str)
1059 char *ptr;
1060 ptr = tcc_malloc(strlen(str) + 1);
1061 strcpy(ptr, str);
1062 return ptr;
1065 #define free(p) use_tcc_free(p)
1066 #define malloc(s) use_tcc_malloc(s)
1067 #define realloc(p, s) use_tcc_realloc(p, s)
1069 static void dynarray_add(void ***ptab, int *nb_ptr, void *data)
1071 int nb, nb_alloc;
1072 void **pp;
1074 nb = *nb_ptr;
1075 pp = *ptab;
1076 /* every power of two we double array size */
1077 if ((nb & (nb - 1)) == 0) {
1078 if (!nb)
1079 nb_alloc = 1;
1080 else
1081 nb_alloc = nb * 2;
1082 pp = tcc_realloc(pp, nb_alloc * sizeof(void *));
1083 if (!pp)
1084 error("memory full");
1085 *ptab = pp;
1087 pp[nb++] = data;
1088 *nb_ptr = nb;
1091 /* symbol allocator */
1092 static Sym *__sym_malloc(void)
1094 Sym *sym_pool, *sym, *last_sym;
1095 int i;
1097 sym_pool = tcc_malloc(SYM_POOL_NB * sizeof(Sym));
1099 last_sym = sym_free_first;
1100 sym = sym_pool;
1101 for(i = 0; i < SYM_POOL_NB; i++) {
1102 sym->next = last_sym;
1103 last_sym = sym;
1104 sym++;
1106 sym_free_first = last_sym;
1107 return last_sym;
1110 static inline Sym *sym_malloc(void)
1112 Sym *sym;
1113 sym = sym_free_first;
1114 if (!sym)
1115 sym = __sym_malloc();
1116 sym_free_first = sym->next;
1117 return sym;
1120 static inline void sym_free(Sym *sym)
1122 sym->next = sym_free_first;
1123 sym_free_first = sym;
1126 Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags)
1128 Section *sec;
1130 sec = tcc_mallocz(sizeof(Section) + strlen(name));
1131 strcpy(sec->name, name);
1132 sec->sh_type = sh_type;
1133 sec->sh_flags = sh_flags;
1134 switch(sh_type) {
1135 case SHT_HASH:
1136 case SHT_REL:
1137 case SHT_DYNSYM:
1138 case SHT_SYMTAB:
1139 case SHT_DYNAMIC:
1140 sec->sh_addralign = 4;
1141 break;
1142 case SHT_STRTAB:
1143 sec->sh_addralign = 1;
1144 break;
1145 default:
1146 sec->sh_addralign = 32; /* default conservative alignment */
1147 break;
1150 /* only add section if not private */
1151 if (!(sh_flags & SHF_PRIVATE)) {
1152 sec->sh_num = s1->nb_sections;
1153 dynarray_add((void ***)&s1->sections, &s1->nb_sections, sec);
1155 return sec;
1158 static void free_section(Section *s)
1160 tcc_free(s->data);
1161 tcc_free(s);
1164 /* realloc section and set its content to zero */
1165 static void section_realloc(Section *sec, unsigned long new_size)
1167 unsigned long size;
1168 unsigned char *data;
1170 size = sec->data_allocated;
1171 if (size == 0)
1172 size = 1;
1173 while (size < new_size)
1174 size = size * 2;
1175 data = tcc_realloc(sec->data, size);
1176 if (!data)
1177 error("memory full");
1178 memset(data + sec->data_allocated, 0, size - sec->data_allocated);
1179 sec->data = data;
1180 sec->data_allocated = size;
1183 /* reserve at least 'size' bytes in section 'sec' from
1184 sec->data_offset. */
1185 static void *section_ptr_add(Section *sec, unsigned long size)
1187 unsigned long offset, offset1;
1189 offset = sec->data_offset;
1190 offset1 = offset + size;
1191 if (offset1 > sec->data_allocated)
1192 section_realloc(sec, offset1);
1193 sec->data_offset = offset1;
1194 return sec->data + offset;
1197 /* return a reference to a section, and create it if it does not
1198 exists */
1199 Section *find_section(TCCState *s1, const char *name)
1201 Section *sec;
1202 int i;
1203 for(i = 1; i < s1->nb_sections; i++) {
1204 sec = s1->sections[i];
1205 if (!strcmp(name, sec->name))
1206 return sec;
1208 /* sections are created as PROGBITS */
1209 return new_section(s1, name, SHT_PROGBITS, SHF_ALLOC);
1212 #define SECTION_ABS ((void *)1)
1214 /* update sym->c so that it points to an external symbol in section
1215 'section' with value 'value' */
1216 static void put_extern_sym(Sym *sym, Section *section,
1217 unsigned long value, unsigned long size)
1219 int sym_type, sym_bind, sh_num, info;
1220 Elf32_Sym *esym;
1221 const char *name;
1223 if (section == NULL)
1224 sh_num = SHN_UNDEF;
1225 else if (section == SECTION_ABS)
1226 sh_num = SHN_ABS;
1227 else
1228 sh_num = section->sh_num;
1229 if (!sym->c) {
1230 if ((sym->type.t & VT_BTYPE) == VT_FUNC)
1231 sym_type = STT_FUNC;
1232 else
1233 sym_type = STT_OBJECT;
1234 if (sym->type.t & VT_STATIC)
1235 sym_bind = STB_LOCAL;
1236 else
1237 sym_bind = STB_GLOBAL;
1239 name = get_tok_str(sym->v, NULL);
1240 #ifdef CONFIG_TCC_BCHECK
1241 if (do_bounds_check) {
1242 char buf[32];
1244 /* XXX: avoid doing that for statics ? */
1245 /* if bound checking is activated, we change some function
1246 names by adding the "__bound" prefix */
1247 switch(sym->v) {
1248 #if 0
1249 /* XXX: we rely only on malloc hooks */
1250 case TOK_malloc:
1251 case TOK_free:
1252 case TOK_realloc:
1253 case TOK_memalign:
1254 case TOK_calloc:
1255 #endif
1256 case TOK_memcpy:
1257 case TOK_memmove:
1258 case TOK_memset:
1259 case TOK_strlen:
1260 case TOK_strcpy:
1261 strcpy(buf, "__bound_");
1262 strcat(buf, name);
1263 name = buf;
1264 break;
1267 #endif
1268 info = ELF32_ST_INFO(sym_bind, sym_type);
1269 sym->c = add_elf_sym(symtab_section, value, size, info, 0, sh_num, name);
1270 } else {
1271 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
1272 esym->st_value = value;
1273 esym->st_size = size;
1274 esym->st_shndx = sh_num;
1278 /* add a new relocation entry to symbol 'sym' in section 's' */
1279 static void greloc(Section *s, Sym *sym, unsigned long offset, int type)
1281 if (!sym->c)
1282 put_extern_sym(sym, NULL, 0, 0);
1283 /* now we can add ELF relocation info */
1284 put_elf_reloc(symtab_section, s, offset, type, sym->c);
1287 static inline int isid(int c)
1289 return (c >= 'a' && c <= 'z') ||
1290 (c >= 'A' && c <= 'Z') ||
1291 c == '_';
1294 static inline int isnum(int c)
1296 return c >= '0' && c <= '9';
1299 static inline int isoct(int c)
1301 return c >= '0' && c <= '7';
1304 static inline int toup(int c)
1306 if (c >= 'a' && c <= 'z')
1307 return c - 'a' + 'A';
1308 else
1309 return c;
1312 static void strcat_vprintf(char *buf, int buf_size, const char *fmt, va_list ap)
1314 int len;
1315 len = strlen(buf);
1316 vsnprintf(buf + len, buf_size - len, fmt, ap);
1319 static void strcat_printf(char *buf, int buf_size, const char *fmt, ...)
1321 va_list ap;
1322 va_start(ap, fmt);
1323 strcat_vprintf(buf, buf_size, fmt, ap);
1324 va_end(ap);
1327 void error1(TCCState *s1, int is_warning, const char *fmt, va_list ap)
1329 char buf[2048];
1330 BufferedFile **f;
1332 buf[0] = '\0';
1333 if (file) {
1334 for(f = s1->include_stack; f < s1->include_stack_ptr; f++)
1335 strcat_printf(buf, sizeof(buf), "In file included from %s:%d:\n",
1336 (*f)->filename, (*f)->line_num);
1337 if (file->line_num > 0) {
1338 strcat_printf(buf, sizeof(buf),
1339 "%s:%d: ", file->filename, file->line_num);
1340 } else {
1341 strcat_printf(buf, sizeof(buf),
1342 "%s: ", file->filename);
1344 } else {
1345 strcat_printf(buf, sizeof(buf),
1346 "tcc: ");
1348 if (is_warning)
1349 strcat_printf(buf, sizeof(buf), "warning: ");
1350 strcat_vprintf(buf, sizeof(buf), fmt, ap);
1352 if (!s1->error_func) {
1353 /* default case: stderr */
1354 fprintf(stderr, "%s\n", buf);
1355 } else {
1356 s1->error_func(s1->error_opaque, buf);
1358 if (!is_warning || s1->warn_error)
1359 s1->nb_errors++;
1362 #ifdef LIBTCC
1363 void tcc_set_error_func(TCCState *s, void *error_opaque,
1364 void (*error_func)(void *opaque, const char *msg))
1366 s->error_opaque = error_opaque;
1367 s->error_func = error_func;
1369 #endif
1371 /* error without aborting current compilation */
1372 void error_noabort(const char *fmt, ...)
1374 TCCState *s1 = tcc_state;
1375 va_list ap;
1377 va_start(ap, fmt);
1378 error1(s1, 0, fmt, ap);
1379 va_end(ap);
1382 void error(const char *fmt, ...)
1384 TCCState *s1 = tcc_state;
1385 va_list ap;
1387 va_start(ap, fmt);
1388 error1(s1, 0, fmt, ap);
1389 va_end(ap);
1390 /* better than nothing: in some cases, we accept to handle errors */
1391 if (s1->error_set_jmp_enabled) {
1392 longjmp(s1->error_jmp_buf, 1);
1393 } else {
1394 /* XXX: eliminate this someday */
1395 exit(1);
1399 void expect(const char *msg)
1401 error("%s expected", msg);
1404 void warning(const char *fmt, ...)
1406 TCCState *s1 = tcc_state;
1407 va_list ap;
1409 if (s1->warn_none)
1410 return;
1412 va_start(ap, fmt);
1413 error1(s1, 1, fmt, ap);
1414 va_end(ap);
1417 void skip(int c)
1419 if (tok != c)
1420 error("'%c' expected", c);
1421 next();
1424 static void test_lvalue(void)
1426 if (!(vtop->r & VT_LVAL))
1427 expect("lvalue");
1430 /* allocate a new token */
1431 static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len)
1433 TokenSym *ts, **ptable;
1434 int i;
1436 if (tok_ident >= SYM_FIRST_ANOM)
1437 error("memory full");
1439 /* expand token table if needed */
1440 i = tok_ident - TOK_IDENT;
1441 if ((i % TOK_ALLOC_INCR) == 0) {
1442 ptable = tcc_realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *));
1443 if (!ptable)
1444 error("memory full");
1445 table_ident = ptable;
1448 ts = tcc_malloc(sizeof(TokenSym) + len);
1449 table_ident[i] = ts;
1450 ts->tok = tok_ident++;
1451 ts->sym_define = NULL;
1452 ts->sym_label = NULL;
1453 ts->sym_struct = NULL;
1454 ts->sym_identifier = NULL;
1455 ts->len = len;
1456 ts->hash_next = NULL;
1457 memcpy(ts->str, str, len);
1458 ts->str[len] = '\0';
1459 *pts = ts;
1460 return ts;
1463 #define TOK_HASH_INIT 1
1464 #define TOK_HASH_FUNC(h, c) ((h) * 263 + (c))
1466 /* find a token and add it if not found */
1467 static TokenSym *tok_alloc(const char *str, int len)
1469 TokenSym *ts, **pts;
1470 int i;
1471 unsigned int h;
1473 h = TOK_HASH_INIT;
1474 for(i=0;i<len;i++)
1475 h = TOK_HASH_FUNC(h, ((unsigned char *)str)[i]);
1476 h &= (TOK_HASH_SIZE - 1);
1478 pts = &hash_ident[h];
1479 for(;;) {
1480 ts = *pts;
1481 if (!ts)
1482 break;
1483 if (ts->len == len && !memcmp(ts->str, str, len))
1484 return ts;
1485 pts = &(ts->hash_next);
1487 return tok_alloc_new(pts, str, len);
1490 /* CString handling */
1492 static void cstr_realloc(CString *cstr, int new_size)
1494 int size;
1495 void *data;
1497 size = cstr->size_allocated;
1498 if (size == 0)
1499 size = 8; /* no need to allocate a too small first string */
1500 while (size < new_size)
1501 size = size * 2;
1502 data = tcc_realloc(cstr->data_allocated, size);
1503 if (!data)
1504 error("memory full");
1505 cstr->data_allocated = data;
1506 cstr->size_allocated = size;
1507 cstr->data = data;
1510 /* add a byte */
1511 static inline void cstr_ccat(CString *cstr, int ch)
1513 int size;
1514 size = cstr->size + 1;
1515 if (size > cstr->size_allocated)
1516 cstr_realloc(cstr, size);
1517 ((unsigned char *)cstr->data)[size - 1] = ch;
1518 cstr->size = size;
1521 static void cstr_cat(CString *cstr, const char *str)
1523 int c;
1524 for(;;) {
1525 c = *str;
1526 if (c == '\0')
1527 break;
1528 cstr_ccat(cstr, c);
1529 str++;
1533 /* add a wide char */
1534 static void cstr_wccat(CString *cstr, int ch)
1536 int size;
1537 size = cstr->size + sizeof(int);
1538 if (size > cstr->size_allocated)
1539 cstr_realloc(cstr, size);
1540 *(int *)(((unsigned char *)cstr->data) + size - sizeof(int)) = ch;
1541 cstr->size = size;
1544 static void cstr_new(CString *cstr)
1546 memset(cstr, 0, sizeof(CString));
1549 /* free string and reset it to NULL */
1550 static void cstr_free(CString *cstr)
1552 tcc_free(cstr->data_allocated);
1553 cstr_new(cstr);
1556 #define cstr_reset(cstr) cstr_free(cstr)
1558 /* XXX: unicode ? */
1559 static void add_char(CString *cstr, int c)
1561 if (c == '\'' || c == '\"' || c == '\\') {
1562 /* XXX: could be more precise if char or string */
1563 cstr_ccat(cstr, '\\');
1565 if (c >= 32 && c <= 126) {
1566 cstr_ccat(cstr, c);
1567 } else {
1568 cstr_ccat(cstr, '\\');
1569 if (c == '\n') {
1570 cstr_ccat(cstr, 'n');
1571 } else {
1572 cstr_ccat(cstr, '0' + ((c >> 6) & 7));
1573 cstr_ccat(cstr, '0' + ((c >> 3) & 7));
1574 cstr_ccat(cstr, '0' + (c & 7));
1579 /* XXX: buffer overflow */
1580 /* XXX: float tokens */
1581 char *get_tok_str(int v, CValue *cv)
1583 static char buf[STRING_MAX_SIZE + 1];
1584 static CString cstr_buf;
1585 CString *cstr;
1586 unsigned char *q;
1587 char *p;
1588 int i, len;
1590 /* NOTE: to go faster, we give a fixed buffer for small strings */
1591 cstr_reset(&cstr_buf);
1592 cstr_buf.data = buf;
1593 cstr_buf.size_allocated = sizeof(buf);
1594 p = buf;
1596 switch(v) {
1597 case TOK_CINT:
1598 case TOK_CUINT:
1599 /* XXX: not quite exact, but only useful for testing */
1600 sprintf(p, "%u", cv->ui);
1601 break;
1602 case TOK_CLLONG:
1603 case TOK_CULLONG:
1604 /* XXX: not quite exact, but only useful for testing */
1605 sprintf(p, "%Lu", cv->ull);
1606 break;
1607 case TOK_CCHAR:
1608 case TOK_LCHAR:
1609 cstr_ccat(&cstr_buf, '\'');
1610 add_char(&cstr_buf, cv->i);
1611 cstr_ccat(&cstr_buf, '\'');
1612 cstr_ccat(&cstr_buf, '\0');
1613 break;
1614 case TOK_PPNUM:
1615 cstr = cv->cstr;
1616 len = cstr->size - 1;
1617 for(i=0;i<len;i++)
1618 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1619 cstr_ccat(&cstr_buf, '\0');
1620 break;
1621 case TOK_STR:
1622 case TOK_LSTR:
1623 cstr = cv->cstr;
1624 cstr_ccat(&cstr_buf, '\"');
1625 if (v == TOK_STR) {
1626 len = cstr->size - 1;
1627 for(i=0;i<len;i++)
1628 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1629 } else {
1630 len = (cstr->size / sizeof(int)) - 1;
1631 for(i=0;i<len;i++)
1632 add_char(&cstr_buf, ((int *)cstr->data)[i]);
1634 cstr_ccat(&cstr_buf, '\"');
1635 cstr_ccat(&cstr_buf, '\0');
1636 break;
1637 case TOK_LT:
1638 v = '<';
1639 goto addv;
1640 case TOK_GT:
1641 v = '>';
1642 goto addv;
1643 case TOK_A_SHL:
1644 return strcpy(p, "<<=");
1645 case TOK_A_SAR:
1646 return strcpy(p, ">>=");
1647 default:
1648 if (v < TOK_IDENT) {
1649 /* search in two bytes table */
1650 q = tok_two_chars;
1651 while (*q) {
1652 if (q[2] == v) {
1653 *p++ = q[0];
1654 *p++ = q[1];
1655 *p = '\0';
1656 return buf;
1658 q += 3;
1660 addv:
1661 *p++ = v;
1662 *p = '\0';
1663 } else if (v < tok_ident) {
1664 return table_ident[v - TOK_IDENT]->str;
1665 } else if (v >= SYM_FIRST_ANOM) {
1666 /* special name for anonymous symbol */
1667 sprintf(p, "L.%u", v - SYM_FIRST_ANOM);
1668 } else {
1669 /* should never happen */
1670 return NULL;
1672 break;
1674 return cstr_buf.data;
1677 /* push, without hashing */
1678 static Sym *sym_push2(Sym **ps, int v, int t, int c)
1680 Sym *s;
1681 s = sym_malloc();
1682 s->v = v;
1683 s->type.t = t;
1684 s->c = c;
1685 s->next = NULL;
1686 /* add in stack */
1687 s->prev = *ps;
1688 *ps = s;
1689 return s;
1692 /* find a symbol and return its associated structure. 's' is the top
1693 of the symbol stack */
1694 static Sym *sym_find2(Sym *s, int v)
1696 while (s) {
1697 if (s->v == v)
1698 return s;
1699 s = s->prev;
1701 return NULL;
1704 /* structure lookup */
1705 static inline Sym *struct_find(int v)
1707 v -= TOK_IDENT;
1708 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1709 return NULL;
1710 return table_ident[v]->sym_struct;
1713 /* find an identifier */
1714 static inline Sym *sym_find(int v)
1716 v -= TOK_IDENT;
1717 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1718 return NULL;
1719 return table_ident[v]->sym_identifier;
1722 /* push a given symbol on the symbol stack */
1723 static Sym *sym_push(int v, CType *type, int r, int c)
1725 Sym *s, **ps;
1726 TokenSym *ts;
1728 if (local_stack)
1729 ps = &local_stack;
1730 else
1731 ps = &global_stack;
1732 s = sym_push2(ps, v, type->t, c);
1733 s->type.ref = type->ref;
1734 s->r = r;
1735 /* don't record fields or anonymous symbols */
1736 /* XXX: simplify */
1737 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1738 /* record symbol in token array */
1739 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1740 if (v & SYM_STRUCT)
1741 ps = &ts->sym_struct;
1742 else
1743 ps = &ts->sym_identifier;
1744 s->prev_tok = *ps;
1745 *ps = s;
1747 return s;
1750 /* push a global identifier */
1751 static Sym *global_identifier_push(int v, int t, int c)
1753 Sym *s, **ps;
1754 s = sym_push2(&global_stack, v, t, c);
1755 /* don't record anonymous symbol */
1756 if (v < SYM_FIRST_ANOM) {
1757 ps = &table_ident[v - TOK_IDENT]->sym_identifier;
1758 /* modify the top most local identifier, so that
1759 sym_identifier will point to 's' when popped */
1760 while (*ps != NULL)
1761 ps = &(*ps)->prev_tok;
1762 s->prev_tok = NULL;
1763 *ps = s;
1765 return s;
1768 /* pop symbols until top reaches 'b' */
1769 static void sym_pop(Sym **ptop, Sym *b)
1771 Sym *s, *ss, **ps;
1772 TokenSym *ts;
1773 int v;
1775 s = *ptop;
1776 while(s != b) {
1777 ss = s->prev;
1778 v = s->v;
1779 /* remove symbol in token array */
1780 /* XXX: simplify */
1781 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1782 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1783 if (v & SYM_STRUCT)
1784 ps = &ts->sym_struct;
1785 else
1786 ps = &ts->sym_identifier;
1787 *ps = s->prev_tok;
1789 sym_free(s);
1790 s = ss;
1792 *ptop = b;
1795 /* I/O layer */
1797 BufferedFile *tcc_open(TCCState *s1, const char *filename)
1799 int fd;
1800 BufferedFile *bf;
1802 fd = open(filename, O_RDONLY | O_BINARY);
1803 if (fd < 0)
1804 return NULL;
1805 bf = tcc_malloc(sizeof(BufferedFile));
1806 if (!bf) {
1807 close(fd);
1808 return NULL;
1810 bf->fd = fd;
1811 bf->buf_ptr = bf->buffer;
1812 bf->buf_end = bf->buffer;
1813 bf->buffer[0] = CH_EOB; /* put eob symbol */
1814 pstrcpy(bf->filename, sizeof(bf->filename), filename);
1815 bf->line_num = 1;
1816 bf->ifndef_macro = 0;
1817 bf->ifdef_stack_ptr = s1->ifdef_stack_ptr;
1818 // printf("opening '%s'\n", filename);
1819 return bf;
1822 void tcc_close(BufferedFile *bf)
1824 total_lines += bf->line_num;
1825 close(bf->fd);
1826 tcc_free(bf);
1829 /* fill input buffer and peek next char */
1830 static int tcc_peekc_slow(BufferedFile *bf)
1832 int len;
1833 /* only tries to read if really end of buffer */
1834 if (bf->buf_ptr >= bf->buf_end) {
1835 if (bf->fd != -1) {
1836 #if defined(PARSE_DEBUG)
1837 len = 8;
1838 #else
1839 len = IO_BUF_SIZE;
1840 #endif
1841 len = read(bf->fd, bf->buffer, len);
1842 if (len < 0)
1843 len = 0;
1844 } else {
1845 len = 0;
1847 total_bytes += len;
1848 bf->buf_ptr = bf->buffer;
1849 bf->buf_end = bf->buffer + len;
1850 *bf->buf_end = CH_EOB;
1852 if (bf->buf_ptr < bf->buf_end) {
1853 return bf->buf_ptr[0];
1854 } else {
1855 bf->buf_ptr = bf->buf_end;
1856 return CH_EOF;
1860 /* return the current character, handling end of block if necessary
1861 (but not stray) */
1862 static int handle_eob(void)
1864 return tcc_peekc_slow(file);
1867 /* read next char from current input file and handle end of input buffer */
1868 static inline void inp(void)
1870 ch = *(++(file->buf_ptr));
1871 /* end of buffer/file handling */
1872 if (ch == CH_EOB)
1873 ch = handle_eob();
1876 /* handle '\[\r]\n' */
1877 static void handle_stray(void)
1879 while (ch == '\\') {
1880 inp();
1881 if (ch == '\n') {
1882 file->line_num++;
1883 inp();
1884 } else if (ch == '\r') {
1885 inp();
1886 if (ch != '\n')
1887 goto fail;
1888 file->line_num++;
1889 inp();
1890 } else {
1891 fail:
1892 error("stray '\\' in program");
1897 /* skip the stray and handle the \\n case. Output an error if
1898 incorrect char after the stray */
1899 static int handle_stray1(uint8_t *p)
1901 int c;
1903 if (p >= file->buf_end) {
1904 file->buf_ptr = p;
1905 c = handle_eob();
1906 p = file->buf_ptr;
1907 if (c == '\\')
1908 goto parse_stray;
1909 } else {
1910 parse_stray:
1911 file->buf_ptr = p;
1912 ch = *p;
1913 handle_stray();
1914 p = file->buf_ptr;
1915 c = *p;
1917 return c;
1920 /* handle just the EOB case, but not stray */
1921 #define PEEKC_EOB(c, p)\
1923 p++;\
1924 c = *p;\
1925 if (c == '\\') {\
1926 file->buf_ptr = p;\
1927 c = handle_eob();\
1928 p = file->buf_ptr;\
1932 /* handle the complicated stray case */
1933 #define PEEKC(c, p)\
1935 p++;\
1936 c = *p;\
1937 if (c == '\\') {\
1938 c = handle_stray1(p);\
1939 p = file->buf_ptr;\
1943 /* input with '\[\r]\n' handling. Note that this function cannot
1944 handle other characters after '\', so you cannot call it inside
1945 strings or comments */
1946 static void minp(void)
1948 inp();
1949 if (ch == '\\')
1950 handle_stray();
1954 /* single line C++ comments */
1955 static uint8_t *parse_line_comment(uint8_t *p)
1957 int c;
1959 p++;
1960 for(;;) {
1961 c = *p;
1962 redo:
1963 if (c == '\n' || c == CH_EOF) {
1964 break;
1965 } else if (c == '\\') {
1966 file->buf_ptr = p;
1967 c = handle_eob();
1968 p = file->buf_ptr;
1969 if (c == '\\') {
1970 PEEKC_EOB(c, p);
1971 if (c == '\n') {
1972 file->line_num++;
1973 PEEKC_EOB(c, p);
1974 } else if (c == '\r') {
1975 PEEKC_EOB(c, p);
1976 if (c == '\n') {
1977 file->line_num++;
1978 PEEKC_EOB(c, p);
1981 } else {
1982 goto redo;
1984 } else {
1985 p++;
1988 return p;
1991 /* C comments */
1992 static uint8_t *parse_comment(uint8_t *p)
1994 int c;
1996 p++;
1997 for(;;) {
1998 /* fast skip loop */
1999 for(;;) {
2000 c = *p;
2001 if (c == '\n' || c == '*' || c == '\\')
2002 break;
2003 p++;
2004 c = *p;
2005 if (c == '\n' || c == '*' || c == '\\')
2006 break;
2007 p++;
2009 /* now we can handle all the cases */
2010 if (c == '\n') {
2011 file->line_num++;
2012 p++;
2013 } else if (c == '*') {
2014 p++;
2015 for(;;) {
2016 c = *p;
2017 if (c == '*') {
2018 p++;
2019 } else if (c == '/') {
2020 goto end_of_comment;
2021 } else if (c == '\\') {
2022 file->buf_ptr = p;
2023 c = handle_eob();
2024 p = file->buf_ptr;
2025 if (c == '\\') {
2026 /* skip '\[\r]\n', otherwise just skip the stray */
2027 while (c == '\\') {
2028 PEEKC_EOB(c, p);
2029 if (c == '\n') {
2030 file->line_num++;
2031 PEEKC_EOB(c, p);
2032 } else if (c == '\r') {
2033 PEEKC_EOB(c, p);
2034 if (c == '\n') {
2035 file->line_num++;
2036 PEEKC_EOB(c, p);
2038 } else {
2039 goto after_star;
2043 } else {
2044 break;
2047 after_star: ;
2048 } else {
2049 /* stray, eob or eof */
2050 file->buf_ptr = p;
2051 c = handle_eob();
2052 p = file->buf_ptr;
2053 if (c == CH_EOF) {
2054 error("unexpected end of file in comment");
2055 } else if (c == '\\') {
2056 p++;
2060 end_of_comment:
2061 p++;
2062 return p;
2065 #define cinp minp
2067 /* space exlcuding newline */
2068 static inline int is_space(int ch)
2070 return ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f' || ch == '\r';
2073 static inline void skip_spaces(void)
2075 while (is_space(ch))
2076 cinp();
2079 /* parse a string without interpreting escapes */
2080 static uint8_t *parse_pp_string(uint8_t *p,
2081 int sep, CString *str)
2083 int c;
2084 p++;
2085 for(;;) {
2086 c = *p;
2087 if (c == sep) {
2088 break;
2089 } else if (c == '\\') {
2090 file->buf_ptr = p;
2091 c = handle_eob();
2092 p = file->buf_ptr;
2093 if (c == CH_EOF) {
2094 unterminated_string:
2095 /* XXX: indicate line number of start of string */
2096 error("missing terminating %c character", sep);
2097 } else if (c == '\\') {
2098 /* escape : just skip \[\r]\n */
2099 PEEKC_EOB(c, p);
2100 if (c == '\n') {
2101 file->line_num++;
2102 p++;
2103 } else if (c == '\r') {
2104 PEEKC_EOB(c, p);
2105 if (c != '\n')
2106 expect("'\n' after '\r'");
2107 file->line_num++;
2108 p++;
2109 } else if (c == CH_EOF) {
2110 goto unterminated_string;
2111 } else {
2112 if (str) {
2113 cstr_ccat(str, '\\');
2114 cstr_ccat(str, c);
2116 p++;
2119 } else if (c == '\n') {
2120 file->line_num++;
2121 goto add_char;
2122 } else if (c == '\r') {
2123 PEEKC_EOB(c, p);
2124 if (c != '\n') {
2125 if (str)
2126 cstr_ccat(str, '\r');
2127 } else {
2128 file->line_num++;
2129 goto add_char;
2131 } else {
2132 add_char:
2133 if (str)
2134 cstr_ccat(str, c);
2135 p++;
2138 p++;
2139 return p;
2142 /* skip block of text until #else, #elif or #endif. skip also pairs of
2143 #if/#endif */
2144 void preprocess_skip(void)
2146 int a, start_of_line, c;
2147 uint8_t *p;
2149 p = file->buf_ptr;
2150 start_of_line = 1;
2151 a = 0;
2152 for(;;) {
2153 redo_no_start:
2154 c = *p;
2155 switch(c) {
2156 case ' ':
2157 case '\t':
2158 case '\f':
2159 case '\v':
2160 case '\r':
2161 p++;
2162 goto redo_no_start;
2163 case '\n':
2164 start_of_line = 1;
2165 file->line_num++;
2166 p++;
2167 goto redo_no_start;
2168 case '\\':
2169 file->buf_ptr = p;
2170 c = handle_eob();
2171 if (c == CH_EOF) {
2172 expect("#endif");
2173 } else if (c == '\\') {
2174 /* XXX: incorrect: should not give an error */
2175 ch = file->buf_ptr[0];
2176 handle_stray();
2178 p = file->buf_ptr;
2179 goto redo_no_start;
2180 /* skip strings */
2181 case '\"':
2182 case '\'':
2183 p = parse_pp_string(p, c, NULL);
2184 break;
2185 /* skip comments */
2186 case '/':
2187 file->buf_ptr = p;
2188 ch = *p;
2189 minp();
2190 p = file->buf_ptr;
2191 if (ch == '*') {
2192 p = parse_comment(p);
2193 } else if (ch == '/') {
2194 p = parse_line_comment(p);
2196 break;
2198 case '#':
2199 p++;
2200 if (start_of_line) {
2201 file->buf_ptr = p;
2202 next_nomacro();
2203 p = file->buf_ptr;
2204 if (a == 0 &&
2205 (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
2206 goto the_end;
2207 if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
2208 a++;
2209 else if (tok == TOK_ENDIF)
2210 a--;
2212 break;
2213 default:
2214 p++;
2215 break;
2217 start_of_line = 0;
2219 the_end: ;
2220 file->buf_ptr = p;
2223 /* ParseState handling */
2225 /* XXX: currently, no include file info is stored. Thus, we cannot display
2226 accurate messages if the function or data definition spans multiple
2227 files */
2229 /* save current parse state in 's' */
2230 void save_parse_state(ParseState *s)
2232 s->line_num = file->line_num;
2233 s->macro_ptr = macro_ptr;
2234 s->tok = tok;
2235 s->tokc = tokc;
2238 /* restore parse state from 's' */
2239 void restore_parse_state(ParseState *s)
2241 file->line_num = s->line_num;
2242 macro_ptr = s->macro_ptr;
2243 tok = s->tok;
2244 tokc = s->tokc;
2247 /* return the number of additional 'ints' necessary to store the
2248 token */
2249 static inline int tok_ext_size(int t)
2251 switch(t) {
2252 /* 4 bytes */
2253 case TOK_CINT:
2254 case TOK_CUINT:
2255 case TOK_CCHAR:
2256 case TOK_LCHAR:
2257 case TOK_CFLOAT:
2258 case TOK_LINENUM:
2259 return 1;
2260 case TOK_STR:
2261 case TOK_LSTR:
2262 case TOK_PPNUM:
2263 error("unsupported token");
2264 return 1;
2265 case TOK_CDOUBLE:
2266 case TOK_CLLONG:
2267 case TOK_CULLONG:
2268 return 2;
2269 case TOK_CLDOUBLE:
2270 return LDOUBLE_SIZE / 4;
2271 default:
2272 return 0;
2276 /* token string handling */
2278 static inline void tok_str_new(TokenString *s)
2280 s->str = NULL;
2281 s->len = 0;
2282 s->allocated_len = 0;
2283 s->last_line_num = -1;
2286 static void tok_str_free(int *str)
2288 tcc_free(str);
2291 static int *tok_str_realloc(TokenString *s)
2293 int *str, len;
2295 if (s->allocated_len == 0) {
2296 len = 8;
2297 } else {
2298 len = s->allocated_len * 2;
2300 str = tcc_realloc(s->str, len * sizeof(int));
2301 if (!str)
2302 error("memory full");
2303 s->allocated_len = len;
2304 s->str = str;
2305 return str;
2308 static void tok_str_add(TokenString *s, int t)
2310 int len, *str;
2312 len = s->len;
2313 str = s->str;
2314 if (len >= s->allocated_len)
2315 str = tok_str_realloc(s);
2316 str[len++] = t;
2317 s->len = len;
2320 static void tok_str_add2(TokenString *s, int t, CValue *cv)
2322 int len, *str;
2324 len = s->len;
2325 str = s->str;
2327 /* allocate space for worst case */
2328 if (len + TOK_MAX_SIZE > s->allocated_len)
2329 str = tok_str_realloc(s);
2330 str[len++] = t;
2331 switch(t) {
2332 case TOK_CINT:
2333 case TOK_CUINT:
2334 case TOK_CCHAR:
2335 case TOK_LCHAR:
2336 case TOK_CFLOAT:
2337 case TOK_LINENUM:
2338 str[len++] = cv->tab[0];
2339 break;
2340 case TOK_PPNUM:
2341 case TOK_STR:
2342 case TOK_LSTR:
2344 int nb_words;
2345 CString *cstr;
2347 nb_words = (sizeof(CString) + cv->cstr->size + 3) >> 2;
2348 while ((len + nb_words) > s->allocated_len)
2349 str = tok_str_realloc(s);
2350 cstr = (CString *)(str + len);
2351 cstr->data = NULL;
2352 cstr->size = cv->cstr->size;
2353 cstr->data_allocated = NULL;
2354 cstr->size_allocated = cstr->size;
2355 memcpy((char *)cstr + sizeof(CString),
2356 cv->cstr->data, cstr->size);
2357 len += nb_words;
2359 break;
2360 case TOK_CDOUBLE:
2361 case TOK_CLLONG:
2362 case TOK_CULLONG:
2363 #if LDOUBLE_SIZE == 8
2364 case TOK_CLDOUBLE:
2365 #endif
2366 str[len++] = cv->tab[0];
2367 str[len++] = cv->tab[1];
2368 break;
2369 #if LDOUBLE_SIZE == 12
2370 case TOK_CLDOUBLE:
2371 str[len++] = cv->tab[0];
2372 str[len++] = cv->tab[1];
2373 str[len++] = cv->tab[2];
2374 #elif LDOUBLE_SIZE != 8
2375 #error add long double size support
2376 #endif
2377 break;
2378 default:
2379 break;
2381 s->len = len;
2384 /* add the current parse token in token string 's' */
2385 static void tok_str_add_tok(TokenString *s)
2387 CValue cval;
2389 /* save line number info */
2390 if (file->line_num != s->last_line_num) {
2391 s->last_line_num = file->line_num;
2392 cval.i = s->last_line_num;
2393 tok_str_add2(s, TOK_LINENUM, &cval);
2395 tok_str_add2(s, tok, &tokc);
2398 #if LDOUBLE_SIZE == 12
2399 #define LDOUBLE_GET(p, cv) \
2400 cv.tab[0] = p[0]; \
2401 cv.tab[1] = p[1]; \
2402 cv.tab[2] = p[2];
2403 #elif LDOUBLE_SIZE == 8
2404 #define LDOUBLE_GET(p, cv) \
2405 cv.tab[0] = p[0]; \
2406 cv.tab[1] = p[1];
2407 #else
2408 #error add long double size support
2409 #endif
2412 /* get a token from an integer array and increment pointer
2413 accordingly. we code it as a macro to avoid pointer aliasing. */
2414 #define TOK_GET(t, p, cv) \
2416 t = *p++; \
2417 switch(t) { \
2418 case TOK_CINT: \
2419 case TOK_CUINT: \
2420 case TOK_CCHAR: \
2421 case TOK_LCHAR: \
2422 case TOK_CFLOAT: \
2423 case TOK_LINENUM: \
2424 cv.tab[0] = *p++; \
2425 break; \
2426 case TOK_STR: \
2427 case TOK_LSTR: \
2428 case TOK_PPNUM: \
2429 cv.cstr = (CString *)p; \
2430 cv.cstr->data = (char *)p + sizeof(CString);\
2431 p += (sizeof(CString) + cv.cstr->size + 3) >> 2;\
2432 break; \
2433 case TOK_CDOUBLE: \
2434 case TOK_CLLONG: \
2435 case TOK_CULLONG: \
2436 cv.tab[0] = p[0]; \
2437 cv.tab[1] = p[1]; \
2438 p += 2; \
2439 break; \
2440 case TOK_CLDOUBLE: \
2441 LDOUBLE_GET(p, cv); \
2442 p += LDOUBLE_SIZE / 4; \
2443 break; \
2444 default: \
2445 break; \
2449 /* defines handling */
2450 static inline void define_push(int v, int macro_type, int *str, Sym *first_arg)
2452 Sym *s;
2454 s = sym_push2(&define_stack, v, macro_type, (int)str);
2455 s->next = first_arg;
2456 table_ident[v - TOK_IDENT]->sym_define = s;
2459 /* undefined a define symbol. Its name is just set to zero */
2460 static void define_undef(Sym *s)
2462 int v;
2463 v = s->v;
2464 if (v >= TOK_IDENT && v < tok_ident)
2465 table_ident[v - TOK_IDENT]->sym_define = NULL;
2466 s->v = 0;
2469 static inline Sym *define_find(int v)
2471 v -= TOK_IDENT;
2472 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2473 return NULL;
2474 return table_ident[v]->sym_define;
2477 /* free define stack until top reaches 'b' */
2478 static void free_defines(Sym *b)
2480 Sym *top, *top1;
2481 int v;
2483 top = define_stack;
2484 while (top != b) {
2485 top1 = top->prev;
2486 /* do not free args or predefined defines */
2487 if (top->c)
2488 tok_str_free((int *)top->c);
2489 v = top->v;
2490 if (v >= TOK_IDENT && v < tok_ident)
2491 table_ident[v - TOK_IDENT]->sym_define = NULL;
2492 sym_free(top);
2493 top = top1;
2495 define_stack = b;
2498 /* label lookup */
2499 static Sym *label_find(int v)
2501 v -= TOK_IDENT;
2502 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2503 return NULL;
2504 return table_ident[v]->sym_label;
2507 static Sym *label_push(Sym **ptop, int v, int flags)
2509 Sym *s, **ps;
2510 s = sym_push2(ptop, v, 0, 0);
2511 s->r = flags;
2512 ps = &table_ident[v - TOK_IDENT]->sym_label;
2513 if (ptop == &global_label_stack) {
2514 /* modify the top most local identifier, so that
2515 sym_identifier will point to 's' when popped */
2516 while (*ps != NULL)
2517 ps = &(*ps)->prev_tok;
2519 s->prev_tok = *ps;
2520 *ps = s;
2521 return s;
2524 /* pop labels until element last is reached. Look if any labels are
2525 undefined. Define symbols if '&&label' was used. */
2526 static void label_pop(Sym **ptop, Sym *slast)
2528 Sym *s, *s1;
2529 for(s = *ptop; s != slast; s = s1) {
2530 s1 = s->prev;
2531 if (s->r == LABEL_DECLARED) {
2532 warning("label '%s' declared but not used", get_tok_str(s->v, NULL));
2533 } else if (s->r == LABEL_FORWARD) {
2534 error("label '%s' used but not defined",
2535 get_tok_str(s->v, NULL));
2536 } else {
2537 if (s->c) {
2538 /* define corresponding symbol. A size of
2539 1 is put. */
2540 put_extern_sym(s, cur_text_section, (long)s->next, 1);
2543 /* remove label */
2544 table_ident[s->v - TOK_IDENT]->sym_label = s->prev_tok;
2545 sym_free(s);
2547 *ptop = slast;
2550 /* eval an expression for #if/#elif */
2551 static int expr_preprocess(void)
2553 int c, t;
2554 TokenString str;
2556 tok_str_new(&str);
2557 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2558 next(); /* do macro subst */
2559 if (tok == TOK_DEFINED) {
2560 next_nomacro();
2561 t = tok;
2562 if (t == '(')
2563 next_nomacro();
2564 c = define_find(tok) != 0;
2565 if (t == '(')
2566 next_nomacro();
2567 tok = TOK_CINT;
2568 tokc.i = c;
2569 } else if (tok >= TOK_IDENT) {
2570 /* if undefined macro */
2571 tok = TOK_CINT;
2572 tokc.i = 0;
2574 tok_str_add_tok(&str);
2576 tok_str_add(&str, -1); /* simulate end of file */
2577 tok_str_add(&str, 0);
2578 /* now evaluate C constant expression */
2579 macro_ptr = str.str;
2580 next();
2581 c = expr_const();
2582 macro_ptr = NULL;
2583 tok_str_free(str.str);
2584 return c != 0;
2587 #if defined(PARSE_DEBUG) || defined(PP_DEBUG)
2588 static void tok_print(int *str)
2590 int t;
2591 CValue cval;
2593 while (1) {
2594 TOK_GET(t, str, cval);
2595 if (!t)
2596 break;
2597 printf(" %s", get_tok_str(t, &cval));
2599 printf("\n");
2601 #endif
2603 /* parse after #define */
2604 static void parse_define(void)
2606 Sym *s, *first, **ps;
2607 int v, t, varg, is_vaargs, c;
2608 TokenString str;
2610 v = tok;
2611 if (v < TOK_IDENT)
2612 error("invalid macro name '%s'", get_tok_str(tok, &tokc));
2613 /* XXX: should check if same macro (ANSI) */
2614 first = NULL;
2615 t = MACRO_OBJ;
2616 /* '(' must be just after macro definition for MACRO_FUNC */
2617 c = file->buf_ptr[0];
2618 if (c == '\\')
2619 c = handle_stray1(file->buf_ptr);
2620 if (c == '(') {
2621 next_nomacro();
2622 next_nomacro();
2623 ps = &first;
2624 while (tok != ')') {
2625 varg = tok;
2626 next_nomacro();
2627 is_vaargs = 0;
2628 if (varg == TOK_DOTS) {
2629 varg = TOK___VA_ARGS__;
2630 is_vaargs = 1;
2631 } else if (tok == TOK_DOTS && gnu_ext) {
2632 is_vaargs = 1;
2633 next_nomacro();
2635 if (varg < TOK_IDENT)
2636 error("badly punctuated parameter list");
2637 s = sym_push2(&define_stack, varg | SYM_FIELD, is_vaargs, 0);
2638 *ps = s;
2639 ps = &s->next;
2640 if (tok != ',')
2641 break;
2642 next_nomacro();
2644 t = MACRO_FUNC;
2646 tok_str_new(&str);
2647 next_nomacro();
2648 /* EOF testing necessary for '-D' handling */
2649 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2650 tok_str_add2(&str, tok, &tokc);
2651 next_nomacro();
2653 tok_str_add(&str, 0);
2654 #ifdef PP_DEBUG
2655 printf("define %s %d: ", get_tok_str(v, NULL), t);
2656 tok_print(str.str);
2657 #endif
2658 define_push(v, t, str.str, first);
2661 static inline int hash_cached_include(int type, const char *filename)
2663 const unsigned char *s;
2664 unsigned int h;
2666 h = TOK_HASH_INIT;
2667 h = TOK_HASH_FUNC(h, type);
2668 s = filename;
2669 while (*s) {
2670 h = TOK_HASH_FUNC(h, *s);
2671 s++;
2673 h &= (CACHED_INCLUDES_HASH_SIZE - 1);
2674 return h;
2677 /* XXX: use a token or a hash table to accelerate matching ? */
2678 static CachedInclude *search_cached_include(TCCState *s1,
2679 int type, const char *filename)
2681 CachedInclude *e;
2682 int i, h;
2683 h = hash_cached_include(type, filename);
2684 i = s1->cached_includes_hash[h];
2685 for(;;) {
2686 if (i == 0)
2687 break;
2688 e = s1->cached_includes[i - 1];
2689 if (e->type == type && !strcmp(e->filename, filename))
2690 return e;
2691 i = e->hash_next;
2693 return NULL;
2696 static inline void add_cached_include(TCCState *s1, int type,
2697 const char *filename, int ifndef_macro)
2699 CachedInclude *e;
2700 int h;
2702 if (search_cached_include(s1, type, filename))
2703 return;
2704 #ifdef INC_DEBUG
2705 printf("adding cached '%s' %s\n", filename, get_tok_str(ifndef_macro, NULL));
2706 #endif
2707 e = tcc_malloc(sizeof(CachedInclude) + strlen(filename));
2708 if (!e)
2709 return;
2710 e->type = type;
2711 strcpy(e->filename, filename);
2712 e->ifndef_macro = ifndef_macro;
2713 dynarray_add((void ***)&s1->cached_includes, &s1->nb_cached_includes, e);
2714 /* add in hash table */
2715 h = hash_cached_include(type, filename);
2716 e->hash_next = s1->cached_includes_hash[h];
2717 s1->cached_includes_hash[h] = s1->nb_cached_includes;
2720 static void pragma_parse(TCCState *s1)
2722 int val;
2724 next();
2725 if (tok == TOK_pack) {
2727 This may be:
2728 #pragma pack(1) // set
2729 #pragma pack() // reset to default
2730 #pragma pack(push,1) // push & set
2731 #pragma pack(pop) // restore previous
2733 skip('(');
2734 if (tok == TOK_ASM_pop) {
2735 next();
2736 if (s1->pack_stack_ptr <= s1->pack_stack) {
2737 stk_error:
2738 error("out of pack stack");
2740 s1->pack_stack_ptr--;
2741 } else {
2742 val = 0;
2743 if (tok != ')') {
2744 if (tok == TOK_ASM_push) {
2745 next();
2746 if (s1->pack_stack_ptr >= s1->pack_stack + PACK_STACK_SIZE - 1)
2747 goto stk_error;
2748 s1->pack_stack_ptr++;
2749 skip(',');
2751 if (tok != TOK_CINT) {
2752 pack_error:
2753 error("invalid pack pragma");
2755 val = tokc.i;
2756 if (val < 1 || val > 16 || (val & (val - 1)) != 0)
2757 goto pack_error;
2758 next();
2760 *s1->pack_stack_ptr = val;
2761 skip(')');
2766 /* is_bof is true if first non space token at beginning of file */
2767 static void preprocess(int is_bof)
2769 TCCState *s1 = tcc_state;
2770 int size, i, c, n, saved_parse_flags;
2771 char buf[1024], *q, *p;
2772 char buf1[1024];
2773 BufferedFile *f;
2774 Sym *s;
2775 CachedInclude *e;
2777 saved_parse_flags = parse_flags;
2778 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM |
2779 PARSE_FLAG_LINEFEED;
2780 next_nomacro();
2781 redo:
2782 switch(tok) {
2783 case TOK_DEFINE:
2784 next_nomacro();
2785 parse_define();
2786 break;
2787 case TOK_UNDEF:
2788 next_nomacro();
2789 s = define_find(tok);
2790 /* undefine symbol by putting an invalid name */
2791 if (s)
2792 define_undef(s);
2793 break;
2794 case TOK_INCLUDE:
2795 case TOK_INCLUDE_NEXT:
2796 ch = file->buf_ptr[0];
2797 /* XXX: incorrect if comments : use next_nomacro with a special mode */
2798 skip_spaces();
2799 if (ch == '<') {
2800 c = '>';
2801 goto read_name;
2802 } else if (ch == '\"') {
2803 c = ch;
2804 read_name:
2805 /* XXX: better stray handling */
2806 minp();
2807 q = buf;
2808 while (ch != c && ch != '\n' && ch != CH_EOF) {
2809 if ((q - buf) < sizeof(buf) - 1)
2810 *q++ = ch;
2811 minp();
2813 *q = '\0';
2814 minp();
2815 #if 0
2816 /* eat all spaces and comments after include */
2817 /* XXX: slightly incorrect */
2818 while (ch1 != '\n' && ch1 != CH_EOF)
2819 inp();
2820 #endif
2821 } else {
2822 /* computed #include : either we have only strings or
2823 we have anything enclosed in '<>' */
2824 next();
2825 buf[0] = '\0';
2826 if (tok == TOK_STR) {
2827 while (tok != TOK_LINEFEED) {
2828 if (tok != TOK_STR) {
2829 include_syntax:
2830 error("'#include' expects \"FILENAME\" or <FILENAME>");
2832 pstrcat(buf, sizeof(buf), (char *)tokc.cstr->data);
2833 next();
2835 c = '\"';
2836 } else {
2837 int len;
2838 while (tok != TOK_LINEFEED) {
2839 pstrcat(buf, sizeof(buf), get_tok_str(tok, &tokc));
2840 next();
2842 len = strlen(buf);
2843 /* check syntax and remove '<>' */
2844 if (len < 2 || buf[0] != '<' || buf[len - 1] != '>')
2845 goto include_syntax;
2846 memmove(buf, buf + 1, len - 2);
2847 buf[len - 2] = '\0';
2848 c = '>';
2852 e = search_cached_include(s1, c, buf);
2853 if (e && define_find(e->ifndef_macro)) {
2854 /* no need to parse the include because the 'ifndef macro'
2855 is defined */
2856 #ifdef INC_DEBUG
2857 printf("%s: skipping %s\n", file->filename, buf);
2858 #endif
2859 } else {
2860 if (c == '\"') {
2861 /* first search in current dir if "header.h" */
2862 size = 0;
2863 p = strrchr(file->filename, '/');
2864 if (p)
2865 size = p + 1 - file->filename;
2866 if (size > sizeof(buf1) - 1)
2867 size = sizeof(buf1) - 1;
2868 memcpy(buf1, file->filename, size);
2869 buf1[size] = '\0';
2870 pstrcat(buf1, sizeof(buf1), buf);
2871 f = tcc_open(s1, buf1);
2872 if (f) {
2873 if (tok == TOK_INCLUDE_NEXT)
2874 tok = TOK_INCLUDE;
2875 else
2876 goto found;
2879 if (s1->include_stack_ptr >= s1->include_stack + INCLUDE_STACK_SIZE)
2880 error("#include recursion too deep");
2881 /* now search in all the include paths */
2882 n = s1->nb_include_paths + s1->nb_sysinclude_paths;
2883 for(i = 0; i < n; i++) {
2884 const char *path;
2885 if (i < s1->nb_include_paths)
2886 path = s1->include_paths[i];
2887 else
2888 path = s1->sysinclude_paths[i - s1->nb_include_paths];
2889 pstrcpy(buf1, sizeof(buf1), path);
2890 pstrcat(buf1, sizeof(buf1), "/");
2891 pstrcat(buf1, sizeof(buf1), buf);
2892 f = tcc_open(s1, buf1);
2893 if (f) {
2894 if (tok == TOK_INCLUDE_NEXT)
2895 tok = TOK_INCLUDE;
2896 else
2897 goto found;
2900 error("include file '%s' not found", buf);
2901 f = NULL;
2902 found:
2903 #ifdef INC_DEBUG
2904 printf("%s: including %s\n", file->filename, buf1);
2905 #endif
2906 f->inc_type = c;
2907 pstrcpy(f->inc_filename, sizeof(f->inc_filename), buf);
2908 /* push current file in stack */
2909 /* XXX: fix current line init */
2910 *s1->include_stack_ptr++ = file;
2911 file = f;
2912 /* add include file debug info */
2913 if (do_debug) {
2914 put_stabs(file->filename, N_BINCL, 0, 0, 0);
2916 tok_flags |= TOK_FLAG_BOF | TOK_FLAG_BOL;
2917 ch = file->buf_ptr[0];
2918 goto the_end;
2920 break;
2921 case TOK_IFNDEF:
2922 c = 1;
2923 goto do_ifdef;
2924 case TOK_IF:
2925 c = expr_preprocess();
2926 goto do_if;
2927 case TOK_IFDEF:
2928 c = 0;
2929 do_ifdef:
2930 next_nomacro();
2931 if (tok < TOK_IDENT)
2932 error("invalid argument for '#if%sdef'", c ? "n" : "");
2933 if (is_bof) {
2934 if (c) {
2935 #ifdef INC_DEBUG
2936 printf("#ifndef %s\n", get_tok_str(tok, NULL));
2937 #endif
2938 file->ifndef_macro = tok;
2941 c = (define_find(tok) != 0) ^ c;
2942 do_if:
2943 if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE)
2944 error("memory full");
2945 *s1->ifdef_stack_ptr++ = c;
2946 goto test_skip;
2947 case TOK_ELSE:
2948 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
2949 error("#else without matching #if");
2950 if (s1->ifdef_stack_ptr[-1] & 2)
2951 error("#else after #else");
2952 c = (s1->ifdef_stack_ptr[-1] ^= 3);
2953 goto test_skip;
2954 case TOK_ELIF:
2955 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
2956 error("#elif without matching #if");
2957 c = s1->ifdef_stack_ptr[-1];
2958 if (c > 1)
2959 error("#elif after #else");
2960 /* last #if/#elif expression was true: we skip */
2961 if (c == 1)
2962 goto skip;
2963 c = expr_preprocess();
2964 s1->ifdef_stack_ptr[-1] = c;
2965 test_skip:
2966 if (!(c & 1)) {
2967 skip:
2968 preprocess_skip();
2969 is_bof = 0;
2970 goto redo;
2972 break;
2973 case TOK_ENDIF:
2974 if (s1->ifdef_stack_ptr <= file->ifdef_stack_ptr)
2975 error("#endif without matching #if");
2976 s1->ifdef_stack_ptr--;
2977 /* '#ifndef macro' was at the start of file. Now we check if
2978 an '#endif' is exactly at the end of file */
2979 if (file->ifndef_macro &&
2980 s1->ifdef_stack_ptr == file->ifdef_stack_ptr) {
2981 file->ifndef_macro_saved = file->ifndef_macro;
2982 /* need to set to zero to avoid false matches if another
2983 #ifndef at middle of file */
2984 file->ifndef_macro = 0;
2985 while (tok != TOK_LINEFEED)
2986 next_nomacro();
2987 tok_flags |= TOK_FLAG_ENDIF;
2988 goto the_end;
2990 break;
2991 case TOK_LINE:
2992 next();
2993 if (tok != TOK_CINT)
2994 error("#line");
2995 file->line_num = tokc.i - 1; /* the line number will be incremented after */
2996 next();
2997 if (tok != TOK_LINEFEED) {
2998 if (tok != TOK_STR)
2999 error("#line");
3000 pstrcpy(file->filename, sizeof(file->filename),
3001 (char *)tokc.cstr->data);
3003 break;
3004 case TOK_ERROR:
3005 case TOK_WARNING:
3006 c = tok;
3007 ch = file->buf_ptr[0];
3008 skip_spaces();
3009 q = buf;
3010 while (ch != '\n' && ch != CH_EOF) {
3011 if ((q - buf) < sizeof(buf) - 1)
3012 *q++ = ch;
3013 minp();
3015 *q = '\0';
3016 if (c == TOK_ERROR)
3017 error("#error %s", buf);
3018 else
3019 warning("#warning %s", buf);
3020 break;
3021 case TOK_PRAGMA:
3022 pragma_parse(s1);
3023 break;
3024 default:
3025 if (tok == TOK_LINEFEED || tok == '!' || tok == TOK_CINT) {
3026 /* '!' is ignored to allow C scripts. numbers are ignored
3027 to emulate cpp behaviour */
3028 } else {
3029 if (!(saved_parse_flags & PARSE_FLAG_ASM_COMMENTS))
3030 error("invalid preprocessing directive #%s", get_tok_str(tok, &tokc));
3032 break;
3034 /* ignore other preprocess commands or #! for C scripts */
3035 while (tok != TOK_LINEFEED)
3036 next_nomacro();
3037 the_end:
3038 parse_flags = saved_parse_flags;
3041 /* evaluate escape codes in a string. */
3042 static void parse_escape_string(CString *outstr, const uint8_t *buf, int is_long)
3044 int c, n;
3045 const uint8_t *p;
3047 p = buf;
3048 for(;;) {
3049 c = *p;
3050 if (c == '\0')
3051 break;
3052 if (c == '\\') {
3053 p++;
3054 /* escape */
3055 c = *p;
3056 switch(c) {
3057 case '0': case '1': case '2': case '3':
3058 case '4': case '5': case '6': case '7':
3059 /* at most three octal digits */
3060 n = c - '0';
3061 p++;
3062 c = *p;
3063 if (isoct(c)) {
3064 n = n * 8 + c - '0';
3065 p++;
3066 c = *p;
3067 if (isoct(c)) {
3068 n = n * 8 + c - '0';
3069 p++;
3072 c = n;
3073 goto add_char_nonext;
3074 case 'x':
3075 p++;
3076 n = 0;
3077 for(;;) {
3078 c = *p;
3079 if (c >= 'a' && c <= 'f')
3080 c = c - 'a' + 10;
3081 else if (c >= 'A' && c <= 'F')
3082 c = c - 'A' + 10;
3083 else if (isnum(c))
3084 c = c - '0';
3085 else
3086 break;
3087 n = n * 16 + c;
3088 p++;
3090 c = n;
3091 goto add_char_nonext;
3092 case 'a':
3093 c = '\a';
3094 break;
3095 case 'b':
3096 c = '\b';
3097 break;
3098 case 'f':
3099 c = '\f';
3100 break;
3101 case 'n':
3102 c = '\n';
3103 break;
3104 case 'r':
3105 c = '\r';
3106 break;
3107 case 't':
3108 c = '\t';
3109 break;
3110 case 'v':
3111 c = '\v';
3112 break;
3113 case 'e':
3114 if (!gnu_ext)
3115 goto invalid_escape;
3116 c = 27;
3117 break;
3118 case '\'':
3119 case '\"':
3120 case '\\':
3121 case '?':
3122 break;
3123 default:
3124 invalid_escape:
3125 if (c >= '!' && c <= '~')
3126 warning("unknown escape sequence: \'\\%c\'", c);
3127 else
3128 warning("unknown escape sequence: \'\\x%x\'", c);
3129 break;
3132 p++;
3133 add_char_nonext:
3134 if (!is_long)
3135 cstr_ccat(outstr, c);
3136 else
3137 cstr_wccat(outstr, c);
3139 /* add a trailing '\0' */
3140 if (!is_long)
3141 cstr_ccat(outstr, '\0');
3142 else
3143 cstr_wccat(outstr, '\0');
3146 /* we use 64 bit numbers */
3147 #define BN_SIZE 2
3149 /* bn = (bn << shift) | or_val */
3150 void bn_lshift(unsigned int *bn, int shift, int or_val)
3152 int i;
3153 unsigned int v;
3154 for(i=0;i<BN_SIZE;i++) {
3155 v = bn[i];
3156 bn[i] = (v << shift) | or_val;
3157 or_val = v >> (32 - shift);
3161 void bn_zero(unsigned int *bn)
3163 int i;
3164 for(i=0;i<BN_SIZE;i++) {
3165 bn[i] = 0;
3169 /* parse number in null terminated string 'p' and return it in the
3170 current token */
3171 void parse_number(const char *p)
3173 int b, t, shift, frac_bits, s, exp_val, ch;
3174 char *q;
3175 unsigned int bn[BN_SIZE];
3176 double d;
3178 /* number */
3179 q = token_buf;
3180 ch = *p++;
3181 t = ch;
3182 ch = *p++;
3183 *q++ = t;
3184 b = 10;
3185 if (t == '.') {
3186 goto float_frac_parse;
3187 } else if (t == '0') {
3188 if (ch == 'x' || ch == 'X') {
3189 q--;
3190 ch = *p++;
3191 b = 16;
3192 } else if (tcc_ext && (ch == 'b' || ch == 'B')) {
3193 q--;
3194 ch = *p++;
3195 b = 2;
3198 /* parse all digits. cannot check octal numbers at this stage
3199 because of floating point constants */
3200 while (1) {
3201 if (ch >= 'a' && ch <= 'f')
3202 t = ch - 'a' + 10;
3203 else if (ch >= 'A' && ch <= 'F')
3204 t = ch - 'A' + 10;
3205 else if (isnum(ch))
3206 t = ch - '0';
3207 else
3208 break;
3209 if (t >= b)
3210 break;
3211 if (q >= token_buf + STRING_MAX_SIZE) {
3212 num_too_long:
3213 error("number too long");
3215 *q++ = ch;
3216 ch = *p++;
3218 if (ch == '.' ||
3219 ((ch == 'e' || ch == 'E') && b == 10) ||
3220 ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
3221 if (b != 10) {
3222 /* NOTE: strtox should support that for hexa numbers, but
3223 non ISOC99 libcs do not support it, so we prefer to do
3224 it by hand */
3225 /* hexadecimal or binary floats */
3226 /* XXX: handle overflows */
3227 *q = '\0';
3228 if (b == 16)
3229 shift = 4;
3230 else
3231 shift = 2;
3232 bn_zero(bn);
3233 q = token_buf;
3234 while (1) {
3235 t = *q++;
3236 if (t == '\0') {
3237 break;
3238 } else if (t >= 'a') {
3239 t = t - 'a' + 10;
3240 } else if (t >= 'A') {
3241 t = t - 'A' + 10;
3242 } else {
3243 t = t - '0';
3245 bn_lshift(bn, shift, t);
3247 frac_bits = 0;
3248 if (ch == '.') {
3249 ch = *p++;
3250 while (1) {
3251 t = ch;
3252 if (t >= 'a' && t <= 'f') {
3253 t = t - 'a' + 10;
3254 } else if (t >= 'A' && t <= 'F') {
3255 t = t - 'A' + 10;
3256 } else if (t >= '0' && t <= '9') {
3257 t = t - '0';
3258 } else {
3259 break;
3261 if (t >= b)
3262 error("invalid digit");
3263 bn_lshift(bn, shift, t);
3264 frac_bits += shift;
3265 ch = *p++;
3268 if (ch != 'p' && ch != 'P')
3269 expect("exponent");
3270 ch = *p++;
3271 s = 1;
3272 exp_val = 0;
3273 if (ch == '+') {
3274 ch = *p++;
3275 } else if (ch == '-') {
3276 s = -1;
3277 ch = *p++;
3279 if (ch < '0' || ch > '9')
3280 expect("exponent digits");
3281 while (ch >= '0' && ch <= '9') {
3282 exp_val = exp_val * 10 + ch - '0';
3283 ch = *p++;
3285 exp_val = exp_val * s;
3287 /* now we can generate the number */
3288 /* XXX: should patch directly float number */
3289 d = (double)bn[1] * 4294967296.0 + (double)bn[0];
3290 d = ldexp(d, exp_val - frac_bits);
3291 t = toup(ch);
3292 if (t == 'F') {
3293 ch = *p++;
3294 tok = TOK_CFLOAT;
3295 /* float : should handle overflow */
3296 tokc.f = (float)d;
3297 } else if (t == 'L') {
3298 ch = *p++;
3299 tok = TOK_CLDOUBLE;
3300 /* XXX: not large enough */
3301 tokc.ld = (long double)d;
3302 } else {
3303 tok = TOK_CDOUBLE;
3304 tokc.d = d;
3306 } else {
3307 /* decimal floats */
3308 if (ch == '.') {
3309 if (q >= token_buf + STRING_MAX_SIZE)
3310 goto num_too_long;
3311 *q++ = ch;
3312 ch = *p++;
3313 float_frac_parse:
3314 while (ch >= '0' && ch <= '9') {
3315 if (q >= token_buf + STRING_MAX_SIZE)
3316 goto num_too_long;
3317 *q++ = ch;
3318 ch = *p++;
3321 if (ch == 'e' || ch == 'E') {
3322 if (q >= token_buf + STRING_MAX_SIZE)
3323 goto num_too_long;
3324 *q++ = ch;
3325 ch = *p++;
3326 if (ch == '-' || ch == '+') {
3327 if (q >= token_buf + STRING_MAX_SIZE)
3328 goto num_too_long;
3329 *q++ = ch;
3330 ch = *p++;
3332 if (ch < '0' || ch > '9')
3333 expect("exponent digits");
3334 while (ch >= '0' && ch <= '9') {
3335 if (q >= token_buf + STRING_MAX_SIZE)
3336 goto num_too_long;
3337 *q++ = ch;
3338 ch = *p++;
3341 *q = '\0';
3342 t = toup(ch);
3343 errno = 0;
3344 if (t == 'F') {
3345 ch = *p++;
3346 tok = TOK_CFLOAT;
3347 tokc.f = strtof(token_buf, NULL);
3348 } else if (t == 'L') {
3349 ch = *p++;
3350 tok = TOK_CLDOUBLE;
3351 tokc.ld = strtold(token_buf, NULL);
3352 } else {
3353 tok = TOK_CDOUBLE;
3354 tokc.d = strtod(token_buf, NULL);
3357 } else {
3358 unsigned long long n, n1;
3359 int lcount, ucount;
3361 /* integer number */
3362 *q = '\0';
3363 q = token_buf;
3364 if (b == 10 && *q == '0') {
3365 b = 8;
3366 q++;
3368 n = 0;
3369 while(1) {
3370 t = *q++;
3371 /* no need for checks except for base 10 / 8 errors */
3372 if (t == '\0') {
3373 break;
3374 } else if (t >= 'a') {
3375 t = t - 'a' + 10;
3376 } else if (t >= 'A') {
3377 t = t - 'A' + 10;
3378 } else {
3379 t = t - '0';
3380 if (t >= b)
3381 error("invalid digit");
3383 n1 = n;
3384 n = n * b + t;
3385 /* detect overflow */
3386 /* XXX: this test is not reliable */
3387 if (n < n1)
3388 error("integer constant overflow");
3391 /* XXX: not exactly ANSI compliant */
3392 if ((n & 0xffffffff00000000LL) != 0) {
3393 if ((n >> 63) != 0)
3394 tok = TOK_CULLONG;
3395 else
3396 tok = TOK_CLLONG;
3397 } else if (n > 0x7fffffff) {
3398 tok = TOK_CUINT;
3399 } else {
3400 tok = TOK_CINT;
3402 lcount = 0;
3403 ucount = 0;
3404 for(;;) {
3405 t = toup(ch);
3406 if (t == 'L') {
3407 if (lcount >= 2)
3408 error("three 'l's in integer constant");
3409 lcount++;
3410 if (lcount == 2) {
3411 if (tok == TOK_CINT)
3412 tok = TOK_CLLONG;
3413 else if (tok == TOK_CUINT)
3414 tok = TOK_CULLONG;
3416 ch = *p++;
3417 } else if (t == 'U') {
3418 if (ucount >= 1)
3419 error("two 'u's in integer constant");
3420 ucount++;
3421 if (tok == TOK_CINT)
3422 tok = TOK_CUINT;
3423 else if (tok == TOK_CLLONG)
3424 tok = TOK_CULLONG;
3425 ch = *p++;
3426 } else {
3427 break;
3430 if (tok == TOK_CINT || tok == TOK_CUINT)
3431 tokc.ui = n;
3432 else
3433 tokc.ull = n;
3438 #define PARSE2(c1, tok1, c2, tok2) \
3439 case c1: \
3440 PEEKC(c, p); \
3441 if (c == c2) { \
3442 p++; \
3443 tok = tok2; \
3444 } else { \
3445 tok = tok1; \
3447 break;
3449 /* return next token without macro substitution */
3450 static inline void next_nomacro1(void)
3452 int t, c, is_long;
3453 TokenSym *ts;
3454 uint8_t *p, *p1;
3455 unsigned int h;
3457 p = file->buf_ptr;
3458 redo_no_start:
3459 c = *p;
3460 switch(c) {
3461 case ' ':
3462 case '\t':
3463 case '\f':
3464 case '\v':
3465 case '\r':
3466 p++;
3467 goto redo_no_start;
3469 case '\\':
3470 /* first look if it is in fact an end of buffer */
3471 if (p >= file->buf_end) {
3472 file->buf_ptr = p;
3473 handle_eob();
3474 p = file->buf_ptr;
3475 if (p >= file->buf_end)
3476 goto parse_eof;
3477 else
3478 goto redo_no_start;
3479 } else {
3480 file->buf_ptr = p;
3481 ch = *p;
3482 handle_stray();
3483 p = file->buf_ptr;
3484 goto redo_no_start;
3486 parse_eof:
3488 TCCState *s1 = tcc_state;
3489 if (parse_flags & PARSE_FLAG_LINEFEED) {
3490 tok = TOK_LINEFEED;
3491 } else if (s1->include_stack_ptr == s1->include_stack ||
3492 !(parse_flags & PARSE_FLAG_PREPROCESS)) {
3493 /* no include left : end of file. */
3494 tok = TOK_EOF;
3495 } else {
3496 /* pop include file */
3498 /* test if previous '#endif' was after a #ifdef at
3499 start of file */
3500 if (tok_flags & TOK_FLAG_ENDIF) {
3501 #ifdef INC_DEBUG
3502 printf("#endif %s\n", get_tok_str(file->ifndef_macro_saved, NULL));
3503 #endif
3504 add_cached_include(s1, file->inc_type, file->inc_filename,
3505 file->ifndef_macro_saved);
3508 /* add end of include file debug info */
3509 if (do_debug) {
3510 put_stabd(N_EINCL, 0, 0);
3512 /* pop include stack */
3513 tcc_close(file);
3514 s1->include_stack_ptr--;
3515 file = *s1->include_stack_ptr;
3516 p = file->buf_ptr;
3517 goto redo_no_start;
3520 break;
3522 case '\n':
3523 if (parse_flags & PARSE_FLAG_LINEFEED) {
3524 tok = TOK_LINEFEED;
3525 } else {
3526 file->line_num++;
3527 tok_flags |= TOK_FLAG_BOL;
3528 p++;
3529 goto redo_no_start;
3531 break;
3533 case '#':
3534 /* XXX: simplify */
3535 PEEKC(c, p);
3536 if ((tok_flags & TOK_FLAG_BOL) &&
3537 (parse_flags & PARSE_FLAG_PREPROCESS)) {
3538 file->buf_ptr = p;
3539 preprocess(tok_flags & TOK_FLAG_BOF);
3540 p = file->buf_ptr;
3541 goto redo_no_start;
3542 } else {
3543 if (c == '#') {
3544 p++;
3545 tok = TOK_TWOSHARPS;
3546 } else {
3547 if (parse_flags & PARSE_FLAG_ASM_COMMENTS) {
3548 p = parse_line_comment(p - 1);
3549 goto redo_no_start;
3550 } else {
3551 tok = '#';
3555 break;
3557 case 'a': case 'b': case 'c': case 'd':
3558 case 'e': case 'f': case 'g': case 'h':
3559 case 'i': case 'j': case 'k': case 'l':
3560 case 'm': case 'n': case 'o': case 'p':
3561 case 'q': case 'r': case 's': case 't':
3562 case 'u': case 'v': case 'w': case 'x':
3563 case 'y': case 'z':
3564 case 'A': case 'B': case 'C': case 'D':
3565 case 'E': case 'F': case 'G': case 'H':
3566 case 'I': case 'J': case 'K':
3567 case 'M': case 'N': case 'O': case 'P':
3568 case 'Q': case 'R': case 'S': case 'T':
3569 case 'U': case 'V': case 'W': case 'X':
3570 case 'Y': case 'Z':
3571 case '_':
3572 parse_ident_fast:
3573 p1 = p;
3574 h = TOK_HASH_INIT;
3575 h = TOK_HASH_FUNC(h, c);
3576 p++;
3577 for(;;) {
3578 c = *p;
3579 if (!isidnum_table[c])
3580 break;
3581 h = TOK_HASH_FUNC(h, c);
3582 p++;
3584 if (c != '\\') {
3585 TokenSym **pts;
3586 int len;
3588 /* fast case : no stray found, so we have the full token
3589 and we have already hashed it */
3590 len = p - p1;
3591 h &= (TOK_HASH_SIZE - 1);
3592 pts = &hash_ident[h];
3593 for(;;) {
3594 ts = *pts;
3595 if (!ts)
3596 break;
3597 if (ts->len == len && !memcmp(ts->str, p1, len))
3598 goto token_found;
3599 pts = &(ts->hash_next);
3601 ts = tok_alloc_new(pts, p1, len);
3602 token_found: ;
3603 } else {
3604 /* slower case */
3605 cstr_reset(&tokcstr);
3607 while (p1 < p) {
3608 cstr_ccat(&tokcstr, *p1);
3609 p1++;
3611 p--;
3612 PEEKC(c, p);
3613 parse_ident_slow:
3614 while (isidnum_table[c]) {
3615 cstr_ccat(&tokcstr, c);
3616 PEEKC(c, p);
3618 ts = tok_alloc(tokcstr.data, tokcstr.size);
3620 tok = ts->tok;
3621 break;
3622 case 'L':
3623 t = p[1];
3624 if (t != '\\' && t != '\'' && t != '\"') {
3625 /* fast case */
3626 goto parse_ident_fast;
3627 } else {
3628 PEEKC(c, p);
3629 if (c == '\'' || c == '\"') {
3630 is_long = 1;
3631 goto str_const;
3632 } else {
3633 cstr_reset(&tokcstr);
3634 cstr_ccat(&tokcstr, 'L');
3635 goto parse_ident_slow;
3638 break;
3639 case '0': case '1': case '2': case '3':
3640 case '4': case '5': case '6': case '7':
3641 case '8': case '9':
3643 cstr_reset(&tokcstr);
3644 /* after the first digit, accept digits, alpha, '.' or sign if
3645 prefixed by 'eEpP' */
3646 parse_num:
3647 for(;;) {
3648 t = c;
3649 cstr_ccat(&tokcstr, c);
3650 PEEKC(c, p);
3651 if (!(isnum(c) || isid(c) || c == '.' ||
3652 ((c == '+' || c == '-') &&
3653 (t == 'e' || t == 'E' || t == 'p' || t == 'P'))))
3654 break;
3656 /* We add a trailing '\0' to ease parsing */
3657 cstr_ccat(&tokcstr, '\0');
3658 tokc.cstr = &tokcstr;
3659 tok = TOK_PPNUM;
3660 break;
3661 case '.':
3662 /* special dot handling because it can also start a number */
3663 PEEKC(c, p);
3664 if (isnum(c)) {
3665 cstr_reset(&tokcstr);
3666 cstr_ccat(&tokcstr, '.');
3667 goto parse_num;
3668 } else if (c == '.') {
3669 PEEKC(c, p);
3670 if (c != '.')
3671 expect("'.'");
3672 PEEKC(c, p);
3673 tok = TOK_DOTS;
3674 } else {
3675 tok = '.';
3677 break;
3678 case '\'':
3679 case '\"':
3680 is_long = 0;
3681 str_const:
3683 CString str;
3684 int sep;
3686 sep = c;
3688 /* parse the string */
3689 cstr_new(&str);
3690 p = parse_pp_string(p, sep, &str);
3691 cstr_ccat(&str, '\0');
3693 /* eval the escape (should be done as TOK_PPNUM) */
3694 cstr_reset(&tokcstr);
3695 parse_escape_string(&tokcstr, str.data, is_long);
3696 cstr_free(&str);
3698 if (sep == '\'') {
3699 int char_size;
3700 /* XXX: make it portable */
3701 if (!is_long)
3702 char_size = 1;
3703 else
3704 char_size = sizeof(int);
3705 if (tokcstr.size <= char_size)
3706 error("empty character constant");
3707 if (tokcstr.size > 2 * char_size)
3708 warning("multi-character character constant");
3709 if (!is_long) {
3710 tokc.i = *(int8_t *)tokcstr.data;
3711 tok = TOK_CCHAR;
3712 } else {
3713 tokc.i = *(int *)tokcstr.data;
3714 tok = TOK_LCHAR;
3716 } else {
3717 tokc.cstr = &tokcstr;
3718 if (!is_long)
3719 tok = TOK_STR;
3720 else
3721 tok = TOK_LSTR;
3724 break;
3726 case '<':
3727 PEEKC(c, p);
3728 if (c == '=') {
3729 p++;
3730 tok = TOK_LE;
3731 } else if (c == '<') {
3732 PEEKC(c, p);
3733 if (c == '=') {
3734 p++;
3735 tok = TOK_A_SHL;
3736 } else {
3737 tok = TOK_SHL;
3739 } else {
3740 tok = TOK_LT;
3742 break;
3744 case '>':
3745 PEEKC(c, p);
3746 if (c == '=') {
3747 p++;
3748 tok = TOK_GE;
3749 } else if (c == '>') {
3750 PEEKC(c, p);
3751 if (c == '=') {
3752 p++;
3753 tok = TOK_A_SAR;
3754 } else {
3755 tok = TOK_SAR;
3757 } else {
3758 tok = TOK_GT;
3760 break;
3762 case '&':
3763 PEEKC(c, p);
3764 if (c == '&') {
3765 p++;
3766 tok = TOK_LAND;
3767 } else if (c == '=') {
3768 p++;
3769 tok = TOK_A_AND;
3770 } else {
3771 tok = '&';
3773 break;
3775 case '|':
3776 PEEKC(c, p);
3777 if (c == '|') {
3778 p++;
3779 tok = TOK_LOR;
3780 } else if (c == '=') {
3781 p++;
3782 tok = TOK_A_OR;
3783 } else {
3784 tok = '|';
3786 break;
3788 case '+':
3789 PEEKC(c, p);
3790 if (c == '+') {
3791 p++;
3792 tok = TOK_INC;
3793 } else if (c == '=') {
3794 p++;
3795 tok = TOK_A_ADD;
3796 } else {
3797 tok = '+';
3799 break;
3801 case '-':
3802 PEEKC(c, p);
3803 if (c == '-') {
3804 p++;
3805 tok = TOK_DEC;
3806 } else if (c == '=') {
3807 p++;
3808 tok = TOK_A_SUB;
3809 } else if (c == '>') {
3810 p++;
3811 tok = TOK_ARROW;
3812 } else {
3813 tok = '-';
3815 break;
3817 PARSE2('!', '!', '=', TOK_NE)
3818 PARSE2('=', '=', '=', TOK_EQ)
3819 PARSE2('*', '*', '=', TOK_A_MUL)
3820 PARSE2('%', '%', '=', TOK_A_MOD)
3821 PARSE2('^', '^', '=', TOK_A_XOR)
3823 /* comments or operator */
3824 case '/':
3825 PEEKC(c, p);
3826 if (c == '*') {
3827 p = parse_comment(p);
3828 goto redo_no_start;
3829 } else if (c == '/') {
3830 p = parse_line_comment(p);
3831 goto redo_no_start;
3832 } else if (c == '=') {
3833 p++;
3834 tok = TOK_A_DIV;
3835 } else {
3836 tok = '/';
3838 break;
3840 /* simple tokens */
3841 case '(':
3842 case ')':
3843 case '[':
3844 case ']':
3845 case '{':
3846 case '}':
3847 case ',':
3848 case ';':
3849 case ':':
3850 case '?':
3851 case '~':
3852 case '$': /* only used in assembler */
3853 tok = c;
3854 p++;
3855 break;
3856 default:
3857 error("unrecognized character \\x%02x", c);
3858 break;
3860 file->buf_ptr = p;
3861 tok_flags = 0;
3862 #if defined(PARSE_DEBUG)
3863 printf("token = %s\n", get_tok_str(tok, &tokc));
3864 #endif
3867 /* return next token without macro substitution. Can read input from
3868 macro_ptr buffer */
3869 static void next_nomacro(void)
3871 if (macro_ptr) {
3872 redo:
3873 tok = *macro_ptr;
3874 if (tok) {
3875 TOK_GET(tok, macro_ptr, tokc);
3876 if (tok == TOK_LINENUM) {
3877 file->line_num = tokc.i;
3878 goto redo;
3881 } else {
3882 next_nomacro1();
3886 /* substitute args in macro_str and return allocated string */
3887 static int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
3889 int *st, last_tok, t, notfirst;
3890 Sym *s;
3891 CValue cval;
3892 TokenString str;
3893 CString cstr;
3895 tok_str_new(&str);
3896 last_tok = 0;
3897 while(1) {
3898 TOK_GET(t, macro_str, cval);
3899 if (!t)
3900 break;
3901 if (t == '#') {
3902 /* stringize */
3903 TOK_GET(t, macro_str, cval);
3904 if (!t)
3905 break;
3906 s = sym_find2(args, t);
3907 if (s) {
3908 cstr_new(&cstr);
3909 st = (int *)s->c;
3910 notfirst = 0;
3911 while (*st) {
3912 if (notfirst)
3913 cstr_ccat(&cstr, ' ');
3914 TOK_GET(t, st, cval);
3915 cstr_cat(&cstr, get_tok_str(t, &cval));
3916 notfirst = 1;
3918 cstr_ccat(&cstr, '\0');
3919 #ifdef PP_DEBUG
3920 printf("stringize: %s\n", (char *)cstr.data);
3921 #endif
3922 /* add string */
3923 cval.cstr = &cstr;
3924 tok_str_add2(&str, TOK_STR, &cval);
3925 cstr_free(&cstr);
3926 } else {
3927 tok_str_add2(&str, t, &cval);
3929 } else if (t >= TOK_IDENT) {
3930 s = sym_find2(args, t);
3931 if (s) {
3932 st = (int *)s->c;
3933 /* if '##' is present before or after, no arg substitution */
3934 if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) {
3935 /* special case for var arg macros : ## eats the
3936 ',' if empty VA_ARGS variable. */
3937 /* XXX: test of the ',' is not 100%
3938 reliable. should fix it to avoid security
3939 problems */
3940 if (gnu_ext && s->type.t &&
3941 last_tok == TOK_TWOSHARPS &&
3942 str.len >= 2 && str.str[str.len - 2] == ',') {
3943 if (*st == 0) {
3944 /* suppress ',' '##' */
3945 str.len -= 2;
3946 } else {
3947 /* suppress '##' and add variable */
3948 str.len--;
3949 goto add_var;
3951 } else {
3952 int t1;
3953 add_var:
3954 for(;;) {
3955 TOK_GET(t1, st, cval);
3956 if (!t1)
3957 break;
3958 tok_str_add2(&str, t1, &cval);
3961 } else {
3962 /* NOTE: the stream cannot be read when macro
3963 substituing an argument */
3964 macro_subst(&str, nested_list, st, 0);
3966 } else {
3967 tok_str_add(&str, t);
3969 } else {
3970 tok_str_add2(&str, t, &cval);
3972 last_tok = t;
3974 tok_str_add(&str, 0);
3975 return str.str;
3978 static char const ab_month_name[12][4] =
3980 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
3981 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
3984 /* do macro substitution of current token with macro 's' and add
3985 result to (tok_str,tok_len). 'nested_list' is the list of all
3986 macros we got inside to avoid recursing. Return non zero if no
3987 substitution needs to be done */
3988 static int macro_subst_tok(TokenString *tok_str,
3989 Sym **nested_list, Sym *s, int can_read_stream)
3991 Sym *args, *sa, *sa1;
3992 int mstr_allocated, parlevel, *mstr, t, t1;
3993 TokenString str;
3994 char *cstrval;
3995 CValue cval;
3996 CString cstr;
3997 char buf[32];
3999 /* if symbol is a macro, prepare substitution */
4000 /* special macros */
4001 if (tok == TOK___LINE__) {
4002 snprintf(buf, sizeof(buf), "%d", file->line_num);
4003 cstrval = buf;
4004 t1 = TOK_PPNUM;
4005 goto add_cstr1;
4006 } else if (tok == TOK___FILE__) {
4007 cstrval = file->filename;
4008 goto add_cstr;
4009 } else if (tok == TOK___DATE__ || tok == TOK___TIME__) {
4010 time_t ti;
4011 struct tm *tm;
4013 time(&ti);
4014 tm = localtime(&ti);
4015 if (tok == TOK___DATE__) {
4016 snprintf(buf, sizeof(buf), "%s %2d %d",
4017 ab_month_name[tm->tm_mon], tm->tm_mday, tm->tm_year + 1900);
4018 } else {
4019 snprintf(buf, sizeof(buf), "%02d:%02d:%02d",
4020 tm->tm_hour, tm->tm_min, tm->tm_sec);
4022 cstrval = buf;
4023 add_cstr:
4024 t1 = TOK_STR;
4025 add_cstr1:
4026 cstr_new(&cstr);
4027 cstr_cat(&cstr, cstrval);
4028 cstr_ccat(&cstr, '\0');
4029 cval.cstr = &cstr;
4030 tok_str_add2(tok_str, t1, &cval);
4031 cstr_free(&cstr);
4032 } else {
4033 mstr = (int *)s->c;
4034 mstr_allocated = 0;
4035 if (s->type.t == MACRO_FUNC) {
4036 /* NOTE: we do not use next_nomacro to avoid eating the
4037 next token. XXX: find better solution */
4038 if (macro_ptr) {
4039 t = *macro_ptr;
4040 if (t == 0 && can_read_stream) {
4041 /* end of macro stream: we must look at the token
4042 after in the file */
4043 macro_ptr = NULL;
4044 goto parse_stream;
4046 } else {
4047 parse_stream:
4048 /* XXX: incorrect with comments */
4049 ch = file->buf_ptr[0];
4050 while (is_space(ch) || ch == '\n')
4051 cinp();
4052 t = ch;
4054 if (t != '(') /* no macro subst */
4055 return -1;
4057 /* argument macro */
4058 next_nomacro();
4059 next_nomacro();
4060 args = NULL;
4061 sa = s->next;
4062 /* NOTE: empty args are allowed, except if no args */
4063 for(;;) {
4064 /* handle '()' case */
4065 if (!args && !sa && tok == ')')
4066 break;
4067 if (!sa)
4068 error("macro '%s' used with too many args",
4069 get_tok_str(s->v, 0));
4070 tok_str_new(&str);
4071 parlevel = 0;
4072 /* NOTE: non zero sa->t indicates VA_ARGS */
4073 while ((parlevel > 0 ||
4074 (tok != ')' &&
4075 (tok != ',' || sa->type.t))) &&
4076 tok != -1) {
4077 if (tok == '(')
4078 parlevel++;
4079 else if (tok == ')')
4080 parlevel--;
4081 tok_str_add2(&str, tok, &tokc);
4082 next_nomacro();
4084 tok_str_add(&str, 0);
4085 sym_push2(&args, sa->v & ~SYM_FIELD, sa->type.t, (int)str.str);
4086 sa = sa->next;
4087 if (tok == ')') {
4088 /* special case for gcc var args: add an empty
4089 var arg argument if it is omitted */
4090 if (sa && sa->type.t && gnu_ext)
4091 continue;
4092 else
4093 break;
4095 if (tok != ',')
4096 expect(",");
4097 next_nomacro();
4099 if (sa) {
4100 error("macro '%s' used with too few args",
4101 get_tok_str(s->v, 0));
4104 /* now subst each arg */
4105 mstr = macro_arg_subst(nested_list, mstr, args);
4106 /* free memory */
4107 sa = args;
4108 while (sa) {
4109 sa1 = sa->prev;
4110 tok_str_free((int *)sa->c);
4111 sym_free(sa);
4112 sa = sa1;
4114 mstr_allocated = 1;
4116 sym_push2(nested_list, s->v, 0, 0);
4117 macro_subst(tok_str, nested_list, mstr, 1);
4118 /* pop nested defined symbol */
4119 sa1 = *nested_list;
4120 *nested_list = sa1->prev;
4121 sym_free(sa1);
4122 if (mstr_allocated)
4123 tok_str_free(mstr);
4125 return 0;
4128 /* handle the '##' operator. Return NULL if no '##' seen. Otherwise
4129 return the resulting string (which must be freed). */
4130 static inline int *macro_twosharps(const int *macro_str)
4132 TokenSym *ts;
4133 const int *macro_ptr1, *start_macro_ptr, *ptr, *saved_macro_ptr;
4134 int t;
4135 const char *p1, *p2;
4136 CValue cval;
4137 TokenString macro_str1;
4138 CString cstr;
4140 start_macro_ptr = macro_str;
4141 /* we search the first '##' */
4142 for(;;) {
4143 macro_ptr1 = macro_str;
4144 TOK_GET(t, macro_str, cval);
4145 /* nothing more to do if end of string */
4146 if (t == 0)
4147 return NULL;
4148 if (*macro_str == TOK_TWOSHARPS)
4149 break;
4152 /* we saw '##', so we need more processing to handle it */
4153 cstr_new(&cstr);
4154 tok_str_new(&macro_str1);
4155 tok = t;
4156 tokc = cval;
4158 /* add all tokens seen so far */
4159 for(ptr = start_macro_ptr; ptr < macro_ptr1;) {
4160 TOK_GET(t, ptr, cval);
4161 tok_str_add2(&macro_str1, t, &cval);
4163 saved_macro_ptr = macro_ptr;
4164 /* XXX: get rid of the use of macro_ptr here */
4165 macro_ptr = (int *)macro_str;
4166 for(;;) {
4167 while (*macro_ptr == TOK_TWOSHARPS) {
4168 macro_ptr++;
4169 macro_ptr1 = macro_ptr;
4170 t = *macro_ptr;
4171 if (t) {
4172 TOK_GET(t, macro_ptr, cval);
4173 /* We concatenate the two tokens if we have an
4174 identifier or a preprocessing number */
4175 cstr_reset(&cstr);
4176 p1 = get_tok_str(tok, &tokc);
4177 cstr_cat(&cstr, p1);
4178 p2 = get_tok_str(t, &cval);
4179 cstr_cat(&cstr, p2);
4180 cstr_ccat(&cstr, '\0');
4182 if ((tok >= TOK_IDENT || tok == TOK_PPNUM) &&
4183 (t >= TOK_IDENT || t == TOK_PPNUM)) {
4184 if (tok == TOK_PPNUM) {
4185 /* if number, then create a number token */
4186 /* NOTE: no need to allocate because
4187 tok_str_add2() does it */
4188 tokc.cstr = &cstr;
4189 } else {
4190 /* if identifier, we must do a test to
4191 validate we have a correct identifier */
4192 if (t == TOK_PPNUM) {
4193 const char *p;
4194 int c;
4196 p = p2;
4197 for(;;) {
4198 c = *p;
4199 if (c == '\0')
4200 break;
4201 p++;
4202 if (!isnum(c) && !isid(c))
4203 goto error_pasting;
4206 ts = tok_alloc(cstr.data, strlen(cstr.data));
4207 tok = ts->tok; /* modify current token */
4209 } else {
4210 const char *str = cstr.data;
4211 const unsigned char *q;
4213 /* we look for a valid token */
4214 /* XXX: do more extensive checks */
4215 if (!strcmp(str, ">>=")) {
4216 tok = TOK_A_SAR;
4217 } else if (!strcmp(str, "<<=")) {
4218 tok = TOK_A_SHL;
4219 } else if (strlen(str) == 2) {
4220 /* search in two bytes table */
4221 q = tok_two_chars;
4222 for(;;) {
4223 if (!*q)
4224 goto error_pasting;
4225 if (q[0] == str[0] && q[1] == str[1])
4226 break;
4227 q += 3;
4229 tok = q[2];
4230 } else {
4231 error_pasting:
4232 /* NOTE: because get_tok_str use a static buffer,
4233 we must save it */
4234 cstr_reset(&cstr);
4235 p1 = get_tok_str(tok, &tokc);
4236 cstr_cat(&cstr, p1);
4237 cstr_ccat(&cstr, '\0');
4238 p2 = get_tok_str(t, &cval);
4239 warning("pasting \"%s\" and \"%s\" does not give a valid preprocessing token", cstr.data, p2);
4240 /* cannot merge tokens: just add them separately */
4241 tok_str_add2(&macro_str1, tok, &tokc);
4242 /* XXX: free associated memory ? */
4243 tok = t;
4244 tokc = cval;
4249 tok_str_add2(&macro_str1, tok, &tokc);
4250 next_nomacro();
4251 if (tok == 0)
4252 break;
4254 macro_ptr = (int *)saved_macro_ptr;
4255 cstr_free(&cstr);
4256 tok_str_add(&macro_str1, 0);
4257 return macro_str1.str;
4261 /* do macro substitution of macro_str and add result to
4262 (tok_str,tok_len). 'nested_list' is the list of all macros we got
4263 inside to avoid recursing. */
4264 static void macro_subst(TokenString *tok_str, Sym **nested_list,
4265 const int *macro_str, int can_read_stream)
4267 Sym *s;
4268 int *saved_macro_ptr, *macro_str1;
4269 const int *ptr;
4270 int t, ret;
4271 CValue cval;
4273 /* first scan for '##' operator handling */
4274 ptr = macro_str;
4275 macro_str1 = macro_twosharps(ptr);
4276 if (macro_str1)
4277 ptr = macro_str1;
4278 while (1) {
4279 /* NOTE: ptr == NULL can only happen if tokens are read from
4280 file stream due to a macro function call */
4281 if (ptr == NULL)
4282 break;
4283 TOK_GET(t, ptr, cval);
4284 if (t == 0)
4285 break;
4286 s = define_find(t);
4287 if (s != NULL) {
4288 /* if nested substitution, do nothing */
4289 if (sym_find2(*nested_list, t))
4290 goto no_subst;
4291 saved_macro_ptr = macro_ptr;
4292 macro_ptr = (int *)ptr;
4293 tok = t;
4294 ret = macro_subst_tok(tok_str, nested_list, s, can_read_stream);
4295 ptr = (int *)macro_ptr;
4296 macro_ptr = saved_macro_ptr;
4297 if (ret != 0)
4298 goto no_subst;
4299 } else {
4300 no_subst:
4301 tok_str_add2(tok_str, t, &cval);
4304 if (macro_str1)
4305 tok_str_free(macro_str1);
4308 /* return next token with macro substitution */
4309 static void next(void)
4311 Sym *nested_list, *s;
4312 TokenString str;
4314 redo:
4315 next_nomacro();
4316 if (!macro_ptr) {
4317 /* if not reading from macro substituted string, then try
4318 to substitute macros */
4319 if (tok >= TOK_IDENT &&
4320 (parse_flags & PARSE_FLAG_PREPROCESS)) {
4321 s = define_find(tok);
4322 if (s) {
4323 /* we have a macro: we try to substitute */
4324 tok_str_new(&str);
4325 nested_list = NULL;
4326 if (macro_subst_tok(&str, &nested_list, s, 1) == 0) {
4327 /* substitution done, NOTE: maybe empty */
4328 tok_str_add(&str, 0);
4329 macro_ptr = str.str;
4330 macro_ptr_allocated = str.str;
4331 goto redo;
4335 } else {
4336 if (tok == 0) {
4337 /* end of macro or end of unget buffer */
4338 if (unget_buffer_enabled) {
4339 macro_ptr = unget_saved_macro_ptr;
4340 unget_buffer_enabled = 0;
4341 } else {
4342 /* end of macro string: free it */
4343 tok_str_free(macro_ptr_allocated);
4344 macro_ptr = NULL;
4346 goto redo;
4350 /* convert preprocessor tokens into C tokens */
4351 if (tok == TOK_PPNUM &&
4352 (parse_flags & PARSE_FLAG_TOK_NUM)) {
4353 parse_number((char *)tokc.cstr->data);
4357 /* push back current token and set current token to 'last_tok'. Only
4358 identifier case handled for labels. */
4359 static inline void unget_tok(int last_tok)
4361 int i, n;
4362 int *q;
4363 unget_saved_macro_ptr = macro_ptr;
4364 unget_buffer_enabled = 1;
4365 q = unget_saved_buffer;
4366 macro_ptr = q;
4367 *q++ = tok;
4368 n = tok_ext_size(tok) - 1;
4369 for(i=0;i<n;i++)
4370 *q++ = tokc.tab[i];
4371 *q = 0; /* end of token string */
4372 tok = last_tok;
4376 void swap(int *p, int *q)
4378 int t;
4379 t = *p;
4380 *p = *q;
4381 *q = t;
4384 void vsetc(CType *type, int r, CValue *vc)
4386 int v;
4388 if (vtop >= vstack + (VSTACK_SIZE - 1))
4389 error("memory full");
4390 /* cannot let cpu flags if other instruction are generated. Also
4391 avoid leaving VT_JMP anywhere except on the top of the stack
4392 because it would complicate the code generator. */
4393 if (vtop >= vstack) {
4394 v = vtop->r & VT_VALMASK;
4395 if (v == VT_CMP || (v & ~1) == VT_JMP)
4396 gv(RC_INT);
4398 vtop++;
4399 vtop->type = *type;
4400 vtop->r = r;
4401 vtop->r2 = VT_CONST;
4402 vtop->c = *vc;
4405 /* push integer constant */
4406 void vpushi(int v)
4408 CValue cval;
4409 cval.i = v;
4410 vsetc(&int_type, VT_CONST, &cval);
4413 /* Return a static symbol pointing to a section */
4414 static Sym *get_sym_ref(CType *type, Section *sec,
4415 unsigned long offset, unsigned long size)
4417 int v;
4418 Sym *sym;
4420 v = anon_sym++;
4421 sym = global_identifier_push(v, type->t | VT_STATIC, 0);
4422 sym->type.ref = type->ref;
4423 sym->r = VT_CONST | VT_SYM;
4424 put_extern_sym(sym, sec, offset, size);
4425 return sym;
4428 /* push a reference to a section offset by adding a dummy symbol */
4429 static void vpush_ref(CType *type, Section *sec, unsigned long offset, unsigned long size)
4431 CValue cval;
4433 cval.ul = 0;
4434 vsetc(type, VT_CONST | VT_SYM, &cval);
4435 vtop->sym = get_sym_ref(type, sec, offset, size);
4438 /* define a new external reference to a symbol 'v' of type 'u' */
4439 static Sym *external_global_sym(int v, CType *type, int r)
4441 Sym *s;
4443 s = sym_find(v);
4444 if (!s) {
4445 /* push forward reference */
4446 s = global_identifier_push(v, type->t | VT_EXTERN, 0);
4447 s->type.ref = type->ref;
4448 s->r = r | VT_CONST | VT_SYM;
4450 return s;
4453 /* define a new external reference to a symbol 'v' of type 'u' */
4454 static Sym *external_sym(int v, CType *type, int r)
4456 Sym *s;
4458 s = sym_find(v);
4459 if (!s) {
4460 /* push forward reference */
4461 s = sym_push(v, type, r | VT_CONST | VT_SYM, 0);
4462 s->type.t |= VT_EXTERN;
4463 } else {
4464 if (!is_compatible_types(&s->type, type))
4465 error("incompatible types for redefinition of '%s'",
4466 get_tok_str(v, NULL));
4468 return s;
4471 /* push a reference to global symbol v */
4472 static void vpush_global_sym(CType *type, int v)
4474 Sym *sym;
4475 CValue cval;
4477 sym = external_global_sym(v, type, 0);
4478 cval.ul = 0;
4479 vsetc(type, VT_CONST | VT_SYM, &cval);
4480 vtop->sym = sym;
4483 void vset(CType *type, int r, int v)
4485 CValue cval;
4487 cval.i = v;
4488 vsetc(type, r, &cval);
4491 void vseti(int r, int v)
4493 CType type;
4494 type.t = VT_INT;
4495 vset(&type, r, v);
4498 void vswap(void)
4500 SValue tmp;
4502 tmp = vtop[0];
4503 vtop[0] = vtop[-1];
4504 vtop[-1] = tmp;
4507 void vpushv(SValue *v)
4509 if (vtop >= vstack + (VSTACK_SIZE - 1))
4510 error("memory full");
4511 vtop++;
4512 *vtop = *v;
4515 void vdup(void)
4517 vpushv(vtop);
4520 /* save r to the memory stack, and mark it as being free */
4521 void save_reg(int r)
4523 int l, saved, size, align;
4524 SValue *p, sv;
4525 CType *type;
4527 /* modify all stack values */
4528 saved = 0;
4529 l = 0;
4530 for(p=vstack;p<=vtop;p++) {
4531 if ((p->r & VT_VALMASK) == r ||
4532 (p->r2 & VT_VALMASK) == r) {
4533 /* must save value on stack if not already done */
4534 if (!saved) {
4535 /* NOTE: must reload 'r' because r might be equal to r2 */
4536 r = p->r & VT_VALMASK;
4537 /* store register in the stack */
4538 type = &p->type;
4539 if ((p->r & VT_LVAL) ||
4540 (!is_float(type->t) && (type->t & VT_BTYPE) != VT_LLONG))
4541 type = &int_type;
4542 size = type_size(type, &align);
4543 loc = (loc - size) & -align;
4544 sv.type.t = type->t;
4545 sv.r = VT_LOCAL | VT_LVAL;
4546 sv.c.ul = loc;
4547 store(r, &sv);
4548 #ifdef TCC_TARGET_I386
4549 /* x86 specific: need to pop fp register ST0 if saved */
4550 if (r == TREG_ST0) {
4551 o(0xd9dd); /* fstp %st(1) */
4553 #endif
4554 /* special long long case */
4555 if ((type->t & VT_BTYPE) == VT_LLONG) {
4556 sv.c.ul += 4;
4557 store(p->r2, &sv);
4559 l = loc;
4560 saved = 1;
4562 /* mark that stack entry as being saved on the stack */
4563 if (p->r & VT_LVAL) {
4564 /* also clear the bounded flag because the
4565 relocation address of the function was stored in
4566 p->c.ul */
4567 p->r = (p->r & ~(VT_VALMASK | VT_BOUNDED)) | VT_LLOCAL;
4568 } else {
4569 p->r = lvalue_type(p->type.t) | VT_LOCAL;
4571 p->r2 = VT_CONST;
4572 p->c.ul = l;
4577 /* find a register of class 'rc2' with at most one reference on stack.
4578 * If none, call get_reg(rc) */
4579 int get_reg_ex(int rc, int rc2)
4581 int r;
4582 SValue *p;
4584 for(r=0;r<NB_REGS;r++) {
4585 if (reg_classes[r] & rc2) {
4586 int n;
4587 n=0;
4588 for(p = vstack; p <= vtop; p++) {
4589 if ((p->r & VT_VALMASK) == r ||
4590 (p->r2 & VT_VALMASK) == r)
4591 n++;
4593 if (n <= 1)
4594 return r;
4597 return get_reg(rc);
4600 /* find a free register of class 'rc'. If none, save one register */
4601 int get_reg(int rc)
4603 int r;
4604 SValue *p;
4606 /* find a free register */
4607 for(r=0;r<NB_REGS;r++) {
4608 if (reg_classes[r] & rc) {
4609 for(p=vstack;p<=vtop;p++) {
4610 if ((p->r & VT_VALMASK) == r ||
4611 (p->r2 & VT_VALMASK) == r)
4612 goto notfound;
4614 return r;
4616 notfound: ;
4619 /* no register left : free the first one on the stack (VERY
4620 IMPORTANT to start from the bottom to ensure that we don't
4621 spill registers used in gen_opi()) */
4622 for(p=vstack;p<=vtop;p++) {
4623 r = p->r & VT_VALMASK;
4624 if (r < VT_CONST && (reg_classes[r] & rc))
4625 goto save_found;
4626 /* also look at second register (if long long) */
4627 r = p->r2 & VT_VALMASK;
4628 if (r < VT_CONST && (reg_classes[r] & rc)) {
4629 save_found:
4630 save_reg(r);
4631 return r;
4634 /* Should never comes here */
4635 return -1;
4638 /* save registers up to (vtop - n) stack entry */
4639 void save_regs(int n)
4641 int r;
4642 SValue *p, *p1;
4643 p1 = vtop - n;
4644 for(p = vstack;p <= p1; p++) {
4645 r = p->r & VT_VALMASK;
4646 if (r < VT_CONST) {
4647 save_reg(r);
4652 /* move register 's' to 'r', and flush previous value of r to memory
4653 if needed */
4654 void move_reg(int r, int s)
4656 SValue sv;
4658 if (r != s) {
4659 save_reg(r);
4660 sv.type.t = VT_INT;
4661 sv.r = s;
4662 sv.c.ul = 0;
4663 load(r, &sv);
4667 /* get address of vtop (vtop MUST BE an lvalue) */
4668 void gaddrof(void)
4670 vtop->r &= ~VT_LVAL;
4671 /* tricky: if saved lvalue, then we can go back to lvalue */
4672 if ((vtop->r & VT_VALMASK) == VT_LLOCAL)
4673 vtop->r = (vtop->r & ~(VT_VALMASK | VT_LVAL_TYPE)) | VT_LOCAL | VT_LVAL;
4676 #ifdef CONFIG_TCC_BCHECK
4677 /* generate lvalue bound code */
4678 void gbound(void)
4680 int lval_type;
4681 CType type1;
4683 vtop->r &= ~VT_MUSTBOUND;
4684 /* if lvalue, then use checking code before dereferencing */
4685 if (vtop->r & VT_LVAL) {
4686 /* if not VT_BOUNDED value, then make one */
4687 if (!(vtop->r & VT_BOUNDED)) {
4688 lval_type = vtop->r & (VT_LVAL_TYPE | VT_LVAL);
4689 /* must save type because we must set it to int to get pointer */
4690 type1 = vtop->type;
4691 vtop->type.t = VT_INT;
4692 gaddrof();
4693 vpushi(0);
4694 gen_bounded_ptr_add();
4695 vtop->r |= lval_type;
4696 vtop->type = type1;
4698 /* then check for dereferencing */
4699 gen_bounded_ptr_deref();
4702 #endif
4704 /* store vtop a register belonging to class 'rc'. lvalues are
4705 converted to values. Cannot be used if cannot be converted to
4706 register value (such as structures). */
4707 int gv(int rc)
4709 int r, r2, rc2, bit_pos, bit_size, size, align, i;
4710 unsigned long long ll;
4712 /* NOTE: get_reg can modify vstack[] */
4713 if (vtop->type.t & VT_BITFIELD) {
4714 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
4715 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
4716 /* remove bit field info to avoid loops */
4717 vtop->type.t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
4718 /* generate shifts */
4719 vpushi(32 - (bit_pos + bit_size));
4720 gen_op(TOK_SHL);
4721 vpushi(32 - bit_size);
4722 /* NOTE: transformed to SHR if unsigned */
4723 gen_op(TOK_SAR);
4724 r = gv(rc);
4725 } else {
4726 if (is_float(vtop->type.t) &&
4727 (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4728 Sym *sym;
4729 int *ptr;
4730 unsigned long offset;
4732 /* XXX: unify with initializers handling ? */
4733 /* CPUs usually cannot use float constants, so we store them
4734 generically in data segment */
4735 size = type_size(&vtop->type, &align);
4736 offset = (data_section->data_offset + align - 1) & -align;
4737 data_section->data_offset = offset;
4738 /* XXX: not portable yet */
4739 ptr = section_ptr_add(data_section, size);
4740 size = size >> 2;
4741 for(i=0;i<size;i++)
4742 ptr[i] = vtop->c.tab[i];
4743 sym = get_sym_ref(&vtop->type, data_section, offset, size << 2);
4744 vtop->r |= VT_LVAL | VT_SYM;
4745 vtop->sym = sym;
4746 vtop->c.ul = 0;
4748 #ifdef CONFIG_TCC_BCHECK
4749 if (vtop->r & VT_MUSTBOUND)
4750 gbound();
4751 #endif
4753 r = vtop->r & VT_VALMASK;
4754 /* need to reload if:
4755 - constant
4756 - lvalue (need to dereference pointer)
4757 - already a register, but not in the right class */
4758 if (r >= VT_CONST ||
4759 (vtop->r & VT_LVAL) ||
4760 !(reg_classes[r] & rc) ||
4761 ((vtop->type.t & VT_BTYPE) == VT_LLONG &&
4762 !(reg_classes[vtop->r2] & rc))) {
4763 r = get_reg(rc);
4764 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
4765 /* two register type load : expand to two words
4766 temporarily */
4767 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4768 /* load constant */
4769 ll = vtop->c.ull;
4770 vtop->c.ui = ll; /* first word */
4771 load(r, vtop);
4772 vtop->r = r; /* save register value */
4773 vpushi(ll >> 32); /* second word */
4774 } else if (r >= VT_CONST || /* XXX: test to VT_CONST incorrect ? */
4775 (vtop->r & VT_LVAL)) {
4776 /* We do not want to modifier the long long
4777 pointer here, so the safest (and less
4778 efficient) is to save all the other registers
4779 in the stack. XXX: totally inefficient. */
4780 save_regs(1);
4781 /* load from memory */
4782 load(r, vtop);
4783 vdup();
4784 vtop[-1].r = r; /* save register value */
4785 /* increment pointer to get second word */
4786 vtop->type.t = VT_INT;
4787 gaddrof();
4788 vpushi(4);
4789 gen_op('+');
4790 vtop->r |= VT_LVAL;
4791 } else {
4792 /* move registers */
4793 load(r, vtop);
4794 vdup();
4795 vtop[-1].r = r; /* save register value */
4796 vtop->r = vtop[-1].r2;
4798 /* allocate second register */
4799 rc2 = RC_INT;
4800 if (rc == RC_IRET)
4801 rc2 = RC_LRET;
4802 r2 = get_reg(rc2);
4803 load(r2, vtop);
4804 vpop();
4805 /* write second register */
4806 vtop->r2 = r2;
4807 } else if ((vtop->r & VT_LVAL) && !is_float(vtop->type.t)) {
4808 int t1, t;
4809 /* lvalue of scalar type : need to use lvalue type
4810 because of possible cast */
4811 t = vtop->type.t;
4812 t1 = t;
4813 /* compute memory access type */
4814 if (vtop->r & VT_LVAL_BYTE)
4815 t = VT_BYTE;
4816 else if (vtop->r & VT_LVAL_SHORT)
4817 t = VT_SHORT;
4818 if (vtop->r & VT_LVAL_UNSIGNED)
4819 t |= VT_UNSIGNED;
4820 vtop->type.t = t;
4821 load(r, vtop);
4822 /* restore wanted type */
4823 vtop->type.t = t1;
4824 } else {
4825 /* one register type load */
4826 load(r, vtop);
4829 vtop->r = r;
4830 #ifdef TCC_TARGET_C67
4831 /* uses register pairs for doubles */
4832 if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE)
4833 vtop->r2 = r+1;
4834 #endif
4836 return r;
4839 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
4840 void gv2(int rc1, int rc2)
4842 int v;
4844 /* generate more generic register first. But VT_JMP or VT_CMP
4845 values must be generated first in all cases to avoid possible
4846 reload errors */
4847 v = vtop[0].r & VT_VALMASK;
4848 if (v != VT_CMP && (v & ~1) != VT_JMP && rc1 <= rc2) {
4849 vswap();
4850 gv(rc1);
4851 vswap();
4852 gv(rc2);
4853 /* test if reload is needed for first register */
4854 if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
4855 vswap();
4856 gv(rc1);
4857 vswap();
4859 } else {
4860 gv(rc2);
4861 vswap();
4862 gv(rc1);
4863 vswap();
4864 /* test if reload is needed for first register */
4865 if ((vtop[0].r & VT_VALMASK) >= VT_CONST) {
4866 gv(rc2);
4871 /* expand long long on stack in two int registers */
4872 void lexpand(void)
4874 int u;
4876 u = vtop->type.t & VT_UNSIGNED;
4877 gv(RC_INT);
4878 vdup();
4879 vtop[0].r = vtop[-1].r2;
4880 vtop[0].r2 = VT_CONST;
4881 vtop[-1].r2 = VT_CONST;
4882 vtop[0].type.t = VT_INT | u;
4883 vtop[-1].type.t = VT_INT | u;
4886 #ifdef TCC_TARGET_ARM
4887 /* expand long long on stack */
4888 void lexpand_nr(void)
4890 int u,v;
4892 u = vtop->type.t & VT_UNSIGNED;
4893 vdup();
4894 vtop->r2 = VT_CONST;
4895 vtop->type.t = VT_INT | u;
4896 v=vtop[-1].r & (VT_VALMASK | VT_LVAL);
4897 if (v == VT_CONST) {
4898 vtop[-1].c.ui = vtop->c.ull;
4899 vtop->c.ui = vtop->c.ull >> 32;
4900 vtop->r = VT_CONST;
4901 } else if (v == (VT_LVAL|VT_CONST) || v == (VT_LVAL|VT_LOCAL)) {
4902 vtop->c.ui += 4;
4903 vtop->r = vtop[-1].r;
4904 } else if (v > VT_CONST) {
4905 vtop--;
4906 lexpand();
4907 } else
4908 vtop->r = vtop[-1].r2;
4909 vtop[-1].r2 = VT_CONST;
4910 vtop[-1].type.t = VT_INT | u;
4912 #endif
4914 /* build a long long from two ints */
4915 void lbuild(int t)
4917 gv2(RC_INT, RC_INT);
4918 vtop[-1].r2 = vtop[0].r;
4919 vtop[-1].type.t = t;
4920 vpop();
4923 /* rotate n first stack elements to the bottom
4924 I1 ... In -> I2 ... In I1 [top is right]
4926 void vrotb(int n)
4928 int i;
4929 SValue tmp;
4931 tmp = vtop[-n + 1];
4932 for(i=-n+1;i!=0;i++)
4933 vtop[i] = vtop[i+1];
4934 vtop[0] = tmp;
4937 /* rotate n first stack elements to the top
4938 I1 ... In -> In I1 ... I(n-1) [top is right]
4940 void vrott(int n)
4942 int i;
4943 SValue tmp;
4945 tmp = vtop[0];
4946 for(i = 0;i < n - 1; i++)
4947 vtop[-i] = vtop[-i - 1];
4948 vtop[-n + 1] = tmp;
4951 #ifdef TCC_TARGET_ARM
4952 /* like vrott but in other direction
4953 In ... I1 -> I(n-1) ... I1 In [top is right]
4955 void vnrott(int n)
4957 int i;
4958 SValue tmp;
4960 tmp = vtop[-n + 1];
4961 for(i = n - 1; i > 0; i--)
4962 vtop[-i] = vtop[-i + 1];
4963 vtop[0] = tmp;
4965 #endif
4967 /* pop stack value */
4968 void vpop(void)
4970 int v;
4971 v = vtop->r & VT_VALMASK;
4972 #ifdef TCC_TARGET_I386
4973 /* for x86, we need to pop the FP stack */
4974 if (v == TREG_ST0 && !nocode_wanted) {
4975 o(0xd9dd); /* fstp %st(1) */
4976 } else
4977 #endif
4978 if (v == VT_JMP || v == VT_JMPI) {
4979 /* need to put correct jump if && or || without test */
4980 gsym(vtop->c.ul);
4982 vtop--;
4985 /* convert stack entry to register and duplicate its value in another
4986 register */
4987 void gv_dup(void)
4989 int rc, t, r, r1;
4990 SValue sv;
4992 t = vtop->type.t;
4993 if ((t & VT_BTYPE) == VT_LLONG) {
4994 lexpand();
4995 gv_dup();
4996 vswap();
4997 vrotb(3);
4998 gv_dup();
4999 vrotb(4);
5000 /* stack: H L L1 H1 */
5001 lbuild(t);
5002 vrotb(3);
5003 vrotb(3);
5004 vswap();
5005 lbuild(t);
5006 vswap();
5007 } else {
5008 /* duplicate value */
5009 rc = RC_INT;
5010 sv.type.t = VT_INT;
5011 if (is_float(t)) {
5012 rc = RC_FLOAT;
5013 sv.type.t = t;
5015 r = gv(rc);
5016 r1 = get_reg(rc);
5017 sv.r = r;
5018 sv.c.ul = 0;
5019 load(r1, &sv); /* move r to r1 */
5020 vdup();
5021 /* duplicates value */
5022 vtop->r = r1;
5026 /* generate CPU independent (unsigned) long long operations */
5027 void gen_opl(int op)
5029 int t, a, b, op1, c, i;
5030 int func;
5031 SValue tmp;
5033 switch(op) {
5034 case '/':
5035 case TOK_PDIV:
5036 func = TOK___divdi3;
5037 goto gen_func;
5038 case TOK_UDIV:
5039 func = TOK___udivdi3;
5040 goto gen_func;
5041 case '%':
5042 func = TOK___moddi3;
5043 goto gen_func;
5044 case TOK_UMOD:
5045 func = TOK___umoddi3;
5046 gen_func:
5047 /* call generic long long function */
5048 vpush_global_sym(&func_old_type, func);
5049 vrott(3);
5050 gfunc_call(2);
5051 vpushi(0);
5052 vtop->r = REG_IRET;
5053 vtop->r2 = REG_LRET;
5054 break;
5055 case '^':
5056 case '&':
5057 case '|':
5058 case '*':
5059 case '+':
5060 case '-':
5061 t = vtop->type.t;
5062 vswap();
5063 lexpand();
5064 vrotb(3);
5065 lexpand();
5066 /* stack: L1 H1 L2 H2 */
5067 tmp = vtop[0];
5068 vtop[0] = vtop[-3];
5069 vtop[-3] = tmp;
5070 tmp = vtop[-2];
5071 vtop[-2] = vtop[-3];
5072 vtop[-3] = tmp;
5073 vswap();
5074 /* stack: H1 H2 L1 L2 */
5075 if (op == '*') {
5076 vpushv(vtop - 1);
5077 vpushv(vtop - 1);
5078 gen_op(TOK_UMULL);
5079 lexpand();
5080 /* stack: H1 H2 L1 L2 ML MH */
5081 for(i=0;i<4;i++)
5082 vrotb(6);
5083 /* stack: ML MH H1 H2 L1 L2 */
5084 tmp = vtop[0];
5085 vtop[0] = vtop[-2];
5086 vtop[-2] = tmp;
5087 /* stack: ML MH H1 L2 H2 L1 */
5088 gen_op('*');
5089 vrotb(3);
5090 vrotb(3);
5091 gen_op('*');
5092 /* stack: ML MH M1 M2 */
5093 gen_op('+');
5094 gen_op('+');
5095 } else if (op == '+' || op == '-') {
5096 /* XXX: add non carry method too (for MIPS or alpha) */
5097 if (op == '+')
5098 op1 = TOK_ADDC1;
5099 else
5100 op1 = TOK_SUBC1;
5101 gen_op(op1);
5102 /* stack: H1 H2 (L1 op L2) */
5103 vrotb(3);
5104 vrotb(3);
5105 gen_op(op1 + 1); /* TOK_xxxC2 */
5106 } else {
5107 gen_op(op);
5108 /* stack: H1 H2 (L1 op L2) */
5109 vrotb(3);
5110 vrotb(3);
5111 /* stack: (L1 op L2) H1 H2 */
5112 gen_op(op);
5113 /* stack: (L1 op L2) (H1 op H2) */
5115 /* stack: L H */
5116 lbuild(t);
5117 break;
5118 case TOK_SAR:
5119 case TOK_SHR:
5120 case TOK_SHL:
5121 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
5122 t = vtop[-1].type.t;
5123 vswap();
5124 lexpand();
5125 vrotb(3);
5126 /* stack: L H shift */
5127 c = (int)vtop->c.i;
5128 /* constant: simpler */
5129 /* NOTE: all comments are for SHL. the other cases are
5130 done by swaping words */
5131 vpop();
5132 if (op != TOK_SHL)
5133 vswap();
5134 if (c >= 32) {
5135 /* stack: L H */
5136 vpop();
5137 if (c > 32) {
5138 vpushi(c - 32);
5139 gen_op(op);
5141 if (op != TOK_SAR) {
5142 vpushi(0);
5143 } else {
5144 gv_dup();
5145 vpushi(31);
5146 gen_op(TOK_SAR);
5148 vswap();
5149 } else {
5150 vswap();
5151 gv_dup();
5152 /* stack: H L L */
5153 vpushi(c);
5154 gen_op(op);
5155 vswap();
5156 vpushi(32 - c);
5157 if (op == TOK_SHL)
5158 gen_op(TOK_SHR);
5159 else
5160 gen_op(TOK_SHL);
5161 vrotb(3);
5162 /* stack: L L H */
5163 vpushi(c);
5164 if (op == TOK_SHL)
5165 gen_op(TOK_SHL);
5166 else
5167 gen_op(TOK_SHR);
5168 gen_op('|');
5170 if (op != TOK_SHL)
5171 vswap();
5172 lbuild(t);
5173 } else {
5174 /* XXX: should provide a faster fallback on x86 ? */
5175 switch(op) {
5176 case TOK_SAR:
5177 func = TOK___sardi3;
5178 goto gen_func;
5179 case TOK_SHR:
5180 func = TOK___shrdi3;
5181 goto gen_func;
5182 case TOK_SHL:
5183 func = TOK___shldi3;
5184 goto gen_func;
5187 break;
5188 default:
5189 /* compare operations */
5190 t = vtop->type.t;
5191 vswap();
5192 lexpand();
5193 vrotb(3);
5194 lexpand();
5195 /* stack: L1 H1 L2 H2 */
5196 tmp = vtop[-1];
5197 vtop[-1] = vtop[-2];
5198 vtop[-2] = tmp;
5199 /* stack: L1 L2 H1 H2 */
5200 /* compare high */
5201 op1 = op;
5202 /* when values are equal, we need to compare low words. since
5203 the jump is inverted, we invert the test too. */
5204 if (op1 == TOK_LT)
5205 op1 = TOK_LE;
5206 else if (op1 == TOK_GT)
5207 op1 = TOK_GE;
5208 else if (op1 == TOK_ULT)
5209 op1 = TOK_ULE;
5210 else if (op1 == TOK_UGT)
5211 op1 = TOK_UGE;
5212 a = 0;
5213 b = 0;
5214 gen_op(op1);
5215 if (op1 != TOK_NE) {
5216 a = gtst(1, 0);
5218 if (op != TOK_EQ) {
5219 /* generate non equal test */
5220 /* XXX: NOT PORTABLE yet */
5221 if (a == 0) {
5222 b = gtst(0, 0);
5223 } else {
5224 #if defined(TCC_TARGET_I386)
5225 b = psym(0x850f, 0);
5226 #elif defined(TCC_TARGET_ARM)
5227 b = ind;
5228 o(0x1A000000 | encbranch(ind, 0, 1));
5229 #elif defined(TCC_TARGET_C67)
5230 error("not implemented");
5231 #else
5232 #error not supported
5233 #endif
5236 /* compare low. Always unsigned */
5237 op1 = op;
5238 if (op1 == TOK_LT)
5239 op1 = TOK_ULT;
5240 else if (op1 == TOK_LE)
5241 op1 = TOK_ULE;
5242 else if (op1 == TOK_GT)
5243 op1 = TOK_UGT;
5244 else if (op1 == TOK_GE)
5245 op1 = TOK_UGE;
5246 gen_op(op1);
5247 a = gtst(1, a);
5248 gsym(b);
5249 vseti(VT_JMPI, a);
5250 break;
5254 /* handle integer constant optimizations and various machine
5255 independent opt */
5256 void gen_opic(int op)
5258 int fc, c1, c2, n;
5259 SValue *v1, *v2;
5261 v1 = vtop - 1;
5262 v2 = vtop;
5263 /* currently, we cannot do computations with forward symbols */
5264 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5265 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5266 if (c1 && c2) {
5267 fc = v2->c.i;
5268 switch(op) {
5269 case '+': v1->c.i += fc; break;
5270 case '-': v1->c.i -= fc; break;
5271 case '&': v1->c.i &= fc; break;
5272 case '^': v1->c.i ^= fc; break;
5273 case '|': v1->c.i |= fc; break;
5274 case '*': v1->c.i *= fc; break;
5276 case TOK_PDIV:
5277 case '/':
5278 case '%':
5279 case TOK_UDIV:
5280 case TOK_UMOD:
5281 /* if division by zero, generate explicit division */
5282 if (fc == 0) {
5283 if (const_wanted)
5284 error("division by zero in constant");
5285 goto general_case;
5287 switch(op) {
5288 default: v1->c.i /= fc; break;
5289 case '%': v1->c.i %= fc; break;
5290 case TOK_UDIV: v1->c.i = (unsigned)v1->c.i / fc; break;
5291 case TOK_UMOD: v1->c.i = (unsigned)v1->c.i % fc; break;
5293 break;
5294 case TOK_SHL: v1->c.i <<= fc; break;
5295 case TOK_SHR: v1->c.i = (unsigned)v1->c.i >> fc; break;
5296 case TOK_SAR: v1->c.i >>= fc; break;
5297 /* tests */
5298 case TOK_ULT: v1->c.i = (unsigned)v1->c.i < (unsigned)fc; break;
5299 case TOK_UGE: v1->c.i = (unsigned)v1->c.i >= (unsigned)fc; break;
5300 case TOK_EQ: v1->c.i = v1->c.i == fc; break;
5301 case TOK_NE: v1->c.i = v1->c.i != fc; break;
5302 case TOK_ULE: v1->c.i = (unsigned)v1->c.i <= (unsigned)fc; break;
5303 case TOK_UGT: v1->c.i = (unsigned)v1->c.i > (unsigned)fc; break;
5304 case TOK_LT: v1->c.i = v1->c.i < fc; break;
5305 case TOK_GE: v1->c.i = v1->c.i >= fc; break;
5306 case TOK_LE: v1->c.i = v1->c.i <= fc; break;
5307 case TOK_GT: v1->c.i = v1->c.i > fc; break;
5308 /* logical */
5309 case TOK_LAND: v1->c.i = v1->c.i && fc; break;
5310 case TOK_LOR: v1->c.i = v1->c.i || fc; break;
5311 default:
5312 goto general_case;
5314 vtop--;
5315 } else {
5316 /* if commutative ops, put c2 as constant */
5317 if (c1 && (op == '+' || op == '&' || op == '^' ||
5318 op == '|' || op == '*')) {
5319 vswap();
5320 swap(&c1, &c2);
5322 fc = vtop->c.i;
5323 if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
5324 op == TOK_PDIV) &&
5325 fc == 1) ||
5326 ((op == '+' || op == '-' || op == '|' || op == '^' ||
5327 op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
5328 fc == 0) ||
5329 (op == '&' &&
5330 fc == -1))) {
5331 /* nothing to do */
5332 vtop--;
5333 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
5334 /* try to use shifts instead of muls or divs */
5335 if (fc > 0 && (fc & (fc - 1)) == 0) {
5336 n = -1;
5337 while (fc) {
5338 fc >>= 1;
5339 n++;
5341 vtop->c.i = n;
5342 if (op == '*')
5343 op = TOK_SHL;
5344 else if (op == TOK_PDIV)
5345 op = TOK_SAR;
5346 else
5347 op = TOK_SHR;
5349 goto general_case;
5350 } else if (c2 && (op == '+' || op == '-') &&
5351 (vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) ==
5352 (VT_CONST | VT_SYM)) {
5353 /* symbol + constant case */
5354 if (op == '-')
5355 fc = -fc;
5356 vtop--;
5357 vtop->c.i += fc;
5358 } else {
5359 general_case:
5360 if (!nocode_wanted) {
5361 /* call low level op generator */
5362 gen_opi(op);
5363 } else {
5364 vtop--;
5370 /* generate a floating point operation with constant propagation */
5371 void gen_opif(int op)
5373 int c1, c2;
5374 SValue *v1, *v2;
5375 long double f1, f2;
5377 v1 = vtop - 1;
5378 v2 = vtop;
5379 /* currently, we cannot do computations with forward symbols */
5380 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5381 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5382 if (c1 && c2) {
5383 if (v1->type.t == VT_FLOAT) {
5384 f1 = v1->c.f;
5385 f2 = v2->c.f;
5386 } else if (v1->type.t == VT_DOUBLE) {
5387 f1 = v1->c.d;
5388 f2 = v2->c.d;
5389 } else {
5390 f1 = v1->c.ld;
5391 f2 = v2->c.ld;
5394 /* NOTE: we only do constant propagation if finite number (not
5395 NaN or infinity) (ANSI spec) */
5396 if (!ieee_finite(f1) || !ieee_finite(f2))
5397 goto general_case;
5399 switch(op) {
5400 case '+': f1 += f2; break;
5401 case '-': f1 -= f2; break;
5402 case '*': f1 *= f2; break;
5403 case '/':
5404 if (f2 == 0.0) {
5405 if (const_wanted)
5406 error("division by zero in constant");
5407 goto general_case;
5409 f1 /= f2;
5410 break;
5411 /* XXX: also handles tests ? */
5412 default:
5413 goto general_case;
5415 /* XXX: overflow test ? */
5416 if (v1->type.t == VT_FLOAT) {
5417 v1->c.f = f1;
5418 } else if (v1->type.t == VT_DOUBLE) {
5419 v1->c.d = f1;
5420 } else {
5421 v1->c.ld = f1;
5423 vtop--;
5424 } else {
5425 general_case:
5426 if (!nocode_wanted) {
5427 gen_opf(op);
5428 } else {
5429 vtop--;
5434 static int pointed_size(CType *type)
5436 int align;
5437 return type_size(pointed_type(type), &align);
5440 static inline int is_null_pointer(SValue *p)
5442 if ((p->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
5443 return 0;
5444 return ((p->type.t & VT_BTYPE) == VT_INT && p->c.i == 0) ||
5445 ((p->type.t & VT_BTYPE) == VT_LLONG && p->c.ll == 0);
5448 static inline int is_integer_btype(int bt)
5450 return (bt == VT_BYTE || bt == VT_SHORT ||
5451 bt == VT_INT || bt == VT_LLONG);
5454 /* check types for comparison or substraction of pointers */
5455 static void check_comparison_pointer_types(SValue *p1, SValue *p2, int op)
5457 CType *type1, *type2, tmp_type1, tmp_type2;
5458 int bt1, bt2;
5460 /* null pointers are accepted for all comparisons as gcc */
5461 if (is_null_pointer(p1) || is_null_pointer(p2))
5462 return;
5463 type1 = &p1->type;
5464 type2 = &p2->type;
5465 bt1 = type1->t & VT_BTYPE;
5466 bt2 = type2->t & VT_BTYPE;
5467 /* accept comparison between pointer and integer with a warning */
5468 if ((is_integer_btype(bt1) || is_integer_btype(bt2)) && op != '-') {
5469 warning("comparison between pointer and integer");
5470 return;
5473 /* both must be pointers or implicit function pointers */
5474 if (bt1 == VT_PTR) {
5475 type1 = pointed_type(type1);
5476 } else if (bt1 != VT_FUNC)
5477 goto invalid_operands;
5479 if (bt2 == VT_PTR) {
5480 type2 = pointed_type(type2);
5481 } else if (bt2 != VT_FUNC) {
5482 invalid_operands:
5483 error("invalid operands to binary %s", get_tok_str(op, NULL));
5485 if ((type1->t & VT_BTYPE) == VT_VOID ||
5486 (type2->t & VT_BTYPE) == VT_VOID)
5487 return;
5488 tmp_type1 = *type1;
5489 tmp_type2 = *type2;
5490 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5491 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5492 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
5493 /* gcc-like error if '-' is used */
5494 if (op == '-')
5495 goto invalid_operands;
5496 else
5497 warning("comparison of distinct pointer types lacks a cast");
5501 /* generic gen_op: handles types problems */
5502 void gen_op(int op)
5504 int u, t1, t2, bt1, bt2, t;
5505 CType type1;
5507 t1 = vtop[-1].type.t;
5508 t2 = vtop[0].type.t;
5509 bt1 = t1 & VT_BTYPE;
5510 bt2 = t2 & VT_BTYPE;
5512 if (bt1 == VT_PTR || bt2 == VT_PTR) {
5513 /* at least one operand is a pointer */
5514 /* relationnal op: must be both pointers */
5515 if (op >= TOK_ULT && op <= TOK_GT) {
5516 check_comparison_pointer_types(vtop - 1, vtop, op);
5517 /* pointers are handled are unsigned */
5518 t = VT_INT | VT_UNSIGNED;
5519 goto std_op;
5521 /* if both pointers, then it must be the '-' op */
5522 if (bt1 == VT_PTR && bt2 == VT_PTR) {
5523 if (op != '-')
5524 error("cannot use pointers here");
5525 check_comparison_pointer_types(vtop - 1, vtop, op);
5526 /* XXX: check that types are compatible */
5527 u = pointed_size(&vtop[-1].type);
5528 gen_opic(op);
5529 /* set to integer type */
5530 vtop->type.t = VT_INT;
5531 vpushi(u);
5532 gen_op(TOK_PDIV);
5533 } else {
5534 /* exactly one pointer : must be '+' or '-'. */
5535 if (op != '-' && op != '+')
5536 error("cannot use pointers here");
5537 /* Put pointer as first operand */
5538 if (bt2 == VT_PTR) {
5539 vswap();
5540 swap(&t1, &t2);
5542 type1 = vtop[-1].type;
5543 /* XXX: cast to int ? (long long case) */
5544 vpushi(pointed_size(&vtop[-1].type));
5545 gen_op('*');
5546 #ifdef CONFIG_TCC_BCHECK
5547 /* if evaluating constant expression, no code should be
5548 generated, so no bound check */
5549 if (do_bounds_check && !const_wanted) {
5550 /* if bounded pointers, we generate a special code to
5551 test bounds */
5552 if (op == '-') {
5553 vpushi(0);
5554 vswap();
5555 gen_op('-');
5557 gen_bounded_ptr_add();
5558 } else
5559 #endif
5561 gen_opic(op);
5563 /* put again type if gen_opic() swaped operands */
5564 vtop->type = type1;
5566 } else if (is_float(bt1) || is_float(bt2)) {
5567 /* compute bigger type and do implicit casts */
5568 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
5569 t = VT_LDOUBLE;
5570 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
5571 t = VT_DOUBLE;
5572 } else {
5573 t = VT_FLOAT;
5575 /* floats can only be used for a few operations */
5576 if (op != '+' && op != '-' && op != '*' && op != '/' &&
5577 (op < TOK_ULT || op > TOK_GT))
5578 error("invalid operands for binary operation");
5579 goto std_op;
5580 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
5581 /* cast to biggest op */
5582 t = VT_LLONG;
5583 /* convert to unsigned if it does not fit in a long long */
5584 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
5585 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
5586 t |= VT_UNSIGNED;
5587 goto std_op;
5588 } else {
5589 /* integer operations */
5590 t = VT_INT;
5591 /* convert to unsigned if it does not fit in an integer */
5592 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
5593 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
5594 t |= VT_UNSIGNED;
5595 std_op:
5596 /* XXX: currently, some unsigned operations are explicit, so
5597 we modify them here */
5598 if (t & VT_UNSIGNED) {
5599 if (op == TOK_SAR)
5600 op = TOK_SHR;
5601 else if (op == '/')
5602 op = TOK_UDIV;
5603 else if (op == '%')
5604 op = TOK_UMOD;
5605 else if (op == TOK_LT)
5606 op = TOK_ULT;
5607 else if (op == TOK_GT)
5608 op = TOK_UGT;
5609 else if (op == TOK_LE)
5610 op = TOK_ULE;
5611 else if (op == TOK_GE)
5612 op = TOK_UGE;
5614 vswap();
5615 type1.t = t;
5616 gen_cast(&type1);
5617 vswap();
5618 /* special case for shifts and long long: we keep the shift as
5619 an integer */
5620 if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL)
5621 type1.t = VT_INT;
5622 gen_cast(&type1);
5623 if (is_float(t))
5624 gen_opif(op);
5625 else if ((t & VT_BTYPE) == VT_LLONG)
5626 gen_opl(op);
5627 else
5628 gen_opic(op);
5629 if (op >= TOK_ULT && op <= TOK_GT) {
5630 /* relationnal op: the result is an int */
5631 vtop->type.t = VT_INT;
5632 } else {
5633 vtop->type.t = t;
5638 /* generic itof for unsigned long long case */
5639 void gen_cvt_itof1(int t)
5641 if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
5642 (VT_LLONG | VT_UNSIGNED)) {
5644 if (t == VT_FLOAT)
5645 vpush_global_sym(&func_old_type, TOK___ulltof);
5646 else if (t == VT_DOUBLE)
5647 vpush_global_sym(&func_old_type, TOK___ulltod);
5648 else
5649 vpush_global_sym(&func_old_type, TOK___ulltold);
5650 vrott(2);
5651 gfunc_call(1);
5652 vpushi(0);
5653 vtop->r = REG_FRET;
5654 } else {
5655 gen_cvt_itof(t);
5659 /* generic ftoi for unsigned long long case */
5660 void gen_cvt_ftoi1(int t)
5662 int st;
5664 if (t == (VT_LLONG | VT_UNSIGNED)) {
5665 /* not handled natively */
5666 st = vtop->type.t & VT_BTYPE;
5667 if (st == VT_FLOAT)
5668 vpush_global_sym(&func_old_type, TOK___fixunssfdi);
5669 else if (st == VT_DOUBLE)
5670 vpush_global_sym(&func_old_type, TOK___fixunsdfdi);
5671 else
5672 vpush_global_sym(&func_old_type, TOK___fixunsxfdi);
5673 vrott(2);
5674 gfunc_call(1);
5675 vpushi(0);
5676 vtop->r = REG_IRET;
5677 vtop->r2 = REG_LRET;
5678 } else {
5679 gen_cvt_ftoi(t);
5683 /* force char or short cast */
5684 void force_charshort_cast(int t)
5686 int bits, dbt;
5687 dbt = t & VT_BTYPE;
5688 /* XXX: add optimization if lvalue : just change type and offset */
5689 if (dbt == VT_BYTE)
5690 bits = 8;
5691 else
5692 bits = 16;
5693 if (t & VT_UNSIGNED) {
5694 vpushi((1 << bits) - 1);
5695 gen_op('&');
5696 } else {
5697 bits = 32 - bits;
5698 vpushi(bits);
5699 gen_op(TOK_SHL);
5700 vpushi(bits);
5701 gen_op(TOK_SAR);
5705 /* cast 'vtop' to 'type'. Casting to bitfields is forbidden. */
5706 static void gen_cast(CType *type)
5708 int sbt, dbt, sf, df, c;
5710 /* special delayed cast for char/short */
5711 /* XXX: in some cases (multiple cascaded casts), it may still
5712 be incorrect */
5713 if (vtop->r & VT_MUSTCAST) {
5714 vtop->r &= ~VT_MUSTCAST;
5715 force_charshort_cast(vtop->type.t);
5718 /* bitfields first get cast to ints */
5719 if (vtop->type.t & VT_BITFIELD) {
5720 gv(RC_INT);
5723 dbt = type->t & (VT_BTYPE | VT_UNSIGNED);
5724 sbt = vtop->type.t & (VT_BTYPE | VT_UNSIGNED);
5726 if (sbt != dbt && !nocode_wanted) {
5727 sf = is_float(sbt);
5728 df = is_float(dbt);
5729 c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5730 if (sf && df) {
5731 /* convert from fp to fp */
5732 if (c) {
5733 /* constant case: we can do it now */
5734 /* XXX: in ISOC, cannot do it if error in convert */
5735 if (dbt == VT_FLOAT && sbt == VT_DOUBLE)
5736 vtop->c.f = (float)vtop->c.d;
5737 else if (dbt == VT_FLOAT && sbt == VT_LDOUBLE)
5738 vtop->c.f = (float)vtop->c.ld;
5739 else if (dbt == VT_DOUBLE && sbt == VT_FLOAT)
5740 vtop->c.d = (double)vtop->c.f;
5741 else if (dbt == VT_DOUBLE && sbt == VT_LDOUBLE)
5742 vtop->c.d = (double)vtop->c.ld;
5743 else if (dbt == VT_LDOUBLE && sbt == VT_FLOAT)
5744 vtop->c.ld = (long double)vtop->c.f;
5745 else if (dbt == VT_LDOUBLE && sbt == VT_DOUBLE)
5746 vtop->c.ld = (long double)vtop->c.d;
5747 } else {
5748 /* non constant case: generate code */
5749 gen_cvt_ftof(dbt);
5751 } else if (df) {
5752 /* convert int to fp */
5753 if (c) {
5754 switch(sbt) {
5755 case VT_LLONG | VT_UNSIGNED:
5756 case VT_LLONG:
5757 /* XXX: add const cases for long long */
5758 goto do_itof;
5759 case VT_INT | VT_UNSIGNED:
5760 switch(dbt) {
5761 case VT_FLOAT: vtop->c.f = (float)vtop->c.ui; break;
5762 case VT_DOUBLE: vtop->c.d = (double)vtop->c.ui; break;
5763 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.ui; break;
5765 break;
5766 default:
5767 switch(dbt) {
5768 case VT_FLOAT: vtop->c.f = (float)vtop->c.i; break;
5769 case VT_DOUBLE: vtop->c.d = (double)vtop->c.i; break;
5770 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.i; break;
5772 break;
5774 } else {
5775 do_itof:
5776 #if !defined(TCC_TARGET_ARM)
5777 gen_cvt_itof1(dbt);
5778 #else
5779 gen_cvt_itof(dbt);
5780 #endif
5782 } else if (sf) {
5783 /* convert fp to int */
5784 /* we handle char/short/etc... with generic code */
5785 if (dbt != (VT_INT | VT_UNSIGNED) &&
5786 dbt != (VT_LLONG | VT_UNSIGNED) &&
5787 dbt != VT_LLONG)
5788 dbt = VT_INT;
5789 if (c) {
5790 switch(dbt) {
5791 case VT_LLONG | VT_UNSIGNED:
5792 case VT_LLONG:
5793 /* XXX: add const cases for long long */
5794 goto do_ftoi;
5795 case VT_INT | VT_UNSIGNED:
5796 switch(sbt) {
5797 case VT_FLOAT: vtop->c.ui = (unsigned int)vtop->c.d; break;
5798 case VT_DOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
5799 case VT_LDOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
5801 break;
5802 default:
5803 /* int case */
5804 switch(sbt) {
5805 case VT_FLOAT: vtop->c.i = (int)vtop->c.d; break;
5806 case VT_DOUBLE: vtop->c.i = (int)vtop->c.d; break;
5807 case VT_LDOUBLE: vtop->c.i = (int)vtop->c.d; break;
5809 break;
5811 } else {
5812 do_ftoi:
5813 gen_cvt_ftoi1(dbt);
5815 if (dbt == VT_INT && (type->t & (VT_BTYPE | VT_UNSIGNED)) != dbt) {
5816 /* additional cast for char/short/bool... */
5817 vtop->type.t = dbt;
5818 gen_cast(type);
5820 } else if ((dbt & VT_BTYPE) == VT_LLONG) {
5821 if ((sbt & VT_BTYPE) != VT_LLONG) {
5822 /* scalar to long long */
5823 if (c) {
5824 if (sbt == (VT_INT | VT_UNSIGNED))
5825 vtop->c.ll = vtop->c.ui;
5826 else
5827 vtop->c.ll = vtop->c.i;
5828 } else {
5829 /* machine independent conversion */
5830 gv(RC_INT);
5831 /* generate high word */
5832 if (sbt == (VT_INT | VT_UNSIGNED)) {
5833 vpushi(0);
5834 gv(RC_INT);
5835 } else {
5836 gv_dup();
5837 vpushi(31);
5838 gen_op(TOK_SAR);
5840 /* patch second register */
5841 vtop[-1].r2 = vtop->r;
5842 vpop();
5845 } else if (dbt == VT_BOOL) {
5846 /* scalar to bool */
5847 vpushi(0);
5848 gen_op(TOK_NE);
5849 } else if ((dbt & VT_BTYPE) == VT_BYTE ||
5850 (dbt & VT_BTYPE) == VT_SHORT) {
5851 force_charshort_cast(dbt);
5852 } else if ((dbt & VT_BTYPE) == VT_INT) {
5853 /* scalar to int */
5854 if (sbt == VT_LLONG) {
5855 /* from long long: just take low order word */
5856 lexpand();
5857 vpop();
5859 /* if lvalue and single word type, nothing to do because
5860 the lvalue already contains the real type size (see
5861 VT_LVAL_xxx constants) */
5864 vtop->type = *type;
5867 /* return type size. Put alignment at 'a' */
5868 static int type_size(CType *type, int *a)
5870 Sym *s;
5871 int bt;
5873 bt = type->t & VT_BTYPE;
5874 if (bt == VT_STRUCT) {
5875 /* struct/union */
5876 s = type->ref;
5877 *a = s->r;
5878 return s->c;
5879 } else if (bt == VT_PTR) {
5880 if (type->t & VT_ARRAY) {
5881 s = type->ref;
5882 return type_size(&s->type, a) * s->c;
5883 } else {
5884 *a = PTR_SIZE;
5885 return PTR_SIZE;
5887 } else if (bt == VT_LDOUBLE) {
5888 *a = LDOUBLE_ALIGN;
5889 return LDOUBLE_SIZE;
5890 } else if (bt == VT_DOUBLE || bt == VT_LLONG) {
5891 #ifdef TCC_TARGET_I386
5892 *a = 4;
5893 #else
5894 *a = 8;
5895 #endif
5896 return 8;
5897 } else if (bt == VT_INT || bt == VT_ENUM || bt == VT_FLOAT) {
5898 *a = 4;
5899 return 4;
5900 } else if (bt == VT_SHORT) {
5901 *a = 2;
5902 return 2;
5903 } else {
5904 /* char, void, function, _Bool */
5905 *a = 1;
5906 return 1;
5910 /* return the pointed type of t */
5911 static inline CType *pointed_type(CType *type)
5913 return &type->ref->type;
5916 /* modify type so that its it is a pointer to type. */
5917 static void mk_pointer(CType *type)
5919 Sym *s;
5920 s = sym_push(SYM_FIELD, type, 0, -1);
5921 type->t = VT_PTR | (type->t & ~VT_TYPE);
5922 type->ref = s;
5925 /* compare function types. OLD functions match any new functions */
5926 static int is_compatible_func(CType *type1, CType *type2)
5928 Sym *s1, *s2;
5930 s1 = type1->ref;
5931 s2 = type2->ref;
5932 if (!is_compatible_types(&s1->type, &s2->type))
5933 return 0;
5934 /* check func_call */
5935 if (s1->r != s2->r)
5936 return 0;
5937 /* XXX: not complete */
5938 if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
5939 return 1;
5940 if (s1->c != s2->c)
5941 return 0;
5942 while (s1 != NULL) {
5943 if (s2 == NULL)
5944 return 0;
5945 if (!is_compatible_types(&s1->type, &s2->type))
5946 return 0;
5947 s1 = s1->next;
5948 s2 = s2->next;
5950 if (s2)
5951 return 0;
5952 return 1;
5955 /* return true if type1 and type2 are exactly the same (including
5956 qualifiers).
5958 - enums are not checked as gcc __builtin_types_compatible_p ()
5960 static int is_compatible_types(CType *type1, CType *type2)
5962 int bt1, t1, t2;
5964 t1 = type1->t & VT_TYPE;
5965 t2 = type2->t & VT_TYPE;
5966 /* XXX: bitfields ? */
5967 if (t1 != t2)
5968 return 0;
5969 /* test more complicated cases */
5970 bt1 = t1 & VT_BTYPE;
5971 if (bt1 == VT_PTR) {
5972 type1 = pointed_type(type1);
5973 type2 = pointed_type(type2);
5974 return is_compatible_types(type1, type2);
5975 } else if (bt1 == VT_STRUCT) {
5976 return (type1->ref == type2->ref);
5977 } else if (bt1 == VT_FUNC) {
5978 return is_compatible_func(type1, type2);
5979 } else {
5980 return 1;
5984 /* print a type. If 'varstr' is not NULL, then the variable is also
5985 printed in the type */
5986 /* XXX: union */
5987 /* XXX: add array and function pointers */
5988 void type_to_str(char *buf, int buf_size,
5989 CType *type, const char *varstr)
5991 int bt, v, t;
5992 Sym *s, *sa;
5993 char buf1[256];
5994 const char *tstr;
5996 t = type->t & VT_TYPE;
5997 bt = t & VT_BTYPE;
5998 buf[0] = '\0';
5999 if (t & VT_CONSTANT)
6000 pstrcat(buf, buf_size, "const ");
6001 if (t & VT_VOLATILE)
6002 pstrcat(buf, buf_size, "volatile ");
6003 if (t & VT_UNSIGNED)
6004 pstrcat(buf, buf_size, "unsigned ");
6005 switch(bt) {
6006 case VT_VOID:
6007 tstr = "void";
6008 goto add_tstr;
6009 case VT_BOOL:
6010 tstr = "_Bool";
6011 goto add_tstr;
6012 case VT_BYTE:
6013 tstr = "char";
6014 goto add_tstr;
6015 case VT_SHORT:
6016 tstr = "short";
6017 goto add_tstr;
6018 case VT_INT:
6019 tstr = "int";
6020 goto add_tstr;
6021 case VT_LONG:
6022 tstr = "long";
6023 goto add_tstr;
6024 case VT_LLONG:
6025 tstr = "long long";
6026 goto add_tstr;
6027 case VT_FLOAT:
6028 tstr = "float";
6029 goto add_tstr;
6030 case VT_DOUBLE:
6031 tstr = "double";
6032 goto add_tstr;
6033 case VT_LDOUBLE:
6034 tstr = "long double";
6035 add_tstr:
6036 pstrcat(buf, buf_size, tstr);
6037 break;
6038 case VT_ENUM:
6039 case VT_STRUCT:
6040 if (bt == VT_STRUCT)
6041 tstr = "struct ";
6042 else
6043 tstr = "enum ";
6044 pstrcat(buf, buf_size, tstr);
6045 v = type->ref->v & ~SYM_STRUCT;
6046 if (v >= SYM_FIRST_ANOM)
6047 pstrcat(buf, buf_size, "<anonymous>");
6048 else
6049 pstrcat(buf, buf_size, get_tok_str(v, NULL));
6050 break;
6051 case VT_FUNC:
6052 s = type->ref;
6053 type_to_str(buf, buf_size, &s->type, varstr);
6054 pstrcat(buf, buf_size, "(");
6055 sa = s->next;
6056 while (sa != NULL) {
6057 type_to_str(buf1, sizeof(buf1), &sa->type, NULL);
6058 pstrcat(buf, buf_size, buf1);
6059 sa = sa->next;
6060 if (sa)
6061 pstrcat(buf, buf_size, ", ");
6063 pstrcat(buf, buf_size, ")");
6064 goto no_var;
6065 case VT_PTR:
6066 s = type->ref;
6067 pstrcpy(buf1, sizeof(buf1), "*");
6068 if (varstr)
6069 pstrcat(buf1, sizeof(buf1), varstr);
6070 type_to_str(buf, buf_size, &s->type, buf1);
6071 goto no_var;
6073 if (varstr) {
6074 pstrcat(buf, buf_size, " ");
6075 pstrcat(buf, buf_size, varstr);
6077 no_var: ;
6080 /* verify type compatibility to store vtop in 'dt' type, and generate
6081 casts if needed. */
6082 static void gen_assign_cast(CType *dt)
6084 CType *st, *type1, *type2, tmp_type1, tmp_type2;
6085 char buf1[256], buf2[256];
6086 int dbt, sbt;
6088 st = &vtop->type; /* source type */
6089 dbt = dt->t & VT_BTYPE;
6090 sbt = st->t & VT_BTYPE;
6091 if (dt->t & VT_CONSTANT)
6092 warning("assignment of read-only location");
6093 switch(dbt) {
6094 case VT_PTR:
6095 /* special cases for pointers */
6096 /* '0' can also be a pointer */
6097 if (is_null_pointer(vtop))
6098 goto type_ok;
6099 /* accept implicit pointer to integer cast with warning */
6100 if (is_integer_btype(sbt)) {
6101 warning("assignment makes pointer from integer without a cast");
6102 goto type_ok;
6104 type1 = pointed_type(dt);
6105 /* a function is implicitely a function pointer */
6106 if (sbt == VT_FUNC) {
6107 if ((type1->t & VT_BTYPE) != VT_VOID &&
6108 !is_compatible_types(pointed_type(dt), st))
6109 goto error;
6110 else
6111 goto type_ok;
6113 if (sbt != VT_PTR)
6114 goto error;
6115 type2 = pointed_type(st);
6116 if ((type1->t & VT_BTYPE) == VT_VOID ||
6117 (type2->t & VT_BTYPE) == VT_VOID) {
6118 /* void * can match anything */
6119 } else {
6120 /* exact type match, except for unsigned */
6121 tmp_type1 = *type1;
6122 tmp_type2 = *type2;
6123 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
6124 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
6125 if (!is_compatible_types(&tmp_type1, &tmp_type2))
6126 goto error;
6128 /* check const and volatile */
6129 if ((!(type1->t & VT_CONSTANT) && (type2->t & VT_CONSTANT)) ||
6130 (!(type1->t & VT_VOLATILE) && (type2->t & VT_VOLATILE)))
6131 warning("assignment discards qualifiers from pointer target type");
6132 break;
6133 case VT_BYTE:
6134 case VT_SHORT:
6135 case VT_INT:
6136 case VT_LLONG:
6137 if (sbt == VT_PTR || sbt == VT_FUNC) {
6138 warning("assignment makes integer from pointer without a cast");
6140 /* XXX: more tests */
6141 break;
6142 case VT_STRUCT:
6143 tmp_type1 = *dt;
6144 tmp_type2 = *st;
6145 tmp_type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
6146 tmp_type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
6147 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
6148 error:
6149 type_to_str(buf1, sizeof(buf1), st, NULL);
6150 type_to_str(buf2, sizeof(buf2), dt, NULL);
6151 error("cannot cast '%s' to '%s'", buf1, buf2);
6153 break;
6155 type_ok:
6156 gen_cast(dt);
6159 /* store vtop in lvalue pushed on stack */
6160 void vstore(void)
6162 int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
6164 ft = vtop[-1].type.t;
6165 sbt = vtop->type.t & VT_BTYPE;
6166 dbt = ft & VT_BTYPE;
6167 if (((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
6168 (sbt == VT_INT && dbt == VT_SHORT)) {
6169 /* optimize char/short casts */
6170 delayed_cast = VT_MUSTCAST;
6171 vtop->type.t = ft & VT_TYPE;
6172 /* XXX: factorize */
6173 if (ft & VT_CONSTANT)
6174 warning("assignment of read-only location");
6175 } else {
6176 delayed_cast = 0;
6177 if (!(ft & VT_BITFIELD))
6178 gen_assign_cast(&vtop[-1].type);
6181 if (sbt == VT_STRUCT) {
6182 /* if structure, only generate pointer */
6183 /* structure assignment : generate memcpy */
6184 /* XXX: optimize if small size */
6185 if (!nocode_wanted) {
6186 size = type_size(&vtop->type, &align);
6188 vpush_global_sym(&func_old_type, TOK_memcpy);
6190 /* destination */
6191 vpushv(vtop - 2);
6192 vtop->type.t = VT_INT;
6193 gaddrof();
6194 /* source */
6195 vpushv(vtop - 2);
6196 vtop->type.t = VT_INT;
6197 gaddrof();
6198 /* type size */
6199 vpushi(size);
6200 gfunc_call(3);
6202 vswap();
6203 vpop();
6204 } else {
6205 vswap();
6206 vpop();
6208 /* leave source on stack */
6209 } else if (ft & VT_BITFIELD) {
6210 /* bitfield store handling */
6211 bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
6212 bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
6213 /* remove bit field info to avoid loops */
6214 vtop[-1].type.t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
6216 /* duplicate destination */
6217 vdup();
6218 vtop[-1] = vtop[-2];
6220 /* mask and shift source */
6221 vpushi((1 << bit_size) - 1);
6222 gen_op('&');
6223 vpushi(bit_pos);
6224 gen_op(TOK_SHL);
6225 /* load destination, mask and or with source */
6226 vswap();
6227 vpushi(~(((1 << bit_size) - 1) << bit_pos));
6228 gen_op('&');
6229 gen_op('|');
6230 /* store result */
6231 vstore();
6232 } else {
6233 #ifdef CONFIG_TCC_BCHECK
6234 /* bound check case */
6235 if (vtop[-1].r & VT_MUSTBOUND) {
6236 vswap();
6237 gbound();
6238 vswap();
6240 #endif
6241 if (!nocode_wanted) {
6242 rc = RC_INT;
6243 if (is_float(ft))
6244 rc = RC_FLOAT;
6245 r = gv(rc); /* generate value */
6246 /* if lvalue was saved on stack, must read it */
6247 if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
6248 SValue sv;
6249 t = get_reg(RC_INT);
6250 sv.type.t = VT_INT;
6251 sv.r = VT_LOCAL | VT_LVAL;
6252 sv.c.ul = vtop[-1].c.ul;
6253 load(t, &sv);
6254 vtop[-1].r = t | VT_LVAL;
6256 store(r, vtop - 1);
6257 /* two word case handling : store second register at word + 4 */
6258 if ((ft & VT_BTYPE) == VT_LLONG) {
6259 vswap();
6260 /* convert to int to increment easily */
6261 vtop->type.t = VT_INT;
6262 gaddrof();
6263 vpushi(4);
6264 gen_op('+');
6265 vtop->r |= VT_LVAL;
6266 vswap();
6267 /* XXX: it works because r2 is spilled last ! */
6268 store(vtop->r2, vtop - 1);
6271 vswap();
6272 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
6273 vtop->r |= delayed_cast;
6277 /* post defines POST/PRE add. c is the token ++ or -- */
6278 void inc(int post, int c)
6280 test_lvalue();
6281 vdup(); /* save lvalue */
6282 if (post) {
6283 gv_dup(); /* duplicate value */
6284 vrotb(3);
6285 vrotb(3);
6287 /* add constant */
6288 vpushi(c - TOK_MID);
6289 gen_op('+');
6290 vstore(); /* store value */
6291 if (post)
6292 vpop(); /* if post op, return saved value */
6295 /* Parse GNUC __attribute__ extension. Currently, the following
6296 extensions are recognized:
6297 - aligned(n) : set data/function alignment.
6298 - packed : force data alignment to 1
6299 - section(x) : generate data/code in this section.
6300 - unused : currently ignored, but may be used someday.
6301 - regparm(n) : pass function parameters in registers (i386 only)
6303 static void parse_attribute(AttributeDef *ad)
6305 int t, n;
6307 while (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) {
6308 next();
6309 skip('(');
6310 skip('(');
6311 while (tok != ')') {
6312 if (tok < TOK_IDENT)
6313 expect("attribute name");
6314 t = tok;
6315 next();
6316 switch(t) {
6317 case TOK_SECTION1:
6318 case TOK_SECTION2:
6319 skip('(');
6320 if (tok != TOK_STR)
6321 expect("section name");
6322 ad->section = find_section(tcc_state, (char *)tokc.cstr->data);
6323 next();
6324 skip(')');
6325 break;
6326 case TOK_ALIGNED1:
6327 case TOK_ALIGNED2:
6328 if (tok == '(') {
6329 next();
6330 n = expr_const();
6331 if (n <= 0 || (n & (n - 1)) != 0)
6332 error("alignment must be a positive power of two");
6333 skip(')');
6334 } else {
6335 n = MAX_ALIGN;
6337 ad->aligned = n;
6338 break;
6339 case TOK_PACKED1:
6340 case TOK_PACKED2:
6341 ad->packed = 1;
6342 break;
6343 case TOK_UNUSED1:
6344 case TOK_UNUSED2:
6345 /* currently, no need to handle it because tcc does not
6346 track unused objects */
6347 break;
6348 case TOK_NORETURN1:
6349 case TOK_NORETURN2:
6350 /* currently, no need to handle it because tcc does not
6351 track unused objects */
6352 break;
6353 case TOK_CDECL1:
6354 case TOK_CDECL2:
6355 case TOK_CDECL3:
6356 ad->func_call = FUNC_CDECL;
6357 break;
6358 case TOK_STDCALL1:
6359 case TOK_STDCALL2:
6360 case TOK_STDCALL3:
6361 ad->func_call = FUNC_STDCALL;
6362 break;
6363 #ifdef TCC_TARGET_I386
6364 case TOK_REGPARM1:
6365 case TOK_REGPARM2:
6366 skip('(');
6367 n = expr_const();
6368 if (n > 3)
6369 n = 3;
6370 else if (n < 0)
6371 n = 0;
6372 if (n > 0)
6373 ad->func_call = FUNC_FASTCALL1 + n - 1;
6374 skip(')');
6375 break;
6376 #endif
6377 case TOK_DLLEXPORT:
6378 ad->dllexport = 1;
6379 break;
6380 default:
6381 if (tcc_state->warn_unsupported)
6382 warning("'%s' attribute ignored", get_tok_str(t, NULL));
6383 /* skip parameters */
6384 /* XXX: skip parenthesis too */
6385 if (tok == '(') {
6386 next();
6387 while (tok != ')' && tok != -1)
6388 next();
6389 next();
6391 break;
6393 if (tok != ',')
6394 break;
6395 next();
6397 skip(')');
6398 skip(')');
6402 /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
6403 static void struct_decl(CType *type, int u)
6405 int a, v, size, align, maxalign, c, offset;
6406 int bit_size, bit_pos, bsize, bt, lbit_pos;
6407 Sym *s, *ss, **ps;
6408 AttributeDef ad;
6409 CType type1, btype;
6411 a = tok; /* save decl type */
6412 next();
6413 if (tok != '{') {
6414 v = tok;
6415 next();
6416 /* struct already defined ? return it */
6417 if (v < TOK_IDENT)
6418 expect("struct/union/enum name");
6419 s = struct_find(v);
6420 if (s) {
6421 if (s->type.t != a)
6422 error("invalid type");
6423 goto do_decl;
6425 } else {
6426 v = anon_sym++;
6428 type1.t = a;
6429 /* we put an undefined size for struct/union */
6430 s = sym_push(v | SYM_STRUCT, &type1, 0, -1);
6431 s->r = 0; /* default alignment is zero as gcc */
6432 /* put struct/union/enum name in type */
6433 do_decl:
6434 type->t = u;
6435 type->ref = s;
6437 if (tok == '{') {
6438 next();
6439 if (s->c != -1)
6440 error("struct/union/enum already defined");
6441 /* cannot be empty */
6442 c = 0;
6443 /* non empty enums are not allowed */
6444 if (a == TOK_ENUM) {
6445 for(;;) {
6446 v = tok;
6447 if (v < TOK_UIDENT)
6448 expect("identifier");
6449 next();
6450 if (tok == '=') {
6451 next();
6452 c = expr_const();
6454 /* enum symbols have static storage */
6455 ss = sym_push(v, &int_type, VT_CONST, c);
6456 ss->type.t |= VT_STATIC;
6457 if (tok != ',')
6458 break;
6459 next();
6460 c++;
6461 /* NOTE: we accept a trailing comma */
6462 if (tok == '}')
6463 break;
6465 skip('}');
6466 } else {
6467 maxalign = 1;
6468 ps = &s->next;
6469 bit_pos = 0;
6470 offset = 0;
6471 while (tok != '}') {
6472 parse_btype(&btype, &ad);
6473 while (1) {
6474 bit_size = -1;
6475 v = 0;
6476 type1 = btype;
6477 if (tok != ':') {
6478 type_decl(&type1, &ad, &v, TYPE_DIRECT);
6479 if ((type1.t & VT_BTYPE) == VT_FUNC ||
6480 (type1.t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN | VT_INLINE)))
6481 error("invalid type for '%s'",
6482 get_tok_str(v, NULL));
6484 if (tok == ':') {
6485 next();
6486 bit_size = expr_const();
6487 /* XXX: handle v = 0 case for messages */
6488 if (bit_size < 0)
6489 error("negative width in bit-field '%s'",
6490 get_tok_str(v, NULL));
6491 if (v && bit_size == 0)
6492 error("zero width for bit-field '%s'",
6493 get_tok_str(v, NULL));
6495 size = type_size(&type1, &align);
6496 if (ad.aligned) {
6497 if (align < ad.aligned)
6498 align = ad.aligned;
6499 } else if (ad.packed) {
6500 align = 1;
6501 } else if (*tcc_state->pack_stack_ptr) {
6502 if (align > *tcc_state->pack_stack_ptr)
6503 align = *tcc_state->pack_stack_ptr;
6505 lbit_pos = 0;
6506 if (bit_size >= 0) {
6507 bt = type1.t & VT_BTYPE;
6508 if (bt != VT_INT &&
6509 bt != VT_BYTE &&
6510 bt != VT_SHORT &&
6511 bt != VT_BOOL &&
6512 bt != VT_ENUM)
6513 error("bitfields must have scalar type");
6514 bsize = size * 8;
6515 if (bit_size > bsize) {
6516 error("width of '%s' exceeds its type",
6517 get_tok_str(v, NULL));
6518 } else if (bit_size == bsize) {
6519 /* no need for bit fields */
6520 bit_pos = 0;
6521 } else if (bit_size == 0) {
6522 /* XXX: what to do if only padding in a
6523 structure ? */
6524 /* zero size: means to pad */
6525 if (bit_pos > 0)
6526 bit_pos = bsize;
6527 } else {
6528 /* we do not have enough room ? */
6529 if ((bit_pos + bit_size) > bsize)
6530 bit_pos = 0;
6531 lbit_pos = bit_pos;
6532 /* XXX: handle LSB first */
6533 type1.t |= VT_BITFIELD |
6534 (bit_pos << VT_STRUCT_SHIFT) |
6535 (bit_size << (VT_STRUCT_SHIFT + 6));
6536 bit_pos += bit_size;
6538 } else {
6539 bit_pos = 0;
6541 if (v) {
6542 /* add new memory data only if starting
6543 bit field */
6544 if (lbit_pos == 0) {
6545 if (a == TOK_STRUCT) {
6546 c = (c + align - 1) & -align;
6547 offset = c;
6548 c += size;
6549 } else {
6550 offset = 0;
6551 if (size > c)
6552 c = size;
6554 if (align > maxalign)
6555 maxalign = align;
6557 #if 0
6558 printf("add field %s offset=%d",
6559 get_tok_str(v, NULL), offset);
6560 if (type1.t & VT_BITFIELD) {
6561 printf(" pos=%d size=%d",
6562 (type1.t >> VT_STRUCT_SHIFT) & 0x3f,
6563 (type1.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
6565 printf("\n");
6566 #endif
6567 ss = sym_push(v | SYM_FIELD, &type1, 0, offset);
6568 *ps = ss;
6569 ps = &ss->next;
6571 if (tok == ';' || tok == TOK_EOF)
6572 break;
6573 skip(',');
6575 skip(';');
6577 skip('}');
6578 /* store size and alignment */
6579 s->c = (c + maxalign - 1) & -maxalign;
6580 s->r = maxalign;
6585 /* return 0 if no type declaration. otherwise, return the basic type
6586 and skip it.
6588 static int parse_btype(CType *type, AttributeDef *ad)
6590 int t, u, type_found, typespec_found;
6591 Sym *s;
6592 CType type1;
6594 memset(ad, 0, sizeof(AttributeDef));
6595 type_found = 0;
6596 typespec_found = 0;
6597 t = 0;
6598 while(1) {
6599 switch(tok) {
6600 case TOK_EXTENSION:
6601 /* currently, we really ignore extension */
6602 next();
6603 continue;
6605 /* basic types */
6606 case TOK_CHAR:
6607 u = VT_BYTE;
6608 basic_type:
6609 next();
6610 basic_type1:
6611 if ((t & VT_BTYPE) != 0)
6612 error("too many basic types");
6613 t |= u;
6614 typespec_found = 1;
6615 break;
6616 case TOK_VOID:
6617 u = VT_VOID;
6618 goto basic_type;
6619 case TOK_SHORT:
6620 u = VT_SHORT;
6621 goto basic_type;
6622 case TOK_INT:
6623 next();
6624 typespec_found = 1;
6625 break;
6626 case TOK_LONG:
6627 next();
6628 if ((t & VT_BTYPE) == VT_DOUBLE) {
6629 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6630 } else if ((t & VT_BTYPE) == VT_LONG) {
6631 t = (t & ~VT_BTYPE) | VT_LLONG;
6632 } else {
6633 u = VT_LONG;
6634 goto basic_type1;
6636 break;
6637 case TOK_BOOL:
6638 u = VT_BOOL;
6639 goto basic_type;
6640 case TOK_FLOAT:
6641 u = VT_FLOAT;
6642 goto basic_type;
6643 case TOK_DOUBLE:
6644 next();
6645 if ((t & VT_BTYPE) == VT_LONG) {
6646 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6647 } else {
6648 u = VT_DOUBLE;
6649 goto basic_type1;
6651 break;
6652 case TOK_ENUM:
6653 struct_decl(&type1, VT_ENUM);
6654 basic_type2:
6655 u = type1.t;
6656 type->ref = type1.ref;
6657 goto basic_type1;
6658 case TOK_STRUCT:
6659 case TOK_UNION:
6660 struct_decl(&type1, VT_STRUCT);
6661 goto basic_type2;
6663 /* type modifiers */
6664 case TOK_CONST1:
6665 case TOK_CONST2:
6666 case TOK_CONST3:
6667 t |= VT_CONSTANT;
6668 next();
6669 break;
6670 case TOK_VOLATILE1:
6671 case TOK_VOLATILE2:
6672 case TOK_VOLATILE3:
6673 t |= VT_VOLATILE;
6674 next();
6675 break;
6676 case TOK_SIGNED1:
6677 case TOK_SIGNED2:
6678 case TOK_SIGNED3:
6679 typespec_found = 1;
6680 t |= VT_SIGNED;
6681 next();
6682 break;
6683 case TOK_REGISTER:
6684 case TOK_AUTO:
6685 case TOK_RESTRICT1:
6686 case TOK_RESTRICT2:
6687 case TOK_RESTRICT3:
6688 next();
6689 break;
6690 case TOK_UNSIGNED:
6691 t |= VT_UNSIGNED;
6692 next();
6693 typespec_found = 1;
6694 break;
6696 /* storage */
6697 case TOK_EXTERN:
6698 t |= VT_EXTERN;
6699 next();
6700 break;
6701 case TOK_STATIC:
6702 t |= VT_STATIC;
6703 next();
6704 break;
6705 case TOK_TYPEDEF:
6706 t |= VT_TYPEDEF;
6707 next();
6708 break;
6709 case TOK_INLINE1:
6710 case TOK_INLINE2:
6711 case TOK_INLINE3:
6712 t |= VT_INLINE;
6713 next();
6714 break;
6716 /* GNUC attribute */
6717 case TOK_ATTRIBUTE1:
6718 case TOK_ATTRIBUTE2:
6719 parse_attribute(ad);
6720 break;
6721 /* GNUC typeof */
6722 case TOK_TYPEOF1:
6723 case TOK_TYPEOF2:
6724 case TOK_TYPEOF3:
6725 next();
6726 parse_expr_type(&type1);
6727 goto basic_type2;
6728 default:
6729 if (typespec_found)
6730 goto the_end;
6731 s = sym_find(tok);
6732 if (!s || !(s->type.t & VT_TYPEDEF))
6733 goto the_end;
6734 t |= (s->type.t & ~VT_TYPEDEF);
6735 type->ref = s->type.ref;
6736 next();
6737 break;
6739 type_found = 1;
6741 the_end:
6742 if ((t & (VT_SIGNED|VT_UNSIGNED)) == (VT_SIGNED|VT_UNSIGNED))
6743 error("signed and unsigned modifier");
6744 if (tcc_state->char_is_unsigned) {
6745 if ((t & (VT_SIGNED|VT_UNSIGNED|VT_BTYPE)) == VT_BYTE)
6746 t |= VT_UNSIGNED;
6748 t &= ~VT_SIGNED;
6750 /* long is never used as type */
6751 if ((t & VT_BTYPE) == VT_LONG)
6752 t = (t & ~VT_BTYPE) | VT_INT;
6753 type->t = t;
6754 return type_found;
6757 /* convert a function parameter type (array to pointer and function to
6758 function pointer) */
6759 static inline void convert_parameter_type(CType *pt)
6761 /* remove const and volatile qualifiers (XXX: const could be used
6762 to indicate a const function parameter */
6763 pt->t &= ~(VT_CONSTANT | VT_VOLATILE);
6764 /* array must be transformed to pointer according to ANSI C */
6765 pt->t &= ~VT_ARRAY;
6766 if ((pt->t & VT_BTYPE) == VT_FUNC) {
6767 mk_pointer(pt);
6771 static void post_type(CType *type, AttributeDef *ad)
6773 int n, l, t1;
6774 Sym **plast, *s, *first;
6775 AttributeDef ad1;
6776 CType pt;
6778 if (tok == '(') {
6779 /* function declaration */
6780 next();
6781 l = 0;
6782 first = NULL;
6783 plast = &first;
6784 while (tok != ')') {
6785 /* read param name and compute offset */
6786 if (l != FUNC_OLD) {
6787 if (!parse_btype(&pt, &ad1)) {
6788 if (l) {
6789 error("invalid type");
6790 } else {
6791 l = FUNC_OLD;
6792 goto old_proto;
6795 l = FUNC_NEW;
6796 if ((pt.t & VT_BTYPE) == VT_VOID && tok == ')')
6797 break;
6798 type_decl(&pt, &ad1, &n, TYPE_DIRECT | TYPE_ABSTRACT);
6799 if ((pt.t & VT_BTYPE) == VT_VOID)
6800 error("parameter declared as void");
6801 } else {
6802 old_proto:
6803 n = tok;
6804 pt.t = VT_INT;
6805 next();
6807 convert_parameter_type(&pt);
6808 s = sym_push(n | SYM_FIELD, &pt, 0, 0);
6809 *plast = s;
6810 plast = &s->next;
6811 if (tok == ',') {
6812 next();
6813 if (l == FUNC_NEW && tok == TOK_DOTS) {
6814 l = FUNC_ELLIPSIS;
6815 next();
6816 break;
6820 /* if no parameters, then old type prototype */
6821 if (l == 0)
6822 l = FUNC_OLD;
6823 skip(')');
6824 t1 = type->t & VT_STORAGE;
6825 /* NOTE: const is ignored in returned type as it has a special
6826 meaning in gcc / C++ */
6827 type->t &= ~(VT_STORAGE | VT_CONSTANT);
6828 post_type(type, ad);
6829 /* we push a anonymous symbol which will contain the function prototype */
6830 s = sym_push(SYM_FIELD, type, ad->func_call, l);
6831 s->next = first;
6832 type->t = t1 | VT_FUNC;
6833 type->ref = s;
6834 } else if (tok == '[') {
6835 /* array definition */
6836 next();
6837 n = -1;
6838 if (tok != ']') {
6839 n = expr_const();
6840 if (n < 0)
6841 error("invalid array size");
6843 skip(']');
6844 /* parse next post type */
6845 t1 = type->t & VT_STORAGE;
6846 type->t &= ~VT_STORAGE;
6847 post_type(type, ad);
6849 /* we push a anonymous symbol which will contain the array
6850 element type */
6851 s = sym_push(SYM_FIELD, type, 0, n);
6852 type->t = t1 | VT_ARRAY | VT_PTR;
6853 type->ref = s;
6857 /* Parse a type declaration (except basic type), and return the type
6858 in 'type'. 'td' is a bitmask indicating which kind of type decl is
6859 expected. 'type' should contain the basic type. 'ad' is the
6860 attribute definition of the basic type. It can be modified by
6861 type_decl().
6863 static void type_decl(CType *type, AttributeDef *ad, int *v, int td)
6865 Sym *s;
6866 CType type1, *type2;
6867 int qualifiers;
6869 while (tok == '*') {
6870 qualifiers = 0;
6871 redo:
6872 next();
6873 switch(tok) {
6874 case TOK_CONST1:
6875 case TOK_CONST2:
6876 case TOK_CONST3:
6877 qualifiers |= VT_CONSTANT;
6878 goto redo;
6879 case TOK_VOLATILE1:
6880 case TOK_VOLATILE2:
6881 case TOK_VOLATILE3:
6882 qualifiers |= VT_VOLATILE;
6883 goto redo;
6884 case TOK_RESTRICT1:
6885 case TOK_RESTRICT2:
6886 case TOK_RESTRICT3:
6887 goto redo;
6889 mk_pointer(type);
6890 type->t |= qualifiers;
6893 /* XXX: clarify attribute handling */
6894 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6895 parse_attribute(ad);
6897 /* recursive type */
6898 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
6899 type1.t = 0; /* XXX: same as int */
6900 if (tok == '(') {
6901 next();
6902 /* XXX: this is not correct to modify 'ad' at this point, but
6903 the syntax is not clear */
6904 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6905 parse_attribute(ad);
6906 type_decl(&type1, ad, v, td);
6907 skip(')');
6908 } else {
6909 /* type identifier */
6910 if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
6911 *v = tok;
6912 next();
6913 } else {
6914 if (!(td & TYPE_ABSTRACT))
6915 expect("identifier");
6916 *v = 0;
6919 post_type(type, ad);
6920 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6921 parse_attribute(ad);
6922 if (!type1.t)
6923 return;
6924 /* append type at the end of type1 */
6925 type2 = &type1;
6926 for(;;) {
6927 s = type2->ref;
6928 type2 = &s->type;
6929 if (!type2->t) {
6930 *type2 = *type;
6931 break;
6934 *type = type1;
6937 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
6938 static int lvalue_type(int t)
6940 int bt, r;
6941 r = VT_LVAL;
6942 bt = t & VT_BTYPE;
6943 if (bt == VT_BYTE || bt == VT_BOOL)
6944 r |= VT_LVAL_BYTE;
6945 else if (bt == VT_SHORT)
6946 r |= VT_LVAL_SHORT;
6947 else
6948 return r;
6949 if (t & VT_UNSIGNED)
6950 r |= VT_LVAL_UNSIGNED;
6951 return r;
6954 /* indirection with full error checking and bound check */
6955 static void indir(void)
6957 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
6958 expect("pointer");
6959 if ((vtop->r & VT_LVAL) && !nocode_wanted)
6960 gv(RC_INT);
6961 vtop->type = *pointed_type(&vtop->type);
6962 /* an array is never an lvalue */
6963 if (!(vtop->type.t & VT_ARRAY)) {
6964 vtop->r |= lvalue_type(vtop->type.t);
6965 /* if bound checking, the referenced pointer must be checked */
6966 if (do_bounds_check)
6967 vtop->r |= VT_MUSTBOUND;
6971 /* pass a parameter to a function and do type checking and casting */
6972 static void gfunc_param_typed(Sym *func, Sym *arg)
6974 int func_type;
6975 CType type;
6977 func_type = func->c;
6978 if (func_type == FUNC_OLD ||
6979 (func_type == FUNC_ELLIPSIS && arg == NULL)) {
6980 /* default casting : only need to convert float to double */
6981 if ((vtop->type.t & VT_BTYPE) == VT_FLOAT) {
6982 type.t = VT_DOUBLE;
6983 gen_cast(&type);
6985 } else if (arg == NULL) {
6986 error("too many arguments to function");
6987 } else {
6988 type = arg->type;
6989 type.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
6990 gen_assign_cast(&type);
6994 /* parse an expression of the form '(type)' or '(expr)' and return its
6995 type */
6996 static void parse_expr_type(CType *type)
6998 int n;
6999 AttributeDef ad;
7001 skip('(');
7002 if (parse_btype(type, &ad)) {
7003 type_decl(type, &ad, &n, TYPE_ABSTRACT);
7004 } else {
7005 expr_type(type);
7007 skip(')');
7010 static void parse_type(CType *type)
7012 AttributeDef ad;
7013 int n;
7015 if (!parse_btype(type, &ad)) {
7016 expect("type");
7018 type_decl(type, &ad, &n, TYPE_ABSTRACT);
7021 static void vpush_tokc(int t)
7023 CType type;
7024 type.t = t;
7025 vsetc(&type, VT_CONST, &tokc);
7028 static void unary(void)
7030 int n, t, align, size, r;
7031 CType type;
7032 Sym *s;
7033 AttributeDef ad;
7035 /* XXX: GCC 2.95.3 does not generate a table although it should be
7036 better here */
7037 tok_next:
7038 switch(tok) {
7039 case TOK_EXTENSION:
7040 next();
7041 goto tok_next;
7042 case TOK_CINT:
7043 case TOK_CCHAR:
7044 case TOK_LCHAR:
7045 vpushi(tokc.i);
7046 next();
7047 break;
7048 case TOK_CUINT:
7049 vpush_tokc(VT_INT | VT_UNSIGNED);
7050 next();
7051 break;
7052 case TOK_CLLONG:
7053 vpush_tokc(VT_LLONG);
7054 next();
7055 break;
7056 case TOK_CULLONG:
7057 vpush_tokc(VT_LLONG | VT_UNSIGNED);
7058 next();
7059 break;
7060 case TOK_CFLOAT:
7061 vpush_tokc(VT_FLOAT);
7062 next();
7063 break;
7064 case TOK_CDOUBLE:
7065 vpush_tokc(VT_DOUBLE);
7066 next();
7067 break;
7068 case TOK_CLDOUBLE:
7069 vpush_tokc(VT_LDOUBLE);
7070 next();
7071 break;
7072 case TOK___FUNCTION__:
7073 if (!gnu_ext)
7074 goto tok_identifier;
7075 /* fall thru */
7076 case TOK___FUNC__:
7078 void *ptr;
7079 int len;
7080 /* special function name identifier */
7081 len = strlen(funcname) + 1;
7082 /* generate char[len] type */
7083 type.t = VT_BYTE;
7084 mk_pointer(&type);
7085 type.t |= VT_ARRAY;
7086 type.ref->c = len;
7087 vpush_ref(&type, data_section, data_section->data_offset, len);
7088 ptr = section_ptr_add(data_section, len);
7089 memcpy(ptr, funcname, len);
7090 next();
7092 break;
7093 case TOK_LSTR:
7094 t = VT_INT;
7095 goto str_init;
7096 case TOK_STR:
7097 /* string parsing */
7098 t = VT_BYTE;
7099 str_init:
7100 if (tcc_state->warn_write_strings)
7101 t |= VT_CONSTANT;
7102 type.t = t;
7103 mk_pointer(&type);
7104 type.t |= VT_ARRAY;
7105 memset(&ad, 0, sizeof(AttributeDef));
7106 decl_initializer_alloc(&type, &ad, VT_CONST, 2, 0, 0);
7107 break;
7108 case '(':
7109 next();
7110 /* cast ? */
7111 if (parse_btype(&type, &ad)) {
7112 type_decl(&type, &ad, &n, TYPE_ABSTRACT);
7113 skip(')');
7114 /* check ISOC99 compound literal */
7115 if (tok == '{') {
7116 /* data is allocated locally by default */
7117 if (global_expr)
7118 r = VT_CONST;
7119 else
7120 r = VT_LOCAL;
7121 /* all except arrays are lvalues */
7122 if (!(type.t & VT_ARRAY))
7123 r |= lvalue_type(type.t);
7124 memset(&ad, 0, sizeof(AttributeDef));
7125 decl_initializer_alloc(&type, &ad, r, 1, 0, 0);
7126 } else {
7127 unary();
7128 gen_cast(&type);
7130 } else if (tok == '{') {
7131 /* save all registers */
7132 save_regs(0);
7133 /* statement expression : we do not accept break/continue
7134 inside as GCC does */
7135 block(NULL, NULL, NULL, NULL, 0, 1);
7136 skip(')');
7137 } else {
7138 gexpr();
7139 skip(')');
7141 break;
7142 case '*':
7143 next();
7144 unary();
7145 indir();
7146 break;
7147 case '&':
7148 next();
7149 unary();
7150 /* functions names must be treated as function pointers,
7151 except for unary '&' and sizeof. Since we consider that
7152 functions are not lvalues, we only have to handle it
7153 there and in function calls. */
7154 /* arrays can also be used although they are not lvalues */
7155 if ((vtop->type.t & VT_BTYPE) != VT_FUNC &&
7156 !(vtop->type.t & VT_ARRAY))
7157 test_lvalue();
7158 mk_pointer(&vtop->type);
7159 gaddrof();
7160 break;
7161 case '!':
7162 next();
7163 unary();
7164 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST)
7165 vtop->c.i = !vtop->c.i;
7166 else if ((vtop->r & VT_VALMASK) == VT_CMP)
7167 vtop->c.i = vtop->c.i ^ 1;
7168 else
7169 vseti(VT_JMP, gtst(1, 0));
7170 break;
7171 case '~':
7172 next();
7173 unary();
7174 vpushi(-1);
7175 gen_op('^');
7176 break;
7177 case '+':
7178 next();
7179 /* in order to force cast, we add zero */
7180 unary();
7181 if ((vtop->type.t & VT_BTYPE) == VT_PTR)
7182 error("pointer not accepted for unary plus");
7183 vpushi(0);
7184 gen_op('+');
7185 break;
7186 case TOK_SIZEOF:
7187 case TOK_ALIGNOF1:
7188 case TOK_ALIGNOF2:
7189 t = tok;
7190 next();
7191 if (tok == '(') {
7192 parse_expr_type(&type);
7193 } else {
7194 unary_type(&type);
7196 size = type_size(&type, &align);
7197 if (t == TOK_SIZEOF) {
7198 if (size < 0)
7199 error("sizeof applied to an incomplete type");
7200 vpushi(size);
7201 } else {
7202 vpushi(align);
7204 break;
7206 case TOK_builtin_types_compatible_p:
7208 CType type1, type2;
7209 next();
7210 skip('(');
7211 parse_type(&type1);
7212 skip(',');
7213 parse_type(&type2);
7214 skip(')');
7215 type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
7216 type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
7217 vpushi(is_compatible_types(&type1, &type2));
7219 break;
7220 case TOK_builtin_constant_p:
7222 int saved_nocode_wanted, res;
7223 next();
7224 skip('(');
7225 saved_nocode_wanted = nocode_wanted;
7226 nocode_wanted = 1;
7227 gexpr();
7228 res = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
7229 vpop();
7230 nocode_wanted = saved_nocode_wanted;
7231 skip(')');
7232 vpushi(res);
7234 break;
7235 case TOK_INC:
7236 case TOK_DEC:
7237 t = tok;
7238 next();
7239 unary();
7240 inc(0, t);
7241 break;
7242 case '-':
7243 next();
7244 vpushi(0);
7245 unary();
7246 gen_op('-');
7247 break;
7248 case TOK_LAND:
7249 if (!gnu_ext)
7250 goto tok_identifier;
7251 next();
7252 /* allow to take the address of a label */
7253 if (tok < TOK_UIDENT)
7254 expect("label identifier");
7255 s = label_find(tok);
7256 if (!s) {
7257 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
7258 } else {
7259 if (s->r == LABEL_DECLARED)
7260 s->r = LABEL_FORWARD;
7262 if (!s->type.t) {
7263 s->type.t = VT_VOID;
7264 mk_pointer(&s->type);
7265 s->type.t |= VT_STATIC;
7267 vset(&s->type, VT_CONST | VT_SYM, 0);
7268 vtop->sym = s;
7269 next();
7270 break;
7271 default:
7272 tok_identifier:
7273 t = tok;
7274 next();
7275 if (t < TOK_UIDENT)
7276 expect("identifier");
7277 s = sym_find(t);
7278 if (!s) {
7279 if (tok != '(')
7280 error("'%s' undeclared", get_tok_str(t, NULL));
7281 /* for simple function calls, we tolerate undeclared
7282 external reference to int() function */
7283 if (tcc_state->warn_implicit_function_declaration)
7284 warning("implicit declaration of function '%s'",
7285 get_tok_str(t, NULL));
7286 s = external_global_sym(t, &func_old_type, 0);
7288 if ((s->type.t & (VT_STATIC | VT_INLINE | VT_BTYPE)) ==
7289 (VT_STATIC | VT_INLINE | VT_FUNC)) {
7290 /* if referencing an inline function, then we generate a
7291 symbol to it if not already done. It will have the
7292 effect to generate code for it at the end of the
7293 compilation unit. Inline function as always
7294 generated in the text section. */
7295 if (!s->c)
7296 put_extern_sym(s, text_section, 0, 0);
7297 r = VT_SYM | VT_CONST;
7298 } else {
7299 r = s->r;
7301 vset(&s->type, r, s->c);
7302 /* if forward reference, we must point to s */
7303 if (vtop->r & VT_SYM) {
7304 vtop->sym = s;
7305 vtop->c.ul = 0;
7307 break;
7310 /* post operations */
7311 while (1) {
7312 if (tok == TOK_INC || tok == TOK_DEC) {
7313 inc(1, tok);
7314 next();
7315 } else if (tok == '.' || tok == TOK_ARROW) {
7316 /* field */
7317 if (tok == TOK_ARROW)
7318 indir();
7319 test_lvalue();
7320 gaddrof();
7321 next();
7322 /* expect pointer on structure */
7323 if ((vtop->type.t & VT_BTYPE) != VT_STRUCT)
7324 expect("struct or union");
7325 s = vtop->type.ref;
7326 /* find field */
7327 tok |= SYM_FIELD;
7328 while ((s = s->next) != NULL) {
7329 if (s->v == tok)
7330 break;
7332 if (!s)
7333 error("field not found");
7334 /* add field offset to pointer */
7335 vtop->type = char_pointer_type; /* change type to 'char *' */
7336 vpushi(s->c);
7337 gen_op('+');
7338 /* change type to field type, and set to lvalue */
7339 vtop->type = s->type;
7340 /* an array is never an lvalue */
7341 if (!(vtop->type.t & VT_ARRAY)) {
7342 vtop->r |= lvalue_type(vtop->type.t);
7343 /* if bound checking, the referenced pointer must be checked */
7344 if (do_bounds_check)
7345 vtop->r |= VT_MUSTBOUND;
7347 next();
7348 } else if (tok == '[') {
7349 next();
7350 gexpr();
7351 gen_op('+');
7352 indir();
7353 skip(']');
7354 } else if (tok == '(') {
7355 SValue ret;
7356 Sym *sa;
7357 int nb_args;
7359 /* function call */
7360 if ((vtop->type.t & VT_BTYPE) != VT_FUNC) {
7361 /* pointer test (no array accepted) */
7362 if ((vtop->type.t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
7363 vtop->type = *pointed_type(&vtop->type);
7364 if ((vtop->type.t & VT_BTYPE) != VT_FUNC)
7365 goto error_func;
7366 } else {
7367 error_func:
7368 expect("function pointer");
7370 } else {
7371 vtop->r &= ~VT_LVAL; /* no lvalue */
7373 /* get return type */
7374 s = vtop->type.ref;
7375 next();
7376 sa = s->next; /* first parameter */
7377 nb_args = 0;
7378 /* compute first implicit argument if a structure is returned */
7379 if ((s->type.t & VT_BTYPE) == VT_STRUCT) {
7380 /* get some space for the returned structure */
7381 size = type_size(&s->type, &align);
7382 loc = (loc - size) & -align;
7383 ret.type = s->type;
7384 ret.r = VT_LOCAL | VT_LVAL;
7385 /* pass it as 'int' to avoid structure arg passing
7386 problems */
7387 vseti(VT_LOCAL, loc);
7388 ret.c = vtop->c;
7389 nb_args++;
7390 } else {
7391 ret.type = s->type;
7392 ret.r2 = VT_CONST;
7393 /* return in register */
7394 if (is_float(ret.type.t)) {
7395 ret.r = REG_FRET;
7396 } else {
7397 if ((ret.type.t & VT_BTYPE) == VT_LLONG)
7398 ret.r2 = REG_LRET;
7399 ret.r = REG_IRET;
7401 ret.c.i = 0;
7403 if (tok != ')') {
7404 for(;;) {
7405 expr_eq();
7406 gfunc_param_typed(s, sa);
7407 nb_args++;
7408 if (sa)
7409 sa = sa->next;
7410 if (tok == ')')
7411 break;
7412 skip(',');
7415 if (sa)
7416 error("too few arguments to function");
7417 skip(')');
7418 if (!nocode_wanted) {
7419 gfunc_call(nb_args);
7420 } else {
7421 vtop -= (nb_args + 1);
7423 /* return value */
7424 vsetc(&ret.type, ret.r, &ret.c);
7425 vtop->r2 = ret.r2;
7426 } else {
7427 break;
7432 static void uneq(void)
7434 int t;
7436 unary();
7437 if (tok == '=' ||
7438 (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
7439 tok == TOK_A_XOR || tok == TOK_A_OR ||
7440 tok == TOK_A_SHL || tok == TOK_A_SAR) {
7441 test_lvalue();
7442 t = tok;
7443 next();
7444 if (t == '=') {
7445 expr_eq();
7446 } else {
7447 vdup();
7448 expr_eq();
7449 gen_op(t & 0x7f);
7451 vstore();
7455 static void expr_prod(void)
7457 int t;
7459 uneq();
7460 while (tok == '*' || tok == '/' || tok == '%') {
7461 t = tok;
7462 next();
7463 uneq();
7464 gen_op(t);
7468 static void expr_sum(void)
7470 int t;
7472 expr_prod();
7473 while (tok == '+' || tok == '-') {
7474 t = tok;
7475 next();
7476 expr_prod();
7477 gen_op(t);
7481 static void expr_shift(void)
7483 int t;
7485 expr_sum();
7486 while (tok == TOK_SHL || tok == TOK_SAR) {
7487 t = tok;
7488 next();
7489 expr_sum();
7490 gen_op(t);
7494 static void expr_cmp(void)
7496 int t;
7498 expr_shift();
7499 while ((tok >= TOK_ULE && tok <= TOK_GT) ||
7500 tok == TOK_ULT || tok == TOK_UGE) {
7501 t = tok;
7502 next();
7503 expr_shift();
7504 gen_op(t);
7508 static void expr_cmpeq(void)
7510 int t;
7512 expr_cmp();
7513 while (tok == TOK_EQ || tok == TOK_NE) {
7514 t = tok;
7515 next();
7516 expr_cmp();
7517 gen_op(t);
7521 static void expr_and(void)
7523 expr_cmpeq();
7524 while (tok == '&') {
7525 next();
7526 expr_cmpeq();
7527 gen_op('&');
7531 static void expr_xor(void)
7533 expr_and();
7534 while (tok == '^') {
7535 next();
7536 expr_and();
7537 gen_op('^');
7541 static void expr_or(void)
7543 expr_xor();
7544 while (tok == '|') {
7545 next();
7546 expr_xor();
7547 gen_op('|');
7551 /* XXX: fix this mess */
7552 static void expr_land_const(void)
7554 expr_or();
7555 while (tok == TOK_LAND) {
7556 next();
7557 expr_or();
7558 gen_op(TOK_LAND);
7562 /* XXX: fix this mess */
7563 static void expr_lor_const(void)
7565 expr_land_const();
7566 while (tok == TOK_LOR) {
7567 next();
7568 expr_land_const();
7569 gen_op(TOK_LOR);
7573 /* only used if non constant */
7574 static void expr_land(void)
7576 int t;
7578 expr_or();
7579 if (tok == TOK_LAND) {
7580 t = 0;
7581 for(;;) {
7582 t = gtst(1, t);
7583 if (tok != TOK_LAND) {
7584 vseti(VT_JMPI, t);
7585 break;
7587 next();
7588 expr_or();
7593 static void expr_lor(void)
7595 int t;
7597 expr_land();
7598 if (tok == TOK_LOR) {
7599 t = 0;
7600 for(;;) {
7601 t = gtst(0, t);
7602 if (tok != TOK_LOR) {
7603 vseti(VT_JMP, t);
7604 break;
7606 next();
7607 expr_land();
7612 /* XXX: better constant handling */
7613 static void expr_eq(void)
7615 int tt, u, r1, r2, rc, t1, t2, bt1, bt2;
7616 SValue sv;
7617 CType type, type1, type2;
7619 if (const_wanted) {
7620 int c1, c;
7621 expr_lor_const();
7622 if (tok == '?') {
7623 c = vtop->c.i;
7624 vpop();
7625 next();
7626 if (tok == ':' && gnu_ext) {
7627 c1 = c;
7628 } else {
7629 gexpr();
7630 c1 = vtop->c.i;
7631 vpop();
7633 skip(':');
7634 expr_eq();
7635 if (c)
7636 vtop->c.i = c1;
7638 } else {
7639 expr_lor();
7640 if (tok == '?') {
7641 next();
7642 if (vtop != vstack) {
7643 /* needed to avoid having different registers saved in
7644 each branch */
7645 if (is_float(vtop->type.t))
7646 rc = RC_FLOAT;
7647 else
7648 rc = RC_INT;
7649 gv(rc);
7650 save_regs(1);
7652 if (tok == ':' && gnu_ext) {
7653 gv_dup();
7654 tt = gtst(1, 0);
7655 } else {
7656 tt = gtst(1, 0);
7657 gexpr();
7659 type1 = vtop->type;
7660 sv = *vtop; /* save value to handle it later */
7661 vtop--; /* no vpop so that FP stack is not flushed */
7662 skip(':');
7663 u = gjmp(0);
7664 gsym(tt);
7665 expr_eq();
7666 type2 = vtop->type;
7668 t1 = type1.t;
7669 bt1 = t1 & VT_BTYPE;
7670 t2 = type2.t;
7671 bt2 = t2 & VT_BTYPE;
7672 /* cast operands to correct type according to ISOC rules */
7673 if (is_float(bt1) || is_float(bt2)) {
7674 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
7675 type.t = VT_LDOUBLE;
7676 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
7677 type.t = VT_DOUBLE;
7678 } else {
7679 type.t = VT_FLOAT;
7681 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
7682 /* cast to biggest op */
7683 type.t = VT_LLONG;
7684 /* convert to unsigned if it does not fit in a long long */
7685 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
7686 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
7687 type.t |= VT_UNSIGNED;
7688 } else if (bt1 == VT_PTR || bt2 == VT_PTR) {
7689 /* XXX: test pointer compatibility */
7690 type = type1;
7691 } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
7692 /* XXX: test structure compatibility */
7693 type = type1;
7694 } else if (bt1 == VT_VOID || bt2 == VT_VOID) {
7695 /* NOTE: as an extension, we accept void on only one side */
7696 type.t = VT_VOID;
7697 } else {
7698 /* integer operations */
7699 type.t = VT_INT;
7700 /* convert to unsigned if it does not fit in an integer */
7701 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
7702 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
7703 type.t |= VT_UNSIGNED;
7706 /* now we convert second operand */
7707 gen_cast(&type);
7708 rc = RC_INT;
7709 if (is_float(type.t)) {
7710 rc = RC_FLOAT;
7711 } else if ((type.t & VT_BTYPE) == VT_LLONG) {
7712 /* for long longs, we use fixed registers to avoid having
7713 to handle a complicated move */
7714 rc = RC_IRET;
7717 r2 = gv(rc);
7718 /* this is horrible, but we must also convert first
7719 operand */
7720 tt = gjmp(0);
7721 gsym(u);
7722 /* put again first value and cast it */
7723 *vtop = sv;
7724 gen_cast(&type);
7725 r1 = gv(rc);
7726 move_reg(r2, r1);
7727 vtop->r = r2;
7728 gsym(tt);
7733 static void gexpr(void)
7735 while (1) {
7736 expr_eq();
7737 if (tok != ',')
7738 break;
7739 vpop();
7740 next();
7744 /* parse an expression and return its type without any side effect. */
7745 static void expr_type(CType *type)
7747 int saved_nocode_wanted;
7749 saved_nocode_wanted = nocode_wanted;
7750 nocode_wanted = 1;
7751 gexpr();
7752 *type = vtop->type;
7753 vpop();
7754 nocode_wanted = saved_nocode_wanted;
7757 /* parse a unary expression and return its type without any side
7758 effect. */
7759 static void unary_type(CType *type)
7761 int a;
7763 a = nocode_wanted;
7764 nocode_wanted = 1;
7765 unary();
7766 *type = vtop->type;
7767 vpop();
7768 nocode_wanted = a;
7771 /* parse a constant expression and return value in vtop. */
7772 static void expr_const1(void)
7774 int a;
7775 a = const_wanted;
7776 const_wanted = 1;
7777 expr_eq();
7778 const_wanted = a;
7781 /* parse an integer constant and return its value. */
7782 static int expr_const(void)
7784 int c;
7785 expr_const1();
7786 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
7787 expect("constant expression");
7788 c = vtop->c.i;
7789 vpop();
7790 return c;
7793 /* return the label token if current token is a label, otherwise
7794 return zero */
7795 static int is_label(void)
7797 int last_tok;
7799 /* fast test first */
7800 if (tok < TOK_UIDENT)
7801 return 0;
7802 /* no need to save tokc because tok is an identifier */
7803 last_tok = tok;
7804 next();
7805 if (tok == ':') {
7806 next();
7807 return last_tok;
7808 } else {
7809 unget_tok(last_tok);
7810 return 0;
7814 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
7815 int case_reg, int is_expr)
7817 int a, b, c, d;
7818 Sym *s;
7820 /* generate line number info */
7821 if (do_debug &&
7822 (last_line_num != file->line_num || last_ind != ind)) {
7823 put_stabn(N_SLINE, 0, file->line_num, ind - func_ind);
7824 last_ind = ind;
7825 last_line_num = file->line_num;
7828 if (is_expr) {
7829 /* default return value is (void) */
7830 vpushi(0);
7831 vtop->type.t = VT_VOID;
7834 if (tok == TOK_IF) {
7835 /* if test */
7836 next();
7837 skip('(');
7838 gexpr();
7839 skip(')');
7840 a = gtst(1, 0);
7841 block(bsym, csym, case_sym, def_sym, case_reg, 0);
7842 c = tok;
7843 if (c == TOK_ELSE) {
7844 next();
7845 d = gjmp(0);
7846 gsym(a);
7847 block(bsym, csym, case_sym, def_sym, case_reg, 0);
7848 gsym(d); /* patch else jmp */
7849 } else
7850 gsym(a);
7851 } else if (tok == TOK_WHILE) {
7852 next();
7853 d = ind;
7854 skip('(');
7855 gexpr();
7856 skip(')');
7857 a = gtst(1, 0);
7858 b = 0;
7859 block(&a, &b, case_sym, def_sym, case_reg, 0);
7860 gjmp_addr(d);
7861 gsym(a);
7862 gsym_addr(b, d);
7863 } else if (tok == '{') {
7864 Sym *llabel;
7866 next();
7867 /* record local declaration stack position */
7868 s = local_stack;
7869 llabel = local_label_stack;
7870 /* handle local labels declarations */
7871 if (tok == TOK_LABEL) {
7872 next();
7873 for(;;) {
7874 if (tok < TOK_UIDENT)
7875 expect("label identifier");
7876 label_push(&local_label_stack, tok, LABEL_DECLARED);
7877 next();
7878 if (tok == ',') {
7879 next();
7880 } else {
7881 skip(';');
7882 break;
7886 while (tok != '}') {
7887 decl(VT_LOCAL);
7888 if (tok != '}') {
7889 if (is_expr)
7890 vpop();
7891 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
7894 /* pop locally defined labels */
7895 label_pop(&local_label_stack, llabel);
7896 /* pop locally defined symbols */
7897 sym_pop(&local_stack, s);
7898 next();
7899 } else if (tok == TOK_RETURN) {
7900 next();
7901 if (tok != ';') {
7902 gexpr();
7903 gen_assign_cast(&func_vt);
7904 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
7905 CType type;
7906 /* if returning structure, must copy it to implicit
7907 first pointer arg location */
7908 type = func_vt;
7909 mk_pointer(&type);
7910 vset(&type, VT_LOCAL | VT_LVAL, func_vc);
7911 indir();
7912 vswap();
7913 /* copy structure value to pointer */
7914 vstore();
7915 } else if (is_float(func_vt.t)) {
7916 gv(RC_FRET);
7917 } else {
7918 gv(RC_IRET);
7920 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
7922 skip(';');
7923 rsym = gjmp(rsym); /* jmp */
7924 } else if (tok == TOK_BREAK) {
7925 /* compute jump */
7926 if (!bsym)
7927 error("cannot break");
7928 *bsym = gjmp(*bsym);
7929 next();
7930 skip(';');
7931 } else if (tok == TOK_CONTINUE) {
7932 /* compute jump */
7933 if (!csym)
7934 error("cannot continue");
7935 *csym = gjmp(*csym);
7936 next();
7937 skip(';');
7938 } else if (tok == TOK_FOR) {
7939 int e;
7940 next();
7941 skip('(');
7942 if (tok != ';') {
7943 gexpr();
7944 vpop();
7946 skip(';');
7947 d = ind;
7948 c = ind;
7949 a = 0;
7950 b = 0;
7951 if (tok != ';') {
7952 gexpr();
7953 a = gtst(1, 0);
7955 skip(';');
7956 if (tok != ')') {
7957 e = gjmp(0);
7958 c = ind;
7959 gexpr();
7960 vpop();
7961 gjmp_addr(d);
7962 gsym(e);
7964 skip(')');
7965 block(&a, &b, case_sym, def_sym, case_reg, 0);
7966 gjmp_addr(c);
7967 gsym(a);
7968 gsym_addr(b, c);
7969 } else
7970 if (tok == TOK_DO) {
7971 next();
7972 a = 0;
7973 b = 0;
7974 d = ind;
7975 block(&a, &b, case_sym, def_sym, case_reg, 0);
7976 skip(TOK_WHILE);
7977 skip('(');
7978 gsym(b);
7979 gexpr();
7980 c = gtst(0, 0);
7981 gsym_addr(c, d);
7982 skip(')');
7983 gsym(a);
7984 skip(';');
7985 } else
7986 if (tok == TOK_SWITCH) {
7987 next();
7988 skip('(');
7989 gexpr();
7990 /* XXX: other types than integer */
7991 case_reg = gv(RC_INT);
7992 vpop();
7993 skip(')');
7994 a = 0;
7995 b = gjmp(0); /* jump to first case */
7996 c = 0;
7997 block(&a, csym, &b, &c, case_reg, 0);
7998 /* if no default, jmp after switch */
7999 if (c == 0)
8000 c = ind;
8001 /* default label */
8002 gsym_addr(b, c);
8003 /* break label */
8004 gsym(a);
8005 } else
8006 if (tok == TOK_CASE) {
8007 int v1, v2;
8008 if (!case_sym)
8009 expect("switch");
8010 next();
8011 v1 = expr_const();
8012 v2 = v1;
8013 if (gnu_ext && tok == TOK_DOTS) {
8014 next();
8015 v2 = expr_const();
8016 if (v2 < v1)
8017 warning("empty case range");
8019 /* since a case is like a label, we must skip it with a jmp */
8020 b = gjmp(0);
8021 gsym(*case_sym);
8022 vseti(case_reg, 0);
8023 vpushi(v1);
8024 if (v1 == v2) {
8025 gen_op(TOK_EQ);
8026 *case_sym = gtst(1, 0);
8027 } else {
8028 gen_op(TOK_GE);
8029 *case_sym = gtst(1, 0);
8030 vseti(case_reg, 0);
8031 vpushi(v2);
8032 gen_op(TOK_LE);
8033 *case_sym = gtst(1, *case_sym);
8035 gsym(b);
8036 skip(':');
8037 is_expr = 0;
8038 goto block_after_label;
8039 } else
8040 if (tok == TOK_DEFAULT) {
8041 next();
8042 skip(':');
8043 if (!def_sym)
8044 expect("switch");
8045 if (*def_sym)
8046 error("too many 'default'");
8047 *def_sym = ind;
8048 is_expr = 0;
8049 goto block_after_label;
8050 } else
8051 if (tok == TOK_GOTO) {
8052 next();
8053 if (tok == '*' && gnu_ext) {
8054 /* computed goto */
8055 next();
8056 gexpr();
8057 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
8058 expect("pointer");
8059 ggoto();
8060 } else if (tok >= TOK_UIDENT) {
8061 s = label_find(tok);
8062 /* put forward definition if needed */
8063 if (!s) {
8064 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
8065 } else {
8066 if (s->r == LABEL_DECLARED)
8067 s->r = LABEL_FORWARD;
8069 /* label already defined */
8070 if (s->r & LABEL_FORWARD)
8071 s->next = (void *)gjmp((long)s->next);
8072 else
8073 gjmp_addr((long)s->next);
8074 next();
8075 } else {
8076 expect("label identifier");
8078 skip(';');
8079 } else if (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3) {
8080 asm_instr();
8081 } else {
8082 b = is_label();
8083 if (b) {
8084 /* label case */
8085 s = label_find(b);
8086 if (s) {
8087 if (s->r == LABEL_DEFINED)
8088 error("duplicate label '%s'", get_tok_str(s->v, NULL));
8089 gsym((long)s->next);
8090 s->r = LABEL_DEFINED;
8091 } else {
8092 s = label_push(&global_label_stack, b, LABEL_DEFINED);
8094 s->next = (void *)ind;
8095 /* we accept this, but it is a mistake */
8096 block_after_label:
8097 if (tok == '}') {
8098 warning("deprecated use of label at end of compound statement");
8099 } else {
8100 if (is_expr)
8101 vpop();
8102 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
8104 } else {
8105 /* expression case */
8106 if (tok != ';') {
8107 if (is_expr) {
8108 vpop();
8109 gexpr();
8110 } else {
8111 gexpr();
8112 vpop();
8115 skip(';');
8120 /* t is the array or struct type. c is the array or struct
8121 address. cur_index/cur_field is the pointer to the current
8122 value. 'size_only' is true if only size info is needed (only used
8123 in arrays) */
8124 static void decl_designator(CType *type, Section *sec, unsigned long c,
8125 int *cur_index, Sym **cur_field,
8126 int size_only)
8128 Sym *s, *f;
8129 int notfirst, index, index_last, align, l, nb_elems, elem_size;
8130 CType type1;
8132 notfirst = 0;
8133 elem_size = 0;
8134 nb_elems = 1;
8135 if (gnu_ext && (l = is_label()) != 0)
8136 goto struct_field;
8137 while (tok == '[' || tok == '.') {
8138 if (tok == '[') {
8139 if (!(type->t & VT_ARRAY))
8140 expect("array type");
8141 s = type->ref;
8142 next();
8143 index = expr_const();
8144 if (index < 0 || (s->c >= 0 && index >= s->c))
8145 expect("invalid index");
8146 if (tok == TOK_DOTS && gnu_ext) {
8147 next();
8148 index_last = expr_const();
8149 if (index_last < 0 ||
8150 (s->c >= 0 && index_last >= s->c) ||
8151 index_last < index)
8152 expect("invalid index");
8153 } else {
8154 index_last = index;
8156 skip(']');
8157 if (!notfirst)
8158 *cur_index = index_last;
8159 type = pointed_type(type);
8160 elem_size = type_size(type, &align);
8161 c += index * elem_size;
8162 /* NOTE: we only support ranges for last designator */
8163 nb_elems = index_last - index + 1;
8164 if (nb_elems != 1) {
8165 notfirst = 1;
8166 break;
8168 } else {
8169 next();
8170 l = tok;
8171 next();
8172 struct_field:
8173 if ((type->t & VT_BTYPE) != VT_STRUCT)
8174 expect("struct/union type");
8175 s = type->ref;
8176 l |= SYM_FIELD;
8177 f = s->next;
8178 while (f) {
8179 if (f->v == l)
8180 break;
8181 f = f->next;
8183 if (!f)
8184 expect("field");
8185 if (!notfirst)
8186 *cur_field = f;
8187 /* XXX: fix this mess by using explicit storage field */
8188 type1 = f->type;
8189 type1.t |= (type->t & ~VT_TYPE);
8190 type = &type1;
8191 c += f->c;
8193 notfirst = 1;
8195 if (notfirst) {
8196 if (tok == '=') {
8197 next();
8198 } else {
8199 if (!gnu_ext)
8200 expect("=");
8202 } else {
8203 if (type->t & VT_ARRAY) {
8204 index = *cur_index;
8205 type = pointed_type(type);
8206 c += index * type_size(type, &align);
8207 } else {
8208 f = *cur_field;
8209 if (!f)
8210 error("too many field init");
8211 /* XXX: fix this mess by using explicit storage field */
8212 type1 = f->type;
8213 type1.t |= (type->t & ~VT_TYPE);
8214 type = &type1;
8215 c += f->c;
8218 decl_initializer(type, sec, c, 0, size_only);
8220 /* XXX: make it more general */
8221 if (!size_only && nb_elems > 1) {
8222 unsigned long c_end;
8223 uint8_t *src, *dst;
8224 int i;
8226 if (!sec)
8227 error("range init not supported yet for dynamic storage");
8228 c_end = c + nb_elems * elem_size;
8229 if (c_end > sec->data_allocated)
8230 section_realloc(sec, c_end);
8231 src = sec->data + c;
8232 dst = src;
8233 for(i = 1; i < nb_elems; i++) {
8234 dst += elem_size;
8235 memcpy(dst, src, elem_size);
8240 #define EXPR_VAL 0
8241 #define EXPR_CONST 1
8242 #define EXPR_ANY 2
8244 /* store a value or an expression directly in global data or in local array */
8245 static void init_putv(CType *type, Section *sec, unsigned long c,
8246 int v, int expr_type)
8248 int saved_global_expr, bt, bit_pos, bit_size;
8249 void *ptr;
8250 unsigned long long bit_mask;
8251 CType dtype;
8253 switch(expr_type) {
8254 case EXPR_VAL:
8255 vpushi(v);
8256 break;
8257 case EXPR_CONST:
8258 /* compound literals must be allocated globally in this case */
8259 saved_global_expr = global_expr;
8260 global_expr = 1;
8261 expr_const1();
8262 global_expr = saved_global_expr;
8263 /* NOTE: symbols are accepted */
8264 if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST)
8265 error("initializer element is not constant");
8266 break;
8267 case EXPR_ANY:
8268 expr_eq();
8269 break;
8272 dtype = *type;
8273 dtype.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
8275 if (sec) {
8276 /* XXX: not portable */
8277 /* XXX: generate error if incorrect relocation */
8278 gen_assign_cast(&dtype);
8279 bt = type->t & VT_BTYPE;
8280 ptr = sec->data + c;
8281 /* XXX: make code faster ? */
8282 if (!(type->t & VT_BITFIELD)) {
8283 bit_pos = 0;
8284 bit_size = 32;
8285 bit_mask = -1LL;
8286 } else {
8287 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
8288 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
8289 bit_mask = (1LL << bit_size) - 1;
8291 if ((vtop->r & VT_SYM) &&
8292 (bt == VT_BYTE ||
8293 bt == VT_SHORT ||
8294 bt == VT_DOUBLE ||
8295 bt == VT_LDOUBLE ||
8296 bt == VT_LLONG ||
8297 (bt == VT_INT && bit_size != 32)))
8298 error("initializer element is not computable at load time");
8299 switch(bt) {
8300 case VT_BYTE:
8301 *(char *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8302 break;
8303 case VT_SHORT:
8304 *(short *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8305 break;
8306 case VT_DOUBLE:
8307 *(double *)ptr = vtop->c.d;
8308 break;
8309 case VT_LDOUBLE:
8310 *(long double *)ptr = vtop->c.ld;
8311 break;
8312 case VT_LLONG:
8313 *(long long *)ptr |= (vtop->c.ll & bit_mask) << bit_pos;
8314 break;
8315 default:
8316 if (vtop->r & VT_SYM) {
8317 greloc(sec, vtop->sym, c, R_DATA_32);
8319 *(int *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8320 break;
8322 vtop--;
8323 } else {
8324 vset(&dtype, VT_LOCAL, c);
8325 vswap();
8326 vstore();
8327 vpop();
8331 /* put zeros for variable based init */
8332 static void init_putz(CType *t, Section *sec, unsigned long c, int size)
8334 if (sec) {
8335 /* nothing to do because globals are already set to zero */
8336 } else {
8337 vpush_global_sym(&func_old_type, TOK_memset);
8338 vseti(VT_LOCAL, c);
8339 vpushi(0);
8340 vpushi(size);
8341 gfunc_call(3);
8345 /* 't' contains the type and storage info. 'c' is the offset of the
8346 object in section 'sec'. If 'sec' is NULL, it means stack based
8347 allocation. 'first' is true if array '{' must be read (multi
8348 dimension implicit array init handling). 'size_only' is true if
8349 size only evaluation is wanted (only for arrays). */
8350 static void decl_initializer(CType *type, Section *sec, unsigned long c,
8351 int first, int size_only)
8353 int index, array_length, n, no_oblock, nb, parlevel, i;
8354 int size1, align1, expr_type;
8355 Sym *s, *f;
8356 CType *t1;
8358 if (type->t & VT_ARRAY) {
8359 s = type->ref;
8360 n = s->c;
8361 array_length = 0;
8362 t1 = pointed_type(type);
8363 size1 = type_size(t1, &align1);
8365 no_oblock = 1;
8366 if ((first && tok != TOK_LSTR && tok != TOK_STR) ||
8367 tok == '{') {
8368 skip('{');
8369 no_oblock = 0;
8372 /* only parse strings here if correct type (otherwise: handle
8373 them as ((w)char *) expressions */
8374 if ((tok == TOK_LSTR &&
8375 (t1->t & VT_BTYPE) == VT_INT) ||
8376 (tok == TOK_STR &&
8377 (t1->t & VT_BTYPE) == VT_BYTE)) {
8378 while (tok == TOK_STR || tok == TOK_LSTR) {
8379 int cstr_len, ch;
8380 CString *cstr;
8382 cstr = tokc.cstr;
8383 /* compute maximum number of chars wanted */
8384 if (tok == TOK_STR)
8385 cstr_len = cstr->size;
8386 else
8387 cstr_len = cstr->size / sizeof(int);
8388 cstr_len--;
8389 nb = cstr_len;
8390 if (n >= 0 && nb > (n - array_length))
8391 nb = n - array_length;
8392 if (!size_only) {
8393 if (cstr_len > nb)
8394 warning("initializer-string for array is too long");
8395 /* in order to go faster for common case (char
8396 string in global variable, we handle it
8397 specifically */
8398 if (sec && tok == TOK_STR && size1 == 1) {
8399 memcpy(sec->data + c + array_length, cstr->data, nb);
8400 } else {
8401 for(i=0;i<nb;i++) {
8402 if (tok == TOK_STR)
8403 ch = ((unsigned char *)cstr->data)[i];
8404 else
8405 ch = ((int *)cstr->data)[i];
8406 init_putv(t1, sec, c + (array_length + i) * size1,
8407 ch, EXPR_VAL);
8411 array_length += nb;
8412 next();
8414 /* only add trailing zero if enough storage (no
8415 warning in this case since it is standard) */
8416 if (n < 0 || array_length < n) {
8417 if (!size_only) {
8418 init_putv(t1, sec, c + (array_length * size1), 0, EXPR_VAL);
8420 array_length++;
8422 } else {
8423 index = 0;
8424 while (tok != '}') {
8425 decl_designator(type, sec, c, &index, NULL, size_only);
8426 if (n >= 0 && index >= n)
8427 error("index too large");
8428 /* must put zero in holes (note that doing it that way
8429 ensures that it even works with designators) */
8430 if (!size_only && array_length < index) {
8431 init_putz(t1, sec, c + array_length * size1,
8432 (index - array_length) * size1);
8434 index++;
8435 if (index > array_length)
8436 array_length = index;
8437 /* special test for multi dimensional arrays (may not
8438 be strictly correct if designators are used at the
8439 same time) */
8440 if (index >= n && no_oblock)
8441 break;
8442 if (tok == '}')
8443 break;
8444 skip(',');
8447 if (!no_oblock)
8448 skip('}');
8449 /* put zeros at the end */
8450 if (!size_only && n >= 0 && array_length < n) {
8451 init_putz(t1, sec, c + array_length * size1,
8452 (n - array_length) * size1);
8454 /* patch type size if needed */
8455 if (n < 0)
8456 s->c = array_length;
8457 } else if ((type->t & VT_BTYPE) == VT_STRUCT &&
8458 (sec || !first || tok == '{')) {
8459 int par_count;
8461 /* NOTE: the previous test is a specific case for automatic
8462 struct/union init */
8463 /* XXX: union needs only one init */
8465 /* XXX: this test is incorrect for local initializers
8466 beginning with ( without {. It would be much more difficult
8467 to do it correctly (ideally, the expression parser should
8468 be used in all cases) */
8469 par_count = 0;
8470 if (tok == '(') {
8471 AttributeDef ad1;
8472 CType type1;
8473 next();
8474 while (tok == '(') {
8475 par_count++;
8476 next();
8478 if (!parse_btype(&type1, &ad1))
8479 expect("cast");
8480 type_decl(&type1, &ad1, &n, TYPE_ABSTRACT);
8481 #if 0
8482 if (!is_assignable_types(type, &type1))
8483 error("invalid type for cast");
8484 #endif
8485 skip(')');
8487 no_oblock = 1;
8488 if (first || tok == '{') {
8489 skip('{');
8490 no_oblock = 0;
8492 s = type->ref;
8493 f = s->next;
8494 array_length = 0;
8495 index = 0;
8496 n = s->c;
8497 while (tok != '}') {
8498 decl_designator(type, sec, c, NULL, &f, size_only);
8499 index = f->c;
8500 if (!size_only && array_length < index) {
8501 init_putz(type, sec, c + array_length,
8502 index - array_length);
8504 index = index + type_size(&f->type, &align1);
8505 if (index > array_length)
8506 array_length = index;
8507 f = f->next;
8508 if (no_oblock && f == NULL)
8509 break;
8510 if (tok == '}')
8511 break;
8512 skip(',');
8514 /* put zeros at the end */
8515 if (!size_only && array_length < n) {
8516 init_putz(type, sec, c + array_length,
8517 n - array_length);
8519 if (!no_oblock)
8520 skip('}');
8521 while (par_count) {
8522 skip(')');
8523 par_count--;
8525 } else if (tok == '{') {
8526 next();
8527 decl_initializer(type, sec, c, first, size_only);
8528 skip('}');
8529 } else if (size_only) {
8530 /* just skip expression */
8531 parlevel = 0;
8532 while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
8533 tok != -1) {
8534 if (tok == '(')
8535 parlevel++;
8536 else if (tok == ')')
8537 parlevel--;
8538 next();
8540 } else {
8541 /* currently, we always use constant expression for globals
8542 (may change for scripting case) */
8543 expr_type = EXPR_CONST;
8544 if (!sec)
8545 expr_type = EXPR_ANY;
8546 init_putv(type, sec, c, 0, expr_type);
8550 /* parse an initializer for type 't' if 'has_init' is non zero, and
8551 allocate space in local or global data space ('r' is either
8552 VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
8553 variable 'v' of scope 'scope' is declared before initializers are
8554 parsed. If 'v' is zero, then a reference to the new object is put
8555 in the value stack. If 'has_init' is 2, a special parsing is done
8556 to handle string constants. */
8557 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
8558 int has_init, int v, int scope)
8560 int size, align, addr, data_offset;
8561 int level;
8562 ParseState saved_parse_state;
8563 TokenString init_str;
8564 Section *sec;
8566 size = type_size(type, &align);
8567 /* If unknown size, we must evaluate it before
8568 evaluating initializers because
8569 initializers can generate global data too
8570 (e.g. string pointers or ISOC99 compound
8571 literals). It also simplifies local
8572 initializers handling */
8573 tok_str_new(&init_str);
8574 if (size < 0) {
8575 if (!has_init)
8576 error("unknown type size");
8577 /* get all init string */
8578 if (has_init == 2) {
8579 /* only get strings */
8580 while (tok == TOK_STR || tok == TOK_LSTR) {
8581 tok_str_add_tok(&init_str);
8582 next();
8584 } else {
8585 level = 0;
8586 while (level > 0 || (tok != ',' && tok != ';')) {
8587 if (tok < 0)
8588 error("unexpected end of file in initializer");
8589 tok_str_add_tok(&init_str);
8590 if (tok == '{')
8591 level++;
8592 else if (tok == '}') {
8593 if (level == 0)
8594 break;
8595 level--;
8597 next();
8600 tok_str_add(&init_str, -1);
8601 tok_str_add(&init_str, 0);
8603 /* compute size */
8604 save_parse_state(&saved_parse_state);
8606 macro_ptr = init_str.str;
8607 next();
8608 decl_initializer(type, NULL, 0, 1, 1);
8609 /* prepare second initializer parsing */
8610 macro_ptr = init_str.str;
8611 next();
8613 /* if still unknown size, error */
8614 size = type_size(type, &align);
8615 if (size < 0)
8616 error("unknown type size");
8618 /* take into account specified alignment if bigger */
8619 if (ad->aligned) {
8620 if (ad->aligned > align)
8621 align = ad->aligned;
8622 } else if (ad->packed) {
8623 align = 1;
8625 if ((r & VT_VALMASK) == VT_LOCAL) {
8626 sec = NULL;
8627 if (do_bounds_check && (type->t & VT_ARRAY))
8628 loc--;
8629 loc = (loc - size) & -align;
8630 addr = loc;
8631 /* handles bounds */
8632 /* XXX: currently, since we do only one pass, we cannot track
8633 '&' operators, so we add only arrays */
8634 if (do_bounds_check && (type->t & VT_ARRAY)) {
8635 unsigned long *bounds_ptr;
8636 /* add padding between regions */
8637 loc--;
8638 /* then add local bound info */
8639 bounds_ptr = section_ptr_add(lbounds_section, 2 * sizeof(unsigned long));
8640 bounds_ptr[0] = addr;
8641 bounds_ptr[1] = size;
8643 if (v) {
8644 /* local variable */
8645 sym_push(v, type, r, addr);
8646 } else {
8647 /* push local reference */
8648 vset(type, r, addr);
8650 } else {
8651 Sym *sym;
8653 sym = NULL;
8654 if (v && scope == VT_CONST) {
8655 /* see if the symbol was already defined */
8656 sym = sym_find(v);
8657 if (sym) {
8658 if (!is_compatible_types(&sym->type, type))
8659 error("incompatible types for redefinition of '%s'",
8660 get_tok_str(v, NULL));
8661 if (sym->type.t & VT_EXTERN) {
8662 /* if the variable is extern, it was not allocated */
8663 sym->type.t &= ~VT_EXTERN;
8664 /* set array size if it was ommited in extern
8665 declaration */
8666 if ((sym->type.t & VT_ARRAY) &&
8667 sym->type.ref->c < 0 &&
8668 type->ref->c >= 0)
8669 sym->type.ref->c = type->ref->c;
8670 } else {
8671 /* we accept several definitions of the same
8672 global variable. this is tricky, because we
8673 must play with the SHN_COMMON type of the symbol */
8674 /* XXX: should check if the variable was already
8675 initialized. It is incorrect to initialized it
8676 twice */
8677 /* no init data, we won't add more to the symbol */
8678 if (!has_init)
8679 goto no_alloc;
8684 /* allocate symbol in corresponding section */
8685 sec = ad->section;
8686 if (!sec) {
8687 if (has_init)
8688 sec = data_section;
8689 else if (tcc_state->nocommon)
8690 sec = bss_section;
8692 if (sec) {
8693 data_offset = sec->data_offset;
8694 data_offset = (data_offset + align - 1) & -align;
8695 addr = data_offset;
8696 /* very important to increment global pointer at this time
8697 because initializers themselves can create new initializers */
8698 data_offset += size;
8699 /* add padding if bound check */
8700 if (do_bounds_check)
8701 data_offset++;
8702 sec->data_offset = data_offset;
8703 /* allocate section space to put the data */
8704 if (sec->sh_type != SHT_NOBITS &&
8705 data_offset > sec->data_allocated)
8706 section_realloc(sec, data_offset);
8707 /* align section if needed */
8708 if (align > sec->sh_addralign)
8709 sec->sh_addralign = align;
8710 } else {
8711 addr = 0; /* avoid warning */
8714 if (v) {
8715 if (scope == VT_CONST) {
8716 if (!sym)
8717 goto do_def;
8718 } else {
8719 do_def:
8720 sym = sym_push(v, type, r | VT_SYM, 0);
8722 /* update symbol definition */
8723 if (sec) {
8724 put_extern_sym(sym, sec, addr, size);
8725 } else {
8726 Elf32_Sym *esym;
8727 /* put a common area */
8728 put_extern_sym(sym, NULL, align, size);
8729 /* XXX: find a nicer way */
8730 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
8731 esym->st_shndx = SHN_COMMON;
8733 } else {
8734 CValue cval;
8736 /* push global reference */
8737 sym = get_sym_ref(type, sec, addr, size);
8738 cval.ul = 0;
8739 vsetc(type, VT_CONST | VT_SYM, &cval);
8740 vtop->sym = sym;
8743 /* handles bounds now because the symbol must be defined
8744 before for the relocation */
8745 if (do_bounds_check) {
8746 unsigned long *bounds_ptr;
8748 greloc(bounds_section, sym, bounds_section->data_offset, R_DATA_32);
8749 /* then add global bound info */
8750 bounds_ptr = section_ptr_add(bounds_section, 2 * sizeof(long));
8751 bounds_ptr[0] = 0; /* relocated */
8752 bounds_ptr[1] = size;
8755 if (has_init) {
8756 decl_initializer(type, sec, addr, 1, 0);
8757 /* restore parse state if needed */
8758 if (init_str.str) {
8759 tok_str_free(init_str.str);
8760 restore_parse_state(&saved_parse_state);
8763 no_alloc: ;
8766 void put_func_debug(Sym *sym)
8768 char buf[512];
8770 /* stabs info */
8771 /* XXX: we put here a dummy type */
8772 snprintf(buf, sizeof(buf), "%s:%c1",
8773 funcname, sym->type.t & VT_STATIC ? 'f' : 'F');
8774 put_stabs_r(buf, N_FUN, 0, file->line_num, 0,
8775 cur_text_section, sym->c);
8776 last_ind = 0;
8777 last_line_num = 0;
8780 /* parse an old style function declaration list */
8781 /* XXX: check multiple parameter */
8782 static void func_decl_list(Sym *func_sym)
8784 AttributeDef ad;
8785 int v;
8786 Sym *s;
8787 CType btype, type;
8789 /* parse each declaration */
8790 while (tok != '{' && tok != ';' && tok != ',' && tok != TOK_EOF) {
8791 if (!parse_btype(&btype, &ad))
8792 expect("declaration list");
8793 if (((btype.t & VT_BTYPE) == VT_ENUM ||
8794 (btype.t & VT_BTYPE) == VT_STRUCT) &&
8795 tok == ';') {
8796 /* we accept no variable after */
8797 } else {
8798 for(;;) {
8799 type = btype;
8800 type_decl(&type, &ad, &v, TYPE_DIRECT);
8801 /* find parameter in function parameter list */
8802 s = func_sym->next;
8803 while (s != NULL) {
8804 if ((s->v & ~SYM_FIELD) == v)
8805 goto found;
8806 s = s->next;
8808 error("declaration for parameter '%s' but no such parameter",
8809 get_tok_str(v, NULL));
8810 found:
8811 /* check that no storage specifier except 'register' was given */
8812 if (type.t & VT_STORAGE)
8813 error("storage class specified for '%s'", get_tok_str(v, NULL));
8814 convert_parameter_type(&type);
8815 /* we can add the type (NOTE: it could be local to the function) */
8816 s->type = type;
8817 /* accept other parameters */
8818 if (tok == ',')
8819 next();
8820 else
8821 break;
8824 skip(';');
8828 /* parse a function defined by symbol 'sym' and generate its code in
8829 'cur_text_section' */
8830 static void gen_function(Sym *sym)
8832 ind = cur_text_section->data_offset;
8833 /* NOTE: we patch the symbol size later */
8834 put_extern_sym(sym, cur_text_section, ind, 0);
8835 funcname = get_tok_str(sym->v, NULL);
8836 func_ind = ind;
8837 /* put debug symbol */
8838 if (do_debug)
8839 put_func_debug(sym);
8840 /* push a dummy symbol to enable local sym storage */
8841 sym_push2(&local_stack, SYM_FIELD, 0, 0);
8842 gfunc_prolog(&sym->type);
8843 rsym = 0;
8844 block(NULL, NULL, NULL, NULL, 0, 0);
8845 gsym(rsym);
8846 gfunc_epilog();
8847 cur_text_section->data_offset = ind;
8848 label_pop(&global_label_stack, NULL);
8849 sym_pop(&local_stack, NULL); /* reset local stack */
8850 /* end of function */
8851 /* patch symbol size */
8852 ((Elf32_Sym *)symtab_section->data)[sym->c].st_size =
8853 ind - func_ind;
8854 if (do_debug) {
8855 put_stabn(N_FUN, 0, 0, ind - func_ind);
8857 funcname = ""; /* for safety */
8858 func_vt.t = VT_VOID; /* for safety */
8859 ind = 0; /* for safety */
8862 static void gen_inline_functions(void)
8864 Sym *sym;
8865 CType *type;
8866 int *str, inline_generated;
8868 /* iterate while inline function are referenced */
8869 for(;;) {
8870 inline_generated = 0;
8871 for(sym = global_stack; sym != NULL; sym = sym->prev) {
8872 type = &sym->type;
8873 if (((type->t & VT_BTYPE) == VT_FUNC) &&
8874 (type->t & (VT_STATIC | VT_INLINE)) ==
8875 (VT_STATIC | VT_INLINE) &&
8876 sym->c != 0) {
8877 /* the function was used: generate its code and
8878 convert it to a normal function */
8879 str = (int *)sym->r;
8880 sym->r = VT_SYM | VT_CONST;
8881 type->t &= ~VT_INLINE;
8883 macro_ptr = str;
8884 next();
8885 cur_text_section = text_section;
8886 gen_function(sym);
8887 macro_ptr = NULL; /* fail safe */
8889 tok_str_free(str);
8890 inline_generated = 1;
8893 if (!inline_generated)
8894 break;
8897 /* free all remaining inline function tokens */
8898 for(sym = global_stack; sym != NULL; sym = sym->prev) {
8899 type = &sym->type;
8900 if (((type->t & VT_BTYPE) == VT_FUNC) &&
8901 (type->t & (VT_STATIC | VT_INLINE)) ==
8902 (VT_STATIC | VT_INLINE)) {
8903 str = (int *)sym->r;
8904 tok_str_free(str);
8905 sym->r = 0; /* fail safe */
8910 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
8911 static void decl(int l)
8913 int v, has_init, r;
8914 CType type, btype;
8915 Sym *sym;
8916 AttributeDef ad;
8918 while (1) {
8919 if (!parse_btype(&btype, &ad)) {
8920 /* skip redundant ';' */
8921 /* XXX: find more elegant solution */
8922 if (tok == ';') {
8923 next();
8924 continue;
8926 if (l == VT_CONST &&
8927 (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3)) {
8928 /* global asm block */
8929 asm_global_instr();
8930 continue;
8932 /* special test for old K&R protos without explicit int
8933 type. Only accepted when defining global data */
8934 if (l == VT_LOCAL || tok < TOK_DEFINE)
8935 break;
8936 btype.t = VT_INT;
8938 if (((btype.t & VT_BTYPE) == VT_ENUM ||
8939 (btype.t & VT_BTYPE) == VT_STRUCT) &&
8940 tok == ';') {
8941 /* we accept no variable after */
8942 next();
8943 continue;
8945 while (1) { /* iterate thru each declaration */
8946 type = btype;
8947 type_decl(&type, &ad, &v, TYPE_DIRECT);
8948 #if 0
8950 char buf[500];
8951 type_to_str(buf, sizeof(buf), t, get_tok_str(v, NULL));
8952 printf("type = '%s'\n", buf);
8954 #endif
8955 if ((type.t & VT_BTYPE) == VT_FUNC) {
8956 /* if old style function prototype, we accept a
8957 declaration list */
8958 sym = type.ref;
8959 if (sym->c == FUNC_OLD)
8960 func_decl_list(sym);
8963 if (tok == '{') {
8964 if (l == VT_LOCAL)
8965 error("cannot use local functions");
8966 if (!(type.t & VT_FUNC))
8967 expect("function definition");
8969 /* reject abstract declarators in function definition */
8970 sym = type.ref;
8971 while ((sym = sym->next) != NULL)
8972 if (!(sym->v & ~SYM_FIELD))
8973 expect("identifier");
8975 /* XXX: cannot do better now: convert extern line to static inline */
8976 if ((type.t & (VT_EXTERN | VT_INLINE)) == (VT_EXTERN | VT_INLINE))
8977 type.t = (type.t & ~VT_EXTERN) | VT_STATIC;
8979 sym = sym_find(v);
8980 if (sym) {
8981 if ((sym->type.t & VT_BTYPE) != VT_FUNC)
8982 goto func_error1;
8983 /* specific case: if not func_call defined, we put
8984 the one of the prototype */
8985 /* XXX: should have default value */
8986 if (sym->type.ref->r != FUNC_CDECL &&
8987 type.ref->r == FUNC_CDECL)
8988 type.ref->r = sym->type.ref->r;
8989 if (!is_compatible_types(&sym->type, &type)) {
8990 func_error1:
8991 error("incompatible types for redefinition of '%s'",
8992 get_tok_str(v, NULL));
8994 /* if symbol is already defined, then put complete type */
8995 sym->type = type;
8996 } else {
8997 /* put function symbol */
8998 sym = global_identifier_push(v, type.t, 0);
8999 sym->type.ref = type.ref;
9002 /* static inline functions are just recorded as a kind
9003 of macro. Their code will be emitted at the end of
9004 the compilation unit only if they are used */
9005 if ((type.t & (VT_INLINE | VT_STATIC)) ==
9006 (VT_INLINE | VT_STATIC)) {
9007 TokenString func_str;
9008 int block_level;
9010 tok_str_new(&func_str);
9012 block_level = 0;
9013 for(;;) {
9014 int t;
9015 if (tok == TOK_EOF)
9016 error("unexpected end of file");
9017 tok_str_add_tok(&func_str);
9018 t = tok;
9019 next();
9020 if (t == '{') {
9021 block_level++;
9022 } else if (t == '}') {
9023 block_level--;
9024 if (block_level == 0)
9025 break;
9028 tok_str_add(&func_str, -1);
9029 tok_str_add(&func_str, 0);
9030 sym->r = (int)func_str.str;
9031 } else {
9032 /* compute text section */
9033 cur_text_section = ad.section;
9034 if (!cur_text_section)
9035 cur_text_section = text_section;
9036 sym->r = VT_SYM | VT_CONST;
9037 gen_function(sym);
9038 #ifdef TCC_TARGET_PE
9039 if (ad.dllexport) {
9040 ((Elf32_Sym *)symtab_section->data)[sym->c].st_other |= 1;
9042 #endif
9044 break;
9045 } else {
9046 if (btype.t & VT_TYPEDEF) {
9047 /* save typedefed type */
9048 /* XXX: test storage specifiers ? */
9049 sym = sym_push(v, &type, 0, 0);
9050 sym->type.t |= VT_TYPEDEF;
9051 } else if ((type.t & VT_BTYPE) == VT_FUNC) {
9052 /* external function definition */
9053 /* specific case for func_call attribute */
9054 if (ad.func_call)
9055 type.ref->r = ad.func_call;
9056 external_sym(v, &type, 0);
9057 } else {
9058 /* not lvalue if array */
9059 r = 0;
9060 if (!(type.t & VT_ARRAY))
9061 r |= lvalue_type(type.t);
9062 has_init = (tok == '=');
9063 if ((btype.t & VT_EXTERN) ||
9064 ((type.t & VT_ARRAY) && (type.t & VT_STATIC) &&
9065 !has_init && l == VT_CONST && type.ref->c < 0)) {
9066 /* external variable */
9067 /* NOTE: as GCC, uninitialized global static
9068 arrays of null size are considered as
9069 extern */
9070 external_sym(v, &type, r);
9071 } else {
9072 if (type.t & VT_STATIC)
9073 r |= VT_CONST;
9074 else
9075 r |= l;
9076 if (has_init)
9077 next();
9078 decl_initializer_alloc(&type, &ad, r,
9079 has_init, v, l);
9082 if (tok != ',') {
9083 skip(';');
9084 break;
9086 next();
9092 /* better than nothing, but needs extension to handle '-E' option
9093 correctly too */
9094 static void preprocess_init(TCCState *s1)
9096 s1->include_stack_ptr = s1->include_stack;
9097 /* XXX: move that before to avoid having to initialize
9098 file->ifdef_stack_ptr ? */
9099 s1->ifdef_stack_ptr = s1->ifdef_stack;
9100 file->ifdef_stack_ptr = s1->ifdef_stack_ptr;
9102 /* XXX: not ANSI compliant: bound checking says error */
9103 vtop = vstack - 1;
9104 s1->pack_stack[0] = 0;
9105 s1->pack_stack_ptr = s1->pack_stack;
9108 /* compile the C file opened in 'file'. Return non zero if errors. */
9109 static int tcc_compile(TCCState *s1)
9111 Sym *define_start;
9112 char buf[512];
9113 volatile int section_sym;
9115 #ifdef INC_DEBUG
9116 printf("%s: **** new file\n", file->filename);
9117 #endif
9118 preprocess_init(s1);
9120 funcname = "";
9121 anon_sym = SYM_FIRST_ANOM;
9123 /* file info: full path + filename */
9124 section_sym = 0; /* avoid warning */
9125 if (do_debug) {
9126 section_sym = put_elf_sym(symtab_section, 0, 0,
9127 ELF32_ST_INFO(STB_LOCAL, STT_SECTION), 0,
9128 text_section->sh_num, NULL);
9129 getcwd(buf, sizeof(buf));
9130 pstrcat(buf, sizeof(buf), "/");
9131 put_stabs_r(buf, N_SO, 0, 0,
9132 text_section->data_offset, text_section, section_sym);
9133 put_stabs_r(file->filename, N_SO, 0, 0,
9134 text_section->data_offset, text_section, section_sym);
9136 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
9137 symbols can be safely used */
9138 put_elf_sym(symtab_section, 0, 0,
9139 ELF32_ST_INFO(STB_LOCAL, STT_FILE), 0,
9140 SHN_ABS, file->filename);
9142 /* define some often used types */
9143 int_type.t = VT_INT;
9145 char_pointer_type.t = VT_BYTE;
9146 mk_pointer(&char_pointer_type);
9148 func_old_type.t = VT_FUNC;
9149 func_old_type.ref = sym_push(SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD);
9151 #if 0
9152 /* define 'void *alloca(unsigned int)' builtin function */
9154 Sym *s1;
9156 p = anon_sym++;
9157 sym = sym_push(p, mk_pointer(VT_VOID), FUNC_CDECL, FUNC_NEW);
9158 s1 = sym_push(SYM_FIELD, VT_UNSIGNED | VT_INT, 0, 0);
9159 s1->next = NULL;
9160 sym->next = s1;
9161 sym_push(TOK_alloca, VT_FUNC | (p << VT_STRUCT_SHIFT), VT_CONST, 0);
9163 #endif
9165 define_start = define_stack;
9167 if (setjmp(s1->error_jmp_buf) == 0) {
9168 s1->nb_errors = 0;
9169 s1->error_set_jmp_enabled = 1;
9171 ch = file->buf_ptr[0];
9172 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
9173 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM;
9174 next();
9175 decl(VT_CONST);
9176 if (tok != TOK_EOF)
9177 expect("declaration");
9179 /* end of translation unit info */
9180 if (do_debug) {
9181 put_stabs_r(NULL, N_SO, 0, 0,
9182 text_section->data_offset, text_section, section_sym);
9185 s1->error_set_jmp_enabled = 0;
9187 /* reset define stack, but leave -Dsymbols (may be incorrect if
9188 they are undefined) */
9189 free_defines(define_start);
9191 gen_inline_functions();
9193 sym_pop(&global_stack, NULL);
9195 return s1->nb_errors != 0 ? -1 : 0;
9198 #ifdef LIBTCC
9199 int tcc_compile_string(TCCState *s, const char *str)
9201 BufferedFile bf1, *bf = &bf1;
9202 int ret, len;
9203 char *buf;
9205 /* init file structure */
9206 bf->fd = -1;
9207 /* XXX: avoid copying */
9208 len = strlen(str);
9209 buf = tcc_malloc(len + 1);
9210 if (!buf)
9211 return -1;
9212 memcpy(buf, str, len);
9213 buf[len] = CH_EOB;
9214 bf->buf_ptr = buf;
9215 bf->buf_end = buf + len;
9216 pstrcpy(bf->filename, sizeof(bf->filename), "<string>");
9217 bf->line_num = 1;
9218 file = bf;
9220 ret = tcc_compile(s);
9222 tcc_free(buf);
9224 /* currently, no need to close */
9225 return ret;
9227 #endif
9229 /* define a preprocessor symbol. A value can also be provided with the '=' operator */
9230 void tcc_define_symbol(TCCState *s1, const char *sym, const char *value)
9232 BufferedFile bf1, *bf = &bf1;
9234 pstrcpy(bf->buffer, IO_BUF_SIZE, sym);
9235 pstrcat(bf->buffer, IO_BUF_SIZE, " ");
9236 /* default value */
9237 if (!value)
9238 value = "1";
9239 pstrcat(bf->buffer, IO_BUF_SIZE, value);
9241 /* init file structure */
9242 bf->fd = -1;
9243 bf->buf_ptr = bf->buffer;
9244 bf->buf_end = bf->buffer + strlen(bf->buffer);
9245 *bf->buf_end = CH_EOB;
9246 bf->filename[0] = '\0';
9247 bf->line_num = 1;
9248 file = bf;
9250 s1->include_stack_ptr = s1->include_stack;
9252 /* parse with define parser */
9253 ch = file->buf_ptr[0];
9254 next_nomacro();
9255 parse_define();
9256 file = NULL;
9259 /* undefine a preprocessor symbol */
9260 void tcc_undefine_symbol(TCCState *s1, const char *sym)
9262 TokenSym *ts;
9263 Sym *s;
9264 ts = tok_alloc(sym, strlen(sym));
9265 s = define_find(ts->tok);
9266 /* undefine symbol by putting an invalid name */
9267 if (s)
9268 define_undef(s);
9271 #ifdef CONFIG_TCC_ASM
9273 #ifdef TCC_TARGET_I386
9274 #include "i386-asm.c"
9275 #endif
9276 #include "tccasm.c"
9278 #else
9279 static void asm_instr(void)
9281 error("inline asm() not supported");
9283 static void asm_global_instr(void)
9285 error("inline asm() not supported");
9287 #endif
9289 #include "tccelf.c"
9291 #ifdef TCC_TARGET_COFF
9292 #include "tcccoff.c"
9293 #endif
9295 #ifdef TCC_TARGET_PE
9296 #include "tccpe.c"
9297 #endif
9299 /* print the position in the source file of PC value 'pc' by reading
9300 the stabs debug information */
9301 static void rt_printline(unsigned long wanted_pc)
9303 Stab_Sym *sym, *sym_end;
9304 char func_name[128], last_func_name[128];
9305 unsigned long func_addr, last_pc, pc;
9306 const char *incl_files[INCLUDE_STACK_SIZE];
9307 int incl_index, len, last_line_num, i;
9308 const char *str, *p;
9310 fprintf(stderr, "0x%08lx:", wanted_pc);
9312 func_name[0] = '\0';
9313 func_addr = 0;
9314 incl_index = 0;
9315 last_func_name[0] = '\0';
9316 last_pc = 0xffffffff;
9317 last_line_num = 1;
9318 sym = (Stab_Sym *)stab_section->data + 1;
9319 sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset);
9320 while (sym < sym_end) {
9321 switch(sym->n_type) {
9322 /* function start or end */
9323 case N_FUN:
9324 if (sym->n_strx == 0) {
9325 /* we test if between last line and end of function */
9326 pc = sym->n_value + func_addr;
9327 if (wanted_pc >= last_pc && wanted_pc < pc)
9328 goto found;
9329 func_name[0] = '\0';
9330 func_addr = 0;
9331 } else {
9332 str = stabstr_section->data + sym->n_strx;
9333 p = strchr(str, ':');
9334 if (!p) {
9335 pstrcpy(func_name, sizeof(func_name), str);
9336 } else {
9337 len = p - str;
9338 if (len > sizeof(func_name) - 1)
9339 len = sizeof(func_name) - 1;
9340 memcpy(func_name, str, len);
9341 func_name[len] = '\0';
9343 func_addr = sym->n_value;
9345 break;
9346 /* line number info */
9347 case N_SLINE:
9348 pc = sym->n_value + func_addr;
9349 if (wanted_pc >= last_pc && wanted_pc < pc)
9350 goto found;
9351 last_pc = pc;
9352 last_line_num = sym->n_desc;
9353 /* XXX: slow! */
9354 strcpy(last_func_name, func_name);
9355 break;
9356 /* include files */
9357 case N_BINCL:
9358 str = stabstr_section->data + sym->n_strx;
9359 add_incl:
9360 if (incl_index < INCLUDE_STACK_SIZE) {
9361 incl_files[incl_index++] = str;
9363 break;
9364 case N_EINCL:
9365 if (incl_index > 1)
9366 incl_index--;
9367 break;
9368 case N_SO:
9369 if (sym->n_strx == 0) {
9370 incl_index = 0; /* end of translation unit */
9371 } else {
9372 str = stabstr_section->data + sym->n_strx;
9373 /* do not add path */
9374 len = strlen(str);
9375 if (len > 0 && str[len - 1] != '/')
9376 goto add_incl;
9378 break;
9380 sym++;
9383 /* second pass: we try symtab symbols (no line number info) */
9384 incl_index = 0;
9386 Elf32_Sym *sym, *sym_end;
9387 int type;
9389 sym_end = (Elf32_Sym *)(symtab_section->data + symtab_section->data_offset);
9390 for(sym = (Elf32_Sym *)symtab_section->data + 1;
9391 sym < sym_end;
9392 sym++) {
9393 type = ELF32_ST_TYPE(sym->st_info);
9394 if (type == STT_FUNC) {
9395 if (wanted_pc >= sym->st_value &&
9396 wanted_pc < sym->st_value + sym->st_size) {
9397 pstrcpy(last_func_name, sizeof(last_func_name),
9398 strtab_section->data + sym->st_name);
9399 goto found;
9404 /* did not find any info: */
9405 fprintf(stderr, " ???\n");
9406 return;
9407 found:
9408 if (last_func_name[0] != '\0') {
9409 fprintf(stderr, " %s()", last_func_name);
9411 if (incl_index > 0) {
9412 fprintf(stderr, " (%s:%d",
9413 incl_files[incl_index - 1], last_line_num);
9414 for(i = incl_index - 2; i >= 0; i--)
9415 fprintf(stderr, ", included from %s", incl_files[i]);
9416 fprintf(stderr, ")");
9418 fprintf(stderr, "\n");
9421 #if !defined(WIN32) && !defined(CONFIG_TCCBOOT)
9423 #ifdef __i386__
9425 /* fix for glibc 2.1 */
9426 #ifndef REG_EIP
9427 #define REG_EIP EIP
9428 #define REG_EBP EBP
9429 #endif
9431 /* return the PC at frame level 'level'. Return non zero if not found */
9432 static int rt_get_caller_pc(unsigned long *paddr,
9433 ucontext_t *uc, int level)
9435 unsigned long fp;
9436 int i;
9438 if (level == 0) {
9439 #if defined(__FreeBSD__)
9440 *paddr = uc->uc_mcontext.mc_eip;
9441 #elif defined(__dietlibc__)
9442 *paddr = uc->uc_mcontext.eip;
9443 #else
9444 *paddr = uc->uc_mcontext.gregs[REG_EIP];
9445 #endif
9446 return 0;
9447 } else {
9448 #if defined(__FreeBSD__)
9449 fp = uc->uc_mcontext.mc_ebp;
9450 #elif defined(__dietlibc__)
9451 fp = uc->uc_mcontext.ebp;
9452 #else
9453 fp = uc->uc_mcontext.gregs[REG_EBP];
9454 #endif
9455 for(i=1;i<level;i++) {
9456 /* XXX: check address validity with program info */
9457 if (fp <= 0x1000 || fp >= 0xc0000000)
9458 return -1;
9459 fp = ((unsigned long *)fp)[0];
9461 *paddr = ((unsigned long *)fp)[1];
9462 return 0;
9465 #else
9467 #warning add arch specific rt_get_caller_pc()
9469 static int rt_get_caller_pc(unsigned long *paddr,
9470 ucontext_t *uc, int level)
9472 return -1;
9474 #endif
9476 /* emit a run time error at position 'pc' */
9477 void rt_error(ucontext_t *uc, const char *fmt, ...)
9479 va_list ap;
9480 unsigned long pc;
9481 int i;
9483 va_start(ap, fmt);
9484 fprintf(stderr, "Runtime error: ");
9485 vfprintf(stderr, fmt, ap);
9486 fprintf(stderr, "\n");
9487 for(i=0;i<num_callers;i++) {
9488 if (rt_get_caller_pc(&pc, uc, i) < 0)
9489 break;
9490 if (i == 0)
9491 fprintf(stderr, "at ");
9492 else
9493 fprintf(stderr, "by ");
9494 rt_printline(pc);
9496 exit(255);
9497 va_end(ap);
9500 /* signal handler for fatal errors */
9501 static void sig_error(int signum, siginfo_t *siginf, void *puc)
9503 ucontext_t *uc = puc;
9505 switch(signum) {
9506 case SIGFPE:
9507 switch(siginf->si_code) {
9508 case FPE_INTDIV:
9509 case FPE_FLTDIV:
9510 rt_error(uc, "division by zero");
9511 break;
9512 default:
9513 rt_error(uc, "floating point exception");
9514 break;
9516 break;
9517 case SIGBUS:
9518 case SIGSEGV:
9519 if (rt_bound_error_msg && *rt_bound_error_msg)
9520 rt_error(uc, *rt_bound_error_msg);
9521 else
9522 rt_error(uc, "dereferencing invalid pointer");
9523 break;
9524 case SIGILL:
9525 rt_error(uc, "illegal instruction");
9526 break;
9527 case SIGABRT:
9528 rt_error(uc, "abort() called");
9529 break;
9530 default:
9531 rt_error(uc, "caught signal %d", signum);
9532 break;
9534 exit(255);
9536 #endif
9538 /* do all relocations (needed before using tcc_get_symbol()) */
9539 int tcc_relocate(TCCState *s1)
9541 Section *s;
9542 int i;
9544 s1->nb_errors = 0;
9546 #ifdef TCC_TARGET_PE
9547 pe_add_runtime(s1);
9548 #else
9549 tcc_add_runtime(s1);
9550 #endif
9552 relocate_common_syms();
9554 tcc_add_linker_symbols(s1);
9556 build_got_entries(s1);
9558 /* compute relocation address : section are relocated in place. We
9559 also alloc the bss space */
9560 for(i = 1; i < s1->nb_sections; i++) {
9561 s = s1->sections[i];
9562 if (s->sh_flags & SHF_ALLOC) {
9563 if (s->sh_type == SHT_NOBITS)
9564 s->data = tcc_mallocz(s->data_offset);
9565 s->sh_addr = (unsigned long)s->data;
9569 relocate_syms(s1, 1);
9571 if (s1->nb_errors != 0)
9572 return -1;
9574 /* relocate each section */
9575 for(i = 1; i < s1->nb_sections; i++) {
9576 s = s1->sections[i];
9577 if (s->reloc)
9578 relocate_section(s1, s);
9580 return 0;
9583 /* launch the compiled program with the given arguments */
9584 int tcc_run(TCCState *s1, int argc, char **argv)
9586 int (*prog_main)(int, char **);
9588 if (tcc_relocate(s1) < 0)
9589 return -1;
9591 prog_main = tcc_get_symbol_err(s1, "main");
9593 if (do_debug) {
9594 #if defined(WIN32) || defined(CONFIG_TCCBOOT)
9595 error("debug mode currently not available for Windows");
9596 #else
9597 struct sigaction sigact;
9598 /* install TCC signal handlers to print debug info on fatal
9599 runtime errors */
9600 sigact.sa_flags = SA_SIGINFO | SA_RESETHAND;
9601 sigact.sa_sigaction = sig_error;
9602 sigemptyset(&sigact.sa_mask);
9603 sigaction(SIGFPE, &sigact, NULL);
9604 sigaction(SIGILL, &sigact, NULL);
9605 sigaction(SIGSEGV, &sigact, NULL);
9606 sigaction(SIGBUS, &sigact, NULL);
9607 sigaction(SIGABRT, &sigact, NULL);
9608 #endif
9611 #ifdef CONFIG_TCC_BCHECK
9612 if (do_bounds_check) {
9613 void (*bound_init)(void);
9615 /* set error function */
9616 rt_bound_error_msg = (void *)tcc_get_symbol_err(s1,
9617 "__bound_error_msg");
9619 /* XXX: use .init section so that it also work in binary ? */
9620 bound_init = (void *)tcc_get_symbol_err(s1, "__bound_init");
9621 bound_init();
9623 #endif
9624 return (*prog_main)(argc, argv);
9627 TCCState *tcc_new(void)
9629 const char *p, *r;
9630 TCCState *s;
9631 TokenSym *ts;
9632 int i, c;
9634 s = tcc_mallocz(sizeof(TCCState));
9635 if (!s)
9636 return NULL;
9637 tcc_state = s;
9638 s->output_type = TCC_OUTPUT_MEMORY;
9640 /* init isid table */
9641 for(i=0;i<256;i++)
9642 isidnum_table[i] = isid(i) || isnum(i);
9644 /* add all tokens */
9645 table_ident = NULL;
9646 memset(hash_ident, 0, TOK_HASH_SIZE * sizeof(TokenSym *));
9648 tok_ident = TOK_IDENT;
9649 p = tcc_keywords;
9650 while (*p) {
9651 r = p;
9652 for(;;) {
9653 c = *r++;
9654 if (c == '\0')
9655 break;
9657 ts = tok_alloc(p, r - p - 1);
9658 p = r;
9661 /* we add dummy defines for some special macros to speed up tests
9662 and to have working defined() */
9663 define_push(TOK___LINE__, MACRO_OBJ, NULL, NULL);
9664 define_push(TOK___FILE__, MACRO_OBJ, NULL, NULL);
9665 define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL);
9666 define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL);
9668 /* standard defines */
9669 tcc_define_symbol(s, "__STDC__", NULL);
9670 #if defined(TCC_TARGET_I386)
9671 tcc_define_symbol(s, "__i386__", NULL);
9672 #endif
9673 #if defined(TCC_TARGET_ARM)
9674 tcc_define_symbol(s, "__ARM_ARCH_4__", NULL);
9675 tcc_define_symbol(s, "__arm_elf__", NULL);
9676 tcc_define_symbol(s, "__arm_elf", NULL);
9677 tcc_define_symbol(s, "arm_elf", NULL);
9678 tcc_define_symbol(s, "__arm__", NULL);
9679 tcc_define_symbol(s, "__arm", NULL);
9680 tcc_define_symbol(s, "arm", NULL);
9681 tcc_define_symbol(s, "__APCS_32__", NULL);
9682 #endif
9683 #if defined(linux)
9684 tcc_define_symbol(s, "__linux__", NULL);
9685 tcc_define_symbol(s, "linux", NULL);
9686 #endif
9687 /* tiny C specific defines */
9688 tcc_define_symbol(s, "__TINYC__", NULL);
9690 /* tiny C & gcc defines */
9691 tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned int");
9692 tcc_define_symbol(s, "__PTRDIFF_TYPE__", "int");
9693 tcc_define_symbol(s, "__WCHAR_TYPE__", "int");
9695 /* default library paths */
9696 #ifdef TCC_TARGET_PE
9698 char buf[1024];
9699 snprintf(buf, sizeof(buf), "%s/lib", tcc_lib_path);
9700 tcc_add_library_path(s, buf);
9702 #else
9703 tcc_add_library_path(s, "/usr/local/lib");
9704 tcc_add_library_path(s, "/usr/lib");
9705 tcc_add_library_path(s, "/lib");
9706 #endif
9708 /* no section zero */
9709 dynarray_add((void ***)&s->sections, &s->nb_sections, NULL);
9711 /* create standard sections */
9712 text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
9713 data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
9714 bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
9716 /* symbols are always generated for linking stage */
9717 symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0,
9718 ".strtab",
9719 ".hashtab", SHF_PRIVATE);
9720 strtab_section = symtab_section->link;
9722 /* private symbol table for dynamic symbols */
9723 s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE,
9724 ".dynstrtab",
9725 ".dynhashtab", SHF_PRIVATE);
9726 s->alacarte_link = 1;
9728 #ifdef CHAR_IS_UNSIGNED
9729 s->char_is_unsigned = 1;
9730 #endif
9731 return s;
9734 void tcc_delete(TCCState *s1)
9736 int i, n;
9738 /* free -D defines */
9739 free_defines(NULL);
9741 /* free tokens */
9742 n = tok_ident - TOK_IDENT;
9743 for(i = 0; i < n; i++)
9744 tcc_free(table_ident[i]);
9745 tcc_free(table_ident);
9747 /* free all sections */
9749 free_section(symtab_section->hash);
9751 free_section(s1->dynsymtab_section->hash);
9752 free_section(s1->dynsymtab_section->link);
9753 free_section(s1->dynsymtab_section);
9755 for(i = 1; i < s1->nb_sections; i++)
9756 free_section(s1->sections[i]);
9757 tcc_free(s1->sections);
9759 /* free loaded dlls array */
9760 for(i = 0; i < s1->nb_loaded_dlls; i++)
9761 tcc_free(s1->loaded_dlls[i]);
9762 tcc_free(s1->loaded_dlls);
9764 /* library paths */
9765 for(i = 0; i < s1->nb_library_paths; i++)
9766 tcc_free(s1->library_paths[i]);
9767 tcc_free(s1->library_paths);
9769 /* cached includes */
9770 for(i = 0; i < s1->nb_cached_includes; i++)
9771 tcc_free(s1->cached_includes[i]);
9772 tcc_free(s1->cached_includes);
9774 for(i = 0; i < s1->nb_include_paths; i++)
9775 tcc_free(s1->include_paths[i]);
9776 tcc_free(s1->include_paths);
9778 for(i = 0; i < s1->nb_sysinclude_paths; i++)
9779 tcc_free(s1->sysinclude_paths[i]);
9780 tcc_free(s1->sysinclude_paths);
9782 tcc_free(s1);
9785 int tcc_add_include_path(TCCState *s1, const char *pathname)
9787 char *pathname1;
9789 pathname1 = tcc_strdup(pathname);
9790 dynarray_add((void ***)&s1->include_paths, &s1->nb_include_paths, pathname1);
9791 return 0;
9794 int tcc_add_sysinclude_path(TCCState *s1, const char *pathname)
9796 char *pathname1;
9798 pathname1 = tcc_strdup(pathname);
9799 dynarray_add((void ***)&s1->sysinclude_paths, &s1->nb_sysinclude_paths, pathname1);
9800 return 0;
9803 static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
9805 const char *ext, *filename1;
9806 Elf32_Ehdr ehdr;
9807 int fd, ret;
9808 BufferedFile *saved_file;
9810 /* find source file type with extension */
9811 filename1 = strrchr(filename, '/');
9812 if (filename1)
9813 filename1++;
9814 else
9815 filename1 = filename;
9816 ext = strrchr(filename1, '.');
9817 if (ext)
9818 ext++;
9820 /* open the file */
9821 saved_file = file;
9822 file = tcc_open(s1, filename);
9823 if (!file) {
9824 if (flags & AFF_PRINT_ERROR) {
9825 error_noabort("file '%s' not found", filename);
9827 ret = -1;
9828 goto fail1;
9831 if (!ext || !strcmp(ext, "c")) {
9832 /* C file assumed */
9833 ret = tcc_compile(s1);
9834 } else
9835 #ifdef CONFIG_TCC_ASM
9836 if (!strcmp(ext, "S")) {
9837 /* preprocessed assembler */
9838 ret = tcc_assemble(s1, 1);
9839 } else if (!strcmp(ext, "s")) {
9840 /* non preprocessed assembler */
9841 ret = tcc_assemble(s1, 0);
9842 } else
9843 #endif
9844 #ifdef TCC_TARGET_PE
9845 if (!strcmp(ext, "def")) {
9846 ret = pe_load_def_file(s1, fdopen(file->fd, "rb"));
9847 } else
9848 #endif
9850 fd = file->fd;
9851 /* assume executable format: auto guess file type */
9852 ret = read(fd, &ehdr, sizeof(ehdr));
9853 lseek(fd, 0, SEEK_SET);
9854 if (ret <= 0) {
9855 error_noabort("could not read header");
9856 goto fail;
9857 } else if (ret != sizeof(ehdr)) {
9858 goto try_load_script;
9861 if (ehdr.e_ident[0] == ELFMAG0 &&
9862 ehdr.e_ident[1] == ELFMAG1 &&
9863 ehdr.e_ident[2] == ELFMAG2 &&
9864 ehdr.e_ident[3] == ELFMAG3) {
9865 file->line_num = 0; /* do not display line number if error */
9866 if (ehdr.e_type == ET_REL) {
9867 ret = tcc_load_object_file(s1, fd, 0);
9868 } else if (ehdr.e_type == ET_DYN) {
9869 if (s1->output_type == TCC_OUTPUT_MEMORY) {
9870 #ifdef TCC_TARGET_PE
9871 ret = -1;
9872 #else
9873 void *h;
9874 h = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY);
9875 if (h)
9876 ret = 0;
9877 else
9878 ret = -1;
9879 #endif
9880 } else {
9881 ret = tcc_load_dll(s1, fd, filename,
9882 (flags & AFF_REFERENCED_DLL) != 0);
9884 } else {
9885 error_noabort("unrecognized ELF file");
9886 goto fail;
9888 } else if (memcmp((char *)&ehdr, ARMAG, 8) == 0) {
9889 file->line_num = 0; /* do not display line number if error */
9890 ret = tcc_load_archive(s1, fd);
9891 } else
9892 #ifdef TCC_TARGET_COFF
9893 if (*(uint16_t *)(&ehdr) == COFF_C67_MAGIC) {
9894 ret = tcc_load_coff(s1, fd);
9895 } else
9896 #endif
9898 /* as GNU ld, consider it is an ld script if not recognized */
9899 try_load_script:
9900 ret = tcc_load_ldscript(s1);
9901 if (ret < 0) {
9902 error_noabort("unrecognized file type");
9903 goto fail;
9907 the_end:
9908 tcc_close(file);
9909 fail1:
9910 file = saved_file;
9911 return ret;
9912 fail:
9913 ret = -1;
9914 goto the_end;
9917 int tcc_add_file(TCCState *s, const char *filename)
9919 return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR);
9922 int tcc_add_library_path(TCCState *s, const char *pathname)
9924 char *pathname1;
9926 pathname1 = tcc_strdup(pathname);
9927 dynarray_add((void ***)&s->library_paths, &s->nb_library_paths, pathname1);
9928 return 0;
9931 /* find and load a dll. Return non zero if not found */
9932 /* XXX: add '-rpath' option support ? */
9933 static int tcc_add_dll(TCCState *s, const char *filename, int flags)
9935 char buf[1024];
9936 int i;
9938 for(i = 0; i < s->nb_library_paths; i++) {
9939 snprintf(buf, sizeof(buf), "%s/%s",
9940 s->library_paths[i], filename);
9941 if (tcc_add_file_internal(s, buf, flags) == 0)
9942 return 0;
9944 return -1;
9947 /* the library name is the same as the argument of the '-l' option */
9948 int tcc_add_library(TCCState *s, const char *libraryname)
9950 char buf[1024];
9951 int i;
9953 /* first we look for the dynamic library if not static linking */
9954 if (!s->static_link) {
9955 #ifdef TCC_TARGET_PE
9956 snprintf(buf, sizeof(buf), "%s.def", libraryname);
9957 #else
9958 snprintf(buf, sizeof(buf), "lib%s.so", libraryname);
9959 #endif
9960 if (tcc_add_dll(s, buf, 0) == 0)
9961 return 0;
9964 /* then we look for the static library */
9965 for(i = 0; i < s->nb_library_paths; i++) {
9966 snprintf(buf, sizeof(buf), "%s/lib%s.a",
9967 s->library_paths[i], libraryname);
9968 if (tcc_add_file_internal(s, buf, 0) == 0)
9969 return 0;
9971 return -1;
9974 int tcc_add_symbol(TCCState *s, const char *name, unsigned long val)
9976 add_elf_sym(symtab_section, val, 0,
9977 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
9978 SHN_ABS, name);
9979 return 0;
9982 int tcc_set_output_type(TCCState *s, int output_type)
9984 s->output_type = output_type;
9986 if (!s->nostdinc) {
9987 char buf[1024];
9989 /* default include paths */
9990 /* XXX: reverse order needed if -isystem support */
9991 #ifndef TCC_TARGET_PE
9992 tcc_add_sysinclude_path(s, "/usr/local/include");
9993 tcc_add_sysinclude_path(s, "/usr/include");
9994 #endif
9995 snprintf(buf, sizeof(buf), "%s/include", tcc_lib_path);
9996 tcc_add_sysinclude_path(s, buf);
9997 #ifdef TCC_TARGET_PE
9998 snprintf(buf, sizeof(buf), "%s/include/winapi", tcc_lib_path);
9999 tcc_add_sysinclude_path(s, buf);
10000 #endif
10003 /* if bound checking, then add corresponding sections */
10004 #ifdef CONFIG_TCC_BCHECK
10005 if (do_bounds_check) {
10006 /* define symbol */
10007 tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL);
10008 /* create bounds sections */
10009 bounds_section = new_section(s, ".bounds",
10010 SHT_PROGBITS, SHF_ALLOC);
10011 lbounds_section = new_section(s, ".lbounds",
10012 SHT_PROGBITS, SHF_ALLOC);
10014 #endif
10016 if (s->char_is_unsigned) {
10017 tcc_define_symbol(s, "__CHAR_UNSIGNED__", NULL);
10020 /* add debug sections */
10021 if (do_debug) {
10022 /* stab symbols */
10023 stab_section = new_section(s, ".stab", SHT_PROGBITS, 0);
10024 stab_section->sh_entsize = sizeof(Stab_Sym);
10025 stabstr_section = new_section(s, ".stabstr", SHT_STRTAB, 0);
10026 put_elf_str(stabstr_section, "");
10027 stab_section->link = stabstr_section;
10028 /* put first entry */
10029 put_stabs("", 0, 0, 0, 0);
10032 /* add libc crt1/crti objects */
10033 #ifndef TCC_TARGET_PE
10034 if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) &&
10035 !s->nostdlib) {
10036 if (output_type != TCC_OUTPUT_DLL)
10037 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crt1.o");
10038 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crti.o");
10040 #endif
10041 return 0;
10044 #define WD_ALL 0x0001 /* warning is activated when using -Wall */
10045 #define FD_INVERT 0x0002 /* invert value before storing */
10047 typedef struct FlagDef {
10048 uint16_t offset;
10049 uint16_t flags;
10050 const char *name;
10051 } FlagDef;
10053 static const FlagDef warning_defs[] = {
10054 { offsetof(TCCState, warn_unsupported), 0, "unsupported" },
10055 { offsetof(TCCState, warn_write_strings), 0, "write-strings" },
10056 { offsetof(TCCState, warn_error), 0, "error" },
10057 { offsetof(TCCState, warn_implicit_function_declaration), WD_ALL,
10058 "implicit-function-declaration" },
10061 static int set_flag(TCCState *s, const FlagDef *flags, int nb_flags,
10062 const char *name, int value)
10064 int i;
10065 const FlagDef *p;
10066 const char *r;
10068 r = name;
10069 if (r[0] == 'n' && r[1] == 'o' && r[2] == '-') {
10070 r += 3;
10071 value = !value;
10073 for(i = 0, p = flags; i < nb_flags; i++, p++) {
10074 if (!strcmp(r, p->name))
10075 goto found;
10077 return -1;
10078 found:
10079 if (p->flags & FD_INVERT)
10080 value = !value;
10081 *(int *)((uint8_t *)s + p->offset) = value;
10082 return 0;
10086 /* set/reset a warning */
10087 int tcc_set_warning(TCCState *s, const char *warning_name, int value)
10089 int i;
10090 const FlagDef *p;
10092 if (!strcmp(warning_name, "all")) {
10093 for(i = 0, p = warning_defs; i < countof(warning_defs); i++, p++) {
10094 if (p->flags & WD_ALL)
10095 *(int *)((uint8_t *)s + p->offset) = 1;
10097 return 0;
10098 } else {
10099 return set_flag(s, warning_defs, countof(warning_defs),
10100 warning_name, value);
10104 static const FlagDef flag_defs[] = {
10105 { offsetof(TCCState, char_is_unsigned), 0, "unsigned-char" },
10106 { offsetof(TCCState, char_is_unsigned), FD_INVERT, "signed-char" },
10107 { offsetof(TCCState, nocommon), FD_INVERT, "common" },
10110 /* set/reset a flag */
10111 int tcc_set_flag(TCCState *s, const char *flag_name, int value)
10113 return set_flag(s, flag_defs, countof(flag_defs),
10114 flag_name, value);
10117 #if !defined(LIBTCC)
10119 /* extract the basename of a file */
10120 static const char *tcc_basename(const char *name)
10122 const char *p;
10123 p = strrchr(name, '/');
10124 #ifdef WIN32
10125 if (!p)
10126 p = strrchr(name, '\\');
10127 #endif
10128 if (!p)
10129 p = name;
10130 else
10131 p++;
10132 return p;
10135 static int64_t getclock_us(void)
10137 #ifdef WIN32
10138 struct _timeb tb;
10139 _ftime(&tb);
10140 return (tb.time * 1000LL + tb.millitm) * 1000LL;
10141 #else
10142 struct timeval tv;
10143 gettimeofday(&tv, NULL);
10144 return tv.tv_sec * 1000000LL + tv.tv_usec;
10145 #endif
10148 void help(void)
10150 printf("tcc version " TCC_VERSION " - Tiny C Compiler - Copyright (C) 2001-2005 Fabrice Bellard\n"
10151 "usage: tcc [-v] [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
10152 " [-Wwarn] [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-static]\n"
10153 " [infile1 infile2...] [-run infile args...]\n"
10154 "\n"
10155 "General options:\n"
10156 " -v display current version\n"
10157 " -c compile only - generate an object file\n"
10158 " -o outfile set output filename\n"
10159 " -Bdir set tcc internal library path\n"
10160 " -bench output compilation statistics\n"
10161 " -run run compiled source\n"
10162 " -fflag set or reset (with 'no-' prefix) 'flag' (see man page)\n"
10163 " -Wwarning set or reset (with 'no-' prefix) 'warning' (see man page)\n"
10164 " -w disable all warnings\n"
10165 "Preprocessor options:\n"
10166 " -Idir add include path 'dir'\n"
10167 " -Dsym[=val] define 'sym' with value 'val'\n"
10168 " -Usym undefine 'sym'\n"
10169 "Linker options:\n"
10170 " -Ldir add library path 'dir'\n"
10171 " -llib link with dynamic or static library 'lib'\n"
10172 " -shared generate a shared library\n"
10173 " -static static linking\n"
10174 " -rdynamic export all global symbols to dynamic linker\n"
10175 " -r relocatable output\n"
10176 "Debugger options:\n"
10177 " -g generate runtime debug info\n"
10178 #ifdef CONFIG_TCC_BCHECK
10179 " -b compile with built-in memory and bounds checker (implies -g)\n"
10180 #endif
10181 " -bt N show N callers in stack traces\n"
10185 #define TCC_OPTION_HAS_ARG 0x0001
10186 #define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
10188 typedef struct TCCOption {
10189 const char *name;
10190 uint16_t index;
10191 uint16_t flags;
10192 } TCCOption;
10194 enum {
10195 TCC_OPTION_HELP,
10196 TCC_OPTION_I,
10197 TCC_OPTION_D,
10198 TCC_OPTION_U,
10199 TCC_OPTION_L,
10200 TCC_OPTION_B,
10201 TCC_OPTION_l,
10202 TCC_OPTION_bench,
10203 TCC_OPTION_bt,
10204 TCC_OPTION_b,
10205 TCC_OPTION_g,
10206 TCC_OPTION_c,
10207 TCC_OPTION_static,
10208 TCC_OPTION_shared,
10209 TCC_OPTION_o,
10210 TCC_OPTION_r,
10211 TCC_OPTION_Wl,
10212 TCC_OPTION_W,
10213 TCC_OPTION_O,
10214 TCC_OPTION_m,
10215 TCC_OPTION_f,
10216 TCC_OPTION_nostdinc,
10217 TCC_OPTION_nostdlib,
10218 TCC_OPTION_print_search_dirs,
10219 TCC_OPTION_rdynamic,
10220 TCC_OPTION_run,
10221 TCC_OPTION_v,
10222 TCC_OPTION_w,
10223 TCC_OPTION_pipe,
10226 static const TCCOption tcc_options[] = {
10227 { "h", TCC_OPTION_HELP, 0 },
10228 { "?", TCC_OPTION_HELP, 0 },
10229 { "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG },
10230 { "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG },
10231 { "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG },
10232 { "L", TCC_OPTION_L, TCC_OPTION_HAS_ARG },
10233 { "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG },
10234 { "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10235 { "bench", TCC_OPTION_bench, 0 },
10236 { "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG },
10237 #ifdef CONFIG_TCC_BCHECK
10238 { "b", TCC_OPTION_b, 0 },
10239 #endif
10240 { "g", TCC_OPTION_g, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10241 { "c", TCC_OPTION_c, 0 },
10242 { "static", TCC_OPTION_static, 0 },
10243 { "shared", TCC_OPTION_shared, 0 },
10244 { "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG },
10245 { "run", TCC_OPTION_run, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10246 { "rdynamic", TCC_OPTION_rdynamic, 0 },
10247 { "r", TCC_OPTION_r, 0 },
10248 { "Wl,", TCC_OPTION_Wl, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10249 { "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10250 { "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10251 { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG },
10252 { "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10253 { "nostdinc", TCC_OPTION_nostdinc, 0 },
10254 { "nostdlib", TCC_OPTION_nostdlib, 0 },
10255 { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 },
10256 { "v", TCC_OPTION_v, 0 },
10257 { "w", TCC_OPTION_w, 0 },
10258 { "pipe", TCC_OPTION_pipe, 0},
10259 { NULL },
10262 /* convert 'str' into an array of space separated strings */
10263 static int expand_args(char ***pargv, const char *str)
10265 const char *s1;
10266 char **argv, *arg;
10267 int argc, len;
10269 argc = 0;
10270 argv = NULL;
10271 for(;;) {
10272 while (is_space(*str))
10273 str++;
10274 if (*str == '\0')
10275 break;
10276 s1 = str;
10277 while (*str != '\0' && !is_space(*str))
10278 str++;
10279 len = str - s1;
10280 arg = tcc_malloc(len + 1);
10281 memcpy(arg, s1, len);
10282 arg[len] = '\0';
10283 dynarray_add((void ***)&argv, &argc, arg);
10285 *pargv = argv;
10286 return argc;
10289 static char **files;
10290 static int nb_files, nb_libraries;
10291 static int multiple_files;
10292 static int print_search_dirs;
10293 static int output_type;
10294 static int reloc_output;
10295 static const char *outfile;
10297 int parse_args(TCCState *s, int argc, char **argv)
10299 int optind;
10300 const TCCOption *popt;
10301 const char *optarg, *p1, *r1;
10302 char *r;
10304 optind = 0;
10305 while (1) {
10306 if (optind >= argc) {
10307 if (nb_files == 0 && !print_search_dirs)
10308 goto show_help;
10309 else
10310 break;
10312 r = argv[optind++];
10313 if (r[0] != '-') {
10314 /* add a new file */
10315 dynarray_add((void ***)&files, &nb_files, r);
10316 if (!multiple_files) {
10317 optind--;
10318 /* argv[0] will be this file */
10319 break;
10321 } else {
10322 /* find option in table (match only the first chars */
10323 popt = tcc_options;
10324 for(;;) {
10325 p1 = popt->name;
10326 if (p1 == NULL)
10327 error("invalid option -- '%s'", r);
10328 r1 = r + 1;
10329 for(;;) {
10330 if (*p1 == '\0')
10331 goto option_found;
10332 if (*r1 != *p1)
10333 break;
10334 p1++;
10335 r1++;
10337 popt++;
10339 option_found:
10340 if (popt->flags & TCC_OPTION_HAS_ARG) {
10341 if (*r1 != '\0' || (popt->flags & TCC_OPTION_NOSEP)) {
10342 optarg = r1;
10343 } else {
10344 if (optind >= argc)
10345 error("argument to '%s' is missing", r);
10346 optarg = argv[optind++];
10348 } else {
10349 if (*r1 != '\0')
10350 goto show_help;
10351 optarg = NULL;
10354 switch(popt->index) {
10355 case TCC_OPTION_HELP:
10356 show_help:
10357 help();
10358 exit(1);
10359 case TCC_OPTION_I:
10360 if (tcc_add_include_path(s, optarg) < 0)
10361 error("too many include paths");
10362 break;
10363 case TCC_OPTION_D:
10365 char *sym, *value;
10366 sym = (char *)optarg;
10367 value = strchr(sym, '=');
10368 if (value) {
10369 *value = '\0';
10370 value++;
10372 tcc_define_symbol(s, sym, value);
10374 break;
10375 case TCC_OPTION_U:
10376 tcc_undefine_symbol(s, optarg);
10377 break;
10378 case TCC_OPTION_L:
10379 tcc_add_library_path(s, optarg);
10380 break;
10381 case TCC_OPTION_B:
10382 /* set tcc utilities path (mainly for tcc development) */
10383 tcc_lib_path = optarg;
10384 break;
10385 case TCC_OPTION_l:
10386 dynarray_add((void ***)&files, &nb_files, r);
10387 nb_libraries++;
10388 break;
10389 case TCC_OPTION_bench:
10390 do_bench = 1;
10391 break;
10392 case TCC_OPTION_bt:
10393 num_callers = atoi(optarg);
10394 break;
10395 #ifdef CONFIG_TCC_BCHECK
10396 case TCC_OPTION_b:
10397 do_bounds_check = 1;
10398 do_debug = 1;
10399 break;
10400 #endif
10401 case TCC_OPTION_g:
10402 do_debug = 1;
10403 break;
10404 case TCC_OPTION_c:
10405 multiple_files = 1;
10406 output_type = TCC_OUTPUT_OBJ;
10407 break;
10408 case TCC_OPTION_static:
10409 s->static_link = 1;
10410 break;
10411 case TCC_OPTION_shared:
10412 output_type = TCC_OUTPUT_DLL;
10413 break;
10414 case TCC_OPTION_o:
10415 multiple_files = 1;
10416 outfile = optarg;
10417 break;
10418 case TCC_OPTION_r:
10419 /* generate a .o merging several output files */
10420 reloc_output = 1;
10421 output_type = TCC_OUTPUT_OBJ;
10422 break;
10423 case TCC_OPTION_nostdinc:
10424 s->nostdinc = 1;
10425 break;
10426 case TCC_OPTION_nostdlib:
10427 s->nostdlib = 1;
10428 break;
10429 case TCC_OPTION_print_search_dirs:
10430 print_search_dirs = 1;
10431 break;
10432 case TCC_OPTION_run:
10434 int argc1;
10435 char **argv1;
10436 argc1 = expand_args(&argv1, optarg);
10437 if (argc1 > 0) {
10438 parse_args(s, argc1, argv1);
10440 multiple_files = 0;
10441 output_type = TCC_OUTPUT_MEMORY;
10443 break;
10444 case TCC_OPTION_v:
10445 printf("tcc version %s\n", TCC_VERSION);
10446 exit(0);
10447 case TCC_OPTION_f:
10448 if (tcc_set_flag(s, optarg, 1) < 0 && s->warn_unsupported)
10449 goto unsupported_option;
10450 break;
10451 case TCC_OPTION_W:
10452 if (tcc_set_warning(s, optarg, 1) < 0 &&
10453 s->warn_unsupported)
10454 goto unsupported_option;
10455 break;
10456 case TCC_OPTION_w:
10457 s->warn_none = 1;
10458 break;
10459 case TCC_OPTION_rdynamic:
10460 s->rdynamic = 1;
10461 break;
10462 case TCC_OPTION_Wl:
10464 const char *p;
10465 if (strstart(optarg, "-Ttext,", &p)) {
10466 s->text_addr = strtoul(p, NULL, 16);
10467 s->has_text_addr = 1;
10468 } else if (strstart(optarg, "--oformat,", &p)) {
10469 if (strstart(p, "elf32-", NULL)) {
10470 s->output_format = TCC_OUTPUT_FORMAT_ELF;
10471 } else if (!strcmp(p, "binary")) {
10472 s->output_format = TCC_OUTPUT_FORMAT_BINARY;
10473 } else
10474 #ifdef TCC_TARGET_COFF
10475 if (!strcmp(p, "coff")) {
10476 s->output_format = TCC_OUTPUT_FORMAT_COFF;
10477 } else
10478 #endif
10480 error("target %s not found", p);
10482 } else {
10483 error("unsupported linker option '%s'", optarg);
10486 break;
10487 default:
10488 if (s->warn_unsupported) {
10489 unsupported_option:
10490 warning("unsupported option '%s'", r);
10492 break;
10496 return optind;
10499 int main(int argc, char **argv)
10501 int i;
10502 TCCState *s;
10503 int nb_objfiles, ret, optind;
10504 char objfilename[1024];
10505 int64_t start_time = 0;
10507 #ifdef WIN32
10508 /* on win32, we suppose the lib and includes are at the location
10509 of 'tcc.exe' */
10511 static char path[1024];
10512 char *p, *d;
10514 GetModuleFileNameA(NULL, path, sizeof path);
10515 p = d = strlwr(path);
10516 while (*d)
10517 if (*d++ == '\\')
10518 (p = d)[-1] = '/';
10519 *p = '\0';
10520 tcc_lib_path = path;
10522 #endif
10524 s = tcc_new();
10525 output_type = TCC_OUTPUT_EXE;
10526 outfile = NULL;
10527 multiple_files = 1;
10528 files = NULL;
10529 nb_files = 0;
10530 nb_libraries = 0;
10531 reloc_output = 0;
10532 print_search_dirs = 0;
10534 optind = parse_args(s, argc - 1, argv + 1) + 1;
10536 if (print_search_dirs) {
10537 /* enough for Linux kernel */
10538 printf("install: %s/\n", tcc_lib_path);
10539 return 0;
10542 nb_objfiles = nb_files - nb_libraries;
10544 /* if outfile provided without other options, we output an
10545 executable */
10546 if (outfile && output_type == TCC_OUTPUT_MEMORY)
10547 output_type = TCC_OUTPUT_EXE;
10549 /* check -c consistency : only single file handled. XXX: checks file type */
10550 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
10551 /* accepts only a single input file */
10552 if (nb_objfiles != 1)
10553 error("cannot specify multiple files with -c");
10554 if (nb_libraries != 0)
10555 error("cannot specify libraries with -c");
10558 /* compute default outfile name */
10559 if (output_type != TCC_OUTPUT_MEMORY && !outfile) {
10560 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
10561 char *ext;
10562 /* strip path */
10563 pstrcpy(objfilename, sizeof(objfilename) - 1,
10564 tcc_basename(files[0]));
10565 /* add .o extension */
10566 ext = strrchr(objfilename, '.');
10567 if (!ext)
10568 goto default_outfile;
10569 strcpy(ext + 1, "o");
10570 } else {
10571 default_outfile:
10572 pstrcpy(objfilename, sizeof(objfilename), "a.out");
10574 outfile = objfilename;
10577 if (do_bench) {
10578 start_time = getclock_us();
10581 tcc_set_output_type(s, output_type);
10583 /* compile or add each files or library */
10584 for(i = 0;i < nb_files; i++) {
10585 const char *filename;
10587 filename = files[i];
10588 if (filename[0] == '-') {
10589 if (tcc_add_library(s, filename + 2) < 0)
10590 error("cannot find %s", filename);
10591 } else {
10592 if (tcc_add_file(s, filename) < 0) {
10593 ret = 1;
10594 goto the_end;
10599 /* free all files */
10600 tcc_free(files);
10602 if (do_bench) {
10603 double total_time;
10604 total_time = (double)(getclock_us() - start_time) / 1000000.0;
10605 if (total_time < 0.001)
10606 total_time = 0.001;
10607 if (total_bytes < 1)
10608 total_bytes = 1;
10609 printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
10610 tok_ident - TOK_IDENT, total_lines, total_bytes,
10611 total_time, (int)(total_lines / total_time),
10612 total_bytes / total_time / 1000000.0);
10615 if (s->output_type == TCC_OUTPUT_MEMORY) {
10616 ret = tcc_run(s, argc - optind, argv + optind);
10617 } else
10618 #ifdef TCC_TARGET_PE
10619 if (s->output_type != TCC_OUTPUT_OBJ) {
10620 ret = tcc_output_pe(s, outfile);
10621 } else
10622 #endif
10624 tcc_output_file(s, outfile);
10625 ret = 0;
10627 the_end:
10628 /* XXX: cannot do it with bound checking because of the malloc hooks */
10629 if (!do_bounds_check)
10630 tcc_delete(s);
10632 #ifdef MEM_DEBUG
10633 if (do_bench) {
10634 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size, mem_max_size);
10636 #endif
10637 return ret;
10640 #endif