win32 fix
[tinycc/daniel.git] / tcc.c
bloba7b5a58deef0aad0fc3ef7dcf08a449d57bc5be7
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;
463 int leading_underscore;
465 /* warning switches */
466 int warn_write_strings;
467 int warn_unsupported;
468 int warn_error;
469 int warn_none;
470 int warn_implicit_function_declaration;
472 /* error handling */
473 void *error_opaque;
474 void (*error_func)(void *opaque, const char *msg);
475 int error_set_jmp_enabled;
476 jmp_buf error_jmp_buf;
477 int nb_errors;
479 /* tiny assembler state */
480 Sym *asm_labels;
482 /* see include_stack_ptr */
483 BufferedFile *include_stack[INCLUDE_STACK_SIZE];
485 /* see ifdef_stack_ptr */
486 int ifdef_stack[IFDEF_STACK_SIZE];
488 /* see cached_includes */
489 int cached_includes_hash[CACHED_INCLUDES_HASH_SIZE];
491 /* pack stack */
492 int pack_stack[PACK_STACK_SIZE];
493 int *pack_stack_ptr;
496 /* The current value can be: */
497 #define VT_VALMASK 0x00ff
498 #define VT_CONST 0x00f0 /* constant in vc
499 (must be first non register value) */
500 #define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */
501 #define VT_LOCAL 0x00f2 /* offset on stack */
502 #define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */
503 #define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */
504 #define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */
505 #define VT_LVAL 0x0100 /* var is an lvalue */
506 #define VT_SYM 0x0200 /* a symbol value is added */
507 #define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for
508 char/short stored in integer registers) */
509 #define VT_MUSTBOUND 0x0800 /* bound checking must be done before
510 dereferencing value */
511 #define VT_BOUNDED 0x8000 /* value is bounded. The address of the
512 bounding function call point is in vc */
513 #define VT_LVAL_BYTE 0x1000 /* lvalue is a byte */
514 #define VT_LVAL_SHORT 0x2000 /* lvalue is a short */
515 #define VT_LVAL_UNSIGNED 0x4000 /* lvalue is unsigned */
516 #define VT_LVAL_TYPE (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)
518 /* types */
519 #define VT_INT 0 /* integer type */
520 #define VT_BYTE 1 /* signed byte type */
521 #define VT_SHORT 2 /* short type */
522 #define VT_VOID 3 /* void type */
523 #define VT_PTR 4 /* pointer */
524 #define VT_ENUM 5 /* enum definition */
525 #define VT_FUNC 6 /* function type */
526 #define VT_STRUCT 7 /* struct/union definition */
527 #define VT_FLOAT 8 /* IEEE float */
528 #define VT_DOUBLE 9 /* IEEE double */
529 #define VT_LDOUBLE 10 /* IEEE long double */
530 #define VT_BOOL 11 /* ISOC99 boolean type */
531 #define VT_LLONG 12 /* 64 bit integer */
532 #define VT_LONG 13 /* long integer (NEVER USED as type, only
533 during parsing) */
534 #define VT_BTYPE 0x000f /* mask for basic type */
535 #define VT_UNSIGNED 0x0010 /* unsigned type */
536 #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
537 #define VT_BITFIELD 0x0040 /* bitfield modifier */
538 #define VT_CONSTANT 0x0800 /* const modifier */
539 #define VT_VOLATILE 0x1000 /* volatile modifier */
540 #define VT_SIGNED 0x2000 /* signed type */
542 /* storage */
543 #define VT_EXTERN 0x00000080 /* extern definition */
544 #define VT_STATIC 0x00000100 /* static variable */
545 #define VT_TYPEDEF 0x00000200 /* typedef definition */
546 #define VT_INLINE 0x00000400 /* inline definition */
548 #define VT_STRUCT_SHIFT 16 /* shift for bitfield shift values */
550 /* type mask (except storage) */
551 #define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE)
552 #define VT_TYPE (~(VT_STORAGE))
554 /* token values */
556 /* warning: the following compare tokens depend on i386 asm code */
557 #define TOK_ULT 0x92
558 #define TOK_UGE 0x93
559 #define TOK_EQ 0x94
560 #define TOK_NE 0x95
561 #define TOK_ULE 0x96
562 #define TOK_UGT 0x97
563 #define TOK_LT 0x9c
564 #define TOK_GE 0x9d
565 #define TOK_LE 0x9e
566 #define TOK_GT 0x9f
568 #define TOK_LAND 0xa0
569 #define TOK_LOR 0xa1
571 #define TOK_DEC 0xa2
572 #define TOK_MID 0xa3 /* inc/dec, to void constant */
573 #define TOK_INC 0xa4
574 #define TOK_UDIV 0xb0 /* unsigned division */
575 #define TOK_UMOD 0xb1 /* unsigned modulo */
576 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
577 #define TOK_CINT 0xb3 /* number in tokc */
578 #define TOK_CCHAR 0xb4 /* char constant in tokc */
579 #define TOK_STR 0xb5 /* pointer to string in tokc */
580 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
581 #define TOK_LCHAR 0xb7
582 #define TOK_LSTR 0xb8
583 #define TOK_CFLOAT 0xb9 /* float constant */
584 #define TOK_LINENUM 0xba /* line number info */
585 #define TOK_CDOUBLE 0xc0 /* double constant */
586 #define TOK_CLDOUBLE 0xc1 /* long double constant */
587 #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
588 #define TOK_ADDC1 0xc3 /* add with carry generation */
589 #define TOK_ADDC2 0xc4 /* add with carry use */
590 #define TOK_SUBC1 0xc5 /* add with carry generation */
591 #define TOK_SUBC2 0xc6 /* add with carry use */
592 #define TOK_CUINT 0xc8 /* unsigned int constant */
593 #define TOK_CLLONG 0xc9 /* long long constant */
594 #define TOK_CULLONG 0xca /* unsigned long long constant */
595 #define TOK_ARROW 0xcb
596 #define TOK_DOTS 0xcc /* three dots */
597 #define TOK_SHR 0xcd /* unsigned shift right */
598 #define TOK_PPNUM 0xce /* preprocessor number */
600 #define TOK_SHL 0x01 /* shift left */
601 #define TOK_SAR 0x02 /* signed shift right */
603 /* assignement operators : normal operator or 0x80 */
604 #define TOK_A_MOD 0xa5
605 #define TOK_A_AND 0xa6
606 #define TOK_A_MUL 0xaa
607 #define TOK_A_ADD 0xab
608 #define TOK_A_SUB 0xad
609 #define TOK_A_DIV 0xaf
610 #define TOK_A_XOR 0xde
611 #define TOK_A_OR 0xfc
612 #define TOK_A_SHL 0x81
613 #define TOK_A_SAR 0x82
615 #ifndef offsetof
616 #define offsetof(type, field) ((size_t) &((type *)0)->field)
617 #endif
619 #ifndef countof
620 #define countof(tab) (sizeof(tab) / sizeof((tab)[0]))
621 #endif
623 /* WARNING: the content of this string encodes token numbers */
624 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";
626 #define TOK_EOF (-1) /* end of file */
627 #define TOK_LINEFEED 10 /* line feed */
629 /* all identificators and strings have token above that */
630 #define TOK_IDENT 256
632 /* only used for i386 asm opcodes definitions */
633 #define DEF_ASM(x) DEF(TOK_ASM_ ## x, #x)
635 #define DEF_BWL(x) \
636 DEF(TOK_ASM_ ## x ## b, #x "b") \
637 DEF(TOK_ASM_ ## x ## w, #x "w") \
638 DEF(TOK_ASM_ ## x ## l, #x "l") \
639 DEF(TOK_ASM_ ## x, #x)
641 #define DEF_WL(x) \
642 DEF(TOK_ASM_ ## x ## w, #x "w") \
643 DEF(TOK_ASM_ ## x ## l, #x "l") \
644 DEF(TOK_ASM_ ## x, #x)
646 #define DEF_FP1(x) \
647 DEF(TOK_ASM_ ## f ## x ## s, "f" #x "s") \
648 DEF(TOK_ASM_ ## fi ## x ## l, "fi" #x "l") \
649 DEF(TOK_ASM_ ## f ## x ## l, "f" #x "l") \
650 DEF(TOK_ASM_ ## fi ## x ## s, "fi" #x "s")
652 #define DEF_FP(x) \
653 DEF(TOK_ASM_ ## f ## x, "f" #x ) \
654 DEF(TOK_ASM_ ## f ## x ## p, "f" #x "p") \
655 DEF_FP1(x)
657 #define DEF_ASMTEST(x) \
658 DEF_ASM(x ## o) \
659 DEF_ASM(x ## no) \
660 DEF_ASM(x ## b) \
661 DEF_ASM(x ## c) \
662 DEF_ASM(x ## nae) \
663 DEF_ASM(x ## nb) \
664 DEF_ASM(x ## nc) \
665 DEF_ASM(x ## ae) \
666 DEF_ASM(x ## e) \
667 DEF_ASM(x ## z) \
668 DEF_ASM(x ## ne) \
669 DEF_ASM(x ## nz) \
670 DEF_ASM(x ## be) \
671 DEF_ASM(x ## na) \
672 DEF_ASM(x ## nbe) \
673 DEF_ASM(x ## a) \
674 DEF_ASM(x ## s) \
675 DEF_ASM(x ## ns) \
676 DEF_ASM(x ## p) \
677 DEF_ASM(x ## pe) \
678 DEF_ASM(x ## np) \
679 DEF_ASM(x ## po) \
680 DEF_ASM(x ## l) \
681 DEF_ASM(x ## nge) \
682 DEF_ASM(x ## nl) \
683 DEF_ASM(x ## ge) \
684 DEF_ASM(x ## le) \
685 DEF_ASM(x ## ng) \
686 DEF_ASM(x ## nle) \
687 DEF_ASM(x ## g)
689 #define TOK_ASM_int TOK_INT
691 enum tcc_token {
692 TOK_LAST = TOK_IDENT - 1,
693 #define DEF(id, str) id,
694 #include "tcctok.h"
695 #undef DEF
698 static const char tcc_keywords[] =
699 #define DEF(id, str) str "\0"
700 #include "tcctok.h"
701 #undef DEF
704 #define TOK_UIDENT TOK_DEFINE
706 #ifdef WIN32
707 int __stdcall GetModuleFileNameA(void *, char *, int);
708 void *__stdcall GetProcAddress(void *, const char *);
709 void *__stdcall GetModuleHandleA(const char *);
710 void *__stdcall LoadLibraryA(const char *);
711 int __stdcall FreeConsole(void);
713 #define snprintf _snprintf
714 #define vsnprintf _vsnprintf
715 #ifndef __GNUC__
716 #define strtold (long double)strtod
717 #define strtof (float)strtod
718 #define strtoll (long long)strtol
719 #endif
720 #elif defined(TCC_UCLIBC) || defined(__FreeBSD__)
721 /* currently incorrect */
722 long double strtold(const char *nptr, char **endptr)
724 return (long double)strtod(nptr, endptr);
726 float strtof(const char *nptr, char **endptr)
728 return (float)strtod(nptr, endptr);
730 #else
731 /* XXX: need to define this to use them in non ISOC99 context */
732 extern float strtof (const char *__nptr, char **__endptr);
733 extern long double strtold (const char *__nptr, char **__endptr);
734 #endif
736 static char *pstrcpy(char *buf, int buf_size, const char *s);
737 static char *pstrcat(char *buf, int buf_size, const char *s);
738 static const char *tcc_basename(const char *name);
740 static void next(void);
741 static void next_nomacro(void);
742 static void parse_expr_type(CType *type);
743 static void expr_type(CType *type);
744 static void unary_type(CType *type);
745 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
746 int case_reg, int is_expr);
747 static int expr_const(void);
748 static void expr_eq(void);
749 static void gexpr(void);
750 static void gen_inline_functions(void);
751 static void decl(int l);
752 static void decl_initializer(CType *type, Section *sec, unsigned long c,
753 int first, int size_only);
754 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
755 int has_init, int v, int scope);
756 int gv(int rc);
757 void gv2(int rc1, int rc2);
758 void move_reg(int r, int s);
759 void save_regs(int n);
760 void save_reg(int r);
761 void vpop(void);
762 void vswap(void);
763 void vdup(void);
764 int get_reg(int rc);
765 int get_reg_ex(int rc,int rc2);
767 static void macro_subst(TokenString *tok_str, Sym **nested_list,
768 const int *macro_str, int can_read_stream);
769 void gen_op(int op);
770 void force_charshort_cast(int t);
771 static void gen_cast(CType *type);
772 void vstore(void);
773 static Sym *sym_find(int v);
774 static Sym *sym_push(int v, CType *type, int r, int c);
776 /* type handling */
777 static int type_size(CType *type, int *a);
778 static inline CType *pointed_type(CType *type);
779 static int pointed_size(CType *type);
780 static int lvalue_type(int t);
781 static int parse_btype(CType *type, AttributeDef *ad);
782 static void type_decl(CType *type, AttributeDef *ad, int *v, int td);
783 static int is_compatible_types(CType *type1, CType *type2);
785 int ieee_finite(double d);
786 void error(const char *fmt, ...);
787 void vpushi(int v);
788 void vrott(int n);
789 void vnrott(int n);
790 void lexpand_nr(void);
791 static void vpush_global_sym(CType *type, int v);
792 void vset(CType *type, int r, int v);
793 void type_to_str(char *buf, int buf_size,
794 CType *type, const char *varstr);
795 char *get_tok_str(int v, CValue *cv);
796 static Sym *get_sym_ref(CType *type, Section *sec,
797 unsigned long offset, unsigned long size);
798 static Sym *external_global_sym(int v, CType *type, int r);
800 /* section generation */
801 static void section_realloc(Section *sec, unsigned long new_size);
802 static void *section_ptr_add(Section *sec, unsigned long size);
803 static void put_extern_sym(Sym *sym, Section *section,
804 unsigned long value, unsigned long size);
805 static void greloc(Section *s, Sym *sym, unsigned long addr, int type);
806 static int put_elf_str(Section *s, const char *sym);
807 static int put_elf_sym(Section *s,
808 unsigned long value, unsigned long size,
809 int info, int other, int shndx, const char *name);
810 static int add_elf_sym(Section *s, unsigned long value, unsigned long size,
811 int info, int other, int sh_num, const char *name);
812 static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
813 int type, int symbol);
814 static void put_stabs(const char *str, int type, int other, int desc,
815 unsigned long value);
816 static void put_stabs_r(const char *str, int type, int other, int desc,
817 unsigned long value, Section *sec, int sym_index);
818 static void put_stabn(int type, int other, int desc, int value);
819 static void put_stabd(int type, int other, int desc);
820 static int tcc_add_dll(TCCState *s, const char *filename, int flags);
822 #define AFF_PRINT_ERROR 0x0001 /* print error if file not found */
823 #define AFF_REFERENCED_DLL 0x0002 /* load a referenced dll from another dll */
824 static int tcc_add_file_internal(TCCState *s, const char *filename, int flags);
826 /* tcccoff.c */
827 int tcc_output_coff(TCCState *s1, FILE *f);
829 /* tccpe.c */
830 void *resolve_sym(TCCState *s1, const char *sym, int type);
831 int pe_load_def_file(struct TCCState *s1, FILE *fp);
832 void pe_setup_paths(struct TCCState *s1, int *p_output_type, const char **p_outfile, char *first_file);
833 unsigned long pe_add_runtime(struct TCCState *s1);
834 int tcc_output_pe(struct TCCState *s1, const char *filename);
836 /* tccasm.c */
838 #ifdef CONFIG_TCC_ASM
840 typedef struct ExprValue {
841 uint32_t v;
842 Sym *sym;
843 } ExprValue;
845 #define MAX_ASM_OPERANDS 30
847 typedef struct ASMOperand {
848 int id; /* GCC 3 optionnal identifier (0 if number only supported */
849 char *constraint;
850 char asm_str[16]; /* computed asm string for operand */
851 SValue *vt; /* C value of the expression */
852 int ref_index; /* if >= 0, gives reference to a output constraint */
853 int input_index; /* if >= 0, gives reference to an input constraint */
854 int priority; /* priority, used to assign registers */
855 int reg; /* if >= 0, register number used for this operand */
856 int is_llong; /* true if double register value */
857 int is_memory; /* true if memory operand */
858 int is_rw; /* for '+' modifier */
859 } ASMOperand;
861 static void asm_expr(TCCState *s1, ExprValue *pe);
862 static int asm_int_expr(TCCState *s1);
863 static int find_constraint(ASMOperand *operands, int nb_operands,
864 const char *name, const char **pp);
866 static int tcc_assemble(TCCState *s1, int do_preprocess);
868 #endif
870 static void asm_instr(void);
871 static void asm_global_instr(void);
873 /* true if float/double/long double type */
874 static inline int is_float(int t)
876 int bt;
877 bt = t & VT_BTYPE;
878 return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT;
881 #ifdef TCC_TARGET_I386
882 #include "i386-gen.c"
883 #endif
885 #ifdef TCC_TARGET_ARM
886 #include "arm-gen.c"
887 #endif
889 #ifdef TCC_TARGET_C67
890 #include "c67-gen.c"
891 #endif
893 #ifdef CONFIG_TCC_STATIC
895 #define RTLD_LAZY 0x001
896 #define RTLD_NOW 0x002
897 #define RTLD_GLOBAL 0x100
898 #define RTLD_DEFAULT NULL
900 /* dummy function for profiling */
901 void *dlopen(const char *filename, int flag)
903 return NULL;
906 const char *dlerror(void)
908 return "error";
911 typedef struct TCCSyms {
912 char *str;
913 void *ptr;
914 } TCCSyms;
916 #define TCCSYM(a) { #a, &a, },
918 /* add the symbol you want here if no dynamic linking is done */
919 static TCCSyms tcc_syms[] = {
920 #if !defined(CONFIG_TCCBOOT)
921 TCCSYM(printf)
922 TCCSYM(fprintf)
923 TCCSYM(fopen)
924 TCCSYM(fclose)
925 #endif
926 { NULL, NULL },
929 void *resolve_sym(TCCState *s1, const char *symbol, int type)
931 TCCSyms *p;
932 p = tcc_syms;
933 while (p->str != NULL) {
934 if (!strcmp(p->str, symbol))
935 return p->ptr;
936 p++;
938 return NULL;
941 #elif !defined(WIN32)
943 #include <dlfcn.h>
945 void *resolve_sym(TCCState *s1, const char *sym, int type)
947 return dlsym(RTLD_DEFAULT, sym);
950 #endif
952 /********************************************************/
954 /* we use our own 'finite' function to avoid potential problems with
955 non standard math libs */
956 /* XXX: endianness dependent */
957 int ieee_finite(double d)
959 int *p = (int *)&d;
960 return ((unsigned)((p[1] | 0x800fffff) + 1)) >> 31;
963 /* copy a string and truncate it. */
964 static char *pstrcpy(char *buf, int buf_size, const char *s)
966 char *q, *q_end;
967 int c;
969 if (buf_size > 0) {
970 q = buf;
971 q_end = buf + buf_size - 1;
972 while (q < q_end) {
973 c = *s++;
974 if (c == '\0')
975 break;
976 *q++ = c;
978 *q = '\0';
980 return buf;
983 /* strcat and truncate. */
984 static char *pstrcat(char *buf, int buf_size, const char *s)
986 int len;
987 len = strlen(buf);
988 if (len < buf_size)
989 pstrcpy(buf + len, buf_size - len, s);
990 return buf;
993 static int strstart(const char *str, const char *val, const char **ptr)
995 const char *p, *q;
996 p = str;
997 q = val;
998 while (*q != '\0') {
999 if (*p != *q)
1000 return 0;
1001 p++;
1002 q++;
1004 if (ptr)
1005 *ptr = p;
1006 return 1;
1009 /* memory management */
1010 #ifdef MEM_DEBUG
1011 int mem_cur_size;
1012 int mem_max_size;
1013 #endif
1015 static inline void tcc_free(void *ptr)
1017 #ifdef MEM_DEBUG
1018 mem_cur_size -= malloc_usable_size(ptr);
1019 #endif
1020 free(ptr);
1023 static void *tcc_malloc(unsigned long size)
1025 void *ptr;
1026 ptr = malloc(size);
1027 if (!ptr && size)
1028 error("memory full");
1029 #ifdef MEM_DEBUG
1030 mem_cur_size += malloc_usable_size(ptr);
1031 if (mem_cur_size > mem_max_size)
1032 mem_max_size = mem_cur_size;
1033 #endif
1034 return ptr;
1037 static void *tcc_mallocz(unsigned long size)
1039 void *ptr;
1040 ptr = tcc_malloc(size);
1041 memset(ptr, 0, size);
1042 return ptr;
1045 static inline void *tcc_realloc(void *ptr, unsigned long size)
1047 void *ptr1;
1048 #ifdef MEM_DEBUG
1049 mem_cur_size -= malloc_usable_size(ptr);
1050 #endif
1051 ptr1 = realloc(ptr, size);
1052 #ifdef MEM_DEBUG
1053 /* NOTE: count not correct if alloc error, but not critical */
1054 mem_cur_size += malloc_usable_size(ptr1);
1055 if (mem_cur_size > mem_max_size)
1056 mem_max_size = mem_cur_size;
1057 #endif
1058 return ptr1;
1061 static char *tcc_strdup(const char *str)
1063 char *ptr;
1064 ptr = tcc_malloc(strlen(str) + 1);
1065 strcpy(ptr, str);
1066 return ptr;
1069 #define free(p) use_tcc_free(p)
1070 #define malloc(s) use_tcc_malloc(s)
1071 #define realloc(p, s) use_tcc_realloc(p, s)
1073 static void dynarray_add(void ***ptab, int *nb_ptr, void *data)
1075 int nb, nb_alloc;
1076 void **pp;
1078 nb = *nb_ptr;
1079 pp = *ptab;
1080 /* every power of two we double array size */
1081 if ((nb & (nb - 1)) == 0) {
1082 if (!nb)
1083 nb_alloc = 1;
1084 else
1085 nb_alloc = nb * 2;
1086 pp = tcc_realloc(pp, nb_alloc * sizeof(void *));
1087 if (!pp)
1088 error("memory full");
1089 *ptab = pp;
1091 pp[nb++] = data;
1092 *nb_ptr = nb;
1095 /* symbol allocator */
1096 static Sym *__sym_malloc(void)
1098 Sym *sym_pool, *sym, *last_sym;
1099 int i;
1101 sym_pool = tcc_malloc(SYM_POOL_NB * sizeof(Sym));
1103 last_sym = sym_free_first;
1104 sym = sym_pool;
1105 for(i = 0; i < SYM_POOL_NB; i++) {
1106 sym->next = last_sym;
1107 last_sym = sym;
1108 sym++;
1110 sym_free_first = last_sym;
1111 return last_sym;
1114 static inline Sym *sym_malloc(void)
1116 Sym *sym;
1117 sym = sym_free_first;
1118 if (!sym)
1119 sym = __sym_malloc();
1120 sym_free_first = sym->next;
1121 return sym;
1124 static inline void sym_free(Sym *sym)
1126 sym->next = sym_free_first;
1127 sym_free_first = sym;
1130 Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags)
1132 Section *sec;
1134 sec = tcc_mallocz(sizeof(Section) + strlen(name));
1135 strcpy(sec->name, name);
1136 sec->sh_type = sh_type;
1137 sec->sh_flags = sh_flags;
1138 switch(sh_type) {
1139 case SHT_HASH:
1140 case SHT_REL:
1141 case SHT_DYNSYM:
1142 case SHT_SYMTAB:
1143 case SHT_DYNAMIC:
1144 sec->sh_addralign = 4;
1145 break;
1146 case SHT_STRTAB:
1147 sec->sh_addralign = 1;
1148 break;
1149 default:
1150 sec->sh_addralign = 32; /* default conservative alignment */
1151 break;
1154 /* only add section if not private */
1155 if (!(sh_flags & SHF_PRIVATE)) {
1156 sec->sh_num = s1->nb_sections;
1157 dynarray_add((void ***)&s1->sections, &s1->nb_sections, sec);
1159 return sec;
1162 static void free_section(Section *s)
1164 tcc_free(s->data);
1165 tcc_free(s);
1168 /* realloc section and set its content to zero */
1169 static void section_realloc(Section *sec, unsigned long new_size)
1171 unsigned long size;
1172 unsigned char *data;
1174 size = sec->data_allocated;
1175 if (size == 0)
1176 size = 1;
1177 while (size < new_size)
1178 size = size * 2;
1179 data = tcc_realloc(sec->data, size);
1180 if (!data)
1181 error("memory full");
1182 memset(data + sec->data_allocated, 0, size - sec->data_allocated);
1183 sec->data = data;
1184 sec->data_allocated = size;
1187 /* reserve at least 'size' bytes in section 'sec' from
1188 sec->data_offset. */
1189 static void *section_ptr_add(Section *sec, unsigned long size)
1191 unsigned long offset, offset1;
1193 offset = sec->data_offset;
1194 offset1 = offset + size;
1195 if (offset1 > sec->data_allocated)
1196 section_realloc(sec, offset1);
1197 sec->data_offset = offset1;
1198 return sec->data + offset;
1201 /* return a reference to a section, and create it if it does not
1202 exists */
1203 Section *find_section(TCCState *s1, const char *name)
1205 Section *sec;
1206 int i;
1207 for(i = 1; i < s1->nb_sections; i++) {
1208 sec = s1->sections[i];
1209 if (!strcmp(name, sec->name))
1210 return sec;
1212 /* sections are created as PROGBITS */
1213 return new_section(s1, name, SHT_PROGBITS, SHF_ALLOC);
1216 #define SECTION_ABS ((void *)1)
1218 /* update sym->c so that it points to an external symbol in section
1219 'section' with value 'value' */
1220 static void put_extern_sym2(Sym *sym, Section *section,
1221 unsigned long value, unsigned long size,
1222 int can_add_underscore)
1224 int sym_type, sym_bind, sh_num, info;
1225 Elf32_Sym *esym;
1226 const char *name;
1227 char buf1[256];
1229 if (section == NULL)
1230 sh_num = SHN_UNDEF;
1231 else if (section == SECTION_ABS)
1232 sh_num = SHN_ABS;
1233 else
1234 sh_num = section->sh_num;
1235 if (!sym->c) {
1236 if ((sym->type.t & VT_BTYPE) == VT_FUNC)
1237 sym_type = STT_FUNC;
1238 else
1239 sym_type = STT_OBJECT;
1240 if (sym->type.t & VT_STATIC)
1241 sym_bind = STB_LOCAL;
1242 else
1243 sym_bind = STB_GLOBAL;
1245 name = get_tok_str(sym->v, NULL);
1246 #ifdef CONFIG_TCC_BCHECK
1247 if (do_bounds_check) {
1248 char buf[32];
1250 /* XXX: avoid doing that for statics ? */
1251 /* if bound checking is activated, we change some function
1252 names by adding the "__bound" prefix */
1253 switch(sym->v) {
1254 #if 0
1255 /* XXX: we rely only on malloc hooks */
1256 case TOK_malloc:
1257 case TOK_free:
1258 case TOK_realloc:
1259 case TOK_memalign:
1260 case TOK_calloc:
1261 #endif
1262 case TOK_memcpy:
1263 case TOK_memmove:
1264 case TOK_memset:
1265 case TOK_strlen:
1266 case TOK_strcpy:
1267 strcpy(buf, "__bound_");
1268 strcat(buf, name);
1269 name = buf;
1270 break;
1273 #endif
1274 if (tcc_state->leading_underscore && can_add_underscore) {
1275 buf1[0] = '_';
1276 pstrcpy(buf1 + 1, sizeof(buf1) - 1, name);
1277 name = buf1;
1279 info = ELF32_ST_INFO(sym_bind, sym_type);
1280 sym->c = add_elf_sym(symtab_section, value, size, info, 0, sh_num, name);
1281 } else {
1282 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
1283 esym->st_value = value;
1284 esym->st_size = size;
1285 esym->st_shndx = sh_num;
1289 static void put_extern_sym(Sym *sym, Section *section,
1290 unsigned long value, unsigned long size)
1292 put_extern_sym2(sym, section, value, size, 1);
1295 /* add a new relocation entry to symbol 'sym' in section 's' */
1296 static void greloc(Section *s, Sym *sym, unsigned long offset, int type)
1298 if (!sym->c)
1299 put_extern_sym(sym, NULL, 0, 0);
1300 /* now we can add ELF relocation info */
1301 put_elf_reloc(symtab_section, s, offset, type, sym->c);
1304 static inline int isid(int c)
1306 return (c >= 'a' && c <= 'z') ||
1307 (c >= 'A' && c <= 'Z') ||
1308 c == '_';
1311 static inline int isnum(int c)
1313 return c >= '0' && c <= '9';
1316 static inline int isoct(int c)
1318 return c >= '0' && c <= '7';
1321 static inline int toup(int c)
1323 if (c >= 'a' && c <= 'z')
1324 return c - 'a' + 'A';
1325 else
1326 return c;
1329 static void strcat_vprintf(char *buf, int buf_size, const char *fmt, va_list ap)
1331 int len;
1332 len = strlen(buf);
1333 vsnprintf(buf + len, buf_size - len, fmt, ap);
1336 static void strcat_printf(char *buf, int buf_size, const char *fmt, ...)
1338 va_list ap;
1339 va_start(ap, fmt);
1340 strcat_vprintf(buf, buf_size, fmt, ap);
1341 va_end(ap);
1344 void error1(TCCState *s1, int is_warning, const char *fmt, va_list ap)
1346 char buf[2048];
1347 BufferedFile **f;
1349 buf[0] = '\0';
1350 if (file) {
1351 for(f = s1->include_stack; f < s1->include_stack_ptr; f++)
1352 strcat_printf(buf, sizeof(buf), "In file included from %s:%d:\n",
1353 (*f)->filename, (*f)->line_num);
1354 if (file->line_num > 0) {
1355 strcat_printf(buf, sizeof(buf),
1356 "%s:%d: ", file->filename, file->line_num);
1357 } else {
1358 strcat_printf(buf, sizeof(buf),
1359 "%s: ", file->filename);
1361 } else {
1362 strcat_printf(buf, sizeof(buf),
1363 "tcc: ");
1365 if (is_warning)
1366 strcat_printf(buf, sizeof(buf), "warning: ");
1367 strcat_vprintf(buf, sizeof(buf), fmt, ap);
1369 if (!s1->error_func) {
1370 /* default case: stderr */
1371 fprintf(stderr, "%s\n", buf);
1372 } else {
1373 s1->error_func(s1->error_opaque, buf);
1375 if (!is_warning || s1->warn_error)
1376 s1->nb_errors++;
1379 #ifdef LIBTCC
1380 void tcc_set_error_func(TCCState *s, void *error_opaque,
1381 void (*error_func)(void *opaque, const char *msg))
1383 s->error_opaque = error_opaque;
1384 s->error_func = error_func;
1386 #endif
1388 /* error without aborting current compilation */
1389 void error_noabort(const char *fmt, ...)
1391 TCCState *s1 = tcc_state;
1392 va_list ap;
1394 va_start(ap, fmt);
1395 error1(s1, 0, fmt, ap);
1396 va_end(ap);
1399 void error(const char *fmt, ...)
1401 TCCState *s1 = tcc_state;
1402 va_list ap;
1404 va_start(ap, fmt);
1405 error1(s1, 0, fmt, ap);
1406 va_end(ap);
1407 /* better than nothing: in some cases, we accept to handle errors */
1408 if (s1->error_set_jmp_enabled) {
1409 longjmp(s1->error_jmp_buf, 1);
1410 } else {
1411 /* XXX: eliminate this someday */
1412 exit(1);
1416 void expect(const char *msg)
1418 error("%s expected", msg);
1421 void warning(const char *fmt, ...)
1423 TCCState *s1 = tcc_state;
1424 va_list ap;
1426 if (s1->warn_none)
1427 return;
1429 va_start(ap, fmt);
1430 error1(s1, 1, fmt, ap);
1431 va_end(ap);
1434 void skip(int c)
1436 if (tok != c)
1437 error("'%c' expected", c);
1438 next();
1441 static void test_lvalue(void)
1443 if (!(vtop->r & VT_LVAL))
1444 expect("lvalue");
1447 /* allocate a new token */
1448 static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len)
1450 TokenSym *ts, **ptable;
1451 int i;
1453 if (tok_ident >= SYM_FIRST_ANOM)
1454 error("memory full");
1456 /* expand token table if needed */
1457 i = tok_ident - TOK_IDENT;
1458 if ((i % TOK_ALLOC_INCR) == 0) {
1459 ptable = tcc_realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *));
1460 if (!ptable)
1461 error("memory full");
1462 table_ident = ptable;
1465 ts = tcc_malloc(sizeof(TokenSym) + len);
1466 table_ident[i] = ts;
1467 ts->tok = tok_ident++;
1468 ts->sym_define = NULL;
1469 ts->sym_label = NULL;
1470 ts->sym_struct = NULL;
1471 ts->sym_identifier = NULL;
1472 ts->len = len;
1473 ts->hash_next = NULL;
1474 memcpy(ts->str, str, len);
1475 ts->str[len] = '\0';
1476 *pts = ts;
1477 return ts;
1480 #define TOK_HASH_INIT 1
1481 #define TOK_HASH_FUNC(h, c) ((h) * 263 + (c))
1483 /* find a token and add it if not found */
1484 static TokenSym *tok_alloc(const char *str, int len)
1486 TokenSym *ts, **pts;
1487 int i;
1488 unsigned int h;
1490 h = TOK_HASH_INIT;
1491 for(i=0;i<len;i++)
1492 h = TOK_HASH_FUNC(h, ((unsigned char *)str)[i]);
1493 h &= (TOK_HASH_SIZE - 1);
1495 pts = &hash_ident[h];
1496 for(;;) {
1497 ts = *pts;
1498 if (!ts)
1499 break;
1500 if (ts->len == len && !memcmp(ts->str, str, len))
1501 return ts;
1502 pts = &(ts->hash_next);
1504 return tok_alloc_new(pts, str, len);
1507 /* CString handling */
1509 static void cstr_realloc(CString *cstr, int new_size)
1511 int size;
1512 void *data;
1514 size = cstr->size_allocated;
1515 if (size == 0)
1516 size = 8; /* no need to allocate a too small first string */
1517 while (size < new_size)
1518 size = size * 2;
1519 data = tcc_realloc(cstr->data_allocated, size);
1520 if (!data)
1521 error("memory full");
1522 cstr->data_allocated = data;
1523 cstr->size_allocated = size;
1524 cstr->data = data;
1527 /* add a byte */
1528 static inline void cstr_ccat(CString *cstr, int ch)
1530 int size;
1531 size = cstr->size + 1;
1532 if (size > cstr->size_allocated)
1533 cstr_realloc(cstr, size);
1534 ((unsigned char *)cstr->data)[size - 1] = ch;
1535 cstr->size = size;
1538 static void cstr_cat(CString *cstr, const char *str)
1540 int c;
1541 for(;;) {
1542 c = *str;
1543 if (c == '\0')
1544 break;
1545 cstr_ccat(cstr, c);
1546 str++;
1550 /* add a wide char */
1551 static void cstr_wccat(CString *cstr, int ch)
1553 int size;
1554 size = cstr->size + sizeof(int);
1555 if (size > cstr->size_allocated)
1556 cstr_realloc(cstr, size);
1557 *(int *)(((unsigned char *)cstr->data) + size - sizeof(int)) = ch;
1558 cstr->size = size;
1561 static void cstr_new(CString *cstr)
1563 memset(cstr, 0, sizeof(CString));
1566 /* free string and reset it to NULL */
1567 static void cstr_free(CString *cstr)
1569 tcc_free(cstr->data_allocated);
1570 cstr_new(cstr);
1573 #define cstr_reset(cstr) cstr_free(cstr)
1575 /* XXX: unicode ? */
1576 static void add_char(CString *cstr, int c)
1578 if (c == '\'' || c == '\"' || c == '\\') {
1579 /* XXX: could be more precise if char or string */
1580 cstr_ccat(cstr, '\\');
1582 if (c >= 32 && c <= 126) {
1583 cstr_ccat(cstr, c);
1584 } else {
1585 cstr_ccat(cstr, '\\');
1586 if (c == '\n') {
1587 cstr_ccat(cstr, 'n');
1588 } else {
1589 cstr_ccat(cstr, '0' + ((c >> 6) & 7));
1590 cstr_ccat(cstr, '0' + ((c >> 3) & 7));
1591 cstr_ccat(cstr, '0' + (c & 7));
1596 /* XXX: buffer overflow */
1597 /* XXX: float tokens */
1598 char *get_tok_str(int v, CValue *cv)
1600 static char buf[STRING_MAX_SIZE + 1];
1601 static CString cstr_buf;
1602 CString *cstr;
1603 unsigned char *q;
1604 char *p;
1605 int i, len;
1607 /* NOTE: to go faster, we give a fixed buffer for small strings */
1608 cstr_reset(&cstr_buf);
1609 cstr_buf.data = buf;
1610 cstr_buf.size_allocated = sizeof(buf);
1611 p = buf;
1613 switch(v) {
1614 case TOK_CINT:
1615 case TOK_CUINT:
1616 /* XXX: not quite exact, but only useful for testing */
1617 sprintf(p, "%u", cv->ui);
1618 break;
1619 case TOK_CLLONG:
1620 case TOK_CULLONG:
1621 /* XXX: not quite exact, but only useful for testing */
1622 sprintf(p, "%Lu", cv->ull);
1623 break;
1624 case TOK_CCHAR:
1625 case TOK_LCHAR:
1626 cstr_ccat(&cstr_buf, '\'');
1627 add_char(&cstr_buf, cv->i);
1628 cstr_ccat(&cstr_buf, '\'');
1629 cstr_ccat(&cstr_buf, '\0');
1630 break;
1631 case TOK_PPNUM:
1632 cstr = cv->cstr;
1633 len = cstr->size - 1;
1634 for(i=0;i<len;i++)
1635 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1636 cstr_ccat(&cstr_buf, '\0');
1637 break;
1638 case TOK_STR:
1639 case TOK_LSTR:
1640 cstr = cv->cstr;
1641 cstr_ccat(&cstr_buf, '\"');
1642 if (v == TOK_STR) {
1643 len = cstr->size - 1;
1644 for(i=0;i<len;i++)
1645 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1646 } else {
1647 len = (cstr->size / sizeof(int)) - 1;
1648 for(i=0;i<len;i++)
1649 add_char(&cstr_buf, ((int *)cstr->data)[i]);
1651 cstr_ccat(&cstr_buf, '\"');
1652 cstr_ccat(&cstr_buf, '\0');
1653 break;
1654 case TOK_LT:
1655 v = '<';
1656 goto addv;
1657 case TOK_GT:
1658 v = '>';
1659 goto addv;
1660 case TOK_A_SHL:
1661 return strcpy(p, "<<=");
1662 case TOK_A_SAR:
1663 return strcpy(p, ">>=");
1664 default:
1665 if (v < TOK_IDENT) {
1666 /* search in two bytes table */
1667 q = tok_two_chars;
1668 while (*q) {
1669 if (q[2] == v) {
1670 *p++ = q[0];
1671 *p++ = q[1];
1672 *p = '\0';
1673 return buf;
1675 q += 3;
1677 addv:
1678 *p++ = v;
1679 *p = '\0';
1680 } else if (v < tok_ident) {
1681 return table_ident[v - TOK_IDENT]->str;
1682 } else if (v >= SYM_FIRST_ANOM) {
1683 /* special name for anonymous symbol */
1684 sprintf(p, "L.%u", v - SYM_FIRST_ANOM);
1685 } else {
1686 /* should never happen */
1687 return NULL;
1689 break;
1691 return cstr_buf.data;
1694 /* push, without hashing */
1695 static Sym *sym_push2(Sym **ps, int v, int t, int c)
1697 Sym *s;
1698 s = sym_malloc();
1699 s->v = v;
1700 s->type.t = t;
1701 s->c = c;
1702 s->next = NULL;
1703 /* add in stack */
1704 s->prev = *ps;
1705 *ps = s;
1706 return s;
1709 /* find a symbol and return its associated structure. 's' is the top
1710 of the symbol stack */
1711 static Sym *sym_find2(Sym *s, int v)
1713 while (s) {
1714 if (s->v == v)
1715 return s;
1716 s = s->prev;
1718 return NULL;
1721 /* structure lookup */
1722 static inline Sym *struct_find(int v)
1724 v -= TOK_IDENT;
1725 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1726 return NULL;
1727 return table_ident[v]->sym_struct;
1730 /* find an identifier */
1731 static inline Sym *sym_find(int v)
1733 v -= TOK_IDENT;
1734 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1735 return NULL;
1736 return table_ident[v]->sym_identifier;
1739 /* push a given symbol on the symbol stack */
1740 static Sym *sym_push(int v, CType *type, int r, int c)
1742 Sym *s, **ps;
1743 TokenSym *ts;
1745 if (local_stack)
1746 ps = &local_stack;
1747 else
1748 ps = &global_stack;
1749 s = sym_push2(ps, v, type->t, c);
1750 s->type.ref = type->ref;
1751 s->r = r;
1752 /* don't record fields or anonymous symbols */
1753 /* XXX: simplify */
1754 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1755 /* record symbol in token array */
1756 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1757 if (v & SYM_STRUCT)
1758 ps = &ts->sym_struct;
1759 else
1760 ps = &ts->sym_identifier;
1761 s->prev_tok = *ps;
1762 *ps = s;
1764 return s;
1767 /* push a global identifier */
1768 static Sym *global_identifier_push(int v, int t, int c)
1770 Sym *s, **ps;
1771 s = sym_push2(&global_stack, v, t, c);
1772 /* don't record anonymous symbol */
1773 if (v < SYM_FIRST_ANOM) {
1774 ps = &table_ident[v - TOK_IDENT]->sym_identifier;
1775 /* modify the top most local identifier, so that
1776 sym_identifier will point to 's' when popped */
1777 while (*ps != NULL)
1778 ps = &(*ps)->prev_tok;
1779 s->prev_tok = NULL;
1780 *ps = s;
1782 return s;
1785 /* pop symbols until top reaches 'b' */
1786 static void sym_pop(Sym **ptop, Sym *b)
1788 Sym *s, *ss, **ps;
1789 TokenSym *ts;
1790 int v;
1792 s = *ptop;
1793 while(s != b) {
1794 ss = s->prev;
1795 v = s->v;
1796 /* remove symbol in token array */
1797 /* XXX: simplify */
1798 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1799 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1800 if (v & SYM_STRUCT)
1801 ps = &ts->sym_struct;
1802 else
1803 ps = &ts->sym_identifier;
1804 *ps = s->prev_tok;
1806 sym_free(s);
1807 s = ss;
1809 *ptop = b;
1812 /* I/O layer */
1814 BufferedFile *tcc_open(TCCState *s1, const char *filename)
1816 int fd;
1817 BufferedFile *bf;
1819 fd = open(filename, O_RDONLY | O_BINARY);
1820 if (fd < 0)
1821 return NULL;
1822 bf = tcc_malloc(sizeof(BufferedFile));
1823 if (!bf) {
1824 close(fd);
1825 return NULL;
1827 bf->fd = fd;
1828 bf->buf_ptr = bf->buffer;
1829 bf->buf_end = bf->buffer;
1830 bf->buffer[0] = CH_EOB; /* put eob symbol */
1831 pstrcpy(bf->filename, sizeof(bf->filename), filename);
1832 bf->line_num = 1;
1833 bf->ifndef_macro = 0;
1834 bf->ifdef_stack_ptr = s1->ifdef_stack_ptr;
1835 // printf("opening '%s'\n", filename);
1836 return bf;
1839 void tcc_close(BufferedFile *bf)
1841 total_lines += bf->line_num;
1842 close(bf->fd);
1843 tcc_free(bf);
1846 /* fill input buffer and peek next char */
1847 static int tcc_peekc_slow(BufferedFile *bf)
1849 int len;
1850 /* only tries to read if really end of buffer */
1851 if (bf->buf_ptr >= bf->buf_end) {
1852 if (bf->fd != -1) {
1853 #if defined(PARSE_DEBUG)
1854 len = 8;
1855 #else
1856 len = IO_BUF_SIZE;
1857 #endif
1858 len = read(bf->fd, bf->buffer, len);
1859 if (len < 0)
1860 len = 0;
1861 } else {
1862 len = 0;
1864 total_bytes += len;
1865 bf->buf_ptr = bf->buffer;
1866 bf->buf_end = bf->buffer + len;
1867 *bf->buf_end = CH_EOB;
1869 if (bf->buf_ptr < bf->buf_end) {
1870 return bf->buf_ptr[0];
1871 } else {
1872 bf->buf_ptr = bf->buf_end;
1873 return CH_EOF;
1877 /* return the current character, handling end of block if necessary
1878 (but not stray) */
1879 static int handle_eob(void)
1881 return tcc_peekc_slow(file);
1884 /* read next char from current input file and handle end of input buffer */
1885 static inline void inp(void)
1887 ch = *(++(file->buf_ptr));
1888 /* end of buffer/file handling */
1889 if (ch == CH_EOB)
1890 ch = handle_eob();
1893 /* handle '\[\r]\n' */
1894 static void handle_stray(void)
1896 while (ch == '\\') {
1897 inp();
1898 if (ch == '\n') {
1899 file->line_num++;
1900 inp();
1901 } else if (ch == '\r') {
1902 inp();
1903 if (ch != '\n')
1904 goto fail;
1905 file->line_num++;
1906 inp();
1907 } else {
1908 fail:
1909 error("stray '\\' in program");
1914 /* skip the stray and handle the \\n case. Output an error if
1915 incorrect char after the stray */
1916 static int handle_stray1(uint8_t *p)
1918 int c;
1920 if (p >= file->buf_end) {
1921 file->buf_ptr = p;
1922 c = handle_eob();
1923 p = file->buf_ptr;
1924 if (c == '\\')
1925 goto parse_stray;
1926 } else {
1927 parse_stray:
1928 file->buf_ptr = p;
1929 ch = *p;
1930 handle_stray();
1931 p = file->buf_ptr;
1932 c = *p;
1934 return c;
1937 /* handle just the EOB case, but not stray */
1938 #define PEEKC_EOB(c, p)\
1940 p++;\
1941 c = *p;\
1942 if (c == '\\') {\
1943 file->buf_ptr = p;\
1944 c = handle_eob();\
1945 p = file->buf_ptr;\
1949 /* handle the complicated stray case */
1950 #define PEEKC(c, p)\
1952 p++;\
1953 c = *p;\
1954 if (c == '\\') {\
1955 c = handle_stray1(p);\
1956 p = file->buf_ptr;\
1960 /* input with '\[\r]\n' handling. Note that this function cannot
1961 handle other characters after '\', so you cannot call it inside
1962 strings or comments */
1963 static void minp(void)
1965 inp();
1966 if (ch == '\\')
1967 handle_stray();
1971 /* single line C++ comments */
1972 static uint8_t *parse_line_comment(uint8_t *p)
1974 int c;
1976 p++;
1977 for(;;) {
1978 c = *p;
1979 redo:
1980 if (c == '\n' || c == CH_EOF) {
1981 break;
1982 } else if (c == '\\') {
1983 file->buf_ptr = p;
1984 c = handle_eob();
1985 p = file->buf_ptr;
1986 if (c == '\\') {
1987 PEEKC_EOB(c, p);
1988 if (c == '\n') {
1989 file->line_num++;
1990 PEEKC_EOB(c, p);
1991 } else if (c == '\r') {
1992 PEEKC_EOB(c, p);
1993 if (c == '\n') {
1994 file->line_num++;
1995 PEEKC_EOB(c, p);
1998 } else {
1999 goto redo;
2001 } else {
2002 p++;
2005 return p;
2008 /* C comments */
2009 static uint8_t *parse_comment(uint8_t *p)
2011 int c;
2013 p++;
2014 for(;;) {
2015 /* fast skip loop */
2016 for(;;) {
2017 c = *p;
2018 if (c == '\n' || c == '*' || c == '\\')
2019 break;
2020 p++;
2021 c = *p;
2022 if (c == '\n' || c == '*' || c == '\\')
2023 break;
2024 p++;
2026 /* now we can handle all the cases */
2027 if (c == '\n') {
2028 file->line_num++;
2029 p++;
2030 } else if (c == '*') {
2031 p++;
2032 for(;;) {
2033 c = *p;
2034 if (c == '*') {
2035 p++;
2036 } else if (c == '/') {
2037 goto end_of_comment;
2038 } else if (c == '\\') {
2039 file->buf_ptr = p;
2040 c = handle_eob();
2041 p = file->buf_ptr;
2042 if (c == '\\') {
2043 /* skip '\[\r]\n', otherwise just skip the stray */
2044 while (c == '\\') {
2045 PEEKC_EOB(c, p);
2046 if (c == '\n') {
2047 file->line_num++;
2048 PEEKC_EOB(c, p);
2049 } else if (c == '\r') {
2050 PEEKC_EOB(c, p);
2051 if (c == '\n') {
2052 file->line_num++;
2053 PEEKC_EOB(c, p);
2055 } else {
2056 goto after_star;
2060 } else {
2061 break;
2064 after_star: ;
2065 } else {
2066 /* stray, eob or eof */
2067 file->buf_ptr = p;
2068 c = handle_eob();
2069 p = file->buf_ptr;
2070 if (c == CH_EOF) {
2071 error("unexpected end of file in comment");
2072 } else if (c == '\\') {
2073 p++;
2077 end_of_comment:
2078 p++;
2079 return p;
2082 #define cinp minp
2084 /* space exlcuding newline */
2085 static inline int is_space(int ch)
2087 return ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f' || ch == '\r';
2090 static inline void skip_spaces(void)
2092 while (is_space(ch))
2093 cinp();
2096 /* parse a string without interpreting escapes */
2097 static uint8_t *parse_pp_string(uint8_t *p,
2098 int sep, CString *str)
2100 int c;
2101 p++;
2102 for(;;) {
2103 c = *p;
2104 if (c == sep) {
2105 break;
2106 } else if (c == '\\') {
2107 file->buf_ptr = p;
2108 c = handle_eob();
2109 p = file->buf_ptr;
2110 if (c == CH_EOF) {
2111 unterminated_string:
2112 /* XXX: indicate line number of start of string */
2113 error("missing terminating %c character", sep);
2114 } else if (c == '\\') {
2115 /* escape : just skip \[\r]\n */
2116 PEEKC_EOB(c, p);
2117 if (c == '\n') {
2118 file->line_num++;
2119 p++;
2120 } else if (c == '\r') {
2121 PEEKC_EOB(c, p);
2122 if (c != '\n')
2123 expect("'\n' after '\r'");
2124 file->line_num++;
2125 p++;
2126 } else if (c == CH_EOF) {
2127 goto unterminated_string;
2128 } else {
2129 if (str) {
2130 cstr_ccat(str, '\\');
2131 cstr_ccat(str, c);
2133 p++;
2136 } else if (c == '\n') {
2137 file->line_num++;
2138 goto add_char;
2139 } else if (c == '\r') {
2140 PEEKC_EOB(c, p);
2141 if (c != '\n') {
2142 if (str)
2143 cstr_ccat(str, '\r');
2144 } else {
2145 file->line_num++;
2146 goto add_char;
2148 } else {
2149 add_char:
2150 if (str)
2151 cstr_ccat(str, c);
2152 p++;
2155 p++;
2156 return p;
2159 /* skip block of text until #else, #elif or #endif. skip also pairs of
2160 #if/#endif */
2161 void preprocess_skip(void)
2163 int a, start_of_line, c;
2164 uint8_t *p;
2166 p = file->buf_ptr;
2167 start_of_line = 1;
2168 a = 0;
2169 for(;;) {
2170 redo_no_start:
2171 c = *p;
2172 switch(c) {
2173 case ' ':
2174 case '\t':
2175 case '\f':
2176 case '\v':
2177 case '\r':
2178 p++;
2179 goto redo_no_start;
2180 case '\n':
2181 start_of_line = 1;
2182 file->line_num++;
2183 p++;
2184 goto redo_no_start;
2185 case '\\':
2186 file->buf_ptr = p;
2187 c = handle_eob();
2188 if (c == CH_EOF) {
2189 expect("#endif");
2190 } else if (c == '\\') {
2191 /* XXX: incorrect: should not give an error */
2192 ch = file->buf_ptr[0];
2193 handle_stray();
2195 p = file->buf_ptr;
2196 goto redo_no_start;
2197 /* skip strings */
2198 case '\"':
2199 case '\'':
2200 p = parse_pp_string(p, c, NULL);
2201 break;
2202 /* skip comments */
2203 case '/':
2204 file->buf_ptr = p;
2205 ch = *p;
2206 minp();
2207 p = file->buf_ptr;
2208 if (ch == '*') {
2209 p = parse_comment(p);
2210 } else if (ch == '/') {
2211 p = parse_line_comment(p);
2213 break;
2215 case '#':
2216 p++;
2217 if (start_of_line) {
2218 file->buf_ptr = p;
2219 next_nomacro();
2220 p = file->buf_ptr;
2221 if (a == 0 &&
2222 (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
2223 goto the_end;
2224 if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
2225 a++;
2226 else if (tok == TOK_ENDIF)
2227 a--;
2229 break;
2230 default:
2231 p++;
2232 break;
2234 start_of_line = 0;
2236 the_end: ;
2237 file->buf_ptr = p;
2240 /* ParseState handling */
2242 /* XXX: currently, no include file info is stored. Thus, we cannot display
2243 accurate messages if the function or data definition spans multiple
2244 files */
2246 /* save current parse state in 's' */
2247 void save_parse_state(ParseState *s)
2249 s->line_num = file->line_num;
2250 s->macro_ptr = macro_ptr;
2251 s->tok = tok;
2252 s->tokc = tokc;
2255 /* restore parse state from 's' */
2256 void restore_parse_state(ParseState *s)
2258 file->line_num = s->line_num;
2259 macro_ptr = s->macro_ptr;
2260 tok = s->tok;
2261 tokc = s->tokc;
2264 /* return the number of additional 'ints' necessary to store the
2265 token */
2266 static inline int tok_ext_size(int t)
2268 switch(t) {
2269 /* 4 bytes */
2270 case TOK_CINT:
2271 case TOK_CUINT:
2272 case TOK_CCHAR:
2273 case TOK_LCHAR:
2274 case TOK_CFLOAT:
2275 case TOK_LINENUM:
2276 return 1;
2277 case TOK_STR:
2278 case TOK_LSTR:
2279 case TOK_PPNUM:
2280 error("unsupported token");
2281 return 1;
2282 case TOK_CDOUBLE:
2283 case TOK_CLLONG:
2284 case TOK_CULLONG:
2285 return 2;
2286 case TOK_CLDOUBLE:
2287 return LDOUBLE_SIZE / 4;
2288 default:
2289 return 0;
2293 /* token string handling */
2295 static inline void tok_str_new(TokenString *s)
2297 s->str = NULL;
2298 s->len = 0;
2299 s->allocated_len = 0;
2300 s->last_line_num = -1;
2303 static void tok_str_free(int *str)
2305 tcc_free(str);
2308 static int *tok_str_realloc(TokenString *s)
2310 int *str, len;
2312 if (s->allocated_len == 0) {
2313 len = 8;
2314 } else {
2315 len = s->allocated_len * 2;
2317 str = tcc_realloc(s->str, len * sizeof(int));
2318 if (!str)
2319 error("memory full");
2320 s->allocated_len = len;
2321 s->str = str;
2322 return str;
2325 static void tok_str_add(TokenString *s, int t)
2327 int len, *str;
2329 len = s->len;
2330 str = s->str;
2331 if (len >= s->allocated_len)
2332 str = tok_str_realloc(s);
2333 str[len++] = t;
2334 s->len = len;
2337 static void tok_str_add2(TokenString *s, int t, CValue *cv)
2339 int len, *str;
2341 len = s->len;
2342 str = s->str;
2344 /* allocate space for worst case */
2345 if (len + TOK_MAX_SIZE > s->allocated_len)
2346 str = tok_str_realloc(s);
2347 str[len++] = t;
2348 switch(t) {
2349 case TOK_CINT:
2350 case TOK_CUINT:
2351 case TOK_CCHAR:
2352 case TOK_LCHAR:
2353 case TOK_CFLOAT:
2354 case TOK_LINENUM:
2355 str[len++] = cv->tab[0];
2356 break;
2357 case TOK_PPNUM:
2358 case TOK_STR:
2359 case TOK_LSTR:
2361 int nb_words;
2362 CString *cstr;
2364 nb_words = (sizeof(CString) + cv->cstr->size + 3) >> 2;
2365 while ((len + nb_words) > s->allocated_len)
2366 str = tok_str_realloc(s);
2367 cstr = (CString *)(str + len);
2368 cstr->data = NULL;
2369 cstr->size = cv->cstr->size;
2370 cstr->data_allocated = NULL;
2371 cstr->size_allocated = cstr->size;
2372 memcpy((char *)cstr + sizeof(CString),
2373 cv->cstr->data, cstr->size);
2374 len += nb_words;
2376 break;
2377 case TOK_CDOUBLE:
2378 case TOK_CLLONG:
2379 case TOK_CULLONG:
2380 #if LDOUBLE_SIZE == 8
2381 case TOK_CLDOUBLE:
2382 #endif
2383 str[len++] = cv->tab[0];
2384 str[len++] = cv->tab[1];
2385 break;
2386 #if LDOUBLE_SIZE == 12
2387 case TOK_CLDOUBLE:
2388 str[len++] = cv->tab[0];
2389 str[len++] = cv->tab[1];
2390 str[len++] = cv->tab[2];
2391 #elif LDOUBLE_SIZE != 8
2392 #error add long double size support
2393 #endif
2394 break;
2395 default:
2396 break;
2398 s->len = len;
2401 /* add the current parse token in token string 's' */
2402 static void tok_str_add_tok(TokenString *s)
2404 CValue cval;
2406 /* save line number info */
2407 if (file->line_num != s->last_line_num) {
2408 s->last_line_num = file->line_num;
2409 cval.i = s->last_line_num;
2410 tok_str_add2(s, TOK_LINENUM, &cval);
2412 tok_str_add2(s, tok, &tokc);
2415 #if LDOUBLE_SIZE == 12
2416 #define LDOUBLE_GET(p, cv) \
2417 cv.tab[0] = p[0]; \
2418 cv.tab[1] = p[1]; \
2419 cv.tab[2] = p[2];
2420 #elif LDOUBLE_SIZE == 8
2421 #define LDOUBLE_GET(p, cv) \
2422 cv.tab[0] = p[0]; \
2423 cv.tab[1] = p[1];
2424 #else
2425 #error add long double size support
2426 #endif
2429 /* get a token from an integer array and increment pointer
2430 accordingly. we code it as a macro to avoid pointer aliasing. */
2431 #define TOK_GET(t, p, cv) \
2433 t = *p++; \
2434 switch(t) { \
2435 case TOK_CINT: \
2436 case TOK_CUINT: \
2437 case TOK_CCHAR: \
2438 case TOK_LCHAR: \
2439 case TOK_CFLOAT: \
2440 case TOK_LINENUM: \
2441 cv.tab[0] = *p++; \
2442 break; \
2443 case TOK_STR: \
2444 case TOK_LSTR: \
2445 case TOK_PPNUM: \
2446 cv.cstr = (CString *)p; \
2447 cv.cstr->data = (char *)p + sizeof(CString);\
2448 p += (sizeof(CString) + cv.cstr->size + 3) >> 2;\
2449 break; \
2450 case TOK_CDOUBLE: \
2451 case TOK_CLLONG: \
2452 case TOK_CULLONG: \
2453 cv.tab[0] = p[0]; \
2454 cv.tab[1] = p[1]; \
2455 p += 2; \
2456 break; \
2457 case TOK_CLDOUBLE: \
2458 LDOUBLE_GET(p, cv); \
2459 p += LDOUBLE_SIZE / 4; \
2460 break; \
2461 default: \
2462 break; \
2466 /* defines handling */
2467 static inline void define_push(int v, int macro_type, int *str, Sym *first_arg)
2469 Sym *s;
2471 s = sym_push2(&define_stack, v, macro_type, (int)str);
2472 s->next = first_arg;
2473 table_ident[v - TOK_IDENT]->sym_define = s;
2476 /* undefined a define symbol. Its name is just set to zero */
2477 static void define_undef(Sym *s)
2479 int v;
2480 v = s->v;
2481 if (v >= TOK_IDENT && v < tok_ident)
2482 table_ident[v - TOK_IDENT]->sym_define = NULL;
2483 s->v = 0;
2486 static inline Sym *define_find(int v)
2488 v -= TOK_IDENT;
2489 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2490 return NULL;
2491 return table_ident[v]->sym_define;
2494 /* free define stack until top reaches 'b' */
2495 static void free_defines(Sym *b)
2497 Sym *top, *top1;
2498 int v;
2500 top = define_stack;
2501 while (top != b) {
2502 top1 = top->prev;
2503 /* do not free args or predefined defines */
2504 if (top->c)
2505 tok_str_free((int *)top->c);
2506 v = top->v;
2507 if (v >= TOK_IDENT && v < tok_ident)
2508 table_ident[v - TOK_IDENT]->sym_define = NULL;
2509 sym_free(top);
2510 top = top1;
2512 define_stack = b;
2515 /* label lookup */
2516 static Sym *label_find(int v)
2518 v -= TOK_IDENT;
2519 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2520 return NULL;
2521 return table_ident[v]->sym_label;
2524 static Sym *label_push(Sym **ptop, int v, int flags)
2526 Sym *s, **ps;
2527 s = sym_push2(ptop, v, 0, 0);
2528 s->r = flags;
2529 ps = &table_ident[v - TOK_IDENT]->sym_label;
2530 if (ptop == &global_label_stack) {
2531 /* modify the top most local identifier, so that
2532 sym_identifier will point to 's' when popped */
2533 while (*ps != NULL)
2534 ps = &(*ps)->prev_tok;
2536 s->prev_tok = *ps;
2537 *ps = s;
2538 return s;
2541 /* pop labels until element last is reached. Look if any labels are
2542 undefined. Define symbols if '&&label' was used. */
2543 static void label_pop(Sym **ptop, Sym *slast)
2545 Sym *s, *s1;
2546 for(s = *ptop; s != slast; s = s1) {
2547 s1 = s->prev;
2548 if (s->r == LABEL_DECLARED) {
2549 warning("label '%s' declared but not used", get_tok_str(s->v, NULL));
2550 } else if (s->r == LABEL_FORWARD) {
2551 error("label '%s' used but not defined",
2552 get_tok_str(s->v, NULL));
2553 } else {
2554 if (s->c) {
2555 /* define corresponding symbol. A size of
2556 1 is put. */
2557 put_extern_sym(s, cur_text_section, (long)s->next, 1);
2560 /* remove label */
2561 table_ident[s->v - TOK_IDENT]->sym_label = s->prev_tok;
2562 sym_free(s);
2564 *ptop = slast;
2567 /* eval an expression for #if/#elif */
2568 static int expr_preprocess(void)
2570 int c, t;
2571 TokenString str;
2573 tok_str_new(&str);
2574 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2575 next(); /* do macro subst */
2576 if (tok == TOK_DEFINED) {
2577 next_nomacro();
2578 t = tok;
2579 if (t == '(')
2580 next_nomacro();
2581 c = define_find(tok) != 0;
2582 if (t == '(')
2583 next_nomacro();
2584 tok = TOK_CINT;
2585 tokc.i = c;
2586 } else if (tok >= TOK_IDENT) {
2587 /* if undefined macro */
2588 tok = TOK_CINT;
2589 tokc.i = 0;
2591 tok_str_add_tok(&str);
2593 tok_str_add(&str, -1); /* simulate end of file */
2594 tok_str_add(&str, 0);
2595 /* now evaluate C constant expression */
2596 macro_ptr = str.str;
2597 next();
2598 c = expr_const();
2599 macro_ptr = NULL;
2600 tok_str_free(str.str);
2601 return c != 0;
2604 #if defined(PARSE_DEBUG) || defined(PP_DEBUG)
2605 static void tok_print(int *str)
2607 int t;
2608 CValue cval;
2610 while (1) {
2611 TOK_GET(t, str, cval);
2612 if (!t)
2613 break;
2614 printf(" %s", get_tok_str(t, &cval));
2616 printf("\n");
2618 #endif
2620 /* parse after #define */
2621 static void parse_define(void)
2623 Sym *s, *first, **ps;
2624 int v, t, varg, is_vaargs, c;
2625 TokenString str;
2627 v = tok;
2628 if (v < TOK_IDENT)
2629 error("invalid macro name '%s'", get_tok_str(tok, &tokc));
2630 /* XXX: should check if same macro (ANSI) */
2631 first = NULL;
2632 t = MACRO_OBJ;
2633 /* '(' must be just after macro definition for MACRO_FUNC */
2634 c = file->buf_ptr[0];
2635 if (c == '\\')
2636 c = handle_stray1(file->buf_ptr);
2637 if (c == '(') {
2638 next_nomacro();
2639 next_nomacro();
2640 ps = &first;
2641 while (tok != ')') {
2642 varg = tok;
2643 next_nomacro();
2644 is_vaargs = 0;
2645 if (varg == TOK_DOTS) {
2646 varg = TOK___VA_ARGS__;
2647 is_vaargs = 1;
2648 } else if (tok == TOK_DOTS && gnu_ext) {
2649 is_vaargs = 1;
2650 next_nomacro();
2652 if (varg < TOK_IDENT)
2653 error("badly punctuated parameter list");
2654 s = sym_push2(&define_stack, varg | SYM_FIELD, is_vaargs, 0);
2655 *ps = s;
2656 ps = &s->next;
2657 if (tok != ',')
2658 break;
2659 next_nomacro();
2661 t = MACRO_FUNC;
2663 tok_str_new(&str);
2664 next_nomacro();
2665 /* EOF testing necessary for '-D' handling */
2666 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2667 tok_str_add2(&str, tok, &tokc);
2668 next_nomacro();
2670 tok_str_add(&str, 0);
2671 #ifdef PP_DEBUG
2672 printf("define %s %d: ", get_tok_str(v, NULL), t);
2673 tok_print(str.str);
2674 #endif
2675 define_push(v, t, str.str, first);
2678 static inline int hash_cached_include(int type, const char *filename)
2680 const unsigned char *s;
2681 unsigned int h;
2683 h = TOK_HASH_INIT;
2684 h = TOK_HASH_FUNC(h, type);
2685 s = filename;
2686 while (*s) {
2687 h = TOK_HASH_FUNC(h, *s);
2688 s++;
2690 h &= (CACHED_INCLUDES_HASH_SIZE - 1);
2691 return h;
2694 /* XXX: use a token or a hash table to accelerate matching ? */
2695 static CachedInclude *search_cached_include(TCCState *s1,
2696 int type, const char *filename)
2698 CachedInclude *e;
2699 int i, h;
2700 h = hash_cached_include(type, filename);
2701 i = s1->cached_includes_hash[h];
2702 for(;;) {
2703 if (i == 0)
2704 break;
2705 e = s1->cached_includes[i - 1];
2706 if (e->type == type && !strcmp(e->filename, filename))
2707 return e;
2708 i = e->hash_next;
2710 return NULL;
2713 static inline void add_cached_include(TCCState *s1, int type,
2714 const char *filename, int ifndef_macro)
2716 CachedInclude *e;
2717 int h;
2719 if (search_cached_include(s1, type, filename))
2720 return;
2721 #ifdef INC_DEBUG
2722 printf("adding cached '%s' %s\n", filename, get_tok_str(ifndef_macro, NULL));
2723 #endif
2724 e = tcc_malloc(sizeof(CachedInclude) + strlen(filename));
2725 if (!e)
2726 return;
2727 e->type = type;
2728 strcpy(e->filename, filename);
2729 e->ifndef_macro = ifndef_macro;
2730 dynarray_add((void ***)&s1->cached_includes, &s1->nb_cached_includes, e);
2731 /* add in hash table */
2732 h = hash_cached_include(type, filename);
2733 e->hash_next = s1->cached_includes_hash[h];
2734 s1->cached_includes_hash[h] = s1->nb_cached_includes;
2737 static void pragma_parse(TCCState *s1)
2739 int val;
2741 next();
2742 if (tok == TOK_pack) {
2744 This may be:
2745 #pragma pack(1) // set
2746 #pragma pack() // reset to default
2747 #pragma pack(push,1) // push & set
2748 #pragma pack(pop) // restore previous
2750 next();
2751 skip('(');
2752 if (tok == TOK_ASM_pop) {
2753 next();
2754 if (s1->pack_stack_ptr <= s1->pack_stack) {
2755 stk_error:
2756 error("out of pack stack");
2758 s1->pack_stack_ptr--;
2759 } else {
2760 val = 0;
2761 if (tok != ')') {
2762 if (tok == TOK_ASM_push) {
2763 next();
2764 if (s1->pack_stack_ptr >= s1->pack_stack + PACK_STACK_SIZE - 1)
2765 goto stk_error;
2766 s1->pack_stack_ptr++;
2767 skip(',');
2769 if (tok != TOK_CINT) {
2770 pack_error:
2771 error("invalid pack pragma");
2773 val = tokc.i;
2774 if (val < 1 || val > 16 || (val & (val - 1)) != 0)
2775 goto pack_error;
2776 next();
2778 *s1->pack_stack_ptr = val;
2779 skip(')');
2784 /* is_bof is true if first non space token at beginning of file */
2785 static void preprocess(int is_bof)
2787 TCCState *s1 = tcc_state;
2788 int size, i, c, n, saved_parse_flags;
2789 char buf[1024], *q, *p;
2790 char buf1[1024];
2791 BufferedFile *f;
2792 Sym *s;
2793 CachedInclude *e;
2795 saved_parse_flags = parse_flags;
2796 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM |
2797 PARSE_FLAG_LINEFEED;
2798 next_nomacro();
2799 redo:
2800 switch(tok) {
2801 case TOK_DEFINE:
2802 next_nomacro();
2803 parse_define();
2804 break;
2805 case TOK_UNDEF:
2806 next_nomacro();
2807 s = define_find(tok);
2808 /* undefine symbol by putting an invalid name */
2809 if (s)
2810 define_undef(s);
2811 break;
2812 case TOK_INCLUDE:
2813 case TOK_INCLUDE_NEXT:
2814 ch = file->buf_ptr[0];
2815 /* XXX: incorrect if comments : use next_nomacro with a special mode */
2816 skip_spaces();
2817 if (ch == '<') {
2818 c = '>';
2819 goto read_name;
2820 } else if (ch == '\"') {
2821 c = ch;
2822 read_name:
2823 /* XXX: better stray handling */
2824 minp();
2825 q = buf;
2826 while (ch != c && ch != '\n' && ch != CH_EOF) {
2827 if ((q - buf) < sizeof(buf) - 1)
2828 *q++ = ch;
2829 minp();
2831 *q = '\0';
2832 minp();
2833 #if 0
2834 /* eat all spaces and comments after include */
2835 /* XXX: slightly incorrect */
2836 while (ch1 != '\n' && ch1 != CH_EOF)
2837 inp();
2838 #endif
2839 } else {
2840 /* computed #include : either we have only strings or
2841 we have anything enclosed in '<>' */
2842 next();
2843 buf[0] = '\0';
2844 if (tok == TOK_STR) {
2845 while (tok != TOK_LINEFEED) {
2846 if (tok != TOK_STR) {
2847 include_syntax:
2848 error("'#include' expects \"FILENAME\" or <FILENAME>");
2850 pstrcat(buf, sizeof(buf), (char *)tokc.cstr->data);
2851 next();
2853 c = '\"';
2854 } else {
2855 int len;
2856 while (tok != TOK_LINEFEED) {
2857 pstrcat(buf, sizeof(buf), get_tok_str(tok, &tokc));
2858 next();
2860 len = strlen(buf);
2861 /* check syntax and remove '<>' */
2862 if (len < 2 || buf[0] != '<' || buf[len - 1] != '>')
2863 goto include_syntax;
2864 memmove(buf, buf + 1, len - 2);
2865 buf[len - 2] = '\0';
2866 c = '>';
2870 e = search_cached_include(s1, c, buf);
2871 if (e && define_find(e->ifndef_macro)) {
2872 /* no need to parse the include because the 'ifndef macro'
2873 is defined */
2874 #ifdef INC_DEBUG
2875 printf("%s: skipping %s\n", file->filename, buf);
2876 #endif
2877 } else {
2878 if (c == '\"') {
2879 /* first search in current dir if "header.h" */
2880 size = 0;
2881 p = strrchr(file->filename, '/');
2882 if (p)
2883 size = p + 1 - file->filename;
2884 if (size > sizeof(buf1) - 1)
2885 size = sizeof(buf1) - 1;
2886 memcpy(buf1, file->filename, size);
2887 buf1[size] = '\0';
2888 pstrcat(buf1, sizeof(buf1), buf);
2889 f = tcc_open(s1, buf1);
2890 if (f) {
2891 if (tok == TOK_INCLUDE_NEXT)
2892 tok = TOK_INCLUDE;
2893 else
2894 goto found;
2897 if (s1->include_stack_ptr >= s1->include_stack + INCLUDE_STACK_SIZE)
2898 error("#include recursion too deep");
2899 /* now search in all the include paths */
2900 n = s1->nb_include_paths + s1->nb_sysinclude_paths;
2901 for(i = 0; i < n; i++) {
2902 const char *path;
2903 if (i < s1->nb_include_paths)
2904 path = s1->include_paths[i];
2905 else
2906 path = s1->sysinclude_paths[i - s1->nb_include_paths];
2907 pstrcpy(buf1, sizeof(buf1), path);
2908 pstrcat(buf1, sizeof(buf1), "/");
2909 pstrcat(buf1, sizeof(buf1), buf);
2910 f = tcc_open(s1, buf1);
2911 if (f) {
2912 if (tok == TOK_INCLUDE_NEXT)
2913 tok = TOK_INCLUDE;
2914 else
2915 goto found;
2918 error("include file '%s' not found", buf);
2919 f = NULL;
2920 found:
2921 #ifdef INC_DEBUG
2922 printf("%s: including %s\n", file->filename, buf1);
2923 #endif
2924 f->inc_type = c;
2925 pstrcpy(f->inc_filename, sizeof(f->inc_filename), buf);
2926 /* push current file in stack */
2927 /* XXX: fix current line init */
2928 *s1->include_stack_ptr++ = file;
2929 file = f;
2930 /* add include file debug info */
2931 if (do_debug) {
2932 put_stabs(file->filename, N_BINCL, 0, 0, 0);
2934 tok_flags |= TOK_FLAG_BOF | TOK_FLAG_BOL;
2935 ch = file->buf_ptr[0];
2936 goto the_end;
2938 break;
2939 case TOK_IFNDEF:
2940 c = 1;
2941 goto do_ifdef;
2942 case TOK_IF:
2943 c = expr_preprocess();
2944 goto do_if;
2945 case TOK_IFDEF:
2946 c = 0;
2947 do_ifdef:
2948 next_nomacro();
2949 if (tok < TOK_IDENT)
2950 error("invalid argument for '#if%sdef'", c ? "n" : "");
2951 if (is_bof) {
2952 if (c) {
2953 #ifdef INC_DEBUG
2954 printf("#ifndef %s\n", get_tok_str(tok, NULL));
2955 #endif
2956 file->ifndef_macro = tok;
2959 c = (define_find(tok) != 0) ^ c;
2960 do_if:
2961 if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE)
2962 error("memory full");
2963 *s1->ifdef_stack_ptr++ = c;
2964 goto test_skip;
2965 case TOK_ELSE:
2966 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
2967 error("#else without matching #if");
2968 if (s1->ifdef_stack_ptr[-1] & 2)
2969 error("#else after #else");
2970 c = (s1->ifdef_stack_ptr[-1] ^= 3);
2971 goto test_skip;
2972 case TOK_ELIF:
2973 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
2974 error("#elif without matching #if");
2975 c = s1->ifdef_stack_ptr[-1];
2976 if (c > 1)
2977 error("#elif after #else");
2978 /* last #if/#elif expression was true: we skip */
2979 if (c == 1)
2980 goto skip;
2981 c = expr_preprocess();
2982 s1->ifdef_stack_ptr[-1] = c;
2983 test_skip:
2984 if (!(c & 1)) {
2985 skip:
2986 preprocess_skip();
2987 is_bof = 0;
2988 goto redo;
2990 break;
2991 case TOK_ENDIF:
2992 if (s1->ifdef_stack_ptr <= file->ifdef_stack_ptr)
2993 error("#endif without matching #if");
2994 s1->ifdef_stack_ptr--;
2995 /* '#ifndef macro' was at the start of file. Now we check if
2996 an '#endif' is exactly at the end of file */
2997 if (file->ifndef_macro &&
2998 s1->ifdef_stack_ptr == file->ifdef_stack_ptr) {
2999 file->ifndef_macro_saved = file->ifndef_macro;
3000 /* need to set to zero to avoid false matches if another
3001 #ifndef at middle of file */
3002 file->ifndef_macro = 0;
3003 while (tok != TOK_LINEFEED)
3004 next_nomacro();
3005 tok_flags |= TOK_FLAG_ENDIF;
3006 goto the_end;
3008 break;
3009 case TOK_LINE:
3010 next();
3011 if (tok != TOK_CINT)
3012 error("#line");
3013 file->line_num = tokc.i - 1; /* the line number will be incremented after */
3014 next();
3015 if (tok != TOK_LINEFEED) {
3016 if (tok != TOK_STR)
3017 error("#line");
3018 pstrcpy(file->filename, sizeof(file->filename),
3019 (char *)tokc.cstr->data);
3021 break;
3022 case TOK_ERROR:
3023 case TOK_WARNING:
3024 c = tok;
3025 ch = file->buf_ptr[0];
3026 skip_spaces();
3027 q = buf;
3028 while (ch != '\n' && ch != CH_EOF) {
3029 if ((q - buf) < sizeof(buf) - 1)
3030 *q++ = ch;
3031 minp();
3033 *q = '\0';
3034 if (c == TOK_ERROR)
3035 error("#error %s", buf);
3036 else
3037 warning("#warning %s", buf);
3038 break;
3039 case TOK_PRAGMA:
3040 pragma_parse(s1);
3041 break;
3042 default:
3043 if (tok == TOK_LINEFEED || tok == '!' || tok == TOK_CINT) {
3044 /* '!' is ignored to allow C scripts. numbers are ignored
3045 to emulate cpp behaviour */
3046 } else {
3047 if (!(saved_parse_flags & PARSE_FLAG_ASM_COMMENTS))
3048 error("invalid preprocessing directive #%s", get_tok_str(tok, &tokc));
3050 break;
3052 /* ignore other preprocess commands or #! for C scripts */
3053 while (tok != TOK_LINEFEED)
3054 next_nomacro();
3055 the_end:
3056 parse_flags = saved_parse_flags;
3059 /* evaluate escape codes in a string. */
3060 static void parse_escape_string(CString *outstr, const uint8_t *buf, int is_long)
3062 int c, n;
3063 const uint8_t *p;
3065 p = buf;
3066 for(;;) {
3067 c = *p;
3068 if (c == '\0')
3069 break;
3070 if (c == '\\') {
3071 p++;
3072 /* escape */
3073 c = *p;
3074 switch(c) {
3075 case '0': case '1': case '2': case '3':
3076 case '4': case '5': case '6': case '7':
3077 /* at most three octal digits */
3078 n = c - '0';
3079 p++;
3080 c = *p;
3081 if (isoct(c)) {
3082 n = n * 8 + c - '0';
3083 p++;
3084 c = *p;
3085 if (isoct(c)) {
3086 n = n * 8 + c - '0';
3087 p++;
3090 c = n;
3091 goto add_char_nonext;
3092 case 'x':
3093 p++;
3094 n = 0;
3095 for(;;) {
3096 c = *p;
3097 if (c >= 'a' && c <= 'f')
3098 c = c - 'a' + 10;
3099 else if (c >= 'A' && c <= 'F')
3100 c = c - 'A' + 10;
3101 else if (isnum(c))
3102 c = c - '0';
3103 else
3104 break;
3105 n = n * 16 + c;
3106 p++;
3108 c = n;
3109 goto add_char_nonext;
3110 case 'a':
3111 c = '\a';
3112 break;
3113 case 'b':
3114 c = '\b';
3115 break;
3116 case 'f':
3117 c = '\f';
3118 break;
3119 case 'n':
3120 c = '\n';
3121 break;
3122 case 'r':
3123 c = '\r';
3124 break;
3125 case 't':
3126 c = '\t';
3127 break;
3128 case 'v':
3129 c = '\v';
3130 break;
3131 case 'e':
3132 if (!gnu_ext)
3133 goto invalid_escape;
3134 c = 27;
3135 break;
3136 case '\'':
3137 case '\"':
3138 case '\\':
3139 case '?':
3140 break;
3141 default:
3142 invalid_escape:
3143 if (c >= '!' && c <= '~')
3144 warning("unknown escape sequence: \'\\%c\'", c);
3145 else
3146 warning("unknown escape sequence: \'\\x%x\'", c);
3147 break;
3150 p++;
3151 add_char_nonext:
3152 if (!is_long)
3153 cstr_ccat(outstr, c);
3154 else
3155 cstr_wccat(outstr, c);
3157 /* add a trailing '\0' */
3158 if (!is_long)
3159 cstr_ccat(outstr, '\0');
3160 else
3161 cstr_wccat(outstr, '\0');
3164 /* we use 64 bit numbers */
3165 #define BN_SIZE 2
3167 /* bn = (bn << shift) | or_val */
3168 void bn_lshift(unsigned int *bn, int shift, int or_val)
3170 int i;
3171 unsigned int v;
3172 for(i=0;i<BN_SIZE;i++) {
3173 v = bn[i];
3174 bn[i] = (v << shift) | or_val;
3175 or_val = v >> (32 - shift);
3179 void bn_zero(unsigned int *bn)
3181 int i;
3182 for(i=0;i<BN_SIZE;i++) {
3183 bn[i] = 0;
3187 /* parse number in null terminated string 'p' and return it in the
3188 current token */
3189 void parse_number(const char *p)
3191 int b, t, shift, frac_bits, s, exp_val, ch;
3192 char *q;
3193 unsigned int bn[BN_SIZE];
3194 double d;
3196 /* number */
3197 q = token_buf;
3198 ch = *p++;
3199 t = ch;
3200 ch = *p++;
3201 *q++ = t;
3202 b = 10;
3203 if (t == '.') {
3204 goto float_frac_parse;
3205 } else if (t == '0') {
3206 if (ch == 'x' || ch == 'X') {
3207 q--;
3208 ch = *p++;
3209 b = 16;
3210 } else if (tcc_ext && (ch == 'b' || ch == 'B')) {
3211 q--;
3212 ch = *p++;
3213 b = 2;
3216 /* parse all digits. cannot check octal numbers at this stage
3217 because of floating point constants */
3218 while (1) {
3219 if (ch >= 'a' && ch <= 'f')
3220 t = ch - 'a' + 10;
3221 else if (ch >= 'A' && ch <= 'F')
3222 t = ch - 'A' + 10;
3223 else if (isnum(ch))
3224 t = ch - '0';
3225 else
3226 break;
3227 if (t >= b)
3228 break;
3229 if (q >= token_buf + STRING_MAX_SIZE) {
3230 num_too_long:
3231 error("number too long");
3233 *q++ = ch;
3234 ch = *p++;
3236 if (ch == '.' ||
3237 ((ch == 'e' || ch == 'E') && b == 10) ||
3238 ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
3239 if (b != 10) {
3240 /* NOTE: strtox should support that for hexa numbers, but
3241 non ISOC99 libcs do not support it, so we prefer to do
3242 it by hand */
3243 /* hexadecimal or binary floats */
3244 /* XXX: handle overflows */
3245 *q = '\0';
3246 if (b == 16)
3247 shift = 4;
3248 else
3249 shift = 2;
3250 bn_zero(bn);
3251 q = token_buf;
3252 while (1) {
3253 t = *q++;
3254 if (t == '\0') {
3255 break;
3256 } else if (t >= 'a') {
3257 t = t - 'a' + 10;
3258 } else if (t >= 'A') {
3259 t = t - 'A' + 10;
3260 } else {
3261 t = t - '0';
3263 bn_lshift(bn, shift, t);
3265 frac_bits = 0;
3266 if (ch == '.') {
3267 ch = *p++;
3268 while (1) {
3269 t = ch;
3270 if (t >= 'a' && t <= 'f') {
3271 t = t - 'a' + 10;
3272 } else if (t >= 'A' && t <= 'F') {
3273 t = t - 'A' + 10;
3274 } else if (t >= '0' && t <= '9') {
3275 t = t - '0';
3276 } else {
3277 break;
3279 if (t >= b)
3280 error("invalid digit");
3281 bn_lshift(bn, shift, t);
3282 frac_bits += shift;
3283 ch = *p++;
3286 if (ch != 'p' && ch != 'P')
3287 expect("exponent");
3288 ch = *p++;
3289 s = 1;
3290 exp_val = 0;
3291 if (ch == '+') {
3292 ch = *p++;
3293 } else if (ch == '-') {
3294 s = -1;
3295 ch = *p++;
3297 if (ch < '0' || ch > '9')
3298 expect("exponent digits");
3299 while (ch >= '0' && ch <= '9') {
3300 exp_val = exp_val * 10 + ch - '0';
3301 ch = *p++;
3303 exp_val = exp_val * s;
3305 /* now we can generate the number */
3306 /* XXX: should patch directly float number */
3307 d = (double)bn[1] * 4294967296.0 + (double)bn[0];
3308 d = ldexp(d, exp_val - frac_bits);
3309 t = toup(ch);
3310 if (t == 'F') {
3311 ch = *p++;
3312 tok = TOK_CFLOAT;
3313 /* float : should handle overflow */
3314 tokc.f = (float)d;
3315 } else if (t == 'L') {
3316 ch = *p++;
3317 tok = TOK_CLDOUBLE;
3318 /* XXX: not large enough */
3319 tokc.ld = (long double)d;
3320 } else {
3321 tok = TOK_CDOUBLE;
3322 tokc.d = d;
3324 } else {
3325 /* decimal floats */
3326 if (ch == '.') {
3327 if (q >= token_buf + STRING_MAX_SIZE)
3328 goto num_too_long;
3329 *q++ = ch;
3330 ch = *p++;
3331 float_frac_parse:
3332 while (ch >= '0' && ch <= '9') {
3333 if (q >= token_buf + STRING_MAX_SIZE)
3334 goto num_too_long;
3335 *q++ = ch;
3336 ch = *p++;
3339 if (ch == 'e' || ch == 'E') {
3340 if (q >= token_buf + STRING_MAX_SIZE)
3341 goto num_too_long;
3342 *q++ = ch;
3343 ch = *p++;
3344 if (ch == '-' || ch == '+') {
3345 if (q >= token_buf + STRING_MAX_SIZE)
3346 goto num_too_long;
3347 *q++ = ch;
3348 ch = *p++;
3350 if (ch < '0' || ch > '9')
3351 expect("exponent digits");
3352 while (ch >= '0' && ch <= '9') {
3353 if (q >= token_buf + STRING_MAX_SIZE)
3354 goto num_too_long;
3355 *q++ = ch;
3356 ch = *p++;
3359 *q = '\0';
3360 t = toup(ch);
3361 errno = 0;
3362 if (t == 'F') {
3363 ch = *p++;
3364 tok = TOK_CFLOAT;
3365 tokc.f = strtof(token_buf, NULL);
3366 } else if (t == 'L') {
3367 ch = *p++;
3368 tok = TOK_CLDOUBLE;
3369 tokc.ld = strtold(token_buf, NULL);
3370 } else {
3371 tok = TOK_CDOUBLE;
3372 tokc.d = strtod(token_buf, NULL);
3375 } else {
3376 unsigned long long n, n1;
3377 int lcount, ucount;
3379 /* integer number */
3380 *q = '\0';
3381 q = token_buf;
3382 if (b == 10 && *q == '0') {
3383 b = 8;
3384 q++;
3386 n = 0;
3387 while(1) {
3388 t = *q++;
3389 /* no need for checks except for base 10 / 8 errors */
3390 if (t == '\0') {
3391 break;
3392 } else if (t >= 'a') {
3393 t = t - 'a' + 10;
3394 } else if (t >= 'A') {
3395 t = t - 'A' + 10;
3396 } else {
3397 t = t - '0';
3398 if (t >= b)
3399 error("invalid digit");
3401 n1 = n;
3402 n = n * b + t;
3403 /* detect overflow */
3404 /* XXX: this test is not reliable */
3405 if (n < n1)
3406 error("integer constant overflow");
3409 /* XXX: not exactly ANSI compliant */
3410 if ((n & 0xffffffff00000000LL) != 0) {
3411 if ((n >> 63) != 0)
3412 tok = TOK_CULLONG;
3413 else
3414 tok = TOK_CLLONG;
3415 } else if (n > 0x7fffffff) {
3416 tok = TOK_CUINT;
3417 } else {
3418 tok = TOK_CINT;
3420 lcount = 0;
3421 ucount = 0;
3422 for(;;) {
3423 t = toup(ch);
3424 if (t == 'L') {
3425 if (lcount >= 2)
3426 error("three 'l's in integer constant");
3427 lcount++;
3428 if (lcount == 2) {
3429 if (tok == TOK_CINT)
3430 tok = TOK_CLLONG;
3431 else if (tok == TOK_CUINT)
3432 tok = TOK_CULLONG;
3434 ch = *p++;
3435 } else if (t == 'U') {
3436 if (ucount >= 1)
3437 error("two 'u's in integer constant");
3438 ucount++;
3439 if (tok == TOK_CINT)
3440 tok = TOK_CUINT;
3441 else if (tok == TOK_CLLONG)
3442 tok = TOK_CULLONG;
3443 ch = *p++;
3444 } else {
3445 break;
3448 if (tok == TOK_CINT || tok == TOK_CUINT)
3449 tokc.ui = n;
3450 else
3451 tokc.ull = n;
3456 #define PARSE2(c1, tok1, c2, tok2) \
3457 case c1: \
3458 PEEKC(c, p); \
3459 if (c == c2) { \
3460 p++; \
3461 tok = tok2; \
3462 } else { \
3463 tok = tok1; \
3465 break;
3467 /* return next token without macro substitution */
3468 static inline void next_nomacro1(void)
3470 int t, c, is_long;
3471 TokenSym *ts;
3472 uint8_t *p, *p1;
3473 unsigned int h;
3475 p = file->buf_ptr;
3476 redo_no_start:
3477 c = *p;
3478 switch(c) {
3479 case ' ':
3480 case '\t':
3481 case '\f':
3482 case '\v':
3483 case '\r':
3484 p++;
3485 goto redo_no_start;
3487 case '\\':
3488 /* first look if it is in fact an end of buffer */
3489 if (p >= file->buf_end) {
3490 file->buf_ptr = p;
3491 handle_eob();
3492 p = file->buf_ptr;
3493 if (p >= file->buf_end)
3494 goto parse_eof;
3495 else
3496 goto redo_no_start;
3497 } else {
3498 file->buf_ptr = p;
3499 ch = *p;
3500 handle_stray();
3501 p = file->buf_ptr;
3502 goto redo_no_start;
3504 parse_eof:
3506 TCCState *s1 = tcc_state;
3507 if (parse_flags & PARSE_FLAG_LINEFEED) {
3508 tok = TOK_LINEFEED;
3509 } else if (s1->include_stack_ptr == s1->include_stack ||
3510 !(parse_flags & PARSE_FLAG_PREPROCESS)) {
3511 /* no include left : end of file. */
3512 tok = TOK_EOF;
3513 } else {
3514 /* pop include file */
3516 /* test if previous '#endif' was after a #ifdef at
3517 start of file */
3518 if (tok_flags & TOK_FLAG_ENDIF) {
3519 #ifdef INC_DEBUG
3520 printf("#endif %s\n", get_tok_str(file->ifndef_macro_saved, NULL));
3521 #endif
3522 add_cached_include(s1, file->inc_type, file->inc_filename,
3523 file->ifndef_macro_saved);
3526 /* add end of include file debug info */
3527 if (do_debug) {
3528 put_stabd(N_EINCL, 0, 0);
3530 /* pop include stack */
3531 tcc_close(file);
3532 s1->include_stack_ptr--;
3533 file = *s1->include_stack_ptr;
3534 p = file->buf_ptr;
3535 goto redo_no_start;
3538 break;
3540 case '\n':
3541 if (parse_flags & PARSE_FLAG_LINEFEED) {
3542 tok = TOK_LINEFEED;
3543 } else {
3544 file->line_num++;
3545 tok_flags |= TOK_FLAG_BOL;
3546 p++;
3547 goto redo_no_start;
3549 break;
3551 case '#':
3552 /* XXX: simplify */
3553 PEEKC(c, p);
3554 if ((tok_flags & TOK_FLAG_BOL) &&
3555 (parse_flags & PARSE_FLAG_PREPROCESS)) {
3556 file->buf_ptr = p;
3557 preprocess(tok_flags & TOK_FLAG_BOF);
3558 p = file->buf_ptr;
3559 goto redo_no_start;
3560 } else {
3561 if (c == '#') {
3562 p++;
3563 tok = TOK_TWOSHARPS;
3564 } else {
3565 if (parse_flags & PARSE_FLAG_ASM_COMMENTS) {
3566 p = parse_line_comment(p - 1);
3567 goto redo_no_start;
3568 } else {
3569 tok = '#';
3573 break;
3575 case 'a': case 'b': case 'c': case 'd':
3576 case 'e': case 'f': case 'g': case 'h':
3577 case 'i': case 'j': case 'k': case 'l':
3578 case 'm': case 'n': case 'o': case 'p':
3579 case 'q': case 'r': case 's': case 't':
3580 case 'u': case 'v': case 'w': case 'x':
3581 case 'y': case 'z':
3582 case 'A': case 'B': case 'C': case 'D':
3583 case 'E': case 'F': case 'G': case 'H':
3584 case 'I': case 'J': case 'K':
3585 case 'M': case 'N': case 'O': case 'P':
3586 case 'Q': case 'R': case 'S': case 'T':
3587 case 'U': case 'V': case 'W': case 'X':
3588 case 'Y': case 'Z':
3589 case '_':
3590 parse_ident_fast:
3591 p1 = p;
3592 h = TOK_HASH_INIT;
3593 h = TOK_HASH_FUNC(h, c);
3594 p++;
3595 for(;;) {
3596 c = *p;
3597 if (!isidnum_table[c])
3598 break;
3599 h = TOK_HASH_FUNC(h, c);
3600 p++;
3602 if (c != '\\') {
3603 TokenSym **pts;
3604 int len;
3606 /* fast case : no stray found, so we have the full token
3607 and we have already hashed it */
3608 len = p - p1;
3609 h &= (TOK_HASH_SIZE - 1);
3610 pts = &hash_ident[h];
3611 for(;;) {
3612 ts = *pts;
3613 if (!ts)
3614 break;
3615 if (ts->len == len && !memcmp(ts->str, p1, len))
3616 goto token_found;
3617 pts = &(ts->hash_next);
3619 ts = tok_alloc_new(pts, p1, len);
3620 token_found: ;
3621 } else {
3622 /* slower case */
3623 cstr_reset(&tokcstr);
3625 while (p1 < p) {
3626 cstr_ccat(&tokcstr, *p1);
3627 p1++;
3629 p--;
3630 PEEKC(c, p);
3631 parse_ident_slow:
3632 while (isidnum_table[c]) {
3633 cstr_ccat(&tokcstr, c);
3634 PEEKC(c, p);
3636 ts = tok_alloc(tokcstr.data, tokcstr.size);
3638 tok = ts->tok;
3639 break;
3640 case 'L':
3641 t = p[1];
3642 if (t != '\\' && t != '\'' && t != '\"') {
3643 /* fast case */
3644 goto parse_ident_fast;
3645 } else {
3646 PEEKC(c, p);
3647 if (c == '\'' || c == '\"') {
3648 is_long = 1;
3649 goto str_const;
3650 } else {
3651 cstr_reset(&tokcstr);
3652 cstr_ccat(&tokcstr, 'L');
3653 goto parse_ident_slow;
3656 break;
3657 case '0': case '1': case '2': case '3':
3658 case '4': case '5': case '6': case '7':
3659 case '8': case '9':
3661 cstr_reset(&tokcstr);
3662 /* after the first digit, accept digits, alpha, '.' or sign if
3663 prefixed by 'eEpP' */
3664 parse_num:
3665 for(;;) {
3666 t = c;
3667 cstr_ccat(&tokcstr, c);
3668 PEEKC(c, p);
3669 if (!(isnum(c) || isid(c) || c == '.' ||
3670 ((c == '+' || c == '-') &&
3671 (t == 'e' || t == 'E' || t == 'p' || t == 'P'))))
3672 break;
3674 /* We add a trailing '\0' to ease parsing */
3675 cstr_ccat(&tokcstr, '\0');
3676 tokc.cstr = &tokcstr;
3677 tok = TOK_PPNUM;
3678 break;
3679 case '.':
3680 /* special dot handling because it can also start a number */
3681 PEEKC(c, p);
3682 if (isnum(c)) {
3683 cstr_reset(&tokcstr);
3684 cstr_ccat(&tokcstr, '.');
3685 goto parse_num;
3686 } else if (c == '.') {
3687 PEEKC(c, p);
3688 if (c != '.')
3689 expect("'.'");
3690 PEEKC(c, p);
3691 tok = TOK_DOTS;
3692 } else {
3693 tok = '.';
3695 break;
3696 case '\'':
3697 case '\"':
3698 is_long = 0;
3699 str_const:
3701 CString str;
3702 int sep;
3704 sep = c;
3706 /* parse the string */
3707 cstr_new(&str);
3708 p = parse_pp_string(p, sep, &str);
3709 cstr_ccat(&str, '\0');
3711 /* eval the escape (should be done as TOK_PPNUM) */
3712 cstr_reset(&tokcstr);
3713 parse_escape_string(&tokcstr, str.data, is_long);
3714 cstr_free(&str);
3716 if (sep == '\'') {
3717 int char_size;
3718 /* XXX: make it portable */
3719 if (!is_long)
3720 char_size = 1;
3721 else
3722 char_size = sizeof(int);
3723 if (tokcstr.size <= char_size)
3724 error("empty character constant");
3725 if (tokcstr.size > 2 * char_size)
3726 warning("multi-character character constant");
3727 if (!is_long) {
3728 tokc.i = *(int8_t *)tokcstr.data;
3729 tok = TOK_CCHAR;
3730 } else {
3731 tokc.i = *(int *)tokcstr.data;
3732 tok = TOK_LCHAR;
3734 } else {
3735 tokc.cstr = &tokcstr;
3736 if (!is_long)
3737 tok = TOK_STR;
3738 else
3739 tok = TOK_LSTR;
3742 break;
3744 case '<':
3745 PEEKC(c, p);
3746 if (c == '=') {
3747 p++;
3748 tok = TOK_LE;
3749 } else if (c == '<') {
3750 PEEKC(c, p);
3751 if (c == '=') {
3752 p++;
3753 tok = TOK_A_SHL;
3754 } else {
3755 tok = TOK_SHL;
3757 } else {
3758 tok = TOK_LT;
3760 break;
3762 case '>':
3763 PEEKC(c, p);
3764 if (c == '=') {
3765 p++;
3766 tok = TOK_GE;
3767 } else if (c == '>') {
3768 PEEKC(c, p);
3769 if (c == '=') {
3770 p++;
3771 tok = TOK_A_SAR;
3772 } else {
3773 tok = TOK_SAR;
3775 } else {
3776 tok = TOK_GT;
3778 break;
3780 case '&':
3781 PEEKC(c, p);
3782 if (c == '&') {
3783 p++;
3784 tok = TOK_LAND;
3785 } else if (c == '=') {
3786 p++;
3787 tok = TOK_A_AND;
3788 } else {
3789 tok = '&';
3791 break;
3793 case '|':
3794 PEEKC(c, p);
3795 if (c == '|') {
3796 p++;
3797 tok = TOK_LOR;
3798 } else if (c == '=') {
3799 p++;
3800 tok = TOK_A_OR;
3801 } else {
3802 tok = '|';
3804 break;
3806 case '+':
3807 PEEKC(c, p);
3808 if (c == '+') {
3809 p++;
3810 tok = TOK_INC;
3811 } else if (c == '=') {
3812 p++;
3813 tok = TOK_A_ADD;
3814 } else {
3815 tok = '+';
3817 break;
3819 case '-':
3820 PEEKC(c, p);
3821 if (c == '-') {
3822 p++;
3823 tok = TOK_DEC;
3824 } else if (c == '=') {
3825 p++;
3826 tok = TOK_A_SUB;
3827 } else if (c == '>') {
3828 p++;
3829 tok = TOK_ARROW;
3830 } else {
3831 tok = '-';
3833 break;
3835 PARSE2('!', '!', '=', TOK_NE)
3836 PARSE2('=', '=', '=', TOK_EQ)
3837 PARSE2('*', '*', '=', TOK_A_MUL)
3838 PARSE2('%', '%', '=', TOK_A_MOD)
3839 PARSE2('^', '^', '=', TOK_A_XOR)
3841 /* comments or operator */
3842 case '/':
3843 PEEKC(c, p);
3844 if (c == '*') {
3845 p = parse_comment(p);
3846 goto redo_no_start;
3847 } else if (c == '/') {
3848 p = parse_line_comment(p);
3849 goto redo_no_start;
3850 } else if (c == '=') {
3851 p++;
3852 tok = TOK_A_DIV;
3853 } else {
3854 tok = '/';
3856 break;
3858 /* simple tokens */
3859 case '(':
3860 case ')':
3861 case '[':
3862 case ']':
3863 case '{':
3864 case '}':
3865 case ',':
3866 case ';':
3867 case ':':
3868 case '?':
3869 case '~':
3870 case '$': /* only used in assembler */
3871 case '@': /* dito */
3872 tok = c;
3873 p++;
3874 break;
3875 default:
3876 error("unrecognized character \\x%02x", c);
3877 break;
3879 file->buf_ptr = p;
3880 tok_flags = 0;
3881 #if defined(PARSE_DEBUG)
3882 printf("token = %s\n", get_tok_str(tok, &tokc));
3883 #endif
3886 /* return next token without macro substitution. Can read input from
3887 macro_ptr buffer */
3888 static void next_nomacro(void)
3890 if (macro_ptr) {
3891 redo:
3892 tok = *macro_ptr;
3893 if (tok) {
3894 TOK_GET(tok, macro_ptr, tokc);
3895 if (tok == TOK_LINENUM) {
3896 file->line_num = tokc.i;
3897 goto redo;
3900 } else {
3901 next_nomacro1();
3905 /* substitute args in macro_str and return allocated string */
3906 static int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
3908 int *st, last_tok, t, notfirst;
3909 Sym *s;
3910 CValue cval;
3911 TokenString str;
3912 CString cstr;
3914 tok_str_new(&str);
3915 last_tok = 0;
3916 while(1) {
3917 TOK_GET(t, macro_str, cval);
3918 if (!t)
3919 break;
3920 if (t == '#') {
3921 /* stringize */
3922 TOK_GET(t, macro_str, cval);
3923 if (!t)
3924 break;
3925 s = sym_find2(args, t);
3926 if (s) {
3927 cstr_new(&cstr);
3928 st = (int *)s->c;
3929 notfirst = 0;
3930 while (*st) {
3931 if (notfirst)
3932 cstr_ccat(&cstr, ' ');
3933 TOK_GET(t, st, cval);
3934 cstr_cat(&cstr, get_tok_str(t, &cval));
3935 notfirst = 1;
3937 cstr_ccat(&cstr, '\0');
3938 #ifdef PP_DEBUG
3939 printf("stringize: %s\n", (char *)cstr.data);
3940 #endif
3941 /* add string */
3942 cval.cstr = &cstr;
3943 tok_str_add2(&str, TOK_STR, &cval);
3944 cstr_free(&cstr);
3945 } else {
3946 tok_str_add2(&str, t, &cval);
3948 } else if (t >= TOK_IDENT) {
3949 s = sym_find2(args, t);
3950 if (s) {
3951 st = (int *)s->c;
3952 /* if '##' is present before or after, no arg substitution */
3953 if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) {
3954 /* special case for var arg macros : ## eats the
3955 ',' if empty VA_ARGS variable. */
3956 /* XXX: test of the ',' is not 100%
3957 reliable. should fix it to avoid security
3958 problems */
3959 if (gnu_ext && s->type.t &&
3960 last_tok == TOK_TWOSHARPS &&
3961 str.len >= 2 && str.str[str.len - 2] == ',') {
3962 if (*st == 0) {
3963 /* suppress ',' '##' */
3964 str.len -= 2;
3965 } else {
3966 /* suppress '##' and add variable */
3967 str.len--;
3968 goto add_var;
3970 } else {
3971 int t1;
3972 add_var:
3973 for(;;) {
3974 TOK_GET(t1, st, cval);
3975 if (!t1)
3976 break;
3977 tok_str_add2(&str, t1, &cval);
3980 } else {
3981 /* NOTE: the stream cannot be read when macro
3982 substituing an argument */
3983 macro_subst(&str, nested_list, st, 0);
3985 } else {
3986 tok_str_add(&str, t);
3988 } else {
3989 tok_str_add2(&str, t, &cval);
3991 last_tok = t;
3993 tok_str_add(&str, 0);
3994 return str.str;
3997 static char const ab_month_name[12][4] =
3999 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
4000 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
4003 /* do macro substitution of current token with macro 's' and add
4004 result to (tok_str,tok_len). 'nested_list' is the list of all
4005 macros we got inside to avoid recursing. Return non zero if no
4006 substitution needs to be done */
4007 static int macro_subst_tok(TokenString *tok_str,
4008 Sym **nested_list, Sym *s, int can_read_stream)
4010 Sym *args, *sa, *sa1;
4011 int mstr_allocated, parlevel, *mstr, t, t1;
4012 TokenString str;
4013 char *cstrval;
4014 CValue cval;
4015 CString cstr;
4016 char buf[32];
4018 /* if symbol is a macro, prepare substitution */
4019 /* special macros */
4020 if (tok == TOK___LINE__) {
4021 snprintf(buf, sizeof(buf), "%d", file->line_num);
4022 cstrval = buf;
4023 t1 = TOK_PPNUM;
4024 goto add_cstr1;
4025 } else if (tok == TOK___FILE__) {
4026 cstrval = file->filename;
4027 goto add_cstr;
4028 } else if (tok == TOK___DATE__ || tok == TOK___TIME__) {
4029 time_t ti;
4030 struct tm *tm;
4032 time(&ti);
4033 tm = localtime(&ti);
4034 if (tok == TOK___DATE__) {
4035 snprintf(buf, sizeof(buf), "%s %2d %d",
4036 ab_month_name[tm->tm_mon], tm->tm_mday, tm->tm_year + 1900);
4037 } else {
4038 snprintf(buf, sizeof(buf), "%02d:%02d:%02d",
4039 tm->tm_hour, tm->tm_min, tm->tm_sec);
4041 cstrval = buf;
4042 add_cstr:
4043 t1 = TOK_STR;
4044 add_cstr1:
4045 cstr_new(&cstr);
4046 cstr_cat(&cstr, cstrval);
4047 cstr_ccat(&cstr, '\0');
4048 cval.cstr = &cstr;
4049 tok_str_add2(tok_str, t1, &cval);
4050 cstr_free(&cstr);
4051 } else {
4052 mstr = (int *)s->c;
4053 mstr_allocated = 0;
4054 if (s->type.t == MACRO_FUNC) {
4055 /* NOTE: we do not use next_nomacro to avoid eating the
4056 next token. XXX: find better solution */
4057 if (macro_ptr) {
4058 t = *macro_ptr;
4059 if (t == 0 && can_read_stream) {
4060 /* end of macro stream: we must look at the token
4061 after in the file */
4062 macro_ptr = NULL;
4063 goto parse_stream;
4065 } else {
4066 parse_stream:
4067 /* XXX: incorrect with comments */
4068 ch = file->buf_ptr[0];
4069 while (is_space(ch) || ch == '\n')
4070 cinp();
4071 t = ch;
4073 if (t != '(') /* no macro subst */
4074 return -1;
4076 /* argument macro */
4077 next_nomacro();
4078 next_nomacro();
4079 args = NULL;
4080 sa = s->next;
4081 /* NOTE: empty args are allowed, except if no args */
4082 for(;;) {
4083 /* handle '()' case */
4084 if (!args && !sa && tok == ')')
4085 break;
4086 if (!sa)
4087 error("macro '%s' used with too many args",
4088 get_tok_str(s->v, 0));
4089 tok_str_new(&str);
4090 parlevel = 0;
4091 /* NOTE: non zero sa->t indicates VA_ARGS */
4092 while ((parlevel > 0 ||
4093 (tok != ')' &&
4094 (tok != ',' || sa->type.t))) &&
4095 tok != -1) {
4096 if (tok == '(')
4097 parlevel++;
4098 else if (tok == ')')
4099 parlevel--;
4100 tok_str_add2(&str, tok, &tokc);
4101 next_nomacro();
4103 tok_str_add(&str, 0);
4104 sym_push2(&args, sa->v & ~SYM_FIELD, sa->type.t, (int)str.str);
4105 sa = sa->next;
4106 if (tok == ')') {
4107 /* special case for gcc var args: add an empty
4108 var arg argument if it is omitted */
4109 if (sa && sa->type.t && gnu_ext)
4110 continue;
4111 else
4112 break;
4114 if (tok != ',')
4115 expect(",");
4116 next_nomacro();
4118 if (sa) {
4119 error("macro '%s' used with too few args",
4120 get_tok_str(s->v, 0));
4123 /* now subst each arg */
4124 mstr = macro_arg_subst(nested_list, mstr, args);
4125 /* free memory */
4126 sa = args;
4127 while (sa) {
4128 sa1 = sa->prev;
4129 tok_str_free((int *)sa->c);
4130 sym_free(sa);
4131 sa = sa1;
4133 mstr_allocated = 1;
4135 sym_push2(nested_list, s->v, 0, 0);
4136 macro_subst(tok_str, nested_list, mstr, 1);
4137 /* pop nested defined symbol */
4138 sa1 = *nested_list;
4139 *nested_list = sa1->prev;
4140 sym_free(sa1);
4141 if (mstr_allocated)
4142 tok_str_free(mstr);
4144 return 0;
4147 /* handle the '##' operator. Return NULL if no '##' seen. Otherwise
4148 return the resulting string (which must be freed). */
4149 static inline int *macro_twosharps(const int *macro_str)
4151 TokenSym *ts;
4152 const int *macro_ptr1, *start_macro_ptr, *ptr, *saved_macro_ptr;
4153 int t;
4154 const char *p1, *p2;
4155 CValue cval;
4156 TokenString macro_str1;
4157 CString cstr;
4159 start_macro_ptr = macro_str;
4160 /* we search the first '##' */
4161 for(;;) {
4162 macro_ptr1 = macro_str;
4163 TOK_GET(t, macro_str, cval);
4164 /* nothing more to do if end of string */
4165 if (t == 0)
4166 return NULL;
4167 if (*macro_str == TOK_TWOSHARPS)
4168 break;
4171 /* we saw '##', so we need more processing to handle it */
4172 cstr_new(&cstr);
4173 tok_str_new(&macro_str1);
4174 tok = t;
4175 tokc = cval;
4177 /* add all tokens seen so far */
4178 for(ptr = start_macro_ptr; ptr < macro_ptr1;) {
4179 TOK_GET(t, ptr, cval);
4180 tok_str_add2(&macro_str1, t, &cval);
4182 saved_macro_ptr = macro_ptr;
4183 /* XXX: get rid of the use of macro_ptr here */
4184 macro_ptr = (int *)macro_str;
4185 for(;;) {
4186 while (*macro_ptr == TOK_TWOSHARPS) {
4187 macro_ptr++;
4188 macro_ptr1 = macro_ptr;
4189 t = *macro_ptr;
4190 if (t) {
4191 TOK_GET(t, macro_ptr, cval);
4192 /* We concatenate the two tokens if we have an
4193 identifier or a preprocessing number */
4194 cstr_reset(&cstr);
4195 p1 = get_tok_str(tok, &tokc);
4196 cstr_cat(&cstr, p1);
4197 p2 = get_tok_str(t, &cval);
4198 cstr_cat(&cstr, p2);
4199 cstr_ccat(&cstr, '\0');
4201 if ((tok >= TOK_IDENT || tok == TOK_PPNUM) &&
4202 (t >= TOK_IDENT || t == TOK_PPNUM)) {
4203 if (tok == TOK_PPNUM) {
4204 /* if number, then create a number token */
4205 /* NOTE: no need to allocate because
4206 tok_str_add2() does it */
4207 tokc.cstr = &cstr;
4208 } else {
4209 /* if identifier, we must do a test to
4210 validate we have a correct identifier */
4211 if (t == TOK_PPNUM) {
4212 const char *p;
4213 int c;
4215 p = p2;
4216 for(;;) {
4217 c = *p;
4218 if (c == '\0')
4219 break;
4220 p++;
4221 if (!isnum(c) && !isid(c))
4222 goto error_pasting;
4225 ts = tok_alloc(cstr.data, strlen(cstr.data));
4226 tok = ts->tok; /* modify current token */
4228 } else {
4229 const char *str = cstr.data;
4230 const unsigned char *q;
4232 /* we look for a valid token */
4233 /* XXX: do more extensive checks */
4234 if (!strcmp(str, ">>=")) {
4235 tok = TOK_A_SAR;
4236 } else if (!strcmp(str, "<<=")) {
4237 tok = TOK_A_SHL;
4238 } else if (strlen(str) == 2) {
4239 /* search in two bytes table */
4240 q = tok_two_chars;
4241 for(;;) {
4242 if (!*q)
4243 goto error_pasting;
4244 if (q[0] == str[0] && q[1] == str[1])
4245 break;
4246 q += 3;
4248 tok = q[2];
4249 } else {
4250 error_pasting:
4251 /* NOTE: because get_tok_str use a static buffer,
4252 we must save it */
4253 cstr_reset(&cstr);
4254 p1 = get_tok_str(tok, &tokc);
4255 cstr_cat(&cstr, p1);
4256 cstr_ccat(&cstr, '\0');
4257 p2 = get_tok_str(t, &cval);
4258 warning("pasting \"%s\" and \"%s\" does not give a valid preprocessing token", cstr.data, p2);
4259 /* cannot merge tokens: just add them separately */
4260 tok_str_add2(&macro_str1, tok, &tokc);
4261 /* XXX: free associated memory ? */
4262 tok = t;
4263 tokc = cval;
4268 tok_str_add2(&macro_str1, tok, &tokc);
4269 next_nomacro();
4270 if (tok == 0)
4271 break;
4273 macro_ptr = (int *)saved_macro_ptr;
4274 cstr_free(&cstr);
4275 tok_str_add(&macro_str1, 0);
4276 return macro_str1.str;
4280 /* do macro substitution of macro_str and add result to
4281 (tok_str,tok_len). 'nested_list' is the list of all macros we got
4282 inside to avoid recursing. */
4283 static void macro_subst(TokenString *tok_str, Sym **nested_list,
4284 const int *macro_str, int can_read_stream)
4286 Sym *s;
4287 int *saved_macro_ptr, *macro_str1;
4288 const int *ptr;
4289 int t, ret;
4290 CValue cval;
4292 /* first scan for '##' operator handling */
4293 ptr = macro_str;
4294 macro_str1 = macro_twosharps(ptr);
4295 if (macro_str1)
4296 ptr = macro_str1;
4297 while (1) {
4298 /* NOTE: ptr == NULL can only happen if tokens are read from
4299 file stream due to a macro function call */
4300 if (ptr == NULL)
4301 break;
4302 TOK_GET(t, ptr, cval);
4303 if (t == 0)
4304 break;
4305 s = define_find(t);
4306 if (s != NULL) {
4307 /* if nested substitution, do nothing */
4308 if (sym_find2(*nested_list, t))
4309 goto no_subst;
4310 saved_macro_ptr = macro_ptr;
4311 macro_ptr = (int *)ptr;
4312 tok = t;
4313 ret = macro_subst_tok(tok_str, nested_list, s, can_read_stream);
4314 ptr = (int *)macro_ptr;
4315 macro_ptr = saved_macro_ptr;
4316 if (ret != 0)
4317 goto no_subst;
4318 } else {
4319 no_subst:
4320 tok_str_add2(tok_str, t, &cval);
4323 if (macro_str1)
4324 tok_str_free(macro_str1);
4327 /* return next token with macro substitution */
4328 static void next(void)
4330 Sym *nested_list, *s;
4331 TokenString str;
4333 redo:
4334 next_nomacro();
4335 if (!macro_ptr) {
4336 /* if not reading from macro substituted string, then try
4337 to substitute macros */
4338 if (tok >= TOK_IDENT &&
4339 (parse_flags & PARSE_FLAG_PREPROCESS)) {
4340 s = define_find(tok);
4341 if (s) {
4342 /* we have a macro: we try to substitute */
4343 tok_str_new(&str);
4344 nested_list = NULL;
4345 if (macro_subst_tok(&str, &nested_list, s, 1) == 0) {
4346 /* substitution done, NOTE: maybe empty */
4347 tok_str_add(&str, 0);
4348 macro_ptr = str.str;
4349 macro_ptr_allocated = str.str;
4350 goto redo;
4354 } else {
4355 if (tok == 0) {
4356 /* end of macro or end of unget buffer */
4357 if (unget_buffer_enabled) {
4358 macro_ptr = unget_saved_macro_ptr;
4359 unget_buffer_enabled = 0;
4360 } else {
4361 /* end of macro string: free it */
4362 tok_str_free(macro_ptr_allocated);
4363 macro_ptr = NULL;
4365 goto redo;
4369 /* convert preprocessor tokens into C tokens */
4370 if (tok == TOK_PPNUM &&
4371 (parse_flags & PARSE_FLAG_TOK_NUM)) {
4372 parse_number((char *)tokc.cstr->data);
4376 /* push back current token and set current token to 'last_tok'. Only
4377 identifier case handled for labels. */
4378 static inline void unget_tok(int last_tok)
4380 int i, n;
4381 int *q;
4382 unget_saved_macro_ptr = macro_ptr;
4383 unget_buffer_enabled = 1;
4384 q = unget_saved_buffer;
4385 macro_ptr = q;
4386 *q++ = tok;
4387 n = tok_ext_size(tok) - 1;
4388 for(i=0;i<n;i++)
4389 *q++ = tokc.tab[i];
4390 *q = 0; /* end of token string */
4391 tok = last_tok;
4395 void swap(int *p, int *q)
4397 int t;
4398 t = *p;
4399 *p = *q;
4400 *q = t;
4403 void vsetc(CType *type, int r, CValue *vc)
4405 int v;
4407 if (vtop >= vstack + (VSTACK_SIZE - 1))
4408 error("memory full");
4409 /* cannot let cpu flags if other instruction are generated. Also
4410 avoid leaving VT_JMP anywhere except on the top of the stack
4411 because it would complicate the code generator. */
4412 if (vtop >= vstack) {
4413 v = vtop->r & VT_VALMASK;
4414 if (v == VT_CMP || (v & ~1) == VT_JMP)
4415 gv(RC_INT);
4417 vtop++;
4418 vtop->type = *type;
4419 vtop->r = r;
4420 vtop->r2 = VT_CONST;
4421 vtop->c = *vc;
4424 /* push integer constant */
4425 void vpushi(int v)
4427 CValue cval;
4428 cval.i = v;
4429 vsetc(&int_type, VT_CONST, &cval);
4432 /* Return a static symbol pointing to a section */
4433 static Sym *get_sym_ref(CType *type, Section *sec,
4434 unsigned long offset, unsigned long size)
4436 int v;
4437 Sym *sym;
4439 v = anon_sym++;
4440 sym = global_identifier_push(v, type->t | VT_STATIC, 0);
4441 sym->type.ref = type->ref;
4442 sym->r = VT_CONST | VT_SYM;
4443 put_extern_sym(sym, sec, offset, size);
4444 return sym;
4447 /* push a reference to a section offset by adding a dummy symbol */
4448 static void vpush_ref(CType *type, Section *sec, unsigned long offset, unsigned long size)
4450 CValue cval;
4452 cval.ul = 0;
4453 vsetc(type, VT_CONST | VT_SYM, &cval);
4454 vtop->sym = get_sym_ref(type, sec, offset, size);
4457 /* define a new external reference to a symbol 'v' of type 'u' */
4458 static Sym *external_global_sym(int v, CType *type, int r)
4460 Sym *s;
4462 s = sym_find(v);
4463 if (!s) {
4464 /* push forward reference */
4465 s = global_identifier_push(v, type->t | VT_EXTERN, 0);
4466 s->type.ref = type->ref;
4467 s->r = r | VT_CONST | VT_SYM;
4469 return s;
4472 /* define a new external reference to a symbol 'v' of type 'u' */
4473 static Sym *external_sym(int v, CType *type, int r)
4475 Sym *s;
4477 s = sym_find(v);
4478 if (!s) {
4479 /* push forward reference */
4480 s = sym_push(v, type, r | VT_CONST | VT_SYM, 0);
4481 s->type.t |= VT_EXTERN;
4482 } else {
4483 if (!is_compatible_types(&s->type, type))
4484 error("incompatible types for redefinition of '%s'",
4485 get_tok_str(v, NULL));
4487 return s;
4490 /* push a reference to global symbol v */
4491 static void vpush_global_sym(CType *type, int v)
4493 Sym *sym;
4494 CValue cval;
4496 sym = external_global_sym(v, type, 0);
4497 cval.ul = 0;
4498 vsetc(type, VT_CONST | VT_SYM, &cval);
4499 vtop->sym = sym;
4502 void vset(CType *type, int r, int v)
4504 CValue cval;
4506 cval.i = v;
4507 vsetc(type, r, &cval);
4510 void vseti(int r, int v)
4512 CType type;
4513 type.t = VT_INT;
4514 vset(&type, r, v);
4517 void vswap(void)
4519 SValue tmp;
4521 tmp = vtop[0];
4522 vtop[0] = vtop[-1];
4523 vtop[-1] = tmp;
4526 void vpushv(SValue *v)
4528 if (vtop >= vstack + (VSTACK_SIZE - 1))
4529 error("memory full");
4530 vtop++;
4531 *vtop = *v;
4534 void vdup(void)
4536 vpushv(vtop);
4539 /* save r to the memory stack, and mark it as being free */
4540 void save_reg(int r)
4542 int l, saved, size, align;
4543 SValue *p, sv;
4544 CType *type;
4546 /* modify all stack values */
4547 saved = 0;
4548 l = 0;
4549 for(p=vstack;p<=vtop;p++) {
4550 if ((p->r & VT_VALMASK) == r ||
4551 (p->r2 & VT_VALMASK) == r) {
4552 /* must save value on stack if not already done */
4553 if (!saved) {
4554 /* NOTE: must reload 'r' because r might be equal to r2 */
4555 r = p->r & VT_VALMASK;
4556 /* store register in the stack */
4557 type = &p->type;
4558 if ((p->r & VT_LVAL) ||
4559 (!is_float(type->t) && (type->t & VT_BTYPE) != VT_LLONG))
4560 type = &int_type;
4561 size = type_size(type, &align);
4562 loc = (loc - size) & -align;
4563 sv.type.t = type->t;
4564 sv.r = VT_LOCAL | VT_LVAL;
4565 sv.c.ul = loc;
4566 store(r, &sv);
4567 #ifdef TCC_TARGET_I386
4568 /* x86 specific: need to pop fp register ST0 if saved */
4569 if (r == TREG_ST0) {
4570 o(0xd9dd); /* fstp %st(1) */
4572 #endif
4573 /* special long long case */
4574 if ((type->t & VT_BTYPE) == VT_LLONG) {
4575 sv.c.ul += 4;
4576 store(p->r2, &sv);
4578 l = loc;
4579 saved = 1;
4581 /* mark that stack entry as being saved on the stack */
4582 if (p->r & VT_LVAL) {
4583 /* also clear the bounded flag because the
4584 relocation address of the function was stored in
4585 p->c.ul */
4586 p->r = (p->r & ~(VT_VALMASK | VT_BOUNDED)) | VT_LLOCAL;
4587 } else {
4588 p->r = lvalue_type(p->type.t) | VT_LOCAL;
4590 p->r2 = VT_CONST;
4591 p->c.ul = l;
4596 /* find a register of class 'rc2' with at most one reference on stack.
4597 * If none, call get_reg(rc) */
4598 int get_reg_ex(int rc, int rc2)
4600 int r;
4601 SValue *p;
4603 for(r=0;r<NB_REGS;r++) {
4604 if (reg_classes[r] & rc2) {
4605 int n;
4606 n=0;
4607 for(p = vstack; p <= vtop; p++) {
4608 if ((p->r & VT_VALMASK) == r ||
4609 (p->r2 & VT_VALMASK) == r)
4610 n++;
4612 if (n <= 1)
4613 return r;
4616 return get_reg(rc);
4619 /* find a free register of class 'rc'. If none, save one register */
4620 int get_reg(int rc)
4622 int r;
4623 SValue *p;
4625 /* find a free register */
4626 for(r=0;r<NB_REGS;r++) {
4627 if (reg_classes[r] & rc) {
4628 for(p=vstack;p<=vtop;p++) {
4629 if ((p->r & VT_VALMASK) == r ||
4630 (p->r2 & VT_VALMASK) == r)
4631 goto notfound;
4633 return r;
4635 notfound: ;
4638 /* no register left : free the first one on the stack (VERY
4639 IMPORTANT to start from the bottom to ensure that we don't
4640 spill registers used in gen_opi()) */
4641 for(p=vstack;p<=vtop;p++) {
4642 r = p->r & VT_VALMASK;
4643 if (r < VT_CONST && (reg_classes[r] & rc))
4644 goto save_found;
4645 /* also look at second register (if long long) */
4646 r = p->r2 & VT_VALMASK;
4647 if (r < VT_CONST && (reg_classes[r] & rc)) {
4648 save_found:
4649 save_reg(r);
4650 return r;
4653 /* Should never comes here */
4654 return -1;
4657 /* save registers up to (vtop - n) stack entry */
4658 void save_regs(int n)
4660 int r;
4661 SValue *p, *p1;
4662 p1 = vtop - n;
4663 for(p = vstack;p <= p1; p++) {
4664 r = p->r & VT_VALMASK;
4665 if (r < VT_CONST) {
4666 save_reg(r);
4671 /* move register 's' to 'r', and flush previous value of r to memory
4672 if needed */
4673 void move_reg(int r, int s)
4675 SValue sv;
4677 if (r != s) {
4678 save_reg(r);
4679 sv.type.t = VT_INT;
4680 sv.r = s;
4681 sv.c.ul = 0;
4682 load(r, &sv);
4686 /* get address of vtop (vtop MUST BE an lvalue) */
4687 void gaddrof(void)
4689 vtop->r &= ~VT_LVAL;
4690 /* tricky: if saved lvalue, then we can go back to lvalue */
4691 if ((vtop->r & VT_VALMASK) == VT_LLOCAL)
4692 vtop->r = (vtop->r & ~(VT_VALMASK | VT_LVAL_TYPE)) | VT_LOCAL | VT_LVAL;
4695 #ifdef CONFIG_TCC_BCHECK
4696 /* generate lvalue bound code */
4697 void gbound(void)
4699 int lval_type;
4700 CType type1;
4702 vtop->r &= ~VT_MUSTBOUND;
4703 /* if lvalue, then use checking code before dereferencing */
4704 if (vtop->r & VT_LVAL) {
4705 /* if not VT_BOUNDED value, then make one */
4706 if (!(vtop->r & VT_BOUNDED)) {
4707 lval_type = vtop->r & (VT_LVAL_TYPE | VT_LVAL);
4708 /* must save type because we must set it to int to get pointer */
4709 type1 = vtop->type;
4710 vtop->type.t = VT_INT;
4711 gaddrof();
4712 vpushi(0);
4713 gen_bounded_ptr_add();
4714 vtop->r |= lval_type;
4715 vtop->type = type1;
4717 /* then check for dereferencing */
4718 gen_bounded_ptr_deref();
4721 #endif
4723 /* store vtop a register belonging to class 'rc'. lvalues are
4724 converted to values. Cannot be used if cannot be converted to
4725 register value (such as structures). */
4726 int gv(int rc)
4728 int r, r2, rc2, bit_pos, bit_size, size, align, i;
4729 unsigned long long ll;
4731 /* NOTE: get_reg can modify vstack[] */
4732 if (vtop->type.t & VT_BITFIELD) {
4733 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
4734 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
4735 /* remove bit field info to avoid loops */
4736 vtop->type.t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
4737 /* generate shifts */
4738 vpushi(32 - (bit_pos + bit_size));
4739 gen_op(TOK_SHL);
4740 vpushi(32 - bit_size);
4741 /* NOTE: transformed to SHR if unsigned */
4742 gen_op(TOK_SAR);
4743 r = gv(rc);
4744 } else {
4745 if (is_float(vtop->type.t) &&
4746 (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4747 Sym *sym;
4748 int *ptr;
4749 unsigned long offset;
4751 /* XXX: unify with initializers handling ? */
4752 /* CPUs usually cannot use float constants, so we store them
4753 generically in data segment */
4754 size = type_size(&vtop->type, &align);
4755 offset = (data_section->data_offset + align - 1) & -align;
4756 data_section->data_offset = offset;
4757 /* XXX: not portable yet */
4758 ptr = section_ptr_add(data_section, size);
4759 size = size >> 2;
4760 for(i=0;i<size;i++)
4761 ptr[i] = vtop->c.tab[i];
4762 sym = get_sym_ref(&vtop->type, data_section, offset, size << 2);
4763 vtop->r |= VT_LVAL | VT_SYM;
4764 vtop->sym = sym;
4765 vtop->c.ul = 0;
4767 #ifdef CONFIG_TCC_BCHECK
4768 if (vtop->r & VT_MUSTBOUND)
4769 gbound();
4770 #endif
4772 r = vtop->r & VT_VALMASK;
4773 /* need to reload if:
4774 - constant
4775 - lvalue (need to dereference pointer)
4776 - already a register, but not in the right class */
4777 if (r >= VT_CONST ||
4778 (vtop->r & VT_LVAL) ||
4779 !(reg_classes[r] & rc) ||
4780 ((vtop->type.t & VT_BTYPE) == VT_LLONG &&
4781 !(reg_classes[vtop->r2] & rc))) {
4782 r = get_reg(rc);
4783 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
4784 /* two register type load : expand to two words
4785 temporarily */
4786 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4787 /* load constant */
4788 ll = vtop->c.ull;
4789 vtop->c.ui = ll; /* first word */
4790 load(r, vtop);
4791 vtop->r = r; /* save register value */
4792 vpushi(ll >> 32); /* second word */
4793 } else if (r >= VT_CONST || /* XXX: test to VT_CONST incorrect ? */
4794 (vtop->r & VT_LVAL)) {
4795 /* We do not want to modifier the long long
4796 pointer here, so the safest (and less
4797 efficient) is to save all the other registers
4798 in the stack. XXX: totally inefficient. */
4799 save_regs(1);
4800 /* load from memory */
4801 load(r, vtop);
4802 vdup();
4803 vtop[-1].r = r; /* save register value */
4804 /* increment pointer to get second word */
4805 vtop->type.t = VT_INT;
4806 gaddrof();
4807 vpushi(4);
4808 gen_op('+');
4809 vtop->r |= VT_LVAL;
4810 } else {
4811 /* move registers */
4812 load(r, vtop);
4813 vdup();
4814 vtop[-1].r = r; /* save register value */
4815 vtop->r = vtop[-1].r2;
4817 /* allocate second register */
4818 rc2 = RC_INT;
4819 if (rc == RC_IRET)
4820 rc2 = RC_LRET;
4821 r2 = get_reg(rc2);
4822 load(r2, vtop);
4823 vpop();
4824 /* write second register */
4825 vtop->r2 = r2;
4826 } else if ((vtop->r & VT_LVAL) && !is_float(vtop->type.t)) {
4827 int t1, t;
4828 /* lvalue of scalar type : need to use lvalue type
4829 because of possible cast */
4830 t = vtop->type.t;
4831 t1 = t;
4832 /* compute memory access type */
4833 if (vtop->r & VT_LVAL_BYTE)
4834 t = VT_BYTE;
4835 else if (vtop->r & VT_LVAL_SHORT)
4836 t = VT_SHORT;
4837 if (vtop->r & VT_LVAL_UNSIGNED)
4838 t |= VT_UNSIGNED;
4839 vtop->type.t = t;
4840 load(r, vtop);
4841 /* restore wanted type */
4842 vtop->type.t = t1;
4843 } else {
4844 /* one register type load */
4845 load(r, vtop);
4848 vtop->r = r;
4849 #ifdef TCC_TARGET_C67
4850 /* uses register pairs for doubles */
4851 if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE)
4852 vtop->r2 = r+1;
4853 #endif
4855 return r;
4858 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
4859 void gv2(int rc1, int rc2)
4861 int v;
4863 /* generate more generic register first. But VT_JMP or VT_CMP
4864 values must be generated first in all cases to avoid possible
4865 reload errors */
4866 v = vtop[0].r & VT_VALMASK;
4867 if (v != VT_CMP && (v & ~1) != VT_JMP && rc1 <= rc2) {
4868 vswap();
4869 gv(rc1);
4870 vswap();
4871 gv(rc2);
4872 /* test if reload is needed for first register */
4873 if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
4874 vswap();
4875 gv(rc1);
4876 vswap();
4878 } else {
4879 gv(rc2);
4880 vswap();
4881 gv(rc1);
4882 vswap();
4883 /* test if reload is needed for first register */
4884 if ((vtop[0].r & VT_VALMASK) >= VT_CONST) {
4885 gv(rc2);
4890 /* expand long long on stack in two int registers */
4891 void lexpand(void)
4893 int u;
4895 u = vtop->type.t & VT_UNSIGNED;
4896 gv(RC_INT);
4897 vdup();
4898 vtop[0].r = vtop[-1].r2;
4899 vtop[0].r2 = VT_CONST;
4900 vtop[-1].r2 = VT_CONST;
4901 vtop[0].type.t = VT_INT | u;
4902 vtop[-1].type.t = VT_INT | u;
4905 #ifdef TCC_TARGET_ARM
4906 /* expand long long on stack */
4907 void lexpand_nr(void)
4909 int u,v;
4911 u = vtop->type.t & VT_UNSIGNED;
4912 vdup();
4913 vtop->r2 = VT_CONST;
4914 vtop->type.t = VT_INT | u;
4915 v=vtop[-1].r & (VT_VALMASK | VT_LVAL);
4916 if (v == VT_CONST) {
4917 vtop[-1].c.ui = vtop->c.ull;
4918 vtop->c.ui = vtop->c.ull >> 32;
4919 vtop->r = VT_CONST;
4920 } else if (v == (VT_LVAL|VT_CONST) || v == (VT_LVAL|VT_LOCAL)) {
4921 vtop->c.ui += 4;
4922 vtop->r = vtop[-1].r;
4923 } else if (v > VT_CONST) {
4924 vtop--;
4925 lexpand();
4926 } else
4927 vtop->r = vtop[-1].r2;
4928 vtop[-1].r2 = VT_CONST;
4929 vtop[-1].type.t = VT_INT | u;
4931 #endif
4933 /* build a long long from two ints */
4934 void lbuild(int t)
4936 gv2(RC_INT, RC_INT);
4937 vtop[-1].r2 = vtop[0].r;
4938 vtop[-1].type.t = t;
4939 vpop();
4942 /* rotate n first stack elements to the bottom
4943 I1 ... In -> I2 ... In I1 [top is right]
4945 void vrotb(int n)
4947 int i;
4948 SValue tmp;
4950 tmp = vtop[-n + 1];
4951 for(i=-n+1;i!=0;i++)
4952 vtop[i] = vtop[i+1];
4953 vtop[0] = tmp;
4956 /* rotate n first stack elements to the top
4957 I1 ... In -> In I1 ... I(n-1) [top is right]
4959 void vrott(int n)
4961 int i;
4962 SValue tmp;
4964 tmp = vtop[0];
4965 for(i = 0;i < n - 1; i++)
4966 vtop[-i] = vtop[-i - 1];
4967 vtop[-n + 1] = tmp;
4970 #ifdef TCC_TARGET_ARM
4971 /* like vrott but in other direction
4972 In ... I1 -> I(n-1) ... I1 In [top is right]
4974 void vnrott(int n)
4976 int i;
4977 SValue tmp;
4979 tmp = vtop[-n + 1];
4980 for(i = n - 1; i > 0; i--)
4981 vtop[-i] = vtop[-i + 1];
4982 vtop[0] = tmp;
4984 #endif
4986 /* pop stack value */
4987 void vpop(void)
4989 int v;
4990 v = vtop->r & VT_VALMASK;
4991 #ifdef TCC_TARGET_I386
4992 /* for x86, we need to pop the FP stack */
4993 if (v == TREG_ST0 && !nocode_wanted) {
4994 o(0xd9dd); /* fstp %st(1) */
4995 } else
4996 #endif
4997 if (v == VT_JMP || v == VT_JMPI) {
4998 /* need to put correct jump if && or || without test */
4999 gsym(vtop->c.ul);
5001 vtop--;
5004 /* convert stack entry to register and duplicate its value in another
5005 register */
5006 void gv_dup(void)
5008 int rc, t, r, r1;
5009 SValue sv;
5011 t = vtop->type.t;
5012 if ((t & VT_BTYPE) == VT_LLONG) {
5013 lexpand();
5014 gv_dup();
5015 vswap();
5016 vrotb(3);
5017 gv_dup();
5018 vrotb(4);
5019 /* stack: H L L1 H1 */
5020 lbuild(t);
5021 vrotb(3);
5022 vrotb(3);
5023 vswap();
5024 lbuild(t);
5025 vswap();
5026 } else {
5027 /* duplicate value */
5028 rc = RC_INT;
5029 sv.type.t = VT_INT;
5030 if (is_float(t)) {
5031 rc = RC_FLOAT;
5032 sv.type.t = t;
5034 r = gv(rc);
5035 r1 = get_reg(rc);
5036 sv.r = r;
5037 sv.c.ul = 0;
5038 load(r1, &sv); /* move r to r1 */
5039 vdup();
5040 /* duplicates value */
5041 vtop->r = r1;
5045 /* generate CPU independent (unsigned) long long operations */
5046 void gen_opl(int op)
5048 int t, a, b, op1, c, i;
5049 int func;
5050 SValue tmp;
5052 switch(op) {
5053 case '/':
5054 case TOK_PDIV:
5055 func = TOK___divdi3;
5056 goto gen_func;
5057 case TOK_UDIV:
5058 func = TOK___udivdi3;
5059 goto gen_func;
5060 case '%':
5061 func = TOK___moddi3;
5062 goto gen_func;
5063 case TOK_UMOD:
5064 func = TOK___umoddi3;
5065 gen_func:
5066 /* call generic long long function */
5067 vpush_global_sym(&func_old_type, func);
5068 vrott(3);
5069 gfunc_call(2);
5070 vpushi(0);
5071 vtop->r = REG_IRET;
5072 vtop->r2 = REG_LRET;
5073 break;
5074 case '^':
5075 case '&':
5076 case '|':
5077 case '*':
5078 case '+':
5079 case '-':
5080 t = vtop->type.t;
5081 vswap();
5082 lexpand();
5083 vrotb(3);
5084 lexpand();
5085 /* stack: L1 H1 L2 H2 */
5086 tmp = vtop[0];
5087 vtop[0] = vtop[-3];
5088 vtop[-3] = tmp;
5089 tmp = vtop[-2];
5090 vtop[-2] = vtop[-3];
5091 vtop[-3] = tmp;
5092 vswap();
5093 /* stack: H1 H2 L1 L2 */
5094 if (op == '*') {
5095 vpushv(vtop - 1);
5096 vpushv(vtop - 1);
5097 gen_op(TOK_UMULL);
5098 lexpand();
5099 /* stack: H1 H2 L1 L2 ML MH */
5100 for(i=0;i<4;i++)
5101 vrotb(6);
5102 /* stack: ML MH H1 H2 L1 L2 */
5103 tmp = vtop[0];
5104 vtop[0] = vtop[-2];
5105 vtop[-2] = tmp;
5106 /* stack: ML MH H1 L2 H2 L1 */
5107 gen_op('*');
5108 vrotb(3);
5109 vrotb(3);
5110 gen_op('*');
5111 /* stack: ML MH M1 M2 */
5112 gen_op('+');
5113 gen_op('+');
5114 } else if (op == '+' || op == '-') {
5115 /* XXX: add non carry method too (for MIPS or alpha) */
5116 if (op == '+')
5117 op1 = TOK_ADDC1;
5118 else
5119 op1 = TOK_SUBC1;
5120 gen_op(op1);
5121 /* stack: H1 H2 (L1 op L2) */
5122 vrotb(3);
5123 vrotb(3);
5124 gen_op(op1 + 1); /* TOK_xxxC2 */
5125 } else {
5126 gen_op(op);
5127 /* stack: H1 H2 (L1 op L2) */
5128 vrotb(3);
5129 vrotb(3);
5130 /* stack: (L1 op L2) H1 H2 */
5131 gen_op(op);
5132 /* stack: (L1 op L2) (H1 op H2) */
5134 /* stack: L H */
5135 lbuild(t);
5136 break;
5137 case TOK_SAR:
5138 case TOK_SHR:
5139 case TOK_SHL:
5140 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
5141 t = vtop[-1].type.t;
5142 vswap();
5143 lexpand();
5144 vrotb(3);
5145 /* stack: L H shift */
5146 c = (int)vtop->c.i;
5147 /* constant: simpler */
5148 /* NOTE: all comments are for SHL. the other cases are
5149 done by swaping words */
5150 vpop();
5151 if (op != TOK_SHL)
5152 vswap();
5153 if (c >= 32) {
5154 /* stack: L H */
5155 vpop();
5156 if (c > 32) {
5157 vpushi(c - 32);
5158 gen_op(op);
5160 if (op != TOK_SAR) {
5161 vpushi(0);
5162 } else {
5163 gv_dup();
5164 vpushi(31);
5165 gen_op(TOK_SAR);
5167 vswap();
5168 } else {
5169 vswap();
5170 gv_dup();
5171 /* stack: H L L */
5172 vpushi(c);
5173 gen_op(op);
5174 vswap();
5175 vpushi(32 - c);
5176 if (op == TOK_SHL)
5177 gen_op(TOK_SHR);
5178 else
5179 gen_op(TOK_SHL);
5180 vrotb(3);
5181 /* stack: L L H */
5182 vpushi(c);
5183 if (op == TOK_SHL)
5184 gen_op(TOK_SHL);
5185 else
5186 gen_op(TOK_SHR);
5187 gen_op('|');
5189 if (op != TOK_SHL)
5190 vswap();
5191 lbuild(t);
5192 } else {
5193 /* XXX: should provide a faster fallback on x86 ? */
5194 switch(op) {
5195 case TOK_SAR:
5196 func = TOK___sardi3;
5197 goto gen_func;
5198 case TOK_SHR:
5199 func = TOK___shrdi3;
5200 goto gen_func;
5201 case TOK_SHL:
5202 func = TOK___shldi3;
5203 goto gen_func;
5206 break;
5207 default:
5208 /* compare operations */
5209 t = vtop->type.t;
5210 vswap();
5211 lexpand();
5212 vrotb(3);
5213 lexpand();
5214 /* stack: L1 H1 L2 H2 */
5215 tmp = vtop[-1];
5216 vtop[-1] = vtop[-2];
5217 vtop[-2] = tmp;
5218 /* stack: L1 L2 H1 H2 */
5219 /* compare high */
5220 op1 = op;
5221 /* when values are equal, we need to compare low words. since
5222 the jump is inverted, we invert the test too. */
5223 if (op1 == TOK_LT)
5224 op1 = TOK_LE;
5225 else if (op1 == TOK_GT)
5226 op1 = TOK_GE;
5227 else if (op1 == TOK_ULT)
5228 op1 = TOK_ULE;
5229 else if (op1 == TOK_UGT)
5230 op1 = TOK_UGE;
5231 a = 0;
5232 b = 0;
5233 gen_op(op1);
5234 if (op1 != TOK_NE) {
5235 a = gtst(1, 0);
5237 if (op != TOK_EQ) {
5238 /* generate non equal test */
5239 /* XXX: NOT PORTABLE yet */
5240 if (a == 0) {
5241 b = gtst(0, 0);
5242 } else {
5243 #if defined(TCC_TARGET_I386)
5244 b = psym(0x850f, 0);
5245 #elif defined(TCC_TARGET_ARM)
5246 b = ind;
5247 o(0x1A000000 | encbranch(ind, 0, 1));
5248 #elif defined(TCC_TARGET_C67)
5249 error("not implemented");
5250 #else
5251 #error not supported
5252 #endif
5255 /* compare low. Always unsigned */
5256 op1 = op;
5257 if (op1 == TOK_LT)
5258 op1 = TOK_ULT;
5259 else if (op1 == TOK_LE)
5260 op1 = TOK_ULE;
5261 else if (op1 == TOK_GT)
5262 op1 = TOK_UGT;
5263 else if (op1 == TOK_GE)
5264 op1 = TOK_UGE;
5265 gen_op(op1);
5266 a = gtst(1, a);
5267 gsym(b);
5268 vseti(VT_JMPI, a);
5269 break;
5273 /* handle integer constant optimizations and various machine
5274 independent opt */
5275 void gen_opic(int op)
5277 int fc, c1, c2, n;
5278 SValue *v1, *v2;
5280 v1 = vtop - 1;
5281 v2 = vtop;
5282 /* currently, we cannot do computations with forward symbols */
5283 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5284 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5285 if (c1 && c2) {
5286 fc = v2->c.i;
5287 switch(op) {
5288 case '+': v1->c.i += fc; break;
5289 case '-': v1->c.i -= fc; break;
5290 case '&': v1->c.i &= fc; break;
5291 case '^': v1->c.i ^= fc; break;
5292 case '|': v1->c.i |= fc; break;
5293 case '*': v1->c.i *= fc; break;
5295 case TOK_PDIV:
5296 case '/':
5297 case '%':
5298 case TOK_UDIV:
5299 case TOK_UMOD:
5300 /* if division by zero, generate explicit division */
5301 if (fc == 0) {
5302 if (const_wanted)
5303 error("division by zero in constant");
5304 goto general_case;
5306 switch(op) {
5307 default: v1->c.i /= fc; break;
5308 case '%': v1->c.i %= fc; break;
5309 case TOK_UDIV: v1->c.i = (unsigned)v1->c.i / fc; break;
5310 case TOK_UMOD: v1->c.i = (unsigned)v1->c.i % fc; break;
5312 break;
5313 case TOK_SHL: v1->c.i <<= fc; break;
5314 case TOK_SHR: v1->c.i = (unsigned)v1->c.i >> fc; break;
5315 case TOK_SAR: v1->c.i >>= fc; break;
5316 /* tests */
5317 case TOK_ULT: v1->c.i = (unsigned)v1->c.i < (unsigned)fc; break;
5318 case TOK_UGE: v1->c.i = (unsigned)v1->c.i >= (unsigned)fc; break;
5319 case TOK_EQ: v1->c.i = v1->c.i == fc; break;
5320 case TOK_NE: v1->c.i = v1->c.i != fc; break;
5321 case TOK_ULE: v1->c.i = (unsigned)v1->c.i <= (unsigned)fc; break;
5322 case TOK_UGT: v1->c.i = (unsigned)v1->c.i > (unsigned)fc; break;
5323 case TOK_LT: v1->c.i = v1->c.i < fc; break;
5324 case TOK_GE: v1->c.i = v1->c.i >= fc; break;
5325 case TOK_LE: v1->c.i = v1->c.i <= fc; break;
5326 case TOK_GT: v1->c.i = v1->c.i > fc; break;
5327 /* logical */
5328 case TOK_LAND: v1->c.i = v1->c.i && fc; break;
5329 case TOK_LOR: v1->c.i = v1->c.i || fc; break;
5330 default:
5331 goto general_case;
5333 vtop--;
5334 } else {
5335 /* if commutative ops, put c2 as constant */
5336 if (c1 && (op == '+' || op == '&' || op == '^' ||
5337 op == '|' || op == '*')) {
5338 vswap();
5339 swap(&c1, &c2);
5341 fc = vtop->c.i;
5342 if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
5343 op == TOK_PDIV) &&
5344 fc == 1) ||
5345 ((op == '+' || op == '-' || op == '|' || op == '^' ||
5346 op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
5347 fc == 0) ||
5348 (op == '&' &&
5349 fc == -1))) {
5350 /* nothing to do */
5351 vtop--;
5352 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
5353 /* try to use shifts instead of muls or divs */
5354 if (fc > 0 && (fc & (fc - 1)) == 0) {
5355 n = -1;
5356 while (fc) {
5357 fc >>= 1;
5358 n++;
5360 vtop->c.i = n;
5361 if (op == '*')
5362 op = TOK_SHL;
5363 else if (op == TOK_PDIV)
5364 op = TOK_SAR;
5365 else
5366 op = TOK_SHR;
5368 goto general_case;
5369 } else if (c2 && (op == '+' || op == '-') &&
5370 (vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) ==
5371 (VT_CONST | VT_SYM)) {
5372 /* symbol + constant case */
5373 if (op == '-')
5374 fc = -fc;
5375 vtop--;
5376 vtop->c.i += fc;
5377 } else {
5378 general_case:
5379 if (!nocode_wanted) {
5380 /* call low level op generator */
5381 gen_opi(op);
5382 } else {
5383 vtop--;
5389 /* generate a floating point operation with constant propagation */
5390 void gen_opif(int op)
5392 int c1, c2;
5393 SValue *v1, *v2;
5394 long double f1, f2;
5396 v1 = vtop - 1;
5397 v2 = vtop;
5398 /* currently, we cannot do computations with forward symbols */
5399 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5400 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5401 if (c1 && c2) {
5402 if (v1->type.t == VT_FLOAT) {
5403 f1 = v1->c.f;
5404 f2 = v2->c.f;
5405 } else if (v1->type.t == VT_DOUBLE) {
5406 f1 = v1->c.d;
5407 f2 = v2->c.d;
5408 } else {
5409 f1 = v1->c.ld;
5410 f2 = v2->c.ld;
5413 /* NOTE: we only do constant propagation if finite number (not
5414 NaN or infinity) (ANSI spec) */
5415 if (!ieee_finite(f1) || !ieee_finite(f2))
5416 goto general_case;
5418 switch(op) {
5419 case '+': f1 += f2; break;
5420 case '-': f1 -= f2; break;
5421 case '*': f1 *= f2; break;
5422 case '/':
5423 if (f2 == 0.0) {
5424 if (const_wanted)
5425 error("division by zero in constant");
5426 goto general_case;
5428 f1 /= f2;
5429 break;
5430 /* XXX: also handles tests ? */
5431 default:
5432 goto general_case;
5434 /* XXX: overflow test ? */
5435 if (v1->type.t == VT_FLOAT) {
5436 v1->c.f = f1;
5437 } else if (v1->type.t == VT_DOUBLE) {
5438 v1->c.d = f1;
5439 } else {
5440 v1->c.ld = f1;
5442 vtop--;
5443 } else {
5444 general_case:
5445 if (!nocode_wanted) {
5446 gen_opf(op);
5447 } else {
5448 vtop--;
5453 static int pointed_size(CType *type)
5455 int align;
5456 return type_size(pointed_type(type), &align);
5459 static inline int is_null_pointer(SValue *p)
5461 if ((p->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
5462 return 0;
5463 return ((p->type.t & VT_BTYPE) == VT_INT && p->c.i == 0) ||
5464 ((p->type.t & VT_BTYPE) == VT_LLONG && p->c.ll == 0);
5467 static inline int is_integer_btype(int bt)
5469 return (bt == VT_BYTE || bt == VT_SHORT ||
5470 bt == VT_INT || bt == VT_LLONG);
5473 /* check types for comparison or substraction of pointers */
5474 static void check_comparison_pointer_types(SValue *p1, SValue *p2, int op)
5476 CType *type1, *type2, tmp_type1, tmp_type2;
5477 int bt1, bt2;
5479 /* null pointers are accepted for all comparisons as gcc */
5480 if (is_null_pointer(p1) || is_null_pointer(p2))
5481 return;
5482 type1 = &p1->type;
5483 type2 = &p2->type;
5484 bt1 = type1->t & VT_BTYPE;
5485 bt2 = type2->t & VT_BTYPE;
5486 /* accept comparison between pointer and integer with a warning */
5487 if ((is_integer_btype(bt1) || is_integer_btype(bt2)) && op != '-') {
5488 warning("comparison between pointer and integer");
5489 return;
5492 /* both must be pointers or implicit function pointers */
5493 if (bt1 == VT_PTR) {
5494 type1 = pointed_type(type1);
5495 } else if (bt1 != VT_FUNC)
5496 goto invalid_operands;
5498 if (bt2 == VT_PTR) {
5499 type2 = pointed_type(type2);
5500 } else if (bt2 != VT_FUNC) {
5501 invalid_operands:
5502 error("invalid operands to binary %s", get_tok_str(op, NULL));
5504 if ((type1->t & VT_BTYPE) == VT_VOID ||
5505 (type2->t & VT_BTYPE) == VT_VOID)
5506 return;
5507 tmp_type1 = *type1;
5508 tmp_type2 = *type2;
5509 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5510 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5511 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
5512 /* gcc-like error if '-' is used */
5513 if (op == '-')
5514 goto invalid_operands;
5515 else
5516 warning("comparison of distinct pointer types lacks a cast");
5520 /* generic gen_op: handles types problems */
5521 void gen_op(int op)
5523 int u, t1, t2, bt1, bt2, t;
5524 CType type1;
5526 t1 = vtop[-1].type.t;
5527 t2 = vtop[0].type.t;
5528 bt1 = t1 & VT_BTYPE;
5529 bt2 = t2 & VT_BTYPE;
5531 if (bt1 == VT_PTR || bt2 == VT_PTR) {
5532 /* at least one operand is a pointer */
5533 /* relationnal op: must be both pointers */
5534 if (op >= TOK_ULT && op <= TOK_GT) {
5535 check_comparison_pointer_types(vtop - 1, vtop, op);
5536 /* pointers are handled are unsigned */
5537 t = VT_INT | VT_UNSIGNED;
5538 goto std_op;
5540 /* if both pointers, then it must be the '-' op */
5541 if (bt1 == VT_PTR && bt2 == VT_PTR) {
5542 if (op != '-')
5543 error("cannot use pointers here");
5544 check_comparison_pointer_types(vtop - 1, vtop, op);
5545 /* XXX: check that types are compatible */
5546 u = pointed_size(&vtop[-1].type);
5547 gen_opic(op);
5548 /* set to integer type */
5549 vtop->type.t = VT_INT;
5550 vpushi(u);
5551 gen_op(TOK_PDIV);
5552 } else {
5553 /* exactly one pointer : must be '+' or '-'. */
5554 if (op != '-' && op != '+')
5555 error("cannot use pointers here");
5556 /* Put pointer as first operand */
5557 if (bt2 == VT_PTR) {
5558 vswap();
5559 swap(&t1, &t2);
5561 type1 = vtop[-1].type;
5562 /* XXX: cast to int ? (long long case) */
5563 vpushi(pointed_size(&vtop[-1].type));
5564 gen_op('*');
5565 #ifdef CONFIG_TCC_BCHECK
5566 /* if evaluating constant expression, no code should be
5567 generated, so no bound check */
5568 if (do_bounds_check && !const_wanted) {
5569 /* if bounded pointers, we generate a special code to
5570 test bounds */
5571 if (op == '-') {
5572 vpushi(0);
5573 vswap();
5574 gen_op('-');
5576 gen_bounded_ptr_add();
5577 } else
5578 #endif
5580 gen_opic(op);
5582 /* put again type if gen_opic() swaped operands */
5583 vtop->type = type1;
5585 } else if (is_float(bt1) || is_float(bt2)) {
5586 /* compute bigger type and do implicit casts */
5587 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
5588 t = VT_LDOUBLE;
5589 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
5590 t = VT_DOUBLE;
5591 } else {
5592 t = VT_FLOAT;
5594 /* floats can only be used for a few operations */
5595 if (op != '+' && op != '-' && op != '*' && op != '/' &&
5596 (op < TOK_ULT || op > TOK_GT))
5597 error("invalid operands for binary operation");
5598 goto std_op;
5599 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
5600 /* cast to biggest op */
5601 t = VT_LLONG;
5602 /* convert to unsigned if it does not fit in a long long */
5603 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
5604 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
5605 t |= VT_UNSIGNED;
5606 goto std_op;
5607 } else {
5608 /* integer operations */
5609 t = VT_INT;
5610 /* convert to unsigned if it does not fit in an integer */
5611 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
5612 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
5613 t |= VT_UNSIGNED;
5614 std_op:
5615 /* XXX: currently, some unsigned operations are explicit, so
5616 we modify them here */
5617 if (t & VT_UNSIGNED) {
5618 if (op == TOK_SAR)
5619 op = TOK_SHR;
5620 else if (op == '/')
5621 op = TOK_UDIV;
5622 else if (op == '%')
5623 op = TOK_UMOD;
5624 else if (op == TOK_LT)
5625 op = TOK_ULT;
5626 else if (op == TOK_GT)
5627 op = TOK_UGT;
5628 else if (op == TOK_LE)
5629 op = TOK_ULE;
5630 else if (op == TOK_GE)
5631 op = TOK_UGE;
5633 vswap();
5634 type1.t = t;
5635 gen_cast(&type1);
5636 vswap();
5637 /* special case for shifts and long long: we keep the shift as
5638 an integer */
5639 if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL)
5640 type1.t = VT_INT;
5641 gen_cast(&type1);
5642 if (is_float(t))
5643 gen_opif(op);
5644 else if ((t & VT_BTYPE) == VT_LLONG)
5645 gen_opl(op);
5646 else
5647 gen_opic(op);
5648 if (op >= TOK_ULT && op <= TOK_GT) {
5649 /* relationnal op: the result is an int */
5650 vtop->type.t = VT_INT;
5651 } else {
5652 vtop->type.t = t;
5657 /* generic itof for unsigned long long case */
5658 void gen_cvt_itof1(int t)
5660 if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
5661 (VT_LLONG | VT_UNSIGNED)) {
5663 if (t == VT_FLOAT)
5664 vpush_global_sym(&func_old_type, TOK___ulltof);
5665 else if (t == VT_DOUBLE)
5666 vpush_global_sym(&func_old_type, TOK___ulltod);
5667 else
5668 vpush_global_sym(&func_old_type, TOK___ulltold);
5669 vrott(2);
5670 gfunc_call(1);
5671 vpushi(0);
5672 vtop->r = REG_FRET;
5673 } else {
5674 gen_cvt_itof(t);
5678 /* generic ftoi for unsigned long long case */
5679 void gen_cvt_ftoi1(int t)
5681 int st;
5683 if (t == (VT_LLONG | VT_UNSIGNED)) {
5684 /* not handled natively */
5685 st = vtop->type.t & VT_BTYPE;
5686 if (st == VT_FLOAT)
5687 vpush_global_sym(&func_old_type, TOK___fixunssfdi);
5688 else if (st == VT_DOUBLE)
5689 vpush_global_sym(&func_old_type, TOK___fixunsdfdi);
5690 else
5691 vpush_global_sym(&func_old_type, TOK___fixunsxfdi);
5692 vrott(2);
5693 gfunc_call(1);
5694 vpushi(0);
5695 vtop->r = REG_IRET;
5696 vtop->r2 = REG_LRET;
5697 } else {
5698 gen_cvt_ftoi(t);
5702 /* force char or short cast */
5703 void force_charshort_cast(int t)
5705 int bits, dbt;
5706 dbt = t & VT_BTYPE;
5707 /* XXX: add optimization if lvalue : just change type and offset */
5708 if (dbt == VT_BYTE)
5709 bits = 8;
5710 else
5711 bits = 16;
5712 if (t & VT_UNSIGNED) {
5713 vpushi((1 << bits) - 1);
5714 gen_op('&');
5715 } else {
5716 bits = 32 - bits;
5717 vpushi(bits);
5718 gen_op(TOK_SHL);
5719 vpushi(bits);
5720 gen_op(TOK_SAR);
5724 /* cast 'vtop' to 'type'. Casting to bitfields is forbidden. */
5725 static void gen_cast(CType *type)
5727 int sbt, dbt, sf, df, c;
5729 /* special delayed cast for char/short */
5730 /* XXX: in some cases (multiple cascaded casts), it may still
5731 be incorrect */
5732 if (vtop->r & VT_MUSTCAST) {
5733 vtop->r &= ~VT_MUSTCAST;
5734 force_charshort_cast(vtop->type.t);
5737 /* bitfields first get cast to ints */
5738 if (vtop->type.t & VT_BITFIELD) {
5739 gv(RC_INT);
5742 dbt = type->t & (VT_BTYPE | VT_UNSIGNED);
5743 sbt = vtop->type.t & (VT_BTYPE | VT_UNSIGNED);
5745 if (sbt != dbt && !nocode_wanted) {
5746 sf = is_float(sbt);
5747 df = is_float(dbt);
5748 c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5749 if (sf && df) {
5750 /* convert from fp to fp */
5751 if (c) {
5752 /* constant case: we can do it now */
5753 /* XXX: in ISOC, cannot do it if error in convert */
5754 if (dbt == VT_FLOAT && sbt == VT_DOUBLE)
5755 vtop->c.f = (float)vtop->c.d;
5756 else if (dbt == VT_FLOAT && sbt == VT_LDOUBLE)
5757 vtop->c.f = (float)vtop->c.ld;
5758 else if (dbt == VT_DOUBLE && sbt == VT_FLOAT)
5759 vtop->c.d = (double)vtop->c.f;
5760 else if (dbt == VT_DOUBLE && sbt == VT_LDOUBLE)
5761 vtop->c.d = (double)vtop->c.ld;
5762 else if (dbt == VT_LDOUBLE && sbt == VT_FLOAT)
5763 vtop->c.ld = (long double)vtop->c.f;
5764 else if (dbt == VT_LDOUBLE && sbt == VT_DOUBLE)
5765 vtop->c.ld = (long double)vtop->c.d;
5766 } else {
5767 /* non constant case: generate code */
5768 gen_cvt_ftof(dbt);
5770 } else if (df) {
5771 /* convert int to fp */
5772 if (c) {
5773 switch(sbt) {
5774 case VT_LLONG | VT_UNSIGNED:
5775 case VT_LLONG:
5776 /* XXX: add const cases for long long */
5777 goto do_itof;
5778 case VT_INT | VT_UNSIGNED:
5779 switch(dbt) {
5780 case VT_FLOAT: vtop->c.f = (float)vtop->c.ui; break;
5781 case VT_DOUBLE: vtop->c.d = (double)vtop->c.ui; break;
5782 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.ui; break;
5784 break;
5785 default:
5786 switch(dbt) {
5787 case VT_FLOAT: vtop->c.f = (float)vtop->c.i; break;
5788 case VT_DOUBLE: vtop->c.d = (double)vtop->c.i; break;
5789 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.i; break;
5791 break;
5793 } else {
5794 do_itof:
5795 #if !defined(TCC_TARGET_ARM)
5796 gen_cvt_itof1(dbt);
5797 #else
5798 gen_cvt_itof(dbt);
5799 #endif
5801 } else if (sf) {
5802 /* convert fp to int */
5803 /* we handle char/short/etc... with generic code */
5804 if (dbt != (VT_INT | VT_UNSIGNED) &&
5805 dbt != (VT_LLONG | VT_UNSIGNED) &&
5806 dbt != VT_LLONG)
5807 dbt = VT_INT;
5808 if (c) {
5809 switch(dbt) {
5810 case VT_LLONG | VT_UNSIGNED:
5811 case VT_LLONG:
5812 /* XXX: add const cases for long long */
5813 goto do_ftoi;
5814 case VT_INT | VT_UNSIGNED:
5815 switch(sbt) {
5816 case VT_FLOAT: vtop->c.ui = (unsigned int)vtop->c.d; break;
5817 case VT_DOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
5818 case VT_LDOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
5820 break;
5821 default:
5822 /* int case */
5823 switch(sbt) {
5824 case VT_FLOAT: vtop->c.i = (int)vtop->c.d; break;
5825 case VT_DOUBLE: vtop->c.i = (int)vtop->c.d; break;
5826 case VT_LDOUBLE: vtop->c.i = (int)vtop->c.d; break;
5828 break;
5830 } else {
5831 do_ftoi:
5832 gen_cvt_ftoi1(dbt);
5834 if (dbt == VT_INT && (type->t & (VT_BTYPE | VT_UNSIGNED)) != dbt) {
5835 /* additional cast for char/short/bool... */
5836 vtop->type.t = dbt;
5837 gen_cast(type);
5839 } else if ((dbt & VT_BTYPE) == VT_LLONG) {
5840 if ((sbt & VT_BTYPE) != VT_LLONG) {
5841 /* scalar to long long */
5842 if (c) {
5843 if (sbt == (VT_INT | VT_UNSIGNED))
5844 vtop->c.ll = vtop->c.ui;
5845 else
5846 vtop->c.ll = vtop->c.i;
5847 } else {
5848 /* machine independent conversion */
5849 gv(RC_INT);
5850 /* generate high word */
5851 if (sbt == (VT_INT | VT_UNSIGNED)) {
5852 vpushi(0);
5853 gv(RC_INT);
5854 } else {
5855 gv_dup();
5856 vpushi(31);
5857 gen_op(TOK_SAR);
5859 /* patch second register */
5860 vtop[-1].r2 = vtop->r;
5861 vpop();
5864 } else if (dbt == VT_BOOL) {
5865 /* scalar to bool */
5866 vpushi(0);
5867 gen_op(TOK_NE);
5868 } else if ((dbt & VT_BTYPE) == VT_BYTE ||
5869 (dbt & VT_BTYPE) == VT_SHORT) {
5870 force_charshort_cast(dbt);
5871 } else if ((dbt & VT_BTYPE) == VT_INT) {
5872 /* scalar to int */
5873 if (sbt == VT_LLONG) {
5874 /* from long long: just take low order word */
5875 lexpand();
5876 vpop();
5878 /* if lvalue and single word type, nothing to do because
5879 the lvalue already contains the real type size (see
5880 VT_LVAL_xxx constants) */
5883 vtop->type = *type;
5886 /* return type size. Put alignment at 'a' */
5887 static int type_size(CType *type, int *a)
5889 Sym *s;
5890 int bt;
5892 bt = type->t & VT_BTYPE;
5893 if (bt == VT_STRUCT) {
5894 /* struct/union */
5895 s = type->ref;
5896 *a = s->r;
5897 return s->c;
5898 } else if (bt == VT_PTR) {
5899 if (type->t & VT_ARRAY) {
5900 s = type->ref;
5901 return type_size(&s->type, a) * s->c;
5902 } else {
5903 *a = PTR_SIZE;
5904 return PTR_SIZE;
5906 } else if (bt == VT_LDOUBLE) {
5907 *a = LDOUBLE_ALIGN;
5908 return LDOUBLE_SIZE;
5909 } else if (bt == VT_DOUBLE || bt == VT_LLONG) {
5910 #ifdef TCC_TARGET_I386
5911 *a = 4;
5912 #else
5913 *a = 8;
5914 #endif
5915 return 8;
5916 } else if (bt == VT_INT || bt == VT_ENUM || bt == VT_FLOAT) {
5917 *a = 4;
5918 return 4;
5919 } else if (bt == VT_SHORT) {
5920 *a = 2;
5921 return 2;
5922 } else {
5923 /* char, void, function, _Bool */
5924 *a = 1;
5925 return 1;
5929 /* return the pointed type of t */
5930 static inline CType *pointed_type(CType *type)
5932 return &type->ref->type;
5935 /* modify type so that its it is a pointer to type. */
5936 static void mk_pointer(CType *type)
5938 Sym *s;
5939 s = sym_push(SYM_FIELD, type, 0, -1);
5940 type->t = VT_PTR | (type->t & ~VT_TYPE);
5941 type->ref = s;
5944 /* compare function types. OLD functions match any new functions */
5945 static int is_compatible_func(CType *type1, CType *type2)
5947 Sym *s1, *s2;
5949 s1 = type1->ref;
5950 s2 = type2->ref;
5951 if (!is_compatible_types(&s1->type, &s2->type))
5952 return 0;
5953 /* check func_call */
5954 if (s1->r != s2->r)
5955 return 0;
5956 /* XXX: not complete */
5957 if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
5958 return 1;
5959 if (s1->c != s2->c)
5960 return 0;
5961 while (s1 != NULL) {
5962 if (s2 == NULL)
5963 return 0;
5964 if (!is_compatible_types(&s1->type, &s2->type))
5965 return 0;
5966 s1 = s1->next;
5967 s2 = s2->next;
5969 if (s2)
5970 return 0;
5971 return 1;
5974 /* return true if type1 and type2 are exactly the same (including
5975 qualifiers).
5977 - enums are not checked as gcc __builtin_types_compatible_p ()
5979 static int is_compatible_types(CType *type1, CType *type2)
5981 int bt1, t1, t2;
5983 t1 = type1->t & VT_TYPE;
5984 t2 = type2->t & VT_TYPE;
5985 /* XXX: bitfields ? */
5986 if (t1 != t2)
5987 return 0;
5988 /* test more complicated cases */
5989 bt1 = t1 & VT_BTYPE;
5990 if (bt1 == VT_PTR) {
5991 type1 = pointed_type(type1);
5992 type2 = pointed_type(type2);
5993 return is_compatible_types(type1, type2);
5994 } else if (bt1 == VT_STRUCT) {
5995 return (type1->ref == type2->ref);
5996 } else if (bt1 == VT_FUNC) {
5997 return is_compatible_func(type1, type2);
5998 } else {
5999 return 1;
6003 /* print a type. If 'varstr' is not NULL, then the variable is also
6004 printed in the type */
6005 /* XXX: union */
6006 /* XXX: add array and function pointers */
6007 void type_to_str(char *buf, int buf_size,
6008 CType *type, const char *varstr)
6010 int bt, v, t;
6011 Sym *s, *sa;
6012 char buf1[256];
6013 const char *tstr;
6015 t = type->t & VT_TYPE;
6016 bt = t & VT_BTYPE;
6017 buf[0] = '\0';
6018 if (t & VT_CONSTANT)
6019 pstrcat(buf, buf_size, "const ");
6020 if (t & VT_VOLATILE)
6021 pstrcat(buf, buf_size, "volatile ");
6022 if (t & VT_UNSIGNED)
6023 pstrcat(buf, buf_size, "unsigned ");
6024 switch(bt) {
6025 case VT_VOID:
6026 tstr = "void";
6027 goto add_tstr;
6028 case VT_BOOL:
6029 tstr = "_Bool";
6030 goto add_tstr;
6031 case VT_BYTE:
6032 tstr = "char";
6033 goto add_tstr;
6034 case VT_SHORT:
6035 tstr = "short";
6036 goto add_tstr;
6037 case VT_INT:
6038 tstr = "int";
6039 goto add_tstr;
6040 case VT_LONG:
6041 tstr = "long";
6042 goto add_tstr;
6043 case VT_LLONG:
6044 tstr = "long long";
6045 goto add_tstr;
6046 case VT_FLOAT:
6047 tstr = "float";
6048 goto add_tstr;
6049 case VT_DOUBLE:
6050 tstr = "double";
6051 goto add_tstr;
6052 case VT_LDOUBLE:
6053 tstr = "long double";
6054 add_tstr:
6055 pstrcat(buf, buf_size, tstr);
6056 break;
6057 case VT_ENUM:
6058 case VT_STRUCT:
6059 if (bt == VT_STRUCT)
6060 tstr = "struct ";
6061 else
6062 tstr = "enum ";
6063 pstrcat(buf, buf_size, tstr);
6064 v = type->ref->v & ~SYM_STRUCT;
6065 if (v >= SYM_FIRST_ANOM)
6066 pstrcat(buf, buf_size, "<anonymous>");
6067 else
6068 pstrcat(buf, buf_size, get_tok_str(v, NULL));
6069 break;
6070 case VT_FUNC:
6071 s = type->ref;
6072 type_to_str(buf, buf_size, &s->type, varstr);
6073 pstrcat(buf, buf_size, "(");
6074 sa = s->next;
6075 while (sa != NULL) {
6076 type_to_str(buf1, sizeof(buf1), &sa->type, NULL);
6077 pstrcat(buf, buf_size, buf1);
6078 sa = sa->next;
6079 if (sa)
6080 pstrcat(buf, buf_size, ", ");
6082 pstrcat(buf, buf_size, ")");
6083 goto no_var;
6084 case VT_PTR:
6085 s = type->ref;
6086 pstrcpy(buf1, sizeof(buf1), "*");
6087 if (varstr)
6088 pstrcat(buf1, sizeof(buf1), varstr);
6089 type_to_str(buf, buf_size, &s->type, buf1);
6090 goto no_var;
6092 if (varstr) {
6093 pstrcat(buf, buf_size, " ");
6094 pstrcat(buf, buf_size, varstr);
6096 no_var: ;
6099 /* verify type compatibility to store vtop in 'dt' type, and generate
6100 casts if needed. */
6101 static void gen_assign_cast(CType *dt)
6103 CType *st, *type1, *type2, tmp_type1, tmp_type2;
6104 char buf1[256], buf2[256];
6105 int dbt, sbt;
6107 st = &vtop->type; /* source type */
6108 dbt = dt->t & VT_BTYPE;
6109 sbt = st->t & VT_BTYPE;
6110 if (dt->t & VT_CONSTANT)
6111 warning("assignment of read-only location");
6112 switch(dbt) {
6113 case VT_PTR:
6114 /* special cases for pointers */
6115 /* '0' can also be a pointer */
6116 if (is_null_pointer(vtop))
6117 goto type_ok;
6118 /* accept implicit pointer to integer cast with warning */
6119 if (is_integer_btype(sbt)) {
6120 warning("assignment makes pointer from integer without a cast");
6121 goto type_ok;
6123 type1 = pointed_type(dt);
6124 /* a function is implicitely a function pointer */
6125 if (sbt == VT_FUNC) {
6126 if ((type1->t & VT_BTYPE) != VT_VOID &&
6127 !is_compatible_types(pointed_type(dt), st))
6128 goto error;
6129 else
6130 goto type_ok;
6132 if (sbt != VT_PTR)
6133 goto error;
6134 type2 = pointed_type(st);
6135 if ((type1->t & VT_BTYPE) == VT_VOID ||
6136 (type2->t & VT_BTYPE) == VT_VOID) {
6137 /* void * can match anything */
6138 } else {
6139 /* exact type match, except for unsigned */
6140 tmp_type1 = *type1;
6141 tmp_type2 = *type2;
6142 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
6143 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
6144 if (!is_compatible_types(&tmp_type1, &tmp_type2))
6145 goto error;
6147 /* check const and volatile */
6148 if ((!(type1->t & VT_CONSTANT) && (type2->t & VT_CONSTANT)) ||
6149 (!(type1->t & VT_VOLATILE) && (type2->t & VT_VOLATILE)))
6150 warning("assignment discards qualifiers from pointer target type");
6151 break;
6152 case VT_BYTE:
6153 case VT_SHORT:
6154 case VT_INT:
6155 case VT_LLONG:
6156 if (sbt == VT_PTR || sbt == VT_FUNC) {
6157 warning("assignment makes integer from pointer without a cast");
6159 /* XXX: more tests */
6160 break;
6161 case VT_STRUCT:
6162 tmp_type1 = *dt;
6163 tmp_type2 = *st;
6164 tmp_type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
6165 tmp_type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
6166 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
6167 error:
6168 type_to_str(buf1, sizeof(buf1), st, NULL);
6169 type_to_str(buf2, sizeof(buf2), dt, NULL);
6170 error("cannot cast '%s' to '%s'", buf1, buf2);
6172 break;
6174 type_ok:
6175 gen_cast(dt);
6178 /* store vtop in lvalue pushed on stack */
6179 void vstore(void)
6181 int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
6183 ft = vtop[-1].type.t;
6184 sbt = vtop->type.t & VT_BTYPE;
6185 dbt = ft & VT_BTYPE;
6186 if (((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
6187 (sbt == VT_INT && dbt == VT_SHORT)) {
6188 /* optimize char/short casts */
6189 delayed_cast = VT_MUSTCAST;
6190 vtop->type.t = ft & VT_TYPE;
6191 /* XXX: factorize */
6192 if (ft & VT_CONSTANT)
6193 warning("assignment of read-only location");
6194 } else {
6195 delayed_cast = 0;
6196 if (!(ft & VT_BITFIELD))
6197 gen_assign_cast(&vtop[-1].type);
6200 if (sbt == VT_STRUCT) {
6201 /* if structure, only generate pointer */
6202 /* structure assignment : generate memcpy */
6203 /* XXX: optimize if small size */
6204 if (!nocode_wanted) {
6205 size = type_size(&vtop->type, &align);
6207 vpush_global_sym(&func_old_type, TOK_memcpy);
6209 /* destination */
6210 vpushv(vtop - 2);
6211 vtop->type.t = VT_INT;
6212 gaddrof();
6213 /* source */
6214 vpushv(vtop - 2);
6215 vtop->type.t = VT_INT;
6216 gaddrof();
6217 /* type size */
6218 vpushi(size);
6219 gfunc_call(3);
6221 vswap();
6222 vpop();
6223 } else {
6224 vswap();
6225 vpop();
6227 /* leave source on stack */
6228 } else if (ft & VT_BITFIELD) {
6229 /* bitfield store handling */
6230 bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
6231 bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
6232 /* remove bit field info to avoid loops */
6233 vtop[-1].type.t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
6235 /* duplicate destination */
6236 vdup();
6237 vtop[-1] = vtop[-2];
6239 /* mask and shift source */
6240 vpushi((1 << bit_size) - 1);
6241 gen_op('&');
6242 vpushi(bit_pos);
6243 gen_op(TOK_SHL);
6244 /* load destination, mask and or with source */
6245 vswap();
6246 vpushi(~(((1 << bit_size) - 1) << bit_pos));
6247 gen_op('&');
6248 gen_op('|');
6249 /* store result */
6250 vstore();
6251 } else {
6252 #ifdef CONFIG_TCC_BCHECK
6253 /* bound check case */
6254 if (vtop[-1].r & VT_MUSTBOUND) {
6255 vswap();
6256 gbound();
6257 vswap();
6259 #endif
6260 if (!nocode_wanted) {
6261 rc = RC_INT;
6262 if (is_float(ft))
6263 rc = RC_FLOAT;
6264 r = gv(rc); /* generate value */
6265 /* if lvalue was saved on stack, must read it */
6266 if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
6267 SValue sv;
6268 t = get_reg(RC_INT);
6269 sv.type.t = VT_INT;
6270 sv.r = VT_LOCAL | VT_LVAL;
6271 sv.c.ul = vtop[-1].c.ul;
6272 load(t, &sv);
6273 vtop[-1].r = t | VT_LVAL;
6275 store(r, vtop - 1);
6276 /* two word case handling : store second register at word + 4 */
6277 if ((ft & VT_BTYPE) == VT_LLONG) {
6278 vswap();
6279 /* convert to int to increment easily */
6280 vtop->type.t = VT_INT;
6281 gaddrof();
6282 vpushi(4);
6283 gen_op('+');
6284 vtop->r |= VT_LVAL;
6285 vswap();
6286 /* XXX: it works because r2 is spilled last ! */
6287 store(vtop->r2, vtop - 1);
6290 vswap();
6291 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
6292 vtop->r |= delayed_cast;
6296 /* post defines POST/PRE add. c is the token ++ or -- */
6297 void inc(int post, int c)
6299 test_lvalue();
6300 vdup(); /* save lvalue */
6301 if (post) {
6302 gv_dup(); /* duplicate value */
6303 vrotb(3);
6304 vrotb(3);
6306 /* add constant */
6307 vpushi(c - TOK_MID);
6308 gen_op('+');
6309 vstore(); /* store value */
6310 if (post)
6311 vpop(); /* if post op, return saved value */
6314 /* Parse GNUC __attribute__ extension. Currently, the following
6315 extensions are recognized:
6316 - aligned(n) : set data/function alignment.
6317 - packed : force data alignment to 1
6318 - section(x) : generate data/code in this section.
6319 - unused : currently ignored, but may be used someday.
6320 - regparm(n) : pass function parameters in registers (i386 only)
6322 static void parse_attribute(AttributeDef *ad)
6324 int t, n;
6326 while (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) {
6327 next();
6328 skip('(');
6329 skip('(');
6330 while (tok != ')') {
6331 if (tok < TOK_IDENT)
6332 expect("attribute name");
6333 t = tok;
6334 next();
6335 switch(t) {
6336 case TOK_SECTION1:
6337 case TOK_SECTION2:
6338 skip('(');
6339 if (tok != TOK_STR)
6340 expect("section name");
6341 ad->section = find_section(tcc_state, (char *)tokc.cstr->data);
6342 next();
6343 skip(')');
6344 break;
6345 case TOK_ALIGNED1:
6346 case TOK_ALIGNED2:
6347 if (tok == '(') {
6348 next();
6349 n = expr_const();
6350 if (n <= 0 || (n & (n - 1)) != 0)
6351 error("alignment must be a positive power of two");
6352 skip(')');
6353 } else {
6354 n = MAX_ALIGN;
6356 ad->aligned = n;
6357 break;
6358 case TOK_PACKED1:
6359 case TOK_PACKED2:
6360 ad->packed = 1;
6361 break;
6362 case TOK_UNUSED1:
6363 case TOK_UNUSED2:
6364 /* currently, no need to handle it because tcc does not
6365 track unused objects */
6366 break;
6367 case TOK_NORETURN1:
6368 case TOK_NORETURN2:
6369 /* currently, no need to handle it because tcc does not
6370 track unused objects */
6371 break;
6372 case TOK_CDECL1:
6373 case TOK_CDECL2:
6374 case TOK_CDECL3:
6375 ad->func_call = FUNC_CDECL;
6376 break;
6377 case TOK_STDCALL1:
6378 case TOK_STDCALL2:
6379 case TOK_STDCALL3:
6380 ad->func_call = FUNC_STDCALL;
6381 break;
6382 #ifdef TCC_TARGET_I386
6383 case TOK_REGPARM1:
6384 case TOK_REGPARM2:
6385 skip('(');
6386 n = expr_const();
6387 if (n > 3)
6388 n = 3;
6389 else if (n < 0)
6390 n = 0;
6391 if (n > 0)
6392 ad->func_call = FUNC_FASTCALL1 + n - 1;
6393 skip(')');
6394 break;
6395 #endif
6396 case TOK_DLLEXPORT:
6397 ad->dllexport = 1;
6398 break;
6399 default:
6400 if (tcc_state->warn_unsupported)
6401 warning("'%s' attribute ignored", get_tok_str(t, NULL));
6402 /* skip parameters */
6403 /* XXX: skip parenthesis too */
6404 if (tok == '(') {
6405 next();
6406 while (tok != ')' && tok != -1)
6407 next();
6408 next();
6410 break;
6412 if (tok != ',')
6413 break;
6414 next();
6416 skip(')');
6417 skip(')');
6421 /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
6422 static void struct_decl(CType *type, int u)
6424 int a, v, size, align, maxalign, c, offset;
6425 int bit_size, bit_pos, bsize, bt, lbit_pos;
6426 Sym *s, *ss, **ps;
6427 AttributeDef ad;
6428 CType type1, btype;
6430 a = tok; /* save decl type */
6431 next();
6432 if (tok != '{') {
6433 v = tok;
6434 next();
6435 /* struct already defined ? return it */
6436 if (v < TOK_IDENT)
6437 expect("struct/union/enum name");
6438 s = struct_find(v);
6439 if (s) {
6440 if (s->type.t != a)
6441 error("invalid type");
6442 goto do_decl;
6444 } else {
6445 v = anon_sym++;
6447 type1.t = a;
6448 /* we put an undefined size for struct/union */
6449 s = sym_push(v | SYM_STRUCT, &type1, 0, -1);
6450 s->r = 0; /* default alignment is zero as gcc */
6451 /* put struct/union/enum name in type */
6452 do_decl:
6453 type->t = u;
6454 type->ref = s;
6456 if (tok == '{') {
6457 next();
6458 if (s->c != -1)
6459 error("struct/union/enum already defined");
6460 /* cannot be empty */
6461 c = 0;
6462 /* non empty enums are not allowed */
6463 if (a == TOK_ENUM) {
6464 for(;;) {
6465 v = tok;
6466 if (v < TOK_UIDENT)
6467 expect("identifier");
6468 next();
6469 if (tok == '=') {
6470 next();
6471 c = expr_const();
6473 /* enum symbols have static storage */
6474 ss = sym_push(v, &int_type, VT_CONST, c);
6475 ss->type.t |= VT_STATIC;
6476 if (tok != ',')
6477 break;
6478 next();
6479 c++;
6480 /* NOTE: we accept a trailing comma */
6481 if (tok == '}')
6482 break;
6484 skip('}');
6485 } else {
6486 maxalign = 1;
6487 ps = &s->next;
6488 bit_pos = 0;
6489 offset = 0;
6490 while (tok != '}') {
6491 parse_btype(&btype, &ad);
6492 while (1) {
6493 bit_size = -1;
6494 v = 0;
6495 type1 = btype;
6496 if (tok != ':') {
6497 type_decl(&type1, &ad, &v, TYPE_DIRECT);
6498 if ((type1.t & VT_BTYPE) == VT_FUNC ||
6499 (type1.t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN | VT_INLINE)))
6500 error("invalid type for '%s'",
6501 get_tok_str(v, NULL));
6503 if (tok == ':') {
6504 next();
6505 bit_size = expr_const();
6506 /* XXX: handle v = 0 case for messages */
6507 if (bit_size < 0)
6508 error("negative width in bit-field '%s'",
6509 get_tok_str(v, NULL));
6510 if (v && bit_size == 0)
6511 error("zero width for bit-field '%s'",
6512 get_tok_str(v, NULL));
6514 size = type_size(&type1, &align);
6515 if (ad.aligned) {
6516 if (align < ad.aligned)
6517 align = ad.aligned;
6518 } else if (ad.packed) {
6519 align = 1;
6520 } else if (*tcc_state->pack_stack_ptr) {
6521 if (align > *tcc_state->pack_stack_ptr)
6522 align = *tcc_state->pack_stack_ptr;
6524 lbit_pos = 0;
6525 if (bit_size >= 0) {
6526 bt = type1.t & VT_BTYPE;
6527 if (bt != VT_INT &&
6528 bt != VT_BYTE &&
6529 bt != VT_SHORT &&
6530 bt != VT_BOOL &&
6531 bt != VT_ENUM)
6532 error("bitfields must have scalar type");
6533 bsize = size * 8;
6534 if (bit_size > bsize) {
6535 error("width of '%s' exceeds its type",
6536 get_tok_str(v, NULL));
6537 } else if (bit_size == bsize) {
6538 /* no need for bit fields */
6539 bit_pos = 0;
6540 } else if (bit_size == 0) {
6541 /* XXX: what to do if only padding in a
6542 structure ? */
6543 /* zero size: means to pad */
6544 if (bit_pos > 0)
6545 bit_pos = bsize;
6546 } else {
6547 /* we do not have enough room ? */
6548 if ((bit_pos + bit_size) > bsize)
6549 bit_pos = 0;
6550 lbit_pos = bit_pos;
6551 /* XXX: handle LSB first */
6552 type1.t |= VT_BITFIELD |
6553 (bit_pos << VT_STRUCT_SHIFT) |
6554 (bit_size << (VT_STRUCT_SHIFT + 6));
6555 bit_pos += bit_size;
6557 } else {
6558 bit_pos = 0;
6560 if (v) {
6561 /* add new memory data only if starting
6562 bit field */
6563 if (lbit_pos == 0) {
6564 if (a == TOK_STRUCT) {
6565 c = (c + align - 1) & -align;
6566 offset = c;
6567 c += size;
6568 } else {
6569 offset = 0;
6570 if (size > c)
6571 c = size;
6573 if (align > maxalign)
6574 maxalign = align;
6576 #if 0
6577 printf("add field %s offset=%d",
6578 get_tok_str(v, NULL), offset);
6579 if (type1.t & VT_BITFIELD) {
6580 printf(" pos=%d size=%d",
6581 (type1.t >> VT_STRUCT_SHIFT) & 0x3f,
6582 (type1.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
6584 printf("\n");
6585 #endif
6586 ss = sym_push(v | SYM_FIELD, &type1, 0, offset);
6587 *ps = ss;
6588 ps = &ss->next;
6590 if (tok == ';' || tok == TOK_EOF)
6591 break;
6592 skip(',');
6594 skip(';');
6596 skip('}');
6597 /* store size and alignment */
6598 s->c = (c + maxalign - 1) & -maxalign;
6599 s->r = maxalign;
6604 /* return 0 if no type declaration. otherwise, return the basic type
6605 and skip it.
6607 static int parse_btype(CType *type, AttributeDef *ad)
6609 int t, u, type_found, typespec_found;
6610 Sym *s;
6611 CType type1;
6613 memset(ad, 0, sizeof(AttributeDef));
6614 type_found = 0;
6615 typespec_found = 0;
6616 t = 0;
6617 while(1) {
6618 switch(tok) {
6619 case TOK_EXTENSION:
6620 /* currently, we really ignore extension */
6621 next();
6622 continue;
6624 /* basic types */
6625 case TOK_CHAR:
6626 u = VT_BYTE;
6627 basic_type:
6628 next();
6629 basic_type1:
6630 if ((t & VT_BTYPE) != 0)
6631 error("too many basic types");
6632 t |= u;
6633 typespec_found = 1;
6634 break;
6635 case TOK_VOID:
6636 u = VT_VOID;
6637 goto basic_type;
6638 case TOK_SHORT:
6639 u = VT_SHORT;
6640 goto basic_type;
6641 case TOK_INT:
6642 next();
6643 typespec_found = 1;
6644 break;
6645 case TOK_LONG:
6646 next();
6647 if ((t & VT_BTYPE) == VT_DOUBLE) {
6648 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6649 } else if ((t & VT_BTYPE) == VT_LONG) {
6650 t = (t & ~VT_BTYPE) | VT_LLONG;
6651 } else {
6652 u = VT_LONG;
6653 goto basic_type1;
6655 break;
6656 case TOK_BOOL:
6657 u = VT_BOOL;
6658 goto basic_type;
6659 case TOK_FLOAT:
6660 u = VT_FLOAT;
6661 goto basic_type;
6662 case TOK_DOUBLE:
6663 next();
6664 if ((t & VT_BTYPE) == VT_LONG) {
6665 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6666 } else {
6667 u = VT_DOUBLE;
6668 goto basic_type1;
6670 break;
6671 case TOK_ENUM:
6672 struct_decl(&type1, VT_ENUM);
6673 basic_type2:
6674 u = type1.t;
6675 type->ref = type1.ref;
6676 goto basic_type1;
6677 case TOK_STRUCT:
6678 case TOK_UNION:
6679 struct_decl(&type1, VT_STRUCT);
6680 goto basic_type2;
6682 /* type modifiers */
6683 case TOK_CONST1:
6684 case TOK_CONST2:
6685 case TOK_CONST3:
6686 t |= VT_CONSTANT;
6687 next();
6688 break;
6689 case TOK_VOLATILE1:
6690 case TOK_VOLATILE2:
6691 case TOK_VOLATILE3:
6692 t |= VT_VOLATILE;
6693 next();
6694 break;
6695 case TOK_SIGNED1:
6696 case TOK_SIGNED2:
6697 case TOK_SIGNED3:
6698 typespec_found = 1;
6699 t |= VT_SIGNED;
6700 next();
6701 break;
6702 case TOK_REGISTER:
6703 case TOK_AUTO:
6704 case TOK_RESTRICT1:
6705 case TOK_RESTRICT2:
6706 case TOK_RESTRICT3:
6707 next();
6708 break;
6709 case TOK_UNSIGNED:
6710 t |= VT_UNSIGNED;
6711 next();
6712 typespec_found = 1;
6713 break;
6715 /* storage */
6716 case TOK_EXTERN:
6717 t |= VT_EXTERN;
6718 next();
6719 break;
6720 case TOK_STATIC:
6721 t |= VT_STATIC;
6722 next();
6723 break;
6724 case TOK_TYPEDEF:
6725 t |= VT_TYPEDEF;
6726 next();
6727 break;
6728 case TOK_INLINE1:
6729 case TOK_INLINE2:
6730 case TOK_INLINE3:
6731 t |= VT_INLINE;
6732 next();
6733 break;
6735 /* GNUC attribute */
6736 case TOK_ATTRIBUTE1:
6737 case TOK_ATTRIBUTE2:
6738 parse_attribute(ad);
6739 break;
6740 /* GNUC typeof */
6741 case TOK_TYPEOF1:
6742 case TOK_TYPEOF2:
6743 case TOK_TYPEOF3:
6744 next();
6745 parse_expr_type(&type1);
6746 goto basic_type2;
6747 default:
6748 if (typespec_found)
6749 goto the_end;
6750 s = sym_find(tok);
6751 if (!s || !(s->type.t & VT_TYPEDEF))
6752 goto the_end;
6753 t |= (s->type.t & ~VT_TYPEDEF);
6754 type->ref = s->type.ref;
6755 next();
6756 break;
6758 type_found = 1;
6760 the_end:
6761 if ((t & (VT_SIGNED|VT_UNSIGNED)) == (VT_SIGNED|VT_UNSIGNED))
6762 error("signed and unsigned modifier");
6763 if (tcc_state->char_is_unsigned) {
6764 if ((t & (VT_SIGNED|VT_UNSIGNED|VT_BTYPE)) == VT_BYTE)
6765 t |= VT_UNSIGNED;
6767 t &= ~VT_SIGNED;
6769 /* long is never used as type */
6770 if ((t & VT_BTYPE) == VT_LONG)
6771 t = (t & ~VT_BTYPE) | VT_INT;
6772 type->t = t;
6773 return type_found;
6776 /* convert a function parameter type (array to pointer and function to
6777 function pointer) */
6778 static inline void convert_parameter_type(CType *pt)
6780 /* remove const and volatile qualifiers (XXX: const could be used
6781 to indicate a const function parameter */
6782 pt->t &= ~(VT_CONSTANT | VT_VOLATILE);
6783 /* array must be transformed to pointer according to ANSI C */
6784 pt->t &= ~VT_ARRAY;
6785 if ((pt->t & VT_BTYPE) == VT_FUNC) {
6786 mk_pointer(pt);
6790 static void post_type(CType *type, AttributeDef *ad)
6792 int n, l, t1;
6793 Sym **plast, *s, *first;
6794 AttributeDef ad1;
6795 CType pt;
6797 if (tok == '(') {
6798 /* function declaration */
6799 next();
6800 l = 0;
6801 first = NULL;
6802 plast = &first;
6803 while (tok != ')') {
6804 /* read param name and compute offset */
6805 if (l != FUNC_OLD) {
6806 if (!parse_btype(&pt, &ad1)) {
6807 if (l) {
6808 error("invalid type");
6809 } else {
6810 l = FUNC_OLD;
6811 goto old_proto;
6814 l = FUNC_NEW;
6815 if ((pt.t & VT_BTYPE) == VT_VOID && tok == ')')
6816 break;
6817 type_decl(&pt, &ad1, &n, TYPE_DIRECT | TYPE_ABSTRACT);
6818 if ((pt.t & VT_BTYPE) == VT_VOID)
6819 error("parameter declared as void");
6820 } else {
6821 old_proto:
6822 n = tok;
6823 pt.t = VT_INT;
6824 next();
6826 convert_parameter_type(&pt);
6827 s = sym_push(n | SYM_FIELD, &pt, 0, 0);
6828 *plast = s;
6829 plast = &s->next;
6830 if (tok == ',') {
6831 next();
6832 if (l == FUNC_NEW && tok == TOK_DOTS) {
6833 l = FUNC_ELLIPSIS;
6834 next();
6835 break;
6839 /* if no parameters, then old type prototype */
6840 if (l == 0)
6841 l = FUNC_OLD;
6842 skip(')');
6843 t1 = type->t & VT_STORAGE;
6844 /* NOTE: const is ignored in returned type as it has a special
6845 meaning in gcc / C++ */
6846 type->t &= ~(VT_STORAGE | VT_CONSTANT);
6847 post_type(type, ad);
6848 /* we push a anonymous symbol which will contain the function prototype */
6849 s = sym_push(SYM_FIELD, type, ad->func_call, l);
6850 s->next = first;
6851 type->t = t1 | VT_FUNC;
6852 type->ref = s;
6853 } else if (tok == '[') {
6854 /* array definition */
6855 next();
6856 n = -1;
6857 if (tok != ']') {
6858 n = expr_const();
6859 if (n < 0)
6860 error("invalid array size");
6862 skip(']');
6863 /* parse next post type */
6864 t1 = type->t & VT_STORAGE;
6865 type->t &= ~VT_STORAGE;
6866 post_type(type, ad);
6868 /* we push a anonymous symbol which will contain the array
6869 element type */
6870 s = sym_push(SYM_FIELD, type, 0, n);
6871 type->t = t1 | VT_ARRAY | VT_PTR;
6872 type->ref = s;
6876 /* Parse a type declaration (except basic type), and return the type
6877 in 'type'. 'td' is a bitmask indicating which kind of type decl is
6878 expected. 'type' should contain the basic type. 'ad' is the
6879 attribute definition of the basic type. It can be modified by
6880 type_decl().
6882 static void type_decl(CType *type, AttributeDef *ad, int *v, int td)
6884 Sym *s;
6885 CType type1, *type2;
6886 int qualifiers;
6888 while (tok == '*') {
6889 qualifiers = 0;
6890 redo:
6891 next();
6892 switch(tok) {
6893 case TOK_CONST1:
6894 case TOK_CONST2:
6895 case TOK_CONST3:
6896 qualifiers |= VT_CONSTANT;
6897 goto redo;
6898 case TOK_VOLATILE1:
6899 case TOK_VOLATILE2:
6900 case TOK_VOLATILE3:
6901 qualifiers |= VT_VOLATILE;
6902 goto redo;
6903 case TOK_RESTRICT1:
6904 case TOK_RESTRICT2:
6905 case TOK_RESTRICT3:
6906 goto redo;
6908 mk_pointer(type);
6909 type->t |= qualifiers;
6912 /* XXX: clarify attribute handling */
6913 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6914 parse_attribute(ad);
6916 /* recursive type */
6917 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
6918 type1.t = 0; /* XXX: same as int */
6919 if (tok == '(') {
6920 next();
6921 /* XXX: this is not correct to modify 'ad' at this point, but
6922 the syntax is not clear */
6923 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6924 parse_attribute(ad);
6925 type_decl(&type1, ad, v, td);
6926 skip(')');
6927 } else {
6928 /* type identifier */
6929 if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
6930 *v = tok;
6931 next();
6932 } else {
6933 if (!(td & TYPE_ABSTRACT))
6934 expect("identifier");
6935 *v = 0;
6938 post_type(type, ad);
6939 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6940 parse_attribute(ad);
6941 if (!type1.t)
6942 return;
6943 /* append type at the end of type1 */
6944 type2 = &type1;
6945 for(;;) {
6946 s = type2->ref;
6947 type2 = &s->type;
6948 if (!type2->t) {
6949 *type2 = *type;
6950 break;
6953 *type = type1;
6956 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
6957 static int lvalue_type(int t)
6959 int bt, r;
6960 r = VT_LVAL;
6961 bt = t & VT_BTYPE;
6962 if (bt == VT_BYTE || bt == VT_BOOL)
6963 r |= VT_LVAL_BYTE;
6964 else if (bt == VT_SHORT)
6965 r |= VT_LVAL_SHORT;
6966 else
6967 return r;
6968 if (t & VT_UNSIGNED)
6969 r |= VT_LVAL_UNSIGNED;
6970 return r;
6973 /* indirection with full error checking and bound check */
6974 static void indir(void)
6976 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
6977 expect("pointer");
6978 if ((vtop->r & VT_LVAL) && !nocode_wanted)
6979 gv(RC_INT);
6980 vtop->type = *pointed_type(&vtop->type);
6981 /* an array is never an lvalue */
6982 if (!(vtop->type.t & VT_ARRAY)) {
6983 vtop->r |= lvalue_type(vtop->type.t);
6984 /* if bound checking, the referenced pointer must be checked */
6985 if (do_bounds_check)
6986 vtop->r |= VT_MUSTBOUND;
6990 /* pass a parameter to a function and do type checking and casting */
6991 static void gfunc_param_typed(Sym *func, Sym *arg)
6993 int func_type;
6994 CType type;
6996 func_type = func->c;
6997 if (func_type == FUNC_OLD ||
6998 (func_type == FUNC_ELLIPSIS && arg == NULL)) {
6999 /* default casting : only need to convert float to double */
7000 if ((vtop->type.t & VT_BTYPE) == VT_FLOAT) {
7001 type.t = VT_DOUBLE;
7002 gen_cast(&type);
7004 } else if (arg == NULL) {
7005 error("too many arguments to function");
7006 } else {
7007 type = arg->type;
7008 type.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
7009 gen_assign_cast(&type);
7013 /* parse an expression of the form '(type)' or '(expr)' and return its
7014 type */
7015 static void parse_expr_type(CType *type)
7017 int n;
7018 AttributeDef ad;
7020 skip('(');
7021 if (parse_btype(type, &ad)) {
7022 type_decl(type, &ad, &n, TYPE_ABSTRACT);
7023 } else {
7024 expr_type(type);
7026 skip(')');
7029 static void parse_type(CType *type)
7031 AttributeDef ad;
7032 int n;
7034 if (!parse_btype(type, &ad)) {
7035 expect("type");
7037 type_decl(type, &ad, &n, TYPE_ABSTRACT);
7040 static void vpush_tokc(int t)
7042 CType type;
7043 type.t = t;
7044 vsetc(&type, VT_CONST, &tokc);
7047 static void unary(void)
7049 int n, t, align, size, r;
7050 CType type;
7051 Sym *s;
7052 AttributeDef ad;
7054 /* XXX: GCC 2.95.3 does not generate a table although it should be
7055 better here */
7056 tok_next:
7057 switch(tok) {
7058 case TOK_EXTENSION:
7059 next();
7060 goto tok_next;
7061 case TOK_CINT:
7062 case TOK_CCHAR:
7063 case TOK_LCHAR:
7064 vpushi(tokc.i);
7065 next();
7066 break;
7067 case TOK_CUINT:
7068 vpush_tokc(VT_INT | VT_UNSIGNED);
7069 next();
7070 break;
7071 case TOK_CLLONG:
7072 vpush_tokc(VT_LLONG);
7073 next();
7074 break;
7075 case TOK_CULLONG:
7076 vpush_tokc(VT_LLONG | VT_UNSIGNED);
7077 next();
7078 break;
7079 case TOK_CFLOAT:
7080 vpush_tokc(VT_FLOAT);
7081 next();
7082 break;
7083 case TOK_CDOUBLE:
7084 vpush_tokc(VT_DOUBLE);
7085 next();
7086 break;
7087 case TOK_CLDOUBLE:
7088 vpush_tokc(VT_LDOUBLE);
7089 next();
7090 break;
7091 case TOK___FUNCTION__:
7092 if (!gnu_ext)
7093 goto tok_identifier;
7094 /* fall thru */
7095 case TOK___FUNC__:
7097 void *ptr;
7098 int len;
7099 /* special function name identifier */
7100 len = strlen(funcname) + 1;
7101 /* generate char[len] type */
7102 type.t = VT_BYTE;
7103 mk_pointer(&type);
7104 type.t |= VT_ARRAY;
7105 type.ref->c = len;
7106 vpush_ref(&type, data_section, data_section->data_offset, len);
7107 ptr = section_ptr_add(data_section, len);
7108 memcpy(ptr, funcname, len);
7109 next();
7111 break;
7112 case TOK_LSTR:
7113 t = VT_INT;
7114 goto str_init;
7115 case TOK_STR:
7116 /* string parsing */
7117 t = VT_BYTE;
7118 str_init:
7119 if (tcc_state->warn_write_strings)
7120 t |= VT_CONSTANT;
7121 type.t = t;
7122 mk_pointer(&type);
7123 type.t |= VT_ARRAY;
7124 memset(&ad, 0, sizeof(AttributeDef));
7125 decl_initializer_alloc(&type, &ad, VT_CONST, 2, 0, 0);
7126 break;
7127 case '(':
7128 next();
7129 /* cast ? */
7130 if (parse_btype(&type, &ad)) {
7131 type_decl(&type, &ad, &n, TYPE_ABSTRACT);
7132 skip(')');
7133 /* check ISOC99 compound literal */
7134 if (tok == '{') {
7135 /* data is allocated locally by default */
7136 if (global_expr)
7137 r = VT_CONST;
7138 else
7139 r = VT_LOCAL;
7140 /* all except arrays are lvalues */
7141 if (!(type.t & VT_ARRAY))
7142 r |= lvalue_type(type.t);
7143 memset(&ad, 0, sizeof(AttributeDef));
7144 decl_initializer_alloc(&type, &ad, r, 1, 0, 0);
7145 } else {
7146 unary();
7147 gen_cast(&type);
7149 } else if (tok == '{') {
7150 /* save all registers */
7151 save_regs(0);
7152 /* statement expression : we do not accept break/continue
7153 inside as GCC does */
7154 block(NULL, NULL, NULL, NULL, 0, 1);
7155 skip(')');
7156 } else {
7157 gexpr();
7158 skip(')');
7160 break;
7161 case '*':
7162 next();
7163 unary();
7164 indir();
7165 break;
7166 case '&':
7167 next();
7168 unary();
7169 /* functions names must be treated as function pointers,
7170 except for unary '&' and sizeof. Since we consider that
7171 functions are not lvalues, we only have to handle it
7172 there and in function calls. */
7173 /* arrays can also be used although they are not lvalues */
7174 if ((vtop->type.t & VT_BTYPE) != VT_FUNC &&
7175 !(vtop->type.t & VT_ARRAY))
7176 test_lvalue();
7177 mk_pointer(&vtop->type);
7178 gaddrof();
7179 break;
7180 case '!':
7181 next();
7182 unary();
7183 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST)
7184 vtop->c.i = !vtop->c.i;
7185 else if ((vtop->r & VT_VALMASK) == VT_CMP)
7186 vtop->c.i = vtop->c.i ^ 1;
7187 else
7188 vseti(VT_JMP, gtst(1, 0));
7189 break;
7190 case '~':
7191 next();
7192 unary();
7193 vpushi(-1);
7194 gen_op('^');
7195 break;
7196 case '+':
7197 next();
7198 /* in order to force cast, we add zero */
7199 unary();
7200 if ((vtop->type.t & VT_BTYPE) == VT_PTR)
7201 error("pointer not accepted for unary plus");
7202 vpushi(0);
7203 gen_op('+');
7204 break;
7205 case TOK_SIZEOF:
7206 case TOK_ALIGNOF1:
7207 case TOK_ALIGNOF2:
7208 t = tok;
7209 next();
7210 if (tok == '(') {
7211 parse_expr_type(&type);
7212 } else {
7213 unary_type(&type);
7215 size = type_size(&type, &align);
7216 if (t == TOK_SIZEOF) {
7217 if (size < 0)
7218 error("sizeof applied to an incomplete type");
7219 vpushi(size);
7220 } else {
7221 vpushi(align);
7223 break;
7225 case TOK_builtin_types_compatible_p:
7227 CType type1, type2;
7228 next();
7229 skip('(');
7230 parse_type(&type1);
7231 skip(',');
7232 parse_type(&type2);
7233 skip(')');
7234 type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
7235 type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
7236 vpushi(is_compatible_types(&type1, &type2));
7238 break;
7239 case TOK_builtin_constant_p:
7241 int saved_nocode_wanted, res;
7242 next();
7243 skip('(');
7244 saved_nocode_wanted = nocode_wanted;
7245 nocode_wanted = 1;
7246 gexpr();
7247 res = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
7248 vpop();
7249 nocode_wanted = saved_nocode_wanted;
7250 skip(')');
7251 vpushi(res);
7253 break;
7254 case TOK_INC:
7255 case TOK_DEC:
7256 t = tok;
7257 next();
7258 unary();
7259 inc(0, t);
7260 break;
7261 case '-':
7262 next();
7263 vpushi(0);
7264 unary();
7265 gen_op('-');
7266 break;
7267 case TOK_LAND:
7268 if (!gnu_ext)
7269 goto tok_identifier;
7270 next();
7271 /* allow to take the address of a label */
7272 if (tok < TOK_UIDENT)
7273 expect("label identifier");
7274 s = label_find(tok);
7275 if (!s) {
7276 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
7277 } else {
7278 if (s->r == LABEL_DECLARED)
7279 s->r = LABEL_FORWARD;
7281 if (!s->type.t) {
7282 s->type.t = VT_VOID;
7283 mk_pointer(&s->type);
7284 s->type.t |= VT_STATIC;
7286 vset(&s->type, VT_CONST | VT_SYM, 0);
7287 vtop->sym = s;
7288 next();
7289 break;
7290 default:
7291 tok_identifier:
7292 t = tok;
7293 next();
7294 if (t < TOK_UIDENT)
7295 expect("identifier");
7296 s = sym_find(t);
7297 if (!s) {
7298 if (tok != '(')
7299 error("'%s' undeclared", get_tok_str(t, NULL));
7300 /* for simple function calls, we tolerate undeclared
7301 external reference to int() function */
7302 if (tcc_state->warn_implicit_function_declaration)
7303 warning("implicit declaration of function '%s'",
7304 get_tok_str(t, NULL));
7305 s = external_global_sym(t, &func_old_type, 0);
7307 if ((s->type.t & (VT_STATIC | VT_INLINE | VT_BTYPE)) ==
7308 (VT_STATIC | VT_INLINE | VT_FUNC)) {
7309 /* if referencing an inline function, then we generate a
7310 symbol to it if not already done. It will have the
7311 effect to generate code for it at the end of the
7312 compilation unit. Inline function as always
7313 generated in the text section. */
7314 if (!s->c)
7315 put_extern_sym(s, text_section, 0, 0);
7316 r = VT_SYM | VT_CONST;
7317 } else {
7318 r = s->r;
7320 vset(&s->type, r, s->c);
7321 /* if forward reference, we must point to s */
7322 if (vtop->r & VT_SYM) {
7323 vtop->sym = s;
7324 vtop->c.ul = 0;
7326 break;
7329 /* post operations */
7330 while (1) {
7331 if (tok == TOK_INC || tok == TOK_DEC) {
7332 inc(1, tok);
7333 next();
7334 } else if (tok == '.' || tok == TOK_ARROW) {
7335 /* field */
7336 if (tok == TOK_ARROW)
7337 indir();
7338 test_lvalue();
7339 gaddrof();
7340 next();
7341 /* expect pointer on structure */
7342 if ((vtop->type.t & VT_BTYPE) != VT_STRUCT)
7343 expect("struct or union");
7344 s = vtop->type.ref;
7345 /* find field */
7346 tok |= SYM_FIELD;
7347 while ((s = s->next) != NULL) {
7348 if (s->v == tok)
7349 break;
7351 if (!s)
7352 error("field not found");
7353 /* add field offset to pointer */
7354 vtop->type = char_pointer_type; /* change type to 'char *' */
7355 vpushi(s->c);
7356 gen_op('+');
7357 /* change type to field type, and set to lvalue */
7358 vtop->type = s->type;
7359 /* an array is never an lvalue */
7360 if (!(vtop->type.t & VT_ARRAY)) {
7361 vtop->r |= lvalue_type(vtop->type.t);
7362 /* if bound checking, the referenced pointer must be checked */
7363 if (do_bounds_check)
7364 vtop->r |= VT_MUSTBOUND;
7366 next();
7367 } else if (tok == '[') {
7368 next();
7369 gexpr();
7370 gen_op('+');
7371 indir();
7372 skip(']');
7373 } else if (tok == '(') {
7374 SValue ret;
7375 Sym *sa;
7376 int nb_args;
7378 /* function call */
7379 if ((vtop->type.t & VT_BTYPE) != VT_FUNC) {
7380 /* pointer test (no array accepted) */
7381 if ((vtop->type.t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
7382 vtop->type = *pointed_type(&vtop->type);
7383 if ((vtop->type.t & VT_BTYPE) != VT_FUNC)
7384 goto error_func;
7385 } else {
7386 error_func:
7387 expect("function pointer");
7389 } else {
7390 vtop->r &= ~VT_LVAL; /* no lvalue */
7392 /* get return type */
7393 s = vtop->type.ref;
7394 next();
7395 sa = s->next; /* first parameter */
7396 nb_args = 0;
7397 /* compute first implicit argument if a structure is returned */
7398 if ((s->type.t & VT_BTYPE) == VT_STRUCT) {
7399 /* get some space for the returned structure */
7400 size = type_size(&s->type, &align);
7401 loc = (loc - size) & -align;
7402 ret.type = s->type;
7403 ret.r = VT_LOCAL | VT_LVAL;
7404 /* pass it as 'int' to avoid structure arg passing
7405 problems */
7406 vseti(VT_LOCAL, loc);
7407 ret.c = vtop->c;
7408 nb_args++;
7409 } else {
7410 ret.type = s->type;
7411 ret.r2 = VT_CONST;
7412 /* return in register */
7413 if (is_float(ret.type.t)) {
7414 ret.r = REG_FRET;
7415 } else {
7416 if ((ret.type.t & VT_BTYPE) == VT_LLONG)
7417 ret.r2 = REG_LRET;
7418 ret.r = REG_IRET;
7420 ret.c.i = 0;
7422 if (tok != ')') {
7423 for(;;) {
7424 expr_eq();
7425 gfunc_param_typed(s, sa);
7426 nb_args++;
7427 if (sa)
7428 sa = sa->next;
7429 if (tok == ')')
7430 break;
7431 skip(',');
7434 if (sa)
7435 error("too few arguments to function");
7436 skip(')');
7437 if (!nocode_wanted) {
7438 gfunc_call(nb_args);
7439 } else {
7440 vtop -= (nb_args + 1);
7442 /* return value */
7443 vsetc(&ret.type, ret.r, &ret.c);
7444 vtop->r2 = ret.r2;
7445 } else {
7446 break;
7451 static void uneq(void)
7453 int t;
7455 unary();
7456 if (tok == '=' ||
7457 (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
7458 tok == TOK_A_XOR || tok == TOK_A_OR ||
7459 tok == TOK_A_SHL || tok == TOK_A_SAR) {
7460 test_lvalue();
7461 t = tok;
7462 next();
7463 if (t == '=') {
7464 expr_eq();
7465 } else {
7466 vdup();
7467 expr_eq();
7468 gen_op(t & 0x7f);
7470 vstore();
7474 static void expr_prod(void)
7476 int t;
7478 uneq();
7479 while (tok == '*' || tok == '/' || tok == '%') {
7480 t = tok;
7481 next();
7482 uneq();
7483 gen_op(t);
7487 static void expr_sum(void)
7489 int t;
7491 expr_prod();
7492 while (tok == '+' || tok == '-') {
7493 t = tok;
7494 next();
7495 expr_prod();
7496 gen_op(t);
7500 static void expr_shift(void)
7502 int t;
7504 expr_sum();
7505 while (tok == TOK_SHL || tok == TOK_SAR) {
7506 t = tok;
7507 next();
7508 expr_sum();
7509 gen_op(t);
7513 static void expr_cmp(void)
7515 int t;
7517 expr_shift();
7518 while ((tok >= TOK_ULE && tok <= TOK_GT) ||
7519 tok == TOK_ULT || tok == TOK_UGE) {
7520 t = tok;
7521 next();
7522 expr_shift();
7523 gen_op(t);
7527 static void expr_cmpeq(void)
7529 int t;
7531 expr_cmp();
7532 while (tok == TOK_EQ || tok == TOK_NE) {
7533 t = tok;
7534 next();
7535 expr_cmp();
7536 gen_op(t);
7540 static void expr_and(void)
7542 expr_cmpeq();
7543 while (tok == '&') {
7544 next();
7545 expr_cmpeq();
7546 gen_op('&');
7550 static void expr_xor(void)
7552 expr_and();
7553 while (tok == '^') {
7554 next();
7555 expr_and();
7556 gen_op('^');
7560 static void expr_or(void)
7562 expr_xor();
7563 while (tok == '|') {
7564 next();
7565 expr_xor();
7566 gen_op('|');
7570 /* XXX: fix this mess */
7571 static void expr_land_const(void)
7573 expr_or();
7574 while (tok == TOK_LAND) {
7575 next();
7576 expr_or();
7577 gen_op(TOK_LAND);
7581 /* XXX: fix this mess */
7582 static void expr_lor_const(void)
7584 expr_land_const();
7585 while (tok == TOK_LOR) {
7586 next();
7587 expr_land_const();
7588 gen_op(TOK_LOR);
7592 /* only used if non constant */
7593 static void expr_land(void)
7595 int t;
7597 expr_or();
7598 if (tok == TOK_LAND) {
7599 t = 0;
7600 for(;;) {
7601 t = gtst(1, t);
7602 if (tok != TOK_LAND) {
7603 vseti(VT_JMPI, t);
7604 break;
7606 next();
7607 expr_or();
7612 static void expr_lor(void)
7614 int t;
7616 expr_land();
7617 if (tok == TOK_LOR) {
7618 t = 0;
7619 for(;;) {
7620 t = gtst(0, t);
7621 if (tok != TOK_LOR) {
7622 vseti(VT_JMP, t);
7623 break;
7625 next();
7626 expr_land();
7631 /* XXX: better constant handling */
7632 static void expr_eq(void)
7634 int tt, u, r1, r2, rc, t1, t2, bt1, bt2;
7635 SValue sv;
7636 CType type, type1, type2;
7638 if (const_wanted) {
7639 int c1, c;
7640 expr_lor_const();
7641 if (tok == '?') {
7642 c = vtop->c.i;
7643 vpop();
7644 next();
7645 if (tok == ':' && gnu_ext) {
7646 c1 = c;
7647 } else {
7648 gexpr();
7649 c1 = vtop->c.i;
7650 vpop();
7652 skip(':');
7653 expr_eq();
7654 if (c)
7655 vtop->c.i = c1;
7657 } else {
7658 expr_lor();
7659 if (tok == '?') {
7660 next();
7661 if (vtop != vstack) {
7662 /* needed to avoid having different registers saved in
7663 each branch */
7664 if (is_float(vtop->type.t))
7665 rc = RC_FLOAT;
7666 else
7667 rc = RC_INT;
7668 gv(rc);
7669 save_regs(1);
7671 if (tok == ':' && gnu_ext) {
7672 gv_dup();
7673 tt = gtst(1, 0);
7674 } else {
7675 tt = gtst(1, 0);
7676 gexpr();
7678 type1 = vtop->type;
7679 sv = *vtop; /* save value to handle it later */
7680 vtop--; /* no vpop so that FP stack is not flushed */
7681 skip(':');
7682 u = gjmp(0);
7683 gsym(tt);
7684 expr_eq();
7685 type2 = vtop->type;
7687 t1 = type1.t;
7688 bt1 = t1 & VT_BTYPE;
7689 t2 = type2.t;
7690 bt2 = t2 & VT_BTYPE;
7691 /* cast operands to correct type according to ISOC rules */
7692 if (is_float(bt1) || is_float(bt2)) {
7693 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
7694 type.t = VT_LDOUBLE;
7695 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
7696 type.t = VT_DOUBLE;
7697 } else {
7698 type.t = VT_FLOAT;
7700 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
7701 /* cast to biggest op */
7702 type.t = VT_LLONG;
7703 /* convert to unsigned if it does not fit in a long long */
7704 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
7705 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
7706 type.t |= VT_UNSIGNED;
7707 } else if (bt1 == VT_PTR || bt2 == VT_PTR) {
7708 /* XXX: test pointer compatibility */
7709 type = type1;
7710 } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
7711 /* XXX: test structure compatibility */
7712 type = type1;
7713 } else if (bt1 == VT_VOID || bt2 == VT_VOID) {
7714 /* NOTE: as an extension, we accept void on only one side */
7715 type.t = VT_VOID;
7716 } else {
7717 /* integer operations */
7718 type.t = VT_INT;
7719 /* convert to unsigned if it does not fit in an integer */
7720 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
7721 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
7722 type.t |= VT_UNSIGNED;
7725 /* now we convert second operand */
7726 gen_cast(&type);
7727 rc = RC_INT;
7728 if (is_float(type.t)) {
7729 rc = RC_FLOAT;
7730 } else if ((type.t & VT_BTYPE) == VT_LLONG) {
7731 /* for long longs, we use fixed registers to avoid having
7732 to handle a complicated move */
7733 rc = RC_IRET;
7736 r2 = gv(rc);
7737 /* this is horrible, but we must also convert first
7738 operand */
7739 tt = gjmp(0);
7740 gsym(u);
7741 /* put again first value and cast it */
7742 *vtop = sv;
7743 gen_cast(&type);
7744 r1 = gv(rc);
7745 move_reg(r2, r1);
7746 vtop->r = r2;
7747 gsym(tt);
7752 static void gexpr(void)
7754 while (1) {
7755 expr_eq();
7756 if (tok != ',')
7757 break;
7758 vpop();
7759 next();
7763 /* parse an expression and return its type without any side effect. */
7764 static void expr_type(CType *type)
7766 int saved_nocode_wanted;
7768 saved_nocode_wanted = nocode_wanted;
7769 nocode_wanted = 1;
7770 gexpr();
7771 *type = vtop->type;
7772 vpop();
7773 nocode_wanted = saved_nocode_wanted;
7776 /* parse a unary expression and return its type without any side
7777 effect. */
7778 static void unary_type(CType *type)
7780 int a;
7782 a = nocode_wanted;
7783 nocode_wanted = 1;
7784 unary();
7785 *type = vtop->type;
7786 vpop();
7787 nocode_wanted = a;
7790 /* parse a constant expression and return value in vtop. */
7791 static void expr_const1(void)
7793 int a;
7794 a = const_wanted;
7795 const_wanted = 1;
7796 expr_eq();
7797 const_wanted = a;
7800 /* parse an integer constant and return its value. */
7801 static int expr_const(void)
7803 int c;
7804 expr_const1();
7805 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
7806 expect("constant expression");
7807 c = vtop->c.i;
7808 vpop();
7809 return c;
7812 /* return the label token if current token is a label, otherwise
7813 return zero */
7814 static int is_label(void)
7816 int last_tok;
7818 /* fast test first */
7819 if (tok < TOK_UIDENT)
7820 return 0;
7821 /* no need to save tokc because tok is an identifier */
7822 last_tok = tok;
7823 next();
7824 if (tok == ':') {
7825 next();
7826 return last_tok;
7827 } else {
7828 unget_tok(last_tok);
7829 return 0;
7833 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
7834 int case_reg, int is_expr)
7836 int a, b, c, d;
7837 Sym *s;
7839 /* generate line number info */
7840 if (do_debug &&
7841 (last_line_num != file->line_num || last_ind != ind)) {
7842 put_stabn(N_SLINE, 0, file->line_num, ind - func_ind);
7843 last_ind = ind;
7844 last_line_num = file->line_num;
7847 if (is_expr) {
7848 /* default return value is (void) */
7849 vpushi(0);
7850 vtop->type.t = VT_VOID;
7853 if (tok == TOK_IF) {
7854 /* if test */
7855 next();
7856 skip('(');
7857 gexpr();
7858 skip(')');
7859 a = gtst(1, 0);
7860 block(bsym, csym, case_sym, def_sym, case_reg, 0);
7861 c = tok;
7862 if (c == TOK_ELSE) {
7863 next();
7864 d = gjmp(0);
7865 gsym(a);
7866 block(bsym, csym, case_sym, def_sym, case_reg, 0);
7867 gsym(d); /* patch else jmp */
7868 } else
7869 gsym(a);
7870 } else if (tok == TOK_WHILE) {
7871 next();
7872 d = ind;
7873 skip('(');
7874 gexpr();
7875 skip(')');
7876 a = gtst(1, 0);
7877 b = 0;
7878 block(&a, &b, case_sym, def_sym, case_reg, 0);
7879 gjmp_addr(d);
7880 gsym(a);
7881 gsym_addr(b, d);
7882 } else if (tok == '{') {
7883 Sym *llabel;
7885 next();
7886 /* record local declaration stack position */
7887 s = local_stack;
7888 llabel = local_label_stack;
7889 /* handle local labels declarations */
7890 if (tok == TOK_LABEL) {
7891 next();
7892 for(;;) {
7893 if (tok < TOK_UIDENT)
7894 expect("label identifier");
7895 label_push(&local_label_stack, tok, LABEL_DECLARED);
7896 next();
7897 if (tok == ',') {
7898 next();
7899 } else {
7900 skip(';');
7901 break;
7905 while (tok != '}') {
7906 decl(VT_LOCAL);
7907 if (tok != '}') {
7908 if (is_expr)
7909 vpop();
7910 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
7913 /* pop locally defined labels */
7914 label_pop(&local_label_stack, llabel);
7915 /* pop locally defined symbols */
7916 sym_pop(&local_stack, s);
7917 next();
7918 } else if (tok == TOK_RETURN) {
7919 next();
7920 if (tok != ';') {
7921 gexpr();
7922 gen_assign_cast(&func_vt);
7923 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
7924 CType type;
7925 /* if returning structure, must copy it to implicit
7926 first pointer arg location */
7927 type = func_vt;
7928 mk_pointer(&type);
7929 vset(&type, VT_LOCAL | VT_LVAL, func_vc);
7930 indir();
7931 vswap();
7932 /* copy structure value to pointer */
7933 vstore();
7934 } else if (is_float(func_vt.t)) {
7935 gv(RC_FRET);
7936 } else {
7937 gv(RC_IRET);
7939 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
7941 skip(';');
7942 rsym = gjmp(rsym); /* jmp */
7943 } else if (tok == TOK_BREAK) {
7944 /* compute jump */
7945 if (!bsym)
7946 error("cannot break");
7947 *bsym = gjmp(*bsym);
7948 next();
7949 skip(';');
7950 } else if (tok == TOK_CONTINUE) {
7951 /* compute jump */
7952 if (!csym)
7953 error("cannot continue");
7954 *csym = gjmp(*csym);
7955 next();
7956 skip(';');
7957 } else if (tok == TOK_FOR) {
7958 int e;
7959 next();
7960 skip('(');
7961 if (tok != ';') {
7962 gexpr();
7963 vpop();
7965 skip(';');
7966 d = ind;
7967 c = ind;
7968 a = 0;
7969 b = 0;
7970 if (tok != ';') {
7971 gexpr();
7972 a = gtst(1, 0);
7974 skip(';');
7975 if (tok != ')') {
7976 e = gjmp(0);
7977 c = ind;
7978 gexpr();
7979 vpop();
7980 gjmp_addr(d);
7981 gsym(e);
7983 skip(')');
7984 block(&a, &b, case_sym, def_sym, case_reg, 0);
7985 gjmp_addr(c);
7986 gsym(a);
7987 gsym_addr(b, c);
7988 } else
7989 if (tok == TOK_DO) {
7990 next();
7991 a = 0;
7992 b = 0;
7993 d = ind;
7994 block(&a, &b, case_sym, def_sym, case_reg, 0);
7995 skip(TOK_WHILE);
7996 skip('(');
7997 gsym(b);
7998 gexpr();
7999 c = gtst(0, 0);
8000 gsym_addr(c, d);
8001 skip(')');
8002 gsym(a);
8003 skip(';');
8004 } else
8005 if (tok == TOK_SWITCH) {
8006 next();
8007 skip('(');
8008 gexpr();
8009 /* XXX: other types than integer */
8010 case_reg = gv(RC_INT);
8011 vpop();
8012 skip(')');
8013 a = 0;
8014 b = gjmp(0); /* jump to first case */
8015 c = 0;
8016 block(&a, csym, &b, &c, case_reg, 0);
8017 /* if no default, jmp after switch */
8018 if (c == 0)
8019 c = ind;
8020 /* default label */
8021 gsym_addr(b, c);
8022 /* break label */
8023 gsym(a);
8024 } else
8025 if (tok == TOK_CASE) {
8026 int v1, v2;
8027 if (!case_sym)
8028 expect("switch");
8029 next();
8030 v1 = expr_const();
8031 v2 = v1;
8032 if (gnu_ext && tok == TOK_DOTS) {
8033 next();
8034 v2 = expr_const();
8035 if (v2 < v1)
8036 warning("empty case range");
8038 /* since a case is like a label, we must skip it with a jmp */
8039 b = gjmp(0);
8040 gsym(*case_sym);
8041 vseti(case_reg, 0);
8042 vpushi(v1);
8043 if (v1 == v2) {
8044 gen_op(TOK_EQ);
8045 *case_sym = gtst(1, 0);
8046 } else {
8047 gen_op(TOK_GE);
8048 *case_sym = gtst(1, 0);
8049 vseti(case_reg, 0);
8050 vpushi(v2);
8051 gen_op(TOK_LE);
8052 *case_sym = gtst(1, *case_sym);
8054 gsym(b);
8055 skip(':');
8056 is_expr = 0;
8057 goto block_after_label;
8058 } else
8059 if (tok == TOK_DEFAULT) {
8060 next();
8061 skip(':');
8062 if (!def_sym)
8063 expect("switch");
8064 if (*def_sym)
8065 error("too many 'default'");
8066 *def_sym = ind;
8067 is_expr = 0;
8068 goto block_after_label;
8069 } else
8070 if (tok == TOK_GOTO) {
8071 next();
8072 if (tok == '*' && gnu_ext) {
8073 /* computed goto */
8074 next();
8075 gexpr();
8076 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
8077 expect("pointer");
8078 ggoto();
8079 } else if (tok >= TOK_UIDENT) {
8080 s = label_find(tok);
8081 /* put forward definition if needed */
8082 if (!s) {
8083 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
8084 } else {
8085 if (s->r == LABEL_DECLARED)
8086 s->r = LABEL_FORWARD;
8088 /* label already defined */
8089 if (s->r & LABEL_FORWARD)
8090 s->next = (void *)gjmp((long)s->next);
8091 else
8092 gjmp_addr((long)s->next);
8093 next();
8094 } else {
8095 expect("label identifier");
8097 skip(';');
8098 } else if (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3) {
8099 asm_instr();
8100 } else {
8101 b = is_label();
8102 if (b) {
8103 /* label case */
8104 s = label_find(b);
8105 if (s) {
8106 if (s->r == LABEL_DEFINED)
8107 error("duplicate label '%s'", get_tok_str(s->v, NULL));
8108 gsym((long)s->next);
8109 s->r = LABEL_DEFINED;
8110 } else {
8111 s = label_push(&global_label_stack, b, LABEL_DEFINED);
8113 s->next = (void *)ind;
8114 /* we accept this, but it is a mistake */
8115 block_after_label:
8116 if (tok == '}') {
8117 warning("deprecated use of label at end of compound statement");
8118 } else {
8119 if (is_expr)
8120 vpop();
8121 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
8123 } else {
8124 /* expression case */
8125 if (tok != ';') {
8126 if (is_expr) {
8127 vpop();
8128 gexpr();
8129 } else {
8130 gexpr();
8131 vpop();
8134 skip(';');
8139 /* t is the array or struct type. c is the array or struct
8140 address. cur_index/cur_field is the pointer to the current
8141 value. 'size_only' is true if only size info is needed (only used
8142 in arrays) */
8143 static void decl_designator(CType *type, Section *sec, unsigned long c,
8144 int *cur_index, Sym **cur_field,
8145 int size_only)
8147 Sym *s, *f;
8148 int notfirst, index, index_last, align, l, nb_elems, elem_size;
8149 CType type1;
8151 notfirst = 0;
8152 elem_size = 0;
8153 nb_elems = 1;
8154 if (gnu_ext && (l = is_label()) != 0)
8155 goto struct_field;
8156 while (tok == '[' || tok == '.') {
8157 if (tok == '[') {
8158 if (!(type->t & VT_ARRAY))
8159 expect("array type");
8160 s = type->ref;
8161 next();
8162 index = expr_const();
8163 if (index < 0 || (s->c >= 0 && index >= s->c))
8164 expect("invalid index");
8165 if (tok == TOK_DOTS && gnu_ext) {
8166 next();
8167 index_last = expr_const();
8168 if (index_last < 0 ||
8169 (s->c >= 0 && index_last >= s->c) ||
8170 index_last < index)
8171 expect("invalid index");
8172 } else {
8173 index_last = index;
8175 skip(']');
8176 if (!notfirst)
8177 *cur_index = index_last;
8178 type = pointed_type(type);
8179 elem_size = type_size(type, &align);
8180 c += index * elem_size;
8181 /* NOTE: we only support ranges for last designator */
8182 nb_elems = index_last - index + 1;
8183 if (nb_elems != 1) {
8184 notfirst = 1;
8185 break;
8187 } else {
8188 next();
8189 l = tok;
8190 next();
8191 struct_field:
8192 if ((type->t & VT_BTYPE) != VT_STRUCT)
8193 expect("struct/union type");
8194 s = type->ref;
8195 l |= SYM_FIELD;
8196 f = s->next;
8197 while (f) {
8198 if (f->v == l)
8199 break;
8200 f = f->next;
8202 if (!f)
8203 expect("field");
8204 if (!notfirst)
8205 *cur_field = f;
8206 /* XXX: fix this mess by using explicit storage field */
8207 type1 = f->type;
8208 type1.t |= (type->t & ~VT_TYPE);
8209 type = &type1;
8210 c += f->c;
8212 notfirst = 1;
8214 if (notfirst) {
8215 if (tok == '=') {
8216 next();
8217 } else {
8218 if (!gnu_ext)
8219 expect("=");
8221 } else {
8222 if (type->t & VT_ARRAY) {
8223 index = *cur_index;
8224 type = pointed_type(type);
8225 c += index * type_size(type, &align);
8226 } else {
8227 f = *cur_field;
8228 if (!f)
8229 error("too many field init");
8230 /* XXX: fix this mess by using explicit storage field */
8231 type1 = f->type;
8232 type1.t |= (type->t & ~VT_TYPE);
8233 type = &type1;
8234 c += f->c;
8237 decl_initializer(type, sec, c, 0, size_only);
8239 /* XXX: make it more general */
8240 if (!size_only && nb_elems > 1) {
8241 unsigned long c_end;
8242 uint8_t *src, *dst;
8243 int i;
8245 if (!sec)
8246 error("range init not supported yet for dynamic storage");
8247 c_end = c + nb_elems * elem_size;
8248 if (c_end > sec->data_allocated)
8249 section_realloc(sec, c_end);
8250 src = sec->data + c;
8251 dst = src;
8252 for(i = 1; i < nb_elems; i++) {
8253 dst += elem_size;
8254 memcpy(dst, src, elem_size);
8259 #define EXPR_VAL 0
8260 #define EXPR_CONST 1
8261 #define EXPR_ANY 2
8263 /* store a value or an expression directly in global data or in local array */
8264 static void init_putv(CType *type, Section *sec, unsigned long c,
8265 int v, int expr_type)
8267 int saved_global_expr, bt, bit_pos, bit_size;
8268 void *ptr;
8269 unsigned long long bit_mask;
8270 CType dtype;
8272 switch(expr_type) {
8273 case EXPR_VAL:
8274 vpushi(v);
8275 break;
8276 case EXPR_CONST:
8277 /* compound literals must be allocated globally in this case */
8278 saved_global_expr = global_expr;
8279 global_expr = 1;
8280 expr_const1();
8281 global_expr = saved_global_expr;
8282 /* NOTE: symbols are accepted */
8283 if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST)
8284 error("initializer element is not constant");
8285 break;
8286 case EXPR_ANY:
8287 expr_eq();
8288 break;
8291 dtype = *type;
8292 dtype.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
8294 if (sec) {
8295 /* XXX: not portable */
8296 /* XXX: generate error if incorrect relocation */
8297 gen_assign_cast(&dtype);
8298 bt = type->t & VT_BTYPE;
8299 ptr = sec->data + c;
8300 /* XXX: make code faster ? */
8301 if (!(type->t & VT_BITFIELD)) {
8302 bit_pos = 0;
8303 bit_size = 32;
8304 bit_mask = -1LL;
8305 } else {
8306 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
8307 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
8308 bit_mask = (1LL << bit_size) - 1;
8310 if ((vtop->r & VT_SYM) &&
8311 (bt == VT_BYTE ||
8312 bt == VT_SHORT ||
8313 bt == VT_DOUBLE ||
8314 bt == VT_LDOUBLE ||
8315 bt == VT_LLONG ||
8316 (bt == VT_INT && bit_size != 32)))
8317 error("initializer element is not computable at load time");
8318 switch(bt) {
8319 case VT_BYTE:
8320 *(char *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8321 break;
8322 case VT_SHORT:
8323 *(short *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8324 break;
8325 case VT_DOUBLE:
8326 *(double *)ptr = vtop->c.d;
8327 break;
8328 case VT_LDOUBLE:
8329 *(long double *)ptr = vtop->c.ld;
8330 break;
8331 case VT_LLONG:
8332 *(long long *)ptr |= (vtop->c.ll & bit_mask) << bit_pos;
8333 break;
8334 default:
8335 if (vtop->r & VT_SYM) {
8336 greloc(sec, vtop->sym, c, R_DATA_32);
8338 *(int *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8339 break;
8341 vtop--;
8342 } else {
8343 vset(&dtype, VT_LOCAL, c);
8344 vswap();
8345 vstore();
8346 vpop();
8350 /* put zeros for variable based init */
8351 static void init_putz(CType *t, Section *sec, unsigned long c, int size)
8353 if (sec) {
8354 /* nothing to do because globals are already set to zero */
8355 } else {
8356 vpush_global_sym(&func_old_type, TOK_memset);
8357 vseti(VT_LOCAL, c);
8358 vpushi(0);
8359 vpushi(size);
8360 gfunc_call(3);
8364 /* 't' contains the type and storage info. 'c' is the offset of the
8365 object in section 'sec'. If 'sec' is NULL, it means stack based
8366 allocation. 'first' is true if array '{' must be read (multi
8367 dimension implicit array init handling). 'size_only' is true if
8368 size only evaluation is wanted (only for arrays). */
8369 static void decl_initializer(CType *type, Section *sec, unsigned long c,
8370 int first, int size_only)
8372 int index, array_length, n, no_oblock, nb, parlevel, i;
8373 int size1, align1, expr_type;
8374 Sym *s, *f;
8375 CType *t1;
8377 if (type->t & VT_ARRAY) {
8378 s = type->ref;
8379 n = s->c;
8380 array_length = 0;
8381 t1 = pointed_type(type);
8382 size1 = type_size(t1, &align1);
8384 no_oblock = 1;
8385 if ((first && tok != TOK_LSTR && tok != TOK_STR) ||
8386 tok == '{') {
8387 skip('{');
8388 no_oblock = 0;
8391 /* only parse strings here if correct type (otherwise: handle
8392 them as ((w)char *) expressions */
8393 if ((tok == TOK_LSTR &&
8394 (t1->t & VT_BTYPE) == VT_INT) ||
8395 (tok == TOK_STR &&
8396 (t1->t & VT_BTYPE) == VT_BYTE)) {
8397 while (tok == TOK_STR || tok == TOK_LSTR) {
8398 int cstr_len, ch;
8399 CString *cstr;
8401 cstr = tokc.cstr;
8402 /* compute maximum number of chars wanted */
8403 if (tok == TOK_STR)
8404 cstr_len = cstr->size;
8405 else
8406 cstr_len = cstr->size / sizeof(int);
8407 cstr_len--;
8408 nb = cstr_len;
8409 if (n >= 0 && nb > (n - array_length))
8410 nb = n - array_length;
8411 if (!size_only) {
8412 if (cstr_len > nb)
8413 warning("initializer-string for array is too long");
8414 /* in order to go faster for common case (char
8415 string in global variable, we handle it
8416 specifically */
8417 if (sec && tok == TOK_STR && size1 == 1) {
8418 memcpy(sec->data + c + array_length, cstr->data, nb);
8419 } else {
8420 for(i=0;i<nb;i++) {
8421 if (tok == TOK_STR)
8422 ch = ((unsigned char *)cstr->data)[i];
8423 else
8424 ch = ((int *)cstr->data)[i];
8425 init_putv(t1, sec, c + (array_length + i) * size1,
8426 ch, EXPR_VAL);
8430 array_length += nb;
8431 next();
8433 /* only add trailing zero if enough storage (no
8434 warning in this case since it is standard) */
8435 if (n < 0 || array_length < n) {
8436 if (!size_only) {
8437 init_putv(t1, sec, c + (array_length * size1), 0, EXPR_VAL);
8439 array_length++;
8441 } else {
8442 index = 0;
8443 while (tok != '}') {
8444 decl_designator(type, sec, c, &index, NULL, size_only);
8445 if (n >= 0 && index >= n)
8446 error("index too large");
8447 /* must put zero in holes (note that doing it that way
8448 ensures that it even works with designators) */
8449 if (!size_only && array_length < index) {
8450 init_putz(t1, sec, c + array_length * size1,
8451 (index - array_length) * size1);
8453 index++;
8454 if (index > array_length)
8455 array_length = index;
8456 /* special test for multi dimensional arrays (may not
8457 be strictly correct if designators are used at the
8458 same time) */
8459 if (index >= n && no_oblock)
8460 break;
8461 if (tok == '}')
8462 break;
8463 skip(',');
8466 if (!no_oblock)
8467 skip('}');
8468 /* put zeros at the end */
8469 if (!size_only && n >= 0 && array_length < n) {
8470 init_putz(t1, sec, c + array_length * size1,
8471 (n - array_length) * size1);
8473 /* patch type size if needed */
8474 if (n < 0)
8475 s->c = array_length;
8476 } else if ((type->t & VT_BTYPE) == VT_STRUCT &&
8477 (sec || !first || tok == '{')) {
8478 int par_count;
8480 /* NOTE: the previous test is a specific case for automatic
8481 struct/union init */
8482 /* XXX: union needs only one init */
8484 /* XXX: this test is incorrect for local initializers
8485 beginning with ( without {. It would be much more difficult
8486 to do it correctly (ideally, the expression parser should
8487 be used in all cases) */
8488 par_count = 0;
8489 if (tok == '(') {
8490 AttributeDef ad1;
8491 CType type1;
8492 next();
8493 while (tok == '(') {
8494 par_count++;
8495 next();
8497 if (!parse_btype(&type1, &ad1))
8498 expect("cast");
8499 type_decl(&type1, &ad1, &n, TYPE_ABSTRACT);
8500 #if 0
8501 if (!is_assignable_types(type, &type1))
8502 error("invalid type for cast");
8503 #endif
8504 skip(')');
8506 no_oblock = 1;
8507 if (first || tok == '{') {
8508 skip('{');
8509 no_oblock = 0;
8511 s = type->ref;
8512 f = s->next;
8513 array_length = 0;
8514 index = 0;
8515 n = s->c;
8516 while (tok != '}') {
8517 decl_designator(type, sec, c, NULL, &f, size_only);
8518 index = f->c;
8519 if (!size_only && array_length < index) {
8520 init_putz(type, sec, c + array_length,
8521 index - array_length);
8523 index = index + type_size(&f->type, &align1);
8524 if (index > array_length)
8525 array_length = index;
8526 f = f->next;
8527 if (no_oblock && f == NULL)
8528 break;
8529 if (tok == '}')
8530 break;
8531 skip(',');
8533 /* put zeros at the end */
8534 if (!size_only && array_length < n) {
8535 init_putz(type, sec, c + array_length,
8536 n - array_length);
8538 if (!no_oblock)
8539 skip('}');
8540 while (par_count) {
8541 skip(')');
8542 par_count--;
8544 } else if (tok == '{') {
8545 next();
8546 decl_initializer(type, sec, c, first, size_only);
8547 skip('}');
8548 } else if (size_only) {
8549 /* just skip expression */
8550 parlevel = 0;
8551 while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
8552 tok != -1) {
8553 if (tok == '(')
8554 parlevel++;
8555 else if (tok == ')')
8556 parlevel--;
8557 next();
8559 } else {
8560 /* currently, we always use constant expression for globals
8561 (may change for scripting case) */
8562 expr_type = EXPR_CONST;
8563 if (!sec)
8564 expr_type = EXPR_ANY;
8565 init_putv(type, sec, c, 0, expr_type);
8569 /* parse an initializer for type 't' if 'has_init' is non zero, and
8570 allocate space in local or global data space ('r' is either
8571 VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
8572 variable 'v' of scope 'scope' is declared before initializers are
8573 parsed. If 'v' is zero, then a reference to the new object is put
8574 in the value stack. If 'has_init' is 2, a special parsing is done
8575 to handle string constants. */
8576 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
8577 int has_init, int v, int scope)
8579 int size, align, addr, data_offset;
8580 int level;
8581 ParseState saved_parse_state;
8582 TokenString init_str;
8583 Section *sec;
8585 size = type_size(type, &align);
8586 /* If unknown size, we must evaluate it before
8587 evaluating initializers because
8588 initializers can generate global data too
8589 (e.g. string pointers or ISOC99 compound
8590 literals). It also simplifies local
8591 initializers handling */
8592 tok_str_new(&init_str);
8593 if (size < 0) {
8594 if (!has_init)
8595 error("unknown type size");
8596 /* get all init string */
8597 if (has_init == 2) {
8598 /* only get strings */
8599 while (tok == TOK_STR || tok == TOK_LSTR) {
8600 tok_str_add_tok(&init_str);
8601 next();
8603 } else {
8604 level = 0;
8605 while (level > 0 || (tok != ',' && tok != ';')) {
8606 if (tok < 0)
8607 error("unexpected end of file in initializer");
8608 tok_str_add_tok(&init_str);
8609 if (tok == '{')
8610 level++;
8611 else if (tok == '}') {
8612 if (level == 0)
8613 break;
8614 level--;
8616 next();
8619 tok_str_add(&init_str, -1);
8620 tok_str_add(&init_str, 0);
8622 /* compute size */
8623 save_parse_state(&saved_parse_state);
8625 macro_ptr = init_str.str;
8626 next();
8627 decl_initializer(type, NULL, 0, 1, 1);
8628 /* prepare second initializer parsing */
8629 macro_ptr = init_str.str;
8630 next();
8632 /* if still unknown size, error */
8633 size = type_size(type, &align);
8634 if (size < 0)
8635 error("unknown type size");
8637 /* take into account specified alignment if bigger */
8638 if (ad->aligned) {
8639 if (ad->aligned > align)
8640 align = ad->aligned;
8641 } else if (ad->packed) {
8642 align = 1;
8644 if ((r & VT_VALMASK) == VT_LOCAL) {
8645 sec = NULL;
8646 if (do_bounds_check && (type->t & VT_ARRAY))
8647 loc--;
8648 loc = (loc - size) & -align;
8649 addr = loc;
8650 /* handles bounds */
8651 /* XXX: currently, since we do only one pass, we cannot track
8652 '&' operators, so we add only arrays */
8653 if (do_bounds_check && (type->t & VT_ARRAY)) {
8654 unsigned long *bounds_ptr;
8655 /* add padding between regions */
8656 loc--;
8657 /* then add local bound info */
8658 bounds_ptr = section_ptr_add(lbounds_section, 2 * sizeof(unsigned long));
8659 bounds_ptr[0] = addr;
8660 bounds_ptr[1] = size;
8662 if (v) {
8663 /* local variable */
8664 sym_push(v, type, r, addr);
8665 } else {
8666 /* push local reference */
8667 vset(type, r, addr);
8669 } else {
8670 Sym *sym;
8672 sym = NULL;
8673 if (v && scope == VT_CONST) {
8674 /* see if the symbol was already defined */
8675 sym = sym_find(v);
8676 if (sym) {
8677 if (!is_compatible_types(&sym->type, type))
8678 error("incompatible types for redefinition of '%s'",
8679 get_tok_str(v, NULL));
8680 if (sym->type.t & VT_EXTERN) {
8681 /* if the variable is extern, it was not allocated */
8682 sym->type.t &= ~VT_EXTERN;
8683 /* set array size if it was ommited in extern
8684 declaration */
8685 if ((sym->type.t & VT_ARRAY) &&
8686 sym->type.ref->c < 0 &&
8687 type->ref->c >= 0)
8688 sym->type.ref->c = type->ref->c;
8689 } else {
8690 /* we accept several definitions of the same
8691 global variable. this is tricky, because we
8692 must play with the SHN_COMMON type of the symbol */
8693 /* XXX: should check if the variable was already
8694 initialized. It is incorrect to initialized it
8695 twice */
8696 /* no init data, we won't add more to the symbol */
8697 if (!has_init)
8698 goto no_alloc;
8703 /* allocate symbol in corresponding section */
8704 sec = ad->section;
8705 if (!sec) {
8706 if (has_init)
8707 sec = data_section;
8708 else if (tcc_state->nocommon)
8709 sec = bss_section;
8711 if (sec) {
8712 data_offset = sec->data_offset;
8713 data_offset = (data_offset + align - 1) & -align;
8714 addr = data_offset;
8715 /* very important to increment global pointer at this time
8716 because initializers themselves can create new initializers */
8717 data_offset += size;
8718 /* add padding if bound check */
8719 if (do_bounds_check)
8720 data_offset++;
8721 sec->data_offset = data_offset;
8722 /* allocate section space to put the data */
8723 if (sec->sh_type != SHT_NOBITS &&
8724 data_offset > sec->data_allocated)
8725 section_realloc(sec, data_offset);
8726 /* align section if needed */
8727 if (align > sec->sh_addralign)
8728 sec->sh_addralign = align;
8729 } else {
8730 addr = 0; /* avoid warning */
8733 if (v) {
8734 if (scope == VT_CONST) {
8735 if (!sym)
8736 goto do_def;
8737 } else {
8738 do_def:
8739 sym = sym_push(v, type, r | VT_SYM, 0);
8741 /* update symbol definition */
8742 if (sec) {
8743 put_extern_sym(sym, sec, addr, size);
8744 } else {
8745 Elf32_Sym *esym;
8746 /* put a common area */
8747 put_extern_sym(sym, NULL, align, size);
8748 /* XXX: find a nicer way */
8749 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
8750 esym->st_shndx = SHN_COMMON;
8752 } else {
8753 CValue cval;
8755 /* push global reference */
8756 sym = get_sym_ref(type, sec, addr, size);
8757 cval.ul = 0;
8758 vsetc(type, VT_CONST | VT_SYM, &cval);
8759 vtop->sym = sym;
8762 /* handles bounds now because the symbol must be defined
8763 before for the relocation */
8764 if (do_bounds_check) {
8765 unsigned long *bounds_ptr;
8767 greloc(bounds_section, sym, bounds_section->data_offset, R_DATA_32);
8768 /* then add global bound info */
8769 bounds_ptr = section_ptr_add(bounds_section, 2 * sizeof(long));
8770 bounds_ptr[0] = 0; /* relocated */
8771 bounds_ptr[1] = size;
8774 if (has_init) {
8775 decl_initializer(type, sec, addr, 1, 0);
8776 /* restore parse state if needed */
8777 if (init_str.str) {
8778 tok_str_free(init_str.str);
8779 restore_parse_state(&saved_parse_state);
8782 no_alloc: ;
8785 void put_func_debug(Sym *sym)
8787 char buf[512];
8789 /* stabs info */
8790 /* XXX: we put here a dummy type */
8791 snprintf(buf, sizeof(buf), "%s:%c1",
8792 funcname, sym->type.t & VT_STATIC ? 'f' : 'F');
8793 put_stabs_r(buf, N_FUN, 0, file->line_num, 0,
8794 cur_text_section, sym->c);
8795 last_ind = 0;
8796 last_line_num = 0;
8799 /* parse an old style function declaration list */
8800 /* XXX: check multiple parameter */
8801 static void func_decl_list(Sym *func_sym)
8803 AttributeDef ad;
8804 int v;
8805 Sym *s;
8806 CType btype, type;
8808 /* parse each declaration */
8809 while (tok != '{' && tok != ';' && tok != ',' && tok != TOK_EOF) {
8810 if (!parse_btype(&btype, &ad))
8811 expect("declaration list");
8812 if (((btype.t & VT_BTYPE) == VT_ENUM ||
8813 (btype.t & VT_BTYPE) == VT_STRUCT) &&
8814 tok == ';') {
8815 /* we accept no variable after */
8816 } else {
8817 for(;;) {
8818 type = btype;
8819 type_decl(&type, &ad, &v, TYPE_DIRECT);
8820 /* find parameter in function parameter list */
8821 s = func_sym->next;
8822 while (s != NULL) {
8823 if ((s->v & ~SYM_FIELD) == v)
8824 goto found;
8825 s = s->next;
8827 error("declaration for parameter '%s' but no such parameter",
8828 get_tok_str(v, NULL));
8829 found:
8830 /* check that no storage specifier except 'register' was given */
8831 if (type.t & VT_STORAGE)
8832 error("storage class specified for '%s'", get_tok_str(v, NULL));
8833 convert_parameter_type(&type);
8834 /* we can add the type (NOTE: it could be local to the function) */
8835 s->type = type;
8836 /* accept other parameters */
8837 if (tok == ',')
8838 next();
8839 else
8840 break;
8843 skip(';');
8847 /* parse a function defined by symbol 'sym' and generate its code in
8848 'cur_text_section' */
8849 static void gen_function(Sym *sym)
8851 ind = cur_text_section->data_offset;
8852 /* NOTE: we patch the symbol size later */
8853 put_extern_sym(sym, cur_text_section, ind, 0);
8854 funcname = get_tok_str(sym->v, NULL);
8855 func_ind = ind;
8856 /* put debug symbol */
8857 if (do_debug)
8858 put_func_debug(sym);
8859 /* push a dummy symbol to enable local sym storage */
8860 sym_push2(&local_stack, SYM_FIELD, 0, 0);
8861 gfunc_prolog(&sym->type);
8862 rsym = 0;
8863 block(NULL, NULL, NULL, NULL, 0, 0);
8864 gsym(rsym);
8865 gfunc_epilog();
8866 cur_text_section->data_offset = ind;
8867 label_pop(&global_label_stack, NULL);
8868 sym_pop(&local_stack, NULL); /* reset local stack */
8869 /* end of function */
8870 /* patch symbol size */
8871 ((Elf32_Sym *)symtab_section->data)[sym->c].st_size =
8872 ind - func_ind;
8873 if (do_debug) {
8874 put_stabn(N_FUN, 0, 0, ind - func_ind);
8876 funcname = ""; /* for safety */
8877 func_vt.t = VT_VOID; /* for safety */
8878 ind = 0; /* for safety */
8881 static void gen_inline_functions(void)
8883 Sym *sym;
8884 CType *type;
8885 int *str, inline_generated;
8887 /* iterate while inline function are referenced */
8888 for(;;) {
8889 inline_generated = 0;
8890 for(sym = global_stack; sym != NULL; sym = sym->prev) {
8891 type = &sym->type;
8892 if (((type->t & VT_BTYPE) == VT_FUNC) &&
8893 (type->t & (VT_STATIC | VT_INLINE)) ==
8894 (VT_STATIC | VT_INLINE) &&
8895 sym->c != 0) {
8896 /* the function was used: generate its code and
8897 convert it to a normal function */
8898 str = (int *)sym->r;
8899 sym->r = VT_SYM | VT_CONST;
8900 type->t &= ~VT_INLINE;
8902 macro_ptr = str;
8903 next();
8904 cur_text_section = text_section;
8905 gen_function(sym);
8906 macro_ptr = NULL; /* fail safe */
8908 tok_str_free(str);
8909 inline_generated = 1;
8912 if (!inline_generated)
8913 break;
8916 /* free all remaining inline function tokens */
8917 for(sym = global_stack; sym != NULL; sym = sym->prev) {
8918 type = &sym->type;
8919 if (((type->t & VT_BTYPE) == VT_FUNC) &&
8920 (type->t & (VT_STATIC | VT_INLINE)) ==
8921 (VT_STATIC | VT_INLINE)) {
8922 str = (int *)sym->r;
8923 tok_str_free(str);
8924 sym->r = 0; /* fail safe */
8929 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
8930 static void decl(int l)
8932 int v, has_init, r;
8933 CType type, btype;
8934 Sym *sym;
8935 AttributeDef ad;
8937 while (1) {
8938 if (!parse_btype(&btype, &ad)) {
8939 /* skip redundant ';' */
8940 /* XXX: find more elegant solution */
8941 if (tok == ';') {
8942 next();
8943 continue;
8945 if (l == VT_CONST &&
8946 (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3)) {
8947 /* global asm block */
8948 asm_global_instr();
8949 continue;
8951 /* special test for old K&R protos without explicit int
8952 type. Only accepted when defining global data */
8953 if (l == VT_LOCAL || tok < TOK_DEFINE)
8954 break;
8955 btype.t = VT_INT;
8957 if (((btype.t & VT_BTYPE) == VT_ENUM ||
8958 (btype.t & VT_BTYPE) == VT_STRUCT) &&
8959 tok == ';') {
8960 /* we accept no variable after */
8961 next();
8962 continue;
8964 while (1) { /* iterate thru each declaration */
8965 type = btype;
8966 type_decl(&type, &ad, &v, TYPE_DIRECT);
8967 #if 0
8969 char buf[500];
8970 type_to_str(buf, sizeof(buf), t, get_tok_str(v, NULL));
8971 printf("type = '%s'\n", buf);
8973 #endif
8974 if ((type.t & VT_BTYPE) == VT_FUNC) {
8975 /* if old style function prototype, we accept a
8976 declaration list */
8977 sym = type.ref;
8978 if (sym->c == FUNC_OLD)
8979 func_decl_list(sym);
8982 if (tok == '{') {
8983 if (l == VT_LOCAL)
8984 error("cannot use local functions");
8985 if (!(type.t & VT_FUNC))
8986 expect("function definition");
8988 /* reject abstract declarators in function definition */
8989 sym = type.ref;
8990 while ((sym = sym->next) != NULL)
8991 if (!(sym->v & ~SYM_FIELD))
8992 expect("identifier");
8994 /* XXX: cannot do better now: convert extern line to static inline */
8995 if ((type.t & (VT_EXTERN | VT_INLINE)) == (VT_EXTERN | VT_INLINE))
8996 type.t = (type.t & ~VT_EXTERN) | VT_STATIC;
8998 sym = sym_find(v);
8999 if (sym) {
9000 if ((sym->type.t & VT_BTYPE) != VT_FUNC)
9001 goto func_error1;
9002 /* specific case: if not func_call defined, we put
9003 the one of the prototype */
9004 /* XXX: should have default value */
9005 if (sym->type.ref->r != FUNC_CDECL &&
9006 type.ref->r == FUNC_CDECL)
9007 type.ref->r = sym->type.ref->r;
9008 if (!is_compatible_types(&sym->type, &type)) {
9009 func_error1:
9010 error("incompatible types for redefinition of '%s'",
9011 get_tok_str(v, NULL));
9013 /* if symbol is already defined, then put complete type */
9014 sym->type = type;
9015 } else {
9016 /* put function symbol */
9017 sym = global_identifier_push(v, type.t, 0);
9018 sym->type.ref = type.ref;
9021 /* static inline functions are just recorded as a kind
9022 of macro. Their code will be emitted at the end of
9023 the compilation unit only if they are used */
9024 if ((type.t & (VT_INLINE | VT_STATIC)) ==
9025 (VT_INLINE | VT_STATIC)) {
9026 TokenString func_str;
9027 int block_level;
9029 tok_str_new(&func_str);
9031 block_level = 0;
9032 for(;;) {
9033 int t;
9034 if (tok == TOK_EOF)
9035 error("unexpected end of file");
9036 tok_str_add_tok(&func_str);
9037 t = tok;
9038 next();
9039 if (t == '{') {
9040 block_level++;
9041 } else if (t == '}') {
9042 block_level--;
9043 if (block_level == 0)
9044 break;
9047 tok_str_add(&func_str, -1);
9048 tok_str_add(&func_str, 0);
9049 sym->r = (int)func_str.str;
9050 } else {
9051 /* compute text section */
9052 cur_text_section = ad.section;
9053 if (!cur_text_section)
9054 cur_text_section = text_section;
9055 sym->r = VT_SYM | VT_CONST;
9056 gen_function(sym);
9057 #ifdef TCC_TARGET_PE
9058 if (ad.dllexport) {
9059 ((Elf32_Sym *)symtab_section->data)[sym->c].st_other |= 1;
9061 #endif
9063 break;
9064 } else {
9065 if (btype.t & VT_TYPEDEF) {
9066 /* save typedefed type */
9067 /* XXX: test storage specifiers ? */
9068 sym = sym_push(v, &type, 0, 0);
9069 sym->type.t |= VT_TYPEDEF;
9070 } else if ((type.t & VT_BTYPE) == VT_FUNC) {
9071 /* external function definition */
9072 /* specific case for func_call attribute */
9073 if (ad.func_call)
9074 type.ref->r = ad.func_call;
9075 external_sym(v, &type, 0);
9076 } else {
9077 /* not lvalue if array */
9078 r = 0;
9079 if (!(type.t & VT_ARRAY))
9080 r |= lvalue_type(type.t);
9081 has_init = (tok == '=');
9082 if ((btype.t & VT_EXTERN) ||
9083 ((type.t & VT_ARRAY) && (type.t & VT_STATIC) &&
9084 !has_init && l == VT_CONST && type.ref->c < 0)) {
9085 /* external variable */
9086 /* NOTE: as GCC, uninitialized global static
9087 arrays of null size are considered as
9088 extern */
9089 external_sym(v, &type, r);
9090 } else {
9091 if (type.t & VT_STATIC)
9092 r |= VT_CONST;
9093 else
9094 r |= l;
9095 if (has_init)
9096 next();
9097 decl_initializer_alloc(&type, &ad, r,
9098 has_init, v, l);
9101 if (tok != ',') {
9102 skip(';');
9103 break;
9105 next();
9111 /* better than nothing, but needs extension to handle '-E' option
9112 correctly too */
9113 static void preprocess_init(TCCState *s1)
9115 s1->include_stack_ptr = s1->include_stack;
9116 /* XXX: move that before to avoid having to initialize
9117 file->ifdef_stack_ptr ? */
9118 s1->ifdef_stack_ptr = s1->ifdef_stack;
9119 file->ifdef_stack_ptr = s1->ifdef_stack_ptr;
9121 /* XXX: not ANSI compliant: bound checking says error */
9122 vtop = vstack - 1;
9123 s1->pack_stack[0] = 0;
9124 s1->pack_stack_ptr = s1->pack_stack;
9127 /* compile the C file opened in 'file'. Return non zero if errors. */
9128 static int tcc_compile(TCCState *s1)
9130 Sym *define_start;
9131 char buf[512];
9132 volatile int section_sym;
9134 #ifdef INC_DEBUG
9135 printf("%s: **** new file\n", file->filename);
9136 #endif
9137 preprocess_init(s1);
9139 funcname = "";
9140 anon_sym = SYM_FIRST_ANOM;
9142 /* file info: full path + filename */
9143 section_sym = 0; /* avoid warning */
9144 if (do_debug) {
9145 section_sym = put_elf_sym(symtab_section, 0, 0,
9146 ELF32_ST_INFO(STB_LOCAL, STT_SECTION), 0,
9147 text_section->sh_num, NULL);
9148 getcwd(buf, sizeof(buf));
9149 pstrcat(buf, sizeof(buf), "/");
9150 put_stabs_r(buf, N_SO, 0, 0,
9151 text_section->data_offset, text_section, section_sym);
9152 put_stabs_r(file->filename, N_SO, 0, 0,
9153 text_section->data_offset, text_section, section_sym);
9155 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
9156 symbols can be safely used */
9157 put_elf_sym(symtab_section, 0, 0,
9158 ELF32_ST_INFO(STB_LOCAL, STT_FILE), 0,
9159 SHN_ABS, file->filename);
9161 /* define some often used types */
9162 int_type.t = VT_INT;
9164 char_pointer_type.t = VT_BYTE;
9165 mk_pointer(&char_pointer_type);
9167 func_old_type.t = VT_FUNC;
9168 func_old_type.ref = sym_push(SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD);
9170 #if 0
9171 /* define 'void *alloca(unsigned int)' builtin function */
9173 Sym *s1;
9175 p = anon_sym++;
9176 sym = sym_push(p, mk_pointer(VT_VOID), FUNC_CDECL, FUNC_NEW);
9177 s1 = sym_push(SYM_FIELD, VT_UNSIGNED | VT_INT, 0, 0);
9178 s1->next = NULL;
9179 sym->next = s1;
9180 sym_push(TOK_alloca, VT_FUNC | (p << VT_STRUCT_SHIFT), VT_CONST, 0);
9182 #endif
9184 define_start = define_stack;
9186 if (setjmp(s1->error_jmp_buf) == 0) {
9187 s1->nb_errors = 0;
9188 s1->error_set_jmp_enabled = 1;
9190 ch = file->buf_ptr[0];
9191 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
9192 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM;
9193 next();
9194 decl(VT_CONST);
9195 if (tok != TOK_EOF)
9196 expect("declaration");
9198 /* end of translation unit info */
9199 if (do_debug) {
9200 put_stabs_r(NULL, N_SO, 0, 0,
9201 text_section->data_offset, text_section, section_sym);
9204 s1->error_set_jmp_enabled = 0;
9206 /* reset define stack, but leave -Dsymbols (may be incorrect if
9207 they are undefined) */
9208 free_defines(define_start);
9210 gen_inline_functions();
9212 sym_pop(&global_stack, NULL);
9214 return s1->nb_errors != 0 ? -1 : 0;
9217 #ifdef LIBTCC
9218 int tcc_compile_string(TCCState *s, const char *str)
9220 BufferedFile bf1, *bf = &bf1;
9221 int ret, len;
9222 char *buf;
9224 /* init file structure */
9225 bf->fd = -1;
9226 /* XXX: avoid copying */
9227 len = strlen(str);
9228 buf = tcc_malloc(len + 1);
9229 if (!buf)
9230 return -1;
9231 memcpy(buf, str, len);
9232 buf[len] = CH_EOB;
9233 bf->buf_ptr = buf;
9234 bf->buf_end = buf + len;
9235 pstrcpy(bf->filename, sizeof(bf->filename), "<string>");
9236 bf->line_num = 1;
9237 file = bf;
9239 ret = tcc_compile(s);
9241 tcc_free(buf);
9243 /* currently, no need to close */
9244 return ret;
9246 #endif
9248 /* define a preprocessor symbol. A value can also be provided with the '=' operator */
9249 void tcc_define_symbol(TCCState *s1, const char *sym, const char *value)
9251 BufferedFile bf1, *bf = &bf1;
9253 pstrcpy(bf->buffer, IO_BUF_SIZE, sym);
9254 pstrcat(bf->buffer, IO_BUF_SIZE, " ");
9255 /* default value */
9256 if (!value)
9257 value = "1";
9258 pstrcat(bf->buffer, IO_BUF_SIZE, value);
9260 /* init file structure */
9261 bf->fd = -1;
9262 bf->buf_ptr = bf->buffer;
9263 bf->buf_end = bf->buffer + strlen(bf->buffer);
9264 *bf->buf_end = CH_EOB;
9265 bf->filename[0] = '\0';
9266 bf->line_num = 1;
9267 file = bf;
9269 s1->include_stack_ptr = s1->include_stack;
9271 /* parse with define parser */
9272 ch = file->buf_ptr[0];
9273 next_nomacro();
9274 parse_define();
9275 file = NULL;
9278 /* undefine a preprocessor symbol */
9279 void tcc_undefine_symbol(TCCState *s1, const char *sym)
9281 TokenSym *ts;
9282 Sym *s;
9283 ts = tok_alloc(sym, strlen(sym));
9284 s = define_find(ts->tok);
9285 /* undefine symbol by putting an invalid name */
9286 if (s)
9287 define_undef(s);
9290 #ifdef CONFIG_TCC_ASM
9292 #ifdef TCC_TARGET_I386
9293 #include "i386-asm.c"
9294 #endif
9295 #include "tccasm.c"
9297 #else
9298 static void asm_instr(void)
9300 error("inline asm() not supported");
9302 static void asm_global_instr(void)
9304 error("inline asm() not supported");
9306 #endif
9308 #include "tccelf.c"
9310 #ifdef TCC_TARGET_COFF
9311 #include "tcccoff.c"
9312 #endif
9314 #ifdef TCC_TARGET_PE
9315 #include "tccpe.c"
9316 #endif
9318 /* print the position in the source file of PC value 'pc' by reading
9319 the stabs debug information */
9320 static void rt_printline(unsigned long wanted_pc)
9322 Stab_Sym *sym, *sym_end;
9323 char func_name[128], last_func_name[128];
9324 unsigned long func_addr, last_pc, pc;
9325 const char *incl_files[INCLUDE_STACK_SIZE];
9326 int incl_index, len, last_line_num, i;
9327 const char *str, *p;
9329 fprintf(stderr, "0x%08lx:", wanted_pc);
9331 func_name[0] = '\0';
9332 func_addr = 0;
9333 incl_index = 0;
9334 last_func_name[0] = '\0';
9335 last_pc = 0xffffffff;
9336 last_line_num = 1;
9337 sym = (Stab_Sym *)stab_section->data + 1;
9338 sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset);
9339 while (sym < sym_end) {
9340 switch(sym->n_type) {
9341 /* function start or end */
9342 case N_FUN:
9343 if (sym->n_strx == 0) {
9344 /* we test if between last line and end of function */
9345 pc = sym->n_value + func_addr;
9346 if (wanted_pc >= last_pc && wanted_pc < pc)
9347 goto found;
9348 func_name[0] = '\0';
9349 func_addr = 0;
9350 } else {
9351 str = stabstr_section->data + sym->n_strx;
9352 p = strchr(str, ':');
9353 if (!p) {
9354 pstrcpy(func_name, sizeof(func_name), str);
9355 } else {
9356 len = p - str;
9357 if (len > sizeof(func_name) - 1)
9358 len = sizeof(func_name) - 1;
9359 memcpy(func_name, str, len);
9360 func_name[len] = '\0';
9362 func_addr = sym->n_value;
9364 break;
9365 /* line number info */
9366 case N_SLINE:
9367 pc = sym->n_value + func_addr;
9368 if (wanted_pc >= last_pc && wanted_pc < pc)
9369 goto found;
9370 last_pc = pc;
9371 last_line_num = sym->n_desc;
9372 /* XXX: slow! */
9373 strcpy(last_func_name, func_name);
9374 break;
9375 /* include files */
9376 case N_BINCL:
9377 str = stabstr_section->data + sym->n_strx;
9378 add_incl:
9379 if (incl_index < INCLUDE_STACK_SIZE) {
9380 incl_files[incl_index++] = str;
9382 break;
9383 case N_EINCL:
9384 if (incl_index > 1)
9385 incl_index--;
9386 break;
9387 case N_SO:
9388 if (sym->n_strx == 0) {
9389 incl_index = 0; /* end of translation unit */
9390 } else {
9391 str = stabstr_section->data + sym->n_strx;
9392 /* do not add path */
9393 len = strlen(str);
9394 if (len > 0 && str[len - 1] != '/')
9395 goto add_incl;
9397 break;
9399 sym++;
9402 /* second pass: we try symtab symbols (no line number info) */
9403 incl_index = 0;
9405 Elf32_Sym *sym, *sym_end;
9406 int type;
9408 sym_end = (Elf32_Sym *)(symtab_section->data + symtab_section->data_offset);
9409 for(sym = (Elf32_Sym *)symtab_section->data + 1;
9410 sym < sym_end;
9411 sym++) {
9412 type = ELF32_ST_TYPE(sym->st_info);
9413 if (type == STT_FUNC) {
9414 if (wanted_pc >= sym->st_value &&
9415 wanted_pc < sym->st_value + sym->st_size) {
9416 pstrcpy(last_func_name, sizeof(last_func_name),
9417 strtab_section->data + sym->st_name);
9418 goto found;
9423 /* did not find any info: */
9424 fprintf(stderr, " ???\n");
9425 return;
9426 found:
9427 if (last_func_name[0] != '\0') {
9428 fprintf(stderr, " %s()", last_func_name);
9430 if (incl_index > 0) {
9431 fprintf(stderr, " (%s:%d",
9432 incl_files[incl_index - 1], last_line_num);
9433 for(i = incl_index - 2; i >= 0; i--)
9434 fprintf(stderr, ", included from %s", incl_files[i]);
9435 fprintf(stderr, ")");
9437 fprintf(stderr, "\n");
9440 #if !defined(WIN32) && !defined(CONFIG_TCCBOOT)
9442 #ifdef __i386__
9444 /* fix for glibc 2.1 */
9445 #ifndef REG_EIP
9446 #define REG_EIP EIP
9447 #define REG_EBP EBP
9448 #endif
9450 /* return the PC at frame level 'level'. Return non zero if not found */
9451 static int rt_get_caller_pc(unsigned long *paddr,
9452 ucontext_t *uc, int level)
9454 unsigned long fp;
9455 int i;
9457 if (level == 0) {
9458 #if defined(__FreeBSD__)
9459 *paddr = uc->uc_mcontext.mc_eip;
9460 #elif defined(__dietlibc__)
9461 *paddr = uc->uc_mcontext.eip;
9462 #else
9463 *paddr = uc->uc_mcontext.gregs[REG_EIP];
9464 #endif
9465 return 0;
9466 } else {
9467 #if defined(__FreeBSD__)
9468 fp = uc->uc_mcontext.mc_ebp;
9469 #elif defined(__dietlibc__)
9470 fp = uc->uc_mcontext.ebp;
9471 #else
9472 fp = uc->uc_mcontext.gregs[REG_EBP];
9473 #endif
9474 for(i=1;i<level;i++) {
9475 /* XXX: check address validity with program info */
9476 if (fp <= 0x1000 || fp >= 0xc0000000)
9477 return -1;
9478 fp = ((unsigned long *)fp)[0];
9480 *paddr = ((unsigned long *)fp)[1];
9481 return 0;
9484 #else
9486 #warning add arch specific rt_get_caller_pc()
9488 static int rt_get_caller_pc(unsigned long *paddr,
9489 ucontext_t *uc, int level)
9491 return -1;
9493 #endif
9495 /* emit a run time error at position 'pc' */
9496 void rt_error(ucontext_t *uc, const char *fmt, ...)
9498 va_list ap;
9499 unsigned long pc;
9500 int i;
9502 va_start(ap, fmt);
9503 fprintf(stderr, "Runtime error: ");
9504 vfprintf(stderr, fmt, ap);
9505 fprintf(stderr, "\n");
9506 for(i=0;i<num_callers;i++) {
9507 if (rt_get_caller_pc(&pc, uc, i) < 0)
9508 break;
9509 if (i == 0)
9510 fprintf(stderr, "at ");
9511 else
9512 fprintf(stderr, "by ");
9513 rt_printline(pc);
9515 exit(255);
9516 va_end(ap);
9519 /* signal handler for fatal errors */
9520 static void sig_error(int signum, siginfo_t *siginf, void *puc)
9522 ucontext_t *uc = puc;
9524 switch(signum) {
9525 case SIGFPE:
9526 switch(siginf->si_code) {
9527 case FPE_INTDIV:
9528 case FPE_FLTDIV:
9529 rt_error(uc, "division by zero");
9530 break;
9531 default:
9532 rt_error(uc, "floating point exception");
9533 break;
9535 break;
9536 case SIGBUS:
9537 case SIGSEGV:
9538 if (rt_bound_error_msg && *rt_bound_error_msg)
9539 rt_error(uc, *rt_bound_error_msg);
9540 else
9541 rt_error(uc, "dereferencing invalid pointer");
9542 break;
9543 case SIGILL:
9544 rt_error(uc, "illegal instruction");
9545 break;
9546 case SIGABRT:
9547 rt_error(uc, "abort() called");
9548 break;
9549 default:
9550 rt_error(uc, "caught signal %d", signum);
9551 break;
9553 exit(255);
9555 #endif
9557 /* do all relocations (needed before using tcc_get_symbol()) */
9558 int tcc_relocate(TCCState *s1)
9560 Section *s;
9561 int i;
9563 s1->nb_errors = 0;
9565 #ifdef TCC_TARGET_PE
9566 pe_add_runtime(s1);
9567 #else
9568 tcc_add_runtime(s1);
9569 #endif
9571 relocate_common_syms();
9573 tcc_add_linker_symbols(s1);
9575 build_got_entries(s1);
9577 /* compute relocation address : section are relocated in place. We
9578 also alloc the bss space */
9579 for(i = 1; i < s1->nb_sections; i++) {
9580 s = s1->sections[i];
9581 if (s->sh_flags & SHF_ALLOC) {
9582 if (s->sh_type == SHT_NOBITS)
9583 s->data = tcc_mallocz(s->data_offset);
9584 s->sh_addr = (unsigned long)s->data;
9588 relocate_syms(s1, 1);
9590 if (s1->nb_errors != 0)
9591 return -1;
9593 /* relocate each section */
9594 for(i = 1; i < s1->nb_sections; i++) {
9595 s = s1->sections[i];
9596 if (s->reloc)
9597 relocate_section(s1, s);
9599 return 0;
9602 /* launch the compiled program with the given arguments */
9603 int tcc_run(TCCState *s1, int argc, char **argv)
9605 int (*prog_main)(int, char **);
9607 if (tcc_relocate(s1) < 0)
9608 return -1;
9610 prog_main = tcc_get_symbol_err(s1, "main");
9612 if (do_debug) {
9613 #if defined(WIN32) || defined(CONFIG_TCCBOOT)
9614 error("debug mode currently not available for Windows");
9615 #else
9616 struct sigaction sigact;
9617 /* install TCC signal handlers to print debug info on fatal
9618 runtime errors */
9619 sigact.sa_flags = SA_SIGINFO | SA_RESETHAND;
9620 sigact.sa_sigaction = sig_error;
9621 sigemptyset(&sigact.sa_mask);
9622 sigaction(SIGFPE, &sigact, NULL);
9623 sigaction(SIGILL, &sigact, NULL);
9624 sigaction(SIGSEGV, &sigact, NULL);
9625 sigaction(SIGBUS, &sigact, NULL);
9626 sigaction(SIGABRT, &sigact, NULL);
9627 #endif
9630 #ifdef CONFIG_TCC_BCHECK
9631 if (do_bounds_check) {
9632 void (*bound_init)(void);
9634 /* set error function */
9635 rt_bound_error_msg = (void *)tcc_get_symbol_err(s1,
9636 "__bound_error_msg");
9638 /* XXX: use .init section so that it also work in binary ? */
9639 bound_init = (void *)tcc_get_symbol_err(s1, "__bound_init");
9640 bound_init();
9642 #endif
9643 return (*prog_main)(argc, argv);
9646 TCCState *tcc_new(void)
9648 const char *p, *r;
9649 TCCState *s;
9650 TokenSym *ts;
9651 int i, c;
9653 s = tcc_mallocz(sizeof(TCCState));
9654 if (!s)
9655 return NULL;
9656 tcc_state = s;
9657 s->output_type = TCC_OUTPUT_MEMORY;
9659 /* init isid table */
9660 for(i=0;i<256;i++)
9661 isidnum_table[i] = isid(i) || isnum(i);
9663 /* add all tokens */
9664 table_ident = NULL;
9665 memset(hash_ident, 0, TOK_HASH_SIZE * sizeof(TokenSym *));
9667 tok_ident = TOK_IDENT;
9668 p = tcc_keywords;
9669 while (*p) {
9670 r = p;
9671 for(;;) {
9672 c = *r++;
9673 if (c == '\0')
9674 break;
9676 ts = tok_alloc(p, r - p - 1);
9677 p = r;
9680 /* we add dummy defines for some special macros to speed up tests
9681 and to have working defined() */
9682 define_push(TOK___LINE__, MACRO_OBJ, NULL, NULL);
9683 define_push(TOK___FILE__, MACRO_OBJ, NULL, NULL);
9684 define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL);
9685 define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL);
9687 /* standard defines */
9688 tcc_define_symbol(s, "__STDC__", NULL);
9689 #if defined(TCC_TARGET_I386)
9690 tcc_define_symbol(s, "__i386__", NULL);
9691 #endif
9692 #if defined(TCC_TARGET_ARM)
9693 tcc_define_symbol(s, "__ARM_ARCH_4__", NULL);
9694 tcc_define_symbol(s, "__arm_elf__", NULL);
9695 tcc_define_symbol(s, "__arm_elf", NULL);
9696 tcc_define_symbol(s, "arm_elf", NULL);
9697 tcc_define_symbol(s, "__arm__", NULL);
9698 tcc_define_symbol(s, "__arm", NULL);
9699 tcc_define_symbol(s, "arm", NULL);
9700 tcc_define_symbol(s, "__APCS_32__", NULL);
9701 #endif
9702 #if defined(linux)
9703 tcc_define_symbol(s, "__linux__", NULL);
9704 tcc_define_symbol(s, "linux", NULL);
9705 #endif
9706 /* tiny C specific defines */
9707 tcc_define_symbol(s, "__TINYC__", NULL);
9709 /* tiny C & gcc defines */
9710 tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned int");
9711 tcc_define_symbol(s, "__PTRDIFF_TYPE__", "int");
9712 tcc_define_symbol(s, "__WCHAR_TYPE__", "int");
9714 /* default library paths */
9715 #ifdef TCC_TARGET_PE
9717 char buf[1024];
9718 snprintf(buf, sizeof(buf), "%s/lib", tcc_lib_path);
9719 tcc_add_library_path(s, buf);
9721 #else
9722 tcc_add_library_path(s, "/usr/local/lib");
9723 tcc_add_library_path(s, "/usr/lib");
9724 tcc_add_library_path(s, "/lib");
9725 #endif
9727 /* no section zero */
9728 dynarray_add((void ***)&s->sections, &s->nb_sections, NULL);
9730 /* create standard sections */
9731 text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
9732 data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
9733 bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
9735 /* symbols are always generated for linking stage */
9736 symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0,
9737 ".strtab",
9738 ".hashtab", SHF_PRIVATE);
9739 strtab_section = symtab_section->link;
9741 /* private symbol table for dynamic symbols */
9742 s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE,
9743 ".dynstrtab",
9744 ".dynhashtab", SHF_PRIVATE);
9745 s->alacarte_link = 1;
9747 #ifdef CHAR_IS_UNSIGNED
9748 s->char_is_unsigned = 1;
9749 #endif
9750 #ifdef TCC_TARGET_PE
9751 s->leading_underscore = 1;
9752 #endif
9753 return s;
9756 void tcc_delete(TCCState *s1)
9758 int i, n;
9760 /* free -D defines */
9761 free_defines(NULL);
9763 /* free tokens */
9764 n = tok_ident - TOK_IDENT;
9765 for(i = 0; i < n; i++)
9766 tcc_free(table_ident[i]);
9767 tcc_free(table_ident);
9769 /* free all sections */
9771 free_section(symtab_section->hash);
9773 free_section(s1->dynsymtab_section->hash);
9774 free_section(s1->dynsymtab_section->link);
9775 free_section(s1->dynsymtab_section);
9777 for(i = 1; i < s1->nb_sections; i++)
9778 free_section(s1->sections[i]);
9779 tcc_free(s1->sections);
9781 /* free loaded dlls array */
9782 for(i = 0; i < s1->nb_loaded_dlls; i++)
9783 tcc_free(s1->loaded_dlls[i]);
9784 tcc_free(s1->loaded_dlls);
9786 /* library paths */
9787 for(i = 0; i < s1->nb_library_paths; i++)
9788 tcc_free(s1->library_paths[i]);
9789 tcc_free(s1->library_paths);
9791 /* cached includes */
9792 for(i = 0; i < s1->nb_cached_includes; i++)
9793 tcc_free(s1->cached_includes[i]);
9794 tcc_free(s1->cached_includes);
9796 for(i = 0; i < s1->nb_include_paths; i++)
9797 tcc_free(s1->include_paths[i]);
9798 tcc_free(s1->include_paths);
9800 for(i = 0; i < s1->nb_sysinclude_paths; i++)
9801 tcc_free(s1->sysinclude_paths[i]);
9802 tcc_free(s1->sysinclude_paths);
9804 tcc_free(s1);
9807 int tcc_add_include_path(TCCState *s1, const char *pathname)
9809 char *pathname1;
9811 pathname1 = tcc_strdup(pathname);
9812 dynarray_add((void ***)&s1->include_paths, &s1->nb_include_paths, pathname1);
9813 return 0;
9816 int tcc_add_sysinclude_path(TCCState *s1, const char *pathname)
9818 char *pathname1;
9820 pathname1 = tcc_strdup(pathname);
9821 dynarray_add((void ***)&s1->sysinclude_paths, &s1->nb_sysinclude_paths, pathname1);
9822 return 0;
9825 static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
9827 const char *ext, *filename1;
9828 Elf32_Ehdr ehdr;
9829 int fd, ret;
9830 BufferedFile *saved_file;
9832 /* find source file type with extension */
9833 filename1 = strrchr(filename, '/');
9834 if (filename1)
9835 filename1++;
9836 else
9837 filename1 = filename;
9838 ext = strrchr(filename1, '.');
9839 if (ext)
9840 ext++;
9842 /* open the file */
9843 saved_file = file;
9844 file = tcc_open(s1, filename);
9845 if (!file) {
9846 if (flags & AFF_PRINT_ERROR) {
9847 error_noabort("file '%s' not found", filename);
9849 ret = -1;
9850 goto fail1;
9853 if (!ext || !strcmp(ext, "c")) {
9854 /* C file assumed */
9855 ret = tcc_compile(s1);
9856 } else
9857 #ifdef CONFIG_TCC_ASM
9858 if (!strcmp(ext, "S")) {
9859 /* preprocessed assembler */
9860 ret = tcc_assemble(s1, 1);
9861 } else if (!strcmp(ext, "s")) {
9862 /* non preprocessed assembler */
9863 ret = tcc_assemble(s1, 0);
9864 } else
9865 #endif
9866 #ifdef TCC_TARGET_PE
9867 if (!strcmp(ext, "def")) {
9868 ret = pe_load_def_file(s1, fdopen(file->fd, "rb"));
9869 } else
9870 #endif
9872 fd = file->fd;
9873 /* assume executable format: auto guess file type */
9874 ret = read(fd, &ehdr, sizeof(ehdr));
9875 lseek(fd, 0, SEEK_SET);
9876 if (ret <= 0) {
9877 error_noabort("could not read header");
9878 goto fail;
9879 } else if (ret != sizeof(ehdr)) {
9880 goto try_load_script;
9883 if (ehdr.e_ident[0] == ELFMAG0 &&
9884 ehdr.e_ident[1] == ELFMAG1 &&
9885 ehdr.e_ident[2] == ELFMAG2 &&
9886 ehdr.e_ident[3] == ELFMAG3) {
9887 file->line_num = 0; /* do not display line number if error */
9888 if (ehdr.e_type == ET_REL) {
9889 ret = tcc_load_object_file(s1, fd, 0);
9890 } else if (ehdr.e_type == ET_DYN) {
9891 if (s1->output_type == TCC_OUTPUT_MEMORY) {
9892 #ifdef TCC_TARGET_PE
9893 ret = -1;
9894 #else
9895 void *h;
9896 h = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY);
9897 if (h)
9898 ret = 0;
9899 else
9900 ret = -1;
9901 #endif
9902 } else {
9903 ret = tcc_load_dll(s1, fd, filename,
9904 (flags & AFF_REFERENCED_DLL) != 0);
9906 } else {
9907 error_noabort("unrecognized ELF file");
9908 goto fail;
9910 } else if (memcmp((char *)&ehdr, ARMAG, 8) == 0) {
9911 file->line_num = 0; /* do not display line number if error */
9912 ret = tcc_load_archive(s1, fd);
9913 } else
9914 #ifdef TCC_TARGET_COFF
9915 if (*(uint16_t *)(&ehdr) == COFF_C67_MAGIC) {
9916 ret = tcc_load_coff(s1, fd);
9917 } else
9918 #endif
9920 /* as GNU ld, consider it is an ld script if not recognized */
9921 try_load_script:
9922 ret = tcc_load_ldscript(s1);
9923 if (ret < 0) {
9924 error_noabort("unrecognized file type");
9925 goto fail;
9929 the_end:
9930 tcc_close(file);
9931 fail1:
9932 file = saved_file;
9933 return ret;
9934 fail:
9935 ret = -1;
9936 goto the_end;
9939 int tcc_add_file(TCCState *s, const char *filename)
9941 return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR);
9944 int tcc_add_library_path(TCCState *s, const char *pathname)
9946 char *pathname1;
9948 pathname1 = tcc_strdup(pathname);
9949 dynarray_add((void ***)&s->library_paths, &s->nb_library_paths, pathname1);
9950 return 0;
9953 /* find and load a dll. Return non zero if not found */
9954 /* XXX: add '-rpath' option support ? */
9955 static int tcc_add_dll(TCCState *s, const char *filename, int flags)
9957 char buf[1024];
9958 int i;
9960 for(i = 0; i < s->nb_library_paths; i++) {
9961 snprintf(buf, sizeof(buf), "%s/%s",
9962 s->library_paths[i], filename);
9963 if (tcc_add_file_internal(s, buf, flags) == 0)
9964 return 0;
9966 return -1;
9969 /* the library name is the same as the argument of the '-l' option */
9970 int tcc_add_library(TCCState *s, const char *libraryname)
9972 char buf[1024];
9973 int i;
9975 /* first we look for the dynamic library if not static linking */
9976 if (!s->static_link) {
9977 #ifdef TCC_TARGET_PE
9978 snprintf(buf, sizeof(buf), "%s.def", libraryname);
9979 #else
9980 snprintf(buf, sizeof(buf), "lib%s.so", libraryname);
9981 #endif
9982 if (tcc_add_dll(s, buf, 0) == 0)
9983 return 0;
9986 /* then we look for the static library */
9987 for(i = 0; i < s->nb_library_paths; i++) {
9988 snprintf(buf, sizeof(buf), "%s/lib%s.a",
9989 s->library_paths[i], libraryname);
9990 if (tcc_add_file_internal(s, buf, 0) == 0)
9991 return 0;
9993 return -1;
9996 int tcc_add_symbol(TCCState *s, const char *name, unsigned long val)
9998 add_elf_sym(symtab_section, val, 0,
9999 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
10000 SHN_ABS, name);
10001 return 0;
10004 int tcc_set_output_type(TCCState *s, int output_type)
10006 s->output_type = output_type;
10008 if (!s->nostdinc) {
10009 char buf[1024];
10011 /* default include paths */
10012 /* XXX: reverse order needed if -isystem support */
10013 #ifndef TCC_TARGET_PE
10014 tcc_add_sysinclude_path(s, "/usr/local/include");
10015 tcc_add_sysinclude_path(s, "/usr/include");
10016 #endif
10017 snprintf(buf, sizeof(buf), "%s/include", tcc_lib_path);
10018 tcc_add_sysinclude_path(s, buf);
10019 #ifdef TCC_TARGET_PE
10020 snprintf(buf, sizeof(buf), "%s/include/winapi", tcc_lib_path);
10021 tcc_add_sysinclude_path(s, buf);
10022 #endif
10025 /* if bound checking, then add corresponding sections */
10026 #ifdef CONFIG_TCC_BCHECK
10027 if (do_bounds_check) {
10028 /* define symbol */
10029 tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL);
10030 /* create bounds sections */
10031 bounds_section = new_section(s, ".bounds",
10032 SHT_PROGBITS, SHF_ALLOC);
10033 lbounds_section = new_section(s, ".lbounds",
10034 SHT_PROGBITS, SHF_ALLOC);
10036 #endif
10038 if (s->char_is_unsigned) {
10039 tcc_define_symbol(s, "__CHAR_UNSIGNED__", NULL);
10042 /* add debug sections */
10043 if (do_debug) {
10044 /* stab symbols */
10045 stab_section = new_section(s, ".stab", SHT_PROGBITS, 0);
10046 stab_section->sh_entsize = sizeof(Stab_Sym);
10047 stabstr_section = new_section(s, ".stabstr", SHT_STRTAB, 0);
10048 put_elf_str(stabstr_section, "");
10049 stab_section->link = stabstr_section;
10050 /* put first entry */
10051 put_stabs("", 0, 0, 0, 0);
10054 /* add libc crt1/crti objects */
10055 #ifndef TCC_TARGET_PE
10056 if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) &&
10057 !s->nostdlib) {
10058 if (output_type != TCC_OUTPUT_DLL)
10059 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crt1.o");
10060 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crti.o");
10062 #endif
10063 return 0;
10066 #define WD_ALL 0x0001 /* warning is activated when using -Wall */
10067 #define FD_INVERT 0x0002 /* invert value before storing */
10069 typedef struct FlagDef {
10070 uint16_t offset;
10071 uint16_t flags;
10072 const char *name;
10073 } FlagDef;
10075 static const FlagDef warning_defs[] = {
10076 { offsetof(TCCState, warn_unsupported), 0, "unsupported" },
10077 { offsetof(TCCState, warn_write_strings), 0, "write-strings" },
10078 { offsetof(TCCState, warn_error), 0, "error" },
10079 { offsetof(TCCState, warn_implicit_function_declaration), WD_ALL,
10080 "implicit-function-declaration" },
10083 static int set_flag(TCCState *s, const FlagDef *flags, int nb_flags,
10084 const char *name, int value)
10086 int i;
10087 const FlagDef *p;
10088 const char *r;
10090 r = name;
10091 if (r[0] == 'n' && r[1] == 'o' && r[2] == '-') {
10092 r += 3;
10093 value = !value;
10095 for(i = 0, p = flags; i < nb_flags; i++, p++) {
10096 if (!strcmp(r, p->name))
10097 goto found;
10099 return -1;
10100 found:
10101 if (p->flags & FD_INVERT)
10102 value = !value;
10103 *(int *)((uint8_t *)s + p->offset) = value;
10104 return 0;
10108 /* set/reset a warning */
10109 int tcc_set_warning(TCCState *s, const char *warning_name, int value)
10111 int i;
10112 const FlagDef *p;
10114 if (!strcmp(warning_name, "all")) {
10115 for(i = 0, p = warning_defs; i < countof(warning_defs); i++, p++) {
10116 if (p->flags & WD_ALL)
10117 *(int *)((uint8_t *)s + p->offset) = 1;
10119 return 0;
10120 } else {
10121 return set_flag(s, warning_defs, countof(warning_defs),
10122 warning_name, value);
10126 static const FlagDef flag_defs[] = {
10127 { offsetof(TCCState, char_is_unsigned), 0, "unsigned-char" },
10128 { offsetof(TCCState, char_is_unsigned), FD_INVERT, "signed-char" },
10129 { offsetof(TCCState, nocommon), FD_INVERT, "common" },
10130 { offsetof(TCCState, leading_underscore), 0, "leading-underscore" },
10133 /* set/reset a flag */
10134 int tcc_set_flag(TCCState *s, const char *flag_name, int value)
10136 return set_flag(s, flag_defs, countof(flag_defs),
10137 flag_name, value);
10140 #if !defined(LIBTCC)
10142 /* extract the basename of a file */
10143 static const char *tcc_basename(const char *name)
10145 const char *p;
10146 p = strrchr(name, '/');
10147 #ifdef WIN32
10148 if (!p)
10149 p = strrchr(name, '\\');
10150 #endif
10151 if (!p)
10152 p = name;
10153 else
10154 p++;
10155 return p;
10158 static int64_t getclock_us(void)
10160 #ifdef WIN32
10161 struct _timeb tb;
10162 _ftime(&tb);
10163 return (tb.time * 1000LL + tb.millitm) * 1000LL;
10164 #else
10165 struct timeval tv;
10166 gettimeofday(&tv, NULL);
10167 return tv.tv_sec * 1000000LL + tv.tv_usec;
10168 #endif
10171 void help(void)
10173 printf("tcc version " TCC_VERSION " - Tiny C Compiler - Copyright (C) 2001-2005 Fabrice Bellard\n"
10174 "usage: tcc [-v] [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
10175 " [-Wwarn] [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-static]\n"
10176 " [infile1 infile2...] [-run infile args...]\n"
10177 "\n"
10178 "General options:\n"
10179 " -v display current version\n"
10180 " -c compile only - generate an object file\n"
10181 " -o outfile set output filename\n"
10182 " -Bdir set tcc internal library path\n"
10183 " -bench output compilation statistics\n"
10184 " -run run compiled source\n"
10185 " -fflag set or reset (with 'no-' prefix) 'flag' (see man page)\n"
10186 " -Wwarning set or reset (with 'no-' prefix) 'warning' (see man page)\n"
10187 " -w disable all warnings\n"
10188 "Preprocessor options:\n"
10189 " -Idir add include path 'dir'\n"
10190 " -Dsym[=val] define 'sym' with value 'val'\n"
10191 " -Usym undefine 'sym'\n"
10192 "Linker options:\n"
10193 " -Ldir add library path 'dir'\n"
10194 " -llib link with dynamic or static library 'lib'\n"
10195 " -shared generate a shared library\n"
10196 " -static static linking\n"
10197 " -rdynamic export all global symbols to dynamic linker\n"
10198 " -r relocatable output\n"
10199 "Debugger options:\n"
10200 " -g generate runtime debug info\n"
10201 #ifdef CONFIG_TCC_BCHECK
10202 " -b compile with built-in memory and bounds checker (implies -g)\n"
10203 #endif
10204 " -bt N show N callers in stack traces\n"
10208 #define TCC_OPTION_HAS_ARG 0x0001
10209 #define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
10211 typedef struct TCCOption {
10212 const char *name;
10213 uint16_t index;
10214 uint16_t flags;
10215 } TCCOption;
10217 enum {
10218 TCC_OPTION_HELP,
10219 TCC_OPTION_I,
10220 TCC_OPTION_D,
10221 TCC_OPTION_U,
10222 TCC_OPTION_L,
10223 TCC_OPTION_B,
10224 TCC_OPTION_l,
10225 TCC_OPTION_bench,
10226 TCC_OPTION_bt,
10227 TCC_OPTION_b,
10228 TCC_OPTION_g,
10229 TCC_OPTION_c,
10230 TCC_OPTION_static,
10231 TCC_OPTION_shared,
10232 TCC_OPTION_o,
10233 TCC_OPTION_r,
10234 TCC_OPTION_Wl,
10235 TCC_OPTION_W,
10236 TCC_OPTION_O,
10237 TCC_OPTION_m,
10238 TCC_OPTION_f,
10239 TCC_OPTION_nostdinc,
10240 TCC_OPTION_nostdlib,
10241 TCC_OPTION_print_search_dirs,
10242 TCC_OPTION_rdynamic,
10243 TCC_OPTION_run,
10244 TCC_OPTION_v,
10245 TCC_OPTION_w,
10246 TCC_OPTION_pipe,
10249 static const TCCOption tcc_options[] = {
10250 { "h", TCC_OPTION_HELP, 0 },
10251 { "?", TCC_OPTION_HELP, 0 },
10252 { "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG },
10253 { "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG },
10254 { "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG },
10255 { "L", TCC_OPTION_L, TCC_OPTION_HAS_ARG },
10256 { "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG },
10257 { "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10258 { "bench", TCC_OPTION_bench, 0 },
10259 { "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG },
10260 #ifdef CONFIG_TCC_BCHECK
10261 { "b", TCC_OPTION_b, 0 },
10262 #endif
10263 { "g", TCC_OPTION_g, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10264 { "c", TCC_OPTION_c, 0 },
10265 { "static", TCC_OPTION_static, 0 },
10266 { "shared", TCC_OPTION_shared, 0 },
10267 { "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG },
10268 { "run", TCC_OPTION_run, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10269 { "rdynamic", TCC_OPTION_rdynamic, 0 },
10270 { "r", TCC_OPTION_r, 0 },
10271 { "Wl,", TCC_OPTION_Wl, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10272 { "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10273 { "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10274 { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG },
10275 { "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10276 { "nostdinc", TCC_OPTION_nostdinc, 0 },
10277 { "nostdlib", TCC_OPTION_nostdlib, 0 },
10278 { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 },
10279 { "v", TCC_OPTION_v, 0 },
10280 { "w", TCC_OPTION_w, 0 },
10281 { "pipe", TCC_OPTION_pipe, 0},
10282 { NULL },
10285 /* convert 'str' into an array of space separated strings */
10286 static int expand_args(char ***pargv, const char *str)
10288 const char *s1;
10289 char **argv, *arg;
10290 int argc, len;
10292 argc = 0;
10293 argv = NULL;
10294 for(;;) {
10295 while (is_space(*str))
10296 str++;
10297 if (*str == '\0')
10298 break;
10299 s1 = str;
10300 while (*str != '\0' && !is_space(*str))
10301 str++;
10302 len = str - s1;
10303 arg = tcc_malloc(len + 1);
10304 memcpy(arg, s1, len);
10305 arg[len] = '\0';
10306 dynarray_add((void ***)&argv, &argc, arg);
10308 *pargv = argv;
10309 return argc;
10312 static char **files;
10313 static int nb_files, nb_libraries;
10314 static int multiple_files;
10315 static int print_search_dirs;
10316 static int output_type;
10317 static int reloc_output;
10318 static const char *outfile;
10320 int parse_args(TCCState *s, int argc, char **argv)
10322 int optind;
10323 const TCCOption *popt;
10324 const char *optarg, *p1, *r1;
10325 char *r;
10327 optind = 0;
10328 while (1) {
10329 if (optind >= argc) {
10330 if (nb_files == 0 && !print_search_dirs)
10331 goto show_help;
10332 else
10333 break;
10335 r = argv[optind++];
10336 if (r[0] != '-') {
10337 /* add a new file */
10338 dynarray_add((void ***)&files, &nb_files, r);
10339 if (!multiple_files) {
10340 optind--;
10341 /* argv[0] will be this file */
10342 break;
10344 } else {
10345 /* find option in table (match only the first chars */
10346 popt = tcc_options;
10347 for(;;) {
10348 p1 = popt->name;
10349 if (p1 == NULL)
10350 error("invalid option -- '%s'", r);
10351 r1 = r + 1;
10352 for(;;) {
10353 if (*p1 == '\0')
10354 goto option_found;
10355 if (*r1 != *p1)
10356 break;
10357 p1++;
10358 r1++;
10360 popt++;
10362 option_found:
10363 if (popt->flags & TCC_OPTION_HAS_ARG) {
10364 if (*r1 != '\0' || (popt->flags & TCC_OPTION_NOSEP)) {
10365 optarg = r1;
10366 } else {
10367 if (optind >= argc)
10368 error("argument to '%s' is missing", r);
10369 optarg = argv[optind++];
10371 } else {
10372 if (*r1 != '\0')
10373 goto show_help;
10374 optarg = NULL;
10377 switch(popt->index) {
10378 case TCC_OPTION_HELP:
10379 show_help:
10380 help();
10381 exit(1);
10382 case TCC_OPTION_I:
10383 if (tcc_add_include_path(s, optarg) < 0)
10384 error("too many include paths");
10385 break;
10386 case TCC_OPTION_D:
10388 char *sym, *value;
10389 sym = (char *)optarg;
10390 value = strchr(sym, '=');
10391 if (value) {
10392 *value = '\0';
10393 value++;
10395 tcc_define_symbol(s, sym, value);
10397 break;
10398 case TCC_OPTION_U:
10399 tcc_undefine_symbol(s, optarg);
10400 break;
10401 case TCC_OPTION_L:
10402 tcc_add_library_path(s, optarg);
10403 break;
10404 case TCC_OPTION_B:
10405 /* set tcc utilities path (mainly for tcc development) */
10406 tcc_lib_path = optarg;
10407 break;
10408 case TCC_OPTION_l:
10409 dynarray_add((void ***)&files, &nb_files, r);
10410 nb_libraries++;
10411 break;
10412 case TCC_OPTION_bench:
10413 do_bench = 1;
10414 break;
10415 case TCC_OPTION_bt:
10416 num_callers = atoi(optarg);
10417 break;
10418 #ifdef CONFIG_TCC_BCHECK
10419 case TCC_OPTION_b:
10420 do_bounds_check = 1;
10421 do_debug = 1;
10422 break;
10423 #endif
10424 case TCC_OPTION_g:
10425 do_debug = 1;
10426 break;
10427 case TCC_OPTION_c:
10428 multiple_files = 1;
10429 output_type = TCC_OUTPUT_OBJ;
10430 break;
10431 case TCC_OPTION_static:
10432 s->static_link = 1;
10433 break;
10434 case TCC_OPTION_shared:
10435 output_type = TCC_OUTPUT_DLL;
10436 break;
10437 case TCC_OPTION_o:
10438 multiple_files = 1;
10439 outfile = optarg;
10440 break;
10441 case TCC_OPTION_r:
10442 /* generate a .o merging several output files */
10443 reloc_output = 1;
10444 output_type = TCC_OUTPUT_OBJ;
10445 break;
10446 case TCC_OPTION_nostdinc:
10447 s->nostdinc = 1;
10448 break;
10449 case TCC_OPTION_nostdlib:
10450 s->nostdlib = 1;
10451 break;
10452 case TCC_OPTION_print_search_dirs:
10453 print_search_dirs = 1;
10454 break;
10455 case TCC_OPTION_run:
10457 int argc1;
10458 char **argv1;
10459 argc1 = expand_args(&argv1, optarg);
10460 if (argc1 > 0) {
10461 parse_args(s, argc1, argv1);
10463 multiple_files = 0;
10464 output_type = TCC_OUTPUT_MEMORY;
10466 break;
10467 case TCC_OPTION_v:
10468 printf("tcc version %s\n", TCC_VERSION);
10469 exit(0);
10470 case TCC_OPTION_f:
10471 if (tcc_set_flag(s, optarg, 1) < 0 && s->warn_unsupported)
10472 goto unsupported_option;
10473 break;
10474 case TCC_OPTION_W:
10475 if (tcc_set_warning(s, optarg, 1) < 0 &&
10476 s->warn_unsupported)
10477 goto unsupported_option;
10478 break;
10479 case TCC_OPTION_w:
10480 s->warn_none = 1;
10481 break;
10482 case TCC_OPTION_rdynamic:
10483 s->rdynamic = 1;
10484 break;
10485 case TCC_OPTION_Wl:
10487 const char *p;
10488 if (strstart(optarg, "-Ttext,", &p)) {
10489 s->text_addr = strtoul(p, NULL, 16);
10490 s->has_text_addr = 1;
10491 } else if (strstart(optarg, "--oformat,", &p)) {
10492 if (strstart(p, "elf32-", NULL)) {
10493 s->output_format = TCC_OUTPUT_FORMAT_ELF;
10494 } else if (!strcmp(p, "binary")) {
10495 s->output_format = TCC_OUTPUT_FORMAT_BINARY;
10496 } else
10497 #ifdef TCC_TARGET_COFF
10498 if (!strcmp(p, "coff")) {
10499 s->output_format = TCC_OUTPUT_FORMAT_COFF;
10500 } else
10501 #endif
10503 error("target %s not found", p);
10505 } else {
10506 error("unsupported linker option '%s'", optarg);
10509 break;
10510 default:
10511 if (s->warn_unsupported) {
10512 unsupported_option:
10513 warning("unsupported option '%s'", r);
10515 break;
10519 return optind;
10522 int main(int argc, char **argv)
10524 int i;
10525 TCCState *s;
10526 int nb_objfiles, ret, optind;
10527 char objfilename[1024];
10528 int64_t start_time = 0;
10530 #ifdef WIN32
10531 /* on win32, we suppose the lib and includes are at the location
10532 of 'tcc.exe' */
10534 static char path[1024];
10535 char *p, *d;
10537 GetModuleFileNameA(NULL, path, sizeof path);
10538 p = d = strlwr(path);
10539 while (*d)
10541 if (*d == '\\') *d = '/', p = d;
10542 ++d;
10544 *p = '\0';
10545 tcc_lib_path = path;
10547 #endif
10549 s = tcc_new();
10550 output_type = TCC_OUTPUT_EXE;
10551 outfile = NULL;
10552 multiple_files = 1;
10553 files = NULL;
10554 nb_files = 0;
10555 nb_libraries = 0;
10556 reloc_output = 0;
10557 print_search_dirs = 0;
10559 optind = parse_args(s, argc - 1, argv + 1) + 1;
10561 if (print_search_dirs) {
10562 /* enough for Linux kernel */
10563 printf("install: %s/\n", tcc_lib_path);
10564 return 0;
10567 nb_objfiles = nb_files - nb_libraries;
10569 /* if outfile provided without other options, we output an
10570 executable */
10571 if (outfile && output_type == TCC_OUTPUT_MEMORY)
10572 output_type = TCC_OUTPUT_EXE;
10574 /* check -c consistency : only single file handled. XXX: checks file type */
10575 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
10576 /* accepts only a single input file */
10577 if (nb_objfiles != 1)
10578 error("cannot specify multiple files with -c");
10579 if (nb_libraries != 0)
10580 error("cannot specify libraries with -c");
10583 if (output_type != TCC_OUTPUT_MEMORY) {
10584 if (!outfile) {
10585 /* compute default outfile name */
10586 pstrcpy(objfilename, sizeof(objfilename) - 1,
10587 /* strip path */
10588 tcc_basename(files[0]));
10589 #ifdef TCC_TARGET_PE
10590 pe_guess_outfile(objfilename, output_type);
10591 #else
10592 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
10593 char *ext = strrchr(objfilename, '.');
10594 if (!ext)
10595 goto default_outfile;
10596 /* add .o extension */
10597 strcpy(ext + 1, "o");
10598 } else {
10599 default_outfile:
10600 pstrcpy(objfilename, sizeof(objfilename), "a.out");
10602 #endif
10603 outfile = objfilename;
10607 if (do_bench) {
10608 start_time = getclock_us();
10611 tcc_set_output_type(s, output_type);
10613 /* compile or add each files or library */
10614 for(i = 0;i < nb_files; i++) {
10615 const char *filename;
10617 filename = files[i];
10618 if (filename[0] == '-') {
10619 if (tcc_add_library(s, filename + 2) < 0)
10620 error("cannot find %s", filename);
10621 } else {
10622 if (tcc_add_file(s, filename) < 0) {
10623 ret = 1;
10624 goto the_end;
10629 /* free all files */
10630 tcc_free(files);
10632 if (do_bench) {
10633 double total_time;
10634 total_time = (double)(getclock_us() - start_time) / 1000000.0;
10635 if (total_time < 0.001)
10636 total_time = 0.001;
10637 if (total_bytes < 1)
10638 total_bytes = 1;
10639 printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
10640 tok_ident - TOK_IDENT, total_lines, total_bytes,
10641 total_time, (int)(total_lines / total_time),
10642 total_bytes / total_time / 1000000.0);
10645 if (s->output_type == TCC_OUTPUT_MEMORY) {
10646 ret = tcc_run(s, argc - optind, argv + optind);
10647 } else
10648 #ifdef TCC_TARGET_PE
10649 if (s->output_type != TCC_OUTPUT_OBJ) {
10650 ret = tcc_output_pe(s, outfile);
10651 } else
10652 #endif
10654 tcc_output_file(s, outfile);
10655 ret = 0;
10657 the_end:
10658 /* XXX: cannot do it with bound checking because of the malloc hooks */
10659 if (!do_bounds_check)
10660 tcc_delete(s);
10662 #ifdef MEM_DEBUG
10663 if (do_bench) {
10664 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size, mem_max_size);
10666 #endif
10667 return ret;
10670 #endif