update
[tinycc.git] / tcc.c
blobd7417e28099ee2f79971a7a4836f607a296a961f
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 struct macro_level {
768 struct macro_level *prev;
769 int *p;
772 static void macro_subst(TokenString *tok_str, Sym **nested_list,
773 const int *macro_str, struct macro_level **can_read_stream);
774 void gen_op(int op);
775 void force_charshort_cast(int t);
776 static void gen_cast(CType *type);
777 void vstore(void);
778 static Sym *sym_find(int v);
779 static Sym *sym_push(int v, CType *type, int r, int c);
781 /* type handling */
782 static int type_size(CType *type, int *a);
783 static inline CType *pointed_type(CType *type);
784 static int pointed_size(CType *type);
785 static int lvalue_type(int t);
786 static int parse_btype(CType *type, AttributeDef *ad);
787 static void type_decl(CType *type, AttributeDef *ad, int *v, int td);
788 static int is_compatible_types(CType *type1, CType *type2);
790 int ieee_finite(double d);
791 void error(const char *fmt, ...);
792 void vpushi(int v);
793 void vrott(int n);
794 void vnrott(int n);
795 void lexpand_nr(void);
796 static void vpush_global_sym(CType *type, int v);
797 void vset(CType *type, int r, int v);
798 void type_to_str(char *buf, int buf_size,
799 CType *type, const char *varstr);
800 char *get_tok_str(int v, CValue *cv);
801 static Sym *get_sym_ref(CType *type, Section *sec,
802 unsigned long offset, unsigned long size);
803 static Sym *external_global_sym(int v, CType *type, int r);
805 /* section generation */
806 static void section_realloc(Section *sec, unsigned long new_size);
807 static void *section_ptr_add(Section *sec, unsigned long size);
808 static void put_extern_sym(Sym *sym, Section *section,
809 unsigned long value, unsigned long size);
810 static void greloc(Section *s, Sym *sym, unsigned long addr, int type);
811 static int put_elf_str(Section *s, const char *sym);
812 static int put_elf_sym(Section *s,
813 unsigned long value, unsigned long size,
814 int info, int other, int shndx, const char *name);
815 static int add_elf_sym(Section *s, unsigned long value, unsigned long size,
816 int info, int other, int sh_num, const char *name);
817 static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
818 int type, int symbol);
819 static void put_stabs(const char *str, int type, int other, int desc,
820 unsigned long value);
821 static void put_stabs_r(const char *str, int type, int other, int desc,
822 unsigned long value, Section *sec, int sym_index);
823 static void put_stabn(int type, int other, int desc, int value);
824 static void put_stabd(int type, int other, int desc);
825 static int tcc_add_dll(TCCState *s, const char *filename, int flags);
827 #define AFF_PRINT_ERROR 0x0001 /* print error if file not found */
828 #define AFF_REFERENCED_DLL 0x0002 /* load a referenced dll from another dll */
829 static int tcc_add_file_internal(TCCState *s, const char *filename, int flags);
831 /* tcccoff.c */
832 int tcc_output_coff(TCCState *s1, FILE *f);
834 /* tccpe.c */
835 void *resolve_sym(TCCState *s1, const char *sym, int type);
836 int pe_load_def_file(struct TCCState *s1, FILE *fp);
837 void pe_setup_paths(struct TCCState *s1, int *p_output_type, const char **p_outfile, char *first_file);
838 unsigned long pe_add_runtime(struct TCCState *s1);
839 int tcc_output_pe(struct TCCState *s1, const char *filename);
841 /* tccasm.c */
843 #ifdef CONFIG_TCC_ASM
845 typedef struct ExprValue {
846 uint32_t v;
847 Sym *sym;
848 } ExprValue;
850 #define MAX_ASM_OPERANDS 30
852 typedef struct ASMOperand {
853 int id; /* GCC 3 optionnal identifier (0 if number only supported */
854 char *constraint;
855 char asm_str[16]; /* computed asm string for operand */
856 SValue *vt; /* C value of the expression */
857 int ref_index; /* if >= 0, gives reference to a output constraint */
858 int input_index; /* if >= 0, gives reference to an input constraint */
859 int priority; /* priority, used to assign registers */
860 int reg; /* if >= 0, register number used for this operand */
861 int is_llong; /* true if double register value */
862 int is_memory; /* true if memory operand */
863 int is_rw; /* for '+' modifier */
864 } ASMOperand;
866 static void asm_expr(TCCState *s1, ExprValue *pe);
867 static int asm_int_expr(TCCState *s1);
868 static int find_constraint(ASMOperand *operands, int nb_operands,
869 const char *name, const char **pp);
871 static int tcc_assemble(TCCState *s1, int do_preprocess);
873 #endif
875 static void asm_instr(void);
876 static void asm_global_instr(void);
878 /* true if float/double/long double type */
879 static inline int is_float(int t)
881 int bt;
882 bt = t & VT_BTYPE;
883 return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT;
886 #ifdef TCC_TARGET_I386
887 #include "i386-gen.c"
888 #endif
890 #ifdef TCC_TARGET_ARM
891 #include "arm-gen.c"
892 #endif
894 #ifdef TCC_TARGET_C67
895 #include "c67-gen.c"
896 #endif
898 #ifdef CONFIG_TCC_STATIC
900 #define RTLD_LAZY 0x001
901 #define RTLD_NOW 0x002
902 #define RTLD_GLOBAL 0x100
903 #define RTLD_DEFAULT NULL
905 /* dummy function for profiling */
906 void *dlopen(const char *filename, int flag)
908 return NULL;
911 const char *dlerror(void)
913 return "error";
916 typedef struct TCCSyms {
917 char *str;
918 void *ptr;
919 } TCCSyms;
921 #define TCCSYM(a) { #a, &a, },
923 /* add the symbol you want here if no dynamic linking is done */
924 static TCCSyms tcc_syms[] = {
925 #if !defined(CONFIG_TCCBOOT)
926 TCCSYM(printf)
927 TCCSYM(fprintf)
928 TCCSYM(fopen)
929 TCCSYM(fclose)
930 #endif
931 { NULL, NULL },
934 void *resolve_sym(TCCState *s1, const char *symbol, int type)
936 TCCSyms *p;
937 p = tcc_syms;
938 while (p->str != NULL) {
939 if (!strcmp(p->str, symbol))
940 return p->ptr;
941 p++;
943 return NULL;
946 #elif !defined(WIN32)
948 #include <dlfcn.h>
950 void *resolve_sym(TCCState *s1, const char *sym, int type)
952 return dlsym(RTLD_DEFAULT, sym);
955 #endif
957 /********************************************************/
959 /* we use our own 'finite' function to avoid potential problems with
960 non standard math libs */
961 /* XXX: endianness dependent */
962 int ieee_finite(double d)
964 int *p = (int *)&d;
965 return ((unsigned)((p[1] | 0x800fffff) + 1)) >> 31;
968 /* copy a string and truncate it. */
969 static char *pstrcpy(char *buf, int buf_size, const char *s)
971 char *q, *q_end;
972 int c;
974 if (buf_size > 0) {
975 q = buf;
976 q_end = buf + buf_size - 1;
977 while (q < q_end) {
978 c = *s++;
979 if (c == '\0')
980 break;
981 *q++ = c;
983 *q = '\0';
985 return buf;
988 /* strcat and truncate. */
989 static char *pstrcat(char *buf, int buf_size, const char *s)
991 int len;
992 len = strlen(buf);
993 if (len < buf_size)
994 pstrcpy(buf + len, buf_size - len, s);
995 return buf;
998 static int strstart(const char *str, const char *val, const char **ptr)
1000 const char *p, *q;
1001 p = str;
1002 q = val;
1003 while (*q != '\0') {
1004 if (*p != *q)
1005 return 0;
1006 p++;
1007 q++;
1009 if (ptr)
1010 *ptr = p;
1011 return 1;
1014 /* memory management */
1015 #ifdef MEM_DEBUG
1016 int mem_cur_size;
1017 int mem_max_size;
1018 #endif
1020 static inline void tcc_free(void *ptr)
1022 #ifdef MEM_DEBUG
1023 mem_cur_size -= malloc_usable_size(ptr);
1024 #endif
1025 free(ptr);
1028 static void *tcc_malloc(unsigned long size)
1030 void *ptr;
1031 ptr = malloc(size);
1032 if (!ptr && size)
1033 error("memory full");
1034 #ifdef MEM_DEBUG
1035 mem_cur_size += malloc_usable_size(ptr);
1036 if (mem_cur_size > mem_max_size)
1037 mem_max_size = mem_cur_size;
1038 #endif
1039 return ptr;
1042 static void *tcc_mallocz(unsigned long size)
1044 void *ptr;
1045 ptr = tcc_malloc(size);
1046 memset(ptr, 0, size);
1047 return ptr;
1050 static inline void *tcc_realloc(void *ptr, unsigned long size)
1052 void *ptr1;
1053 #ifdef MEM_DEBUG
1054 mem_cur_size -= malloc_usable_size(ptr);
1055 #endif
1056 ptr1 = realloc(ptr, size);
1057 #ifdef MEM_DEBUG
1058 /* NOTE: count not correct if alloc error, but not critical */
1059 mem_cur_size += malloc_usable_size(ptr1);
1060 if (mem_cur_size > mem_max_size)
1061 mem_max_size = mem_cur_size;
1062 #endif
1063 return ptr1;
1066 static char *tcc_strdup(const char *str)
1068 char *ptr;
1069 ptr = tcc_malloc(strlen(str) + 1);
1070 strcpy(ptr, str);
1071 return ptr;
1074 #define free(p) use_tcc_free(p)
1075 #define malloc(s) use_tcc_malloc(s)
1076 #define realloc(p, s) use_tcc_realloc(p, s)
1078 static void dynarray_add(void ***ptab, int *nb_ptr, void *data)
1080 int nb, nb_alloc;
1081 void **pp;
1083 nb = *nb_ptr;
1084 pp = *ptab;
1085 /* every power of two we double array size */
1086 if ((nb & (nb - 1)) == 0) {
1087 if (!nb)
1088 nb_alloc = 1;
1089 else
1090 nb_alloc = nb * 2;
1091 pp = tcc_realloc(pp, nb_alloc * sizeof(void *));
1092 if (!pp)
1093 error("memory full");
1094 *ptab = pp;
1096 pp[nb++] = data;
1097 *nb_ptr = nb;
1100 /* symbol allocator */
1101 static Sym *__sym_malloc(void)
1103 Sym *sym_pool, *sym, *last_sym;
1104 int i;
1106 sym_pool = tcc_malloc(SYM_POOL_NB * sizeof(Sym));
1108 last_sym = sym_free_first;
1109 sym = sym_pool;
1110 for(i = 0; i < SYM_POOL_NB; i++) {
1111 sym->next = last_sym;
1112 last_sym = sym;
1113 sym++;
1115 sym_free_first = last_sym;
1116 return last_sym;
1119 static inline Sym *sym_malloc(void)
1121 Sym *sym;
1122 sym = sym_free_first;
1123 if (!sym)
1124 sym = __sym_malloc();
1125 sym_free_first = sym->next;
1126 return sym;
1129 static inline void sym_free(Sym *sym)
1131 sym->next = sym_free_first;
1132 sym_free_first = sym;
1135 Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags)
1137 Section *sec;
1139 sec = tcc_mallocz(sizeof(Section) + strlen(name));
1140 strcpy(sec->name, name);
1141 sec->sh_type = sh_type;
1142 sec->sh_flags = sh_flags;
1143 switch(sh_type) {
1144 case SHT_HASH:
1145 case SHT_REL:
1146 case SHT_DYNSYM:
1147 case SHT_SYMTAB:
1148 case SHT_DYNAMIC:
1149 sec->sh_addralign = 4;
1150 break;
1151 case SHT_STRTAB:
1152 sec->sh_addralign = 1;
1153 break;
1154 default:
1155 sec->sh_addralign = 32; /* default conservative alignment */
1156 break;
1159 /* only add section if not private */
1160 if (!(sh_flags & SHF_PRIVATE)) {
1161 sec->sh_num = s1->nb_sections;
1162 dynarray_add((void ***)&s1->sections, &s1->nb_sections, sec);
1164 return sec;
1167 static void free_section(Section *s)
1169 tcc_free(s->data);
1170 tcc_free(s);
1173 /* realloc section and set its content to zero */
1174 static void section_realloc(Section *sec, unsigned long new_size)
1176 unsigned long size;
1177 unsigned char *data;
1179 size = sec->data_allocated;
1180 if (size == 0)
1181 size = 1;
1182 while (size < new_size)
1183 size = size * 2;
1184 data = tcc_realloc(sec->data, size);
1185 if (!data)
1186 error("memory full");
1187 memset(data + sec->data_allocated, 0, size - sec->data_allocated);
1188 sec->data = data;
1189 sec->data_allocated = size;
1192 /* reserve at least 'size' bytes in section 'sec' from
1193 sec->data_offset. */
1194 static void *section_ptr_add(Section *sec, unsigned long size)
1196 unsigned long offset, offset1;
1198 offset = sec->data_offset;
1199 offset1 = offset + size;
1200 if (offset1 > sec->data_allocated)
1201 section_realloc(sec, offset1);
1202 sec->data_offset = offset1;
1203 return sec->data + offset;
1206 /* return a reference to a section, and create it if it does not
1207 exists */
1208 Section *find_section(TCCState *s1, const char *name)
1210 Section *sec;
1211 int i;
1212 for(i = 1; i < s1->nb_sections; i++) {
1213 sec = s1->sections[i];
1214 if (!strcmp(name, sec->name))
1215 return sec;
1217 /* sections are created as PROGBITS */
1218 return new_section(s1, name, SHT_PROGBITS, SHF_ALLOC);
1221 #define SECTION_ABS ((void *)1)
1223 /* update sym->c so that it points to an external symbol in section
1224 'section' with value 'value' */
1225 static void put_extern_sym2(Sym *sym, Section *section,
1226 unsigned long value, unsigned long size,
1227 int can_add_underscore)
1229 int sym_type, sym_bind, sh_num, info;
1230 Elf32_Sym *esym;
1231 const char *name;
1232 char buf1[256];
1234 if (section == NULL)
1235 sh_num = SHN_UNDEF;
1236 else if (section == SECTION_ABS)
1237 sh_num = SHN_ABS;
1238 else
1239 sh_num = section->sh_num;
1240 if (!sym->c) {
1241 if ((sym->type.t & VT_BTYPE) == VT_FUNC)
1242 sym_type = STT_FUNC;
1243 else
1244 sym_type = STT_OBJECT;
1245 if (sym->type.t & VT_STATIC)
1246 sym_bind = STB_LOCAL;
1247 else
1248 sym_bind = STB_GLOBAL;
1250 name = get_tok_str(sym->v, NULL);
1251 #ifdef CONFIG_TCC_BCHECK
1252 if (do_bounds_check) {
1253 char buf[32];
1255 /* XXX: avoid doing that for statics ? */
1256 /* if bound checking is activated, we change some function
1257 names by adding the "__bound" prefix */
1258 switch(sym->v) {
1259 #if 0
1260 /* XXX: we rely only on malloc hooks */
1261 case TOK_malloc:
1262 case TOK_free:
1263 case TOK_realloc:
1264 case TOK_memalign:
1265 case TOK_calloc:
1266 #endif
1267 case TOK_memcpy:
1268 case TOK_memmove:
1269 case TOK_memset:
1270 case TOK_strlen:
1271 case TOK_strcpy:
1272 strcpy(buf, "__bound_");
1273 strcat(buf, name);
1274 name = buf;
1275 break;
1278 #endif
1279 if (tcc_state->leading_underscore && can_add_underscore) {
1280 buf1[0] = '_';
1281 pstrcpy(buf1 + 1, sizeof(buf1) - 1, name);
1282 name = buf1;
1284 info = ELF32_ST_INFO(sym_bind, sym_type);
1285 sym->c = add_elf_sym(symtab_section, value, size, info, 0, sh_num, name);
1286 } else {
1287 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
1288 esym->st_value = value;
1289 esym->st_size = size;
1290 esym->st_shndx = sh_num;
1294 static void put_extern_sym(Sym *sym, Section *section,
1295 unsigned long value, unsigned long size)
1297 put_extern_sym2(sym, section, value, size, 1);
1300 /* add a new relocation entry to symbol 'sym' in section 's' */
1301 static void greloc(Section *s, Sym *sym, unsigned long offset, int type)
1303 if (!sym->c)
1304 put_extern_sym(sym, NULL, 0, 0);
1305 /* now we can add ELF relocation info */
1306 put_elf_reloc(symtab_section, s, offset, type, sym->c);
1309 static inline int isid(int c)
1311 return (c >= 'a' && c <= 'z') ||
1312 (c >= 'A' && c <= 'Z') ||
1313 c == '_';
1316 static inline int isnum(int c)
1318 return c >= '0' && c <= '9';
1321 static inline int isoct(int c)
1323 return c >= '0' && c <= '7';
1326 static inline int toup(int c)
1328 if (c >= 'a' && c <= 'z')
1329 return c - 'a' + 'A';
1330 else
1331 return c;
1334 static void strcat_vprintf(char *buf, int buf_size, const char *fmt, va_list ap)
1336 int len;
1337 len = strlen(buf);
1338 vsnprintf(buf + len, buf_size - len, fmt, ap);
1341 static void strcat_printf(char *buf, int buf_size, const char *fmt, ...)
1343 va_list ap;
1344 va_start(ap, fmt);
1345 strcat_vprintf(buf, buf_size, fmt, ap);
1346 va_end(ap);
1349 void error1(TCCState *s1, int is_warning, const char *fmt, va_list ap)
1351 char buf[2048];
1352 BufferedFile **f;
1354 buf[0] = '\0';
1355 if (file) {
1356 for(f = s1->include_stack; f < s1->include_stack_ptr; f++)
1357 strcat_printf(buf, sizeof(buf), "In file included from %s:%d:\n",
1358 (*f)->filename, (*f)->line_num);
1359 if (file->line_num > 0) {
1360 strcat_printf(buf, sizeof(buf),
1361 "%s:%d: ", file->filename, file->line_num);
1362 } else {
1363 strcat_printf(buf, sizeof(buf),
1364 "%s: ", file->filename);
1366 } else {
1367 strcat_printf(buf, sizeof(buf),
1368 "tcc: ");
1370 if (is_warning)
1371 strcat_printf(buf, sizeof(buf), "warning: ");
1372 strcat_vprintf(buf, sizeof(buf), fmt, ap);
1374 if (!s1->error_func) {
1375 /* default case: stderr */
1376 fprintf(stderr, "%s\n", buf);
1377 } else {
1378 s1->error_func(s1->error_opaque, buf);
1380 if (!is_warning || s1->warn_error)
1381 s1->nb_errors++;
1384 #ifdef LIBTCC
1385 void tcc_set_error_func(TCCState *s, void *error_opaque,
1386 void (*error_func)(void *opaque, const char *msg))
1388 s->error_opaque = error_opaque;
1389 s->error_func = error_func;
1391 #endif
1393 /* error without aborting current compilation */
1394 void error_noabort(const char *fmt, ...)
1396 TCCState *s1 = tcc_state;
1397 va_list ap;
1399 va_start(ap, fmt);
1400 error1(s1, 0, fmt, ap);
1401 va_end(ap);
1404 void error(const char *fmt, ...)
1406 TCCState *s1 = tcc_state;
1407 va_list ap;
1409 va_start(ap, fmt);
1410 error1(s1, 0, fmt, ap);
1411 va_end(ap);
1412 /* better than nothing: in some cases, we accept to handle errors */
1413 if (s1->error_set_jmp_enabled) {
1414 longjmp(s1->error_jmp_buf, 1);
1415 } else {
1416 /* XXX: eliminate this someday */
1417 exit(1);
1421 void expect(const char *msg)
1423 error("%s expected", msg);
1426 void warning(const char *fmt, ...)
1428 TCCState *s1 = tcc_state;
1429 va_list ap;
1431 if (s1->warn_none)
1432 return;
1434 va_start(ap, fmt);
1435 error1(s1, 1, fmt, ap);
1436 va_end(ap);
1439 void skip(int c)
1441 if (tok != c)
1442 error("'%c' expected", c);
1443 next();
1446 static void test_lvalue(void)
1448 if (!(vtop->r & VT_LVAL))
1449 expect("lvalue");
1452 /* allocate a new token */
1453 static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len)
1455 TokenSym *ts, **ptable;
1456 int i;
1458 if (tok_ident >= SYM_FIRST_ANOM)
1459 error("memory full");
1461 /* expand token table if needed */
1462 i = tok_ident - TOK_IDENT;
1463 if ((i % TOK_ALLOC_INCR) == 0) {
1464 ptable = tcc_realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *));
1465 if (!ptable)
1466 error("memory full");
1467 table_ident = ptable;
1470 ts = tcc_malloc(sizeof(TokenSym) + len);
1471 table_ident[i] = ts;
1472 ts->tok = tok_ident++;
1473 ts->sym_define = NULL;
1474 ts->sym_label = NULL;
1475 ts->sym_struct = NULL;
1476 ts->sym_identifier = NULL;
1477 ts->len = len;
1478 ts->hash_next = NULL;
1479 memcpy(ts->str, str, len);
1480 ts->str[len] = '\0';
1481 *pts = ts;
1482 return ts;
1485 #define TOK_HASH_INIT 1
1486 #define TOK_HASH_FUNC(h, c) ((h) * 263 + (c))
1488 /* find a token and add it if not found */
1489 static TokenSym *tok_alloc(const char *str, int len)
1491 TokenSym *ts, **pts;
1492 int i;
1493 unsigned int h;
1495 h = TOK_HASH_INIT;
1496 for(i=0;i<len;i++)
1497 h = TOK_HASH_FUNC(h, ((unsigned char *)str)[i]);
1498 h &= (TOK_HASH_SIZE - 1);
1500 pts = &hash_ident[h];
1501 for(;;) {
1502 ts = *pts;
1503 if (!ts)
1504 break;
1505 if (ts->len == len && !memcmp(ts->str, str, len))
1506 return ts;
1507 pts = &(ts->hash_next);
1509 return tok_alloc_new(pts, str, len);
1512 /* CString handling */
1514 static void cstr_realloc(CString *cstr, int new_size)
1516 int size;
1517 void *data;
1519 size = cstr->size_allocated;
1520 if (size == 0)
1521 size = 8; /* no need to allocate a too small first string */
1522 while (size < new_size)
1523 size = size * 2;
1524 data = tcc_realloc(cstr->data_allocated, size);
1525 if (!data)
1526 error("memory full");
1527 cstr->data_allocated = data;
1528 cstr->size_allocated = size;
1529 cstr->data = data;
1532 /* add a byte */
1533 static inline void cstr_ccat(CString *cstr, int ch)
1535 int size;
1536 size = cstr->size + 1;
1537 if (size > cstr->size_allocated)
1538 cstr_realloc(cstr, size);
1539 ((unsigned char *)cstr->data)[size - 1] = ch;
1540 cstr->size = size;
1543 static void cstr_cat(CString *cstr, const char *str)
1545 int c;
1546 for(;;) {
1547 c = *str;
1548 if (c == '\0')
1549 break;
1550 cstr_ccat(cstr, c);
1551 str++;
1555 /* add a wide char */
1556 static void cstr_wccat(CString *cstr, int ch)
1558 int size;
1559 size = cstr->size + sizeof(int);
1560 if (size > cstr->size_allocated)
1561 cstr_realloc(cstr, size);
1562 *(int *)(((unsigned char *)cstr->data) + size - sizeof(int)) = ch;
1563 cstr->size = size;
1566 static void cstr_new(CString *cstr)
1568 memset(cstr, 0, sizeof(CString));
1571 /* free string and reset it to NULL */
1572 static void cstr_free(CString *cstr)
1574 tcc_free(cstr->data_allocated);
1575 cstr_new(cstr);
1578 #define cstr_reset(cstr) cstr_free(cstr)
1580 /* XXX: unicode ? */
1581 static void add_char(CString *cstr, int c)
1583 if (c == '\'' || c == '\"' || c == '\\') {
1584 /* XXX: could be more precise if char or string */
1585 cstr_ccat(cstr, '\\');
1587 if (c >= 32 && c <= 126) {
1588 cstr_ccat(cstr, c);
1589 } else {
1590 cstr_ccat(cstr, '\\');
1591 if (c == '\n') {
1592 cstr_ccat(cstr, 'n');
1593 } else {
1594 cstr_ccat(cstr, '0' + ((c >> 6) & 7));
1595 cstr_ccat(cstr, '0' + ((c >> 3) & 7));
1596 cstr_ccat(cstr, '0' + (c & 7));
1601 /* XXX: buffer overflow */
1602 /* XXX: float tokens */
1603 char *get_tok_str(int v, CValue *cv)
1605 static char buf[STRING_MAX_SIZE + 1];
1606 static CString cstr_buf;
1607 CString *cstr;
1608 unsigned char *q;
1609 char *p;
1610 int i, len;
1612 /* NOTE: to go faster, we give a fixed buffer for small strings */
1613 cstr_reset(&cstr_buf);
1614 cstr_buf.data = buf;
1615 cstr_buf.size_allocated = sizeof(buf);
1616 p = buf;
1618 switch(v) {
1619 case TOK_CINT:
1620 case TOK_CUINT:
1621 /* XXX: not quite exact, but only useful for testing */
1622 sprintf(p, "%u", cv->ui);
1623 break;
1624 case TOK_CLLONG:
1625 case TOK_CULLONG:
1626 /* XXX: not quite exact, but only useful for testing */
1627 sprintf(p, "%Lu", cv->ull);
1628 break;
1629 case TOK_CCHAR:
1630 case TOK_LCHAR:
1631 cstr_ccat(&cstr_buf, '\'');
1632 add_char(&cstr_buf, cv->i);
1633 cstr_ccat(&cstr_buf, '\'');
1634 cstr_ccat(&cstr_buf, '\0');
1635 break;
1636 case TOK_PPNUM:
1637 cstr = cv->cstr;
1638 len = cstr->size - 1;
1639 for(i=0;i<len;i++)
1640 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1641 cstr_ccat(&cstr_buf, '\0');
1642 break;
1643 case TOK_STR:
1644 case TOK_LSTR:
1645 cstr = cv->cstr;
1646 cstr_ccat(&cstr_buf, '\"');
1647 if (v == TOK_STR) {
1648 len = cstr->size - 1;
1649 for(i=0;i<len;i++)
1650 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1651 } else {
1652 len = (cstr->size / sizeof(int)) - 1;
1653 for(i=0;i<len;i++)
1654 add_char(&cstr_buf, ((int *)cstr->data)[i]);
1656 cstr_ccat(&cstr_buf, '\"');
1657 cstr_ccat(&cstr_buf, '\0');
1658 break;
1659 case TOK_LT:
1660 v = '<';
1661 goto addv;
1662 case TOK_GT:
1663 v = '>';
1664 goto addv;
1665 case TOK_A_SHL:
1666 return strcpy(p, "<<=");
1667 case TOK_A_SAR:
1668 return strcpy(p, ">>=");
1669 default:
1670 if (v < TOK_IDENT) {
1671 /* search in two bytes table */
1672 q = tok_two_chars;
1673 while (*q) {
1674 if (q[2] == v) {
1675 *p++ = q[0];
1676 *p++ = q[1];
1677 *p = '\0';
1678 return buf;
1680 q += 3;
1682 addv:
1683 *p++ = v;
1684 *p = '\0';
1685 } else if (v < tok_ident) {
1686 return table_ident[v - TOK_IDENT]->str;
1687 } else if (v >= SYM_FIRST_ANOM) {
1688 /* special name for anonymous symbol */
1689 sprintf(p, "L.%u", v - SYM_FIRST_ANOM);
1690 } else {
1691 /* should never happen */
1692 return NULL;
1694 break;
1696 return cstr_buf.data;
1699 /* push, without hashing */
1700 static Sym *sym_push2(Sym **ps, int v, int t, int c)
1702 Sym *s;
1703 s = sym_malloc();
1704 s->v = v;
1705 s->type.t = t;
1706 s->c = c;
1707 s->next = NULL;
1708 /* add in stack */
1709 s->prev = *ps;
1710 *ps = s;
1711 return s;
1714 /* find a symbol and return its associated structure. 's' is the top
1715 of the symbol stack */
1716 static Sym *sym_find2(Sym *s, int v)
1718 while (s) {
1719 if (s->v == v)
1720 return s;
1721 s = s->prev;
1723 return NULL;
1726 /* structure lookup */
1727 static inline Sym *struct_find(int v)
1729 v -= TOK_IDENT;
1730 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1731 return NULL;
1732 return table_ident[v]->sym_struct;
1735 /* find an identifier */
1736 static inline Sym *sym_find(int v)
1738 v -= TOK_IDENT;
1739 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1740 return NULL;
1741 return table_ident[v]->sym_identifier;
1744 /* push a given symbol on the symbol stack */
1745 static Sym *sym_push(int v, CType *type, int r, int c)
1747 Sym *s, **ps;
1748 TokenSym *ts;
1750 if (local_stack)
1751 ps = &local_stack;
1752 else
1753 ps = &global_stack;
1754 s = sym_push2(ps, v, type->t, c);
1755 s->type.ref = type->ref;
1756 s->r = r;
1757 /* don't record fields or anonymous symbols */
1758 /* XXX: simplify */
1759 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1760 /* record symbol in token array */
1761 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1762 if (v & SYM_STRUCT)
1763 ps = &ts->sym_struct;
1764 else
1765 ps = &ts->sym_identifier;
1766 s->prev_tok = *ps;
1767 *ps = s;
1769 return s;
1772 /* push a global identifier */
1773 static Sym *global_identifier_push(int v, int t, int c)
1775 Sym *s, **ps;
1776 s = sym_push2(&global_stack, v, t, c);
1777 /* don't record anonymous symbol */
1778 if (v < SYM_FIRST_ANOM) {
1779 ps = &table_ident[v - TOK_IDENT]->sym_identifier;
1780 /* modify the top most local identifier, so that
1781 sym_identifier will point to 's' when popped */
1782 while (*ps != NULL)
1783 ps = &(*ps)->prev_tok;
1784 s->prev_tok = NULL;
1785 *ps = s;
1787 return s;
1790 /* pop symbols until top reaches 'b' */
1791 static void sym_pop(Sym **ptop, Sym *b)
1793 Sym *s, *ss, **ps;
1794 TokenSym *ts;
1795 int v;
1797 s = *ptop;
1798 while(s != b) {
1799 ss = s->prev;
1800 v = s->v;
1801 /* remove symbol in token array */
1802 /* XXX: simplify */
1803 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1804 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1805 if (v & SYM_STRUCT)
1806 ps = &ts->sym_struct;
1807 else
1808 ps = &ts->sym_identifier;
1809 *ps = s->prev_tok;
1811 sym_free(s);
1812 s = ss;
1814 *ptop = b;
1817 /* I/O layer */
1819 BufferedFile *tcc_open(TCCState *s1, const char *filename)
1821 int fd;
1822 BufferedFile *bf;
1824 fd = open(filename, O_RDONLY | O_BINARY);
1825 if (fd < 0)
1826 return NULL;
1827 bf = tcc_malloc(sizeof(BufferedFile));
1828 if (!bf) {
1829 close(fd);
1830 return NULL;
1832 bf->fd = fd;
1833 bf->buf_ptr = bf->buffer;
1834 bf->buf_end = bf->buffer;
1835 bf->buffer[0] = CH_EOB; /* put eob symbol */
1836 pstrcpy(bf->filename, sizeof(bf->filename), filename);
1837 bf->line_num = 1;
1838 bf->ifndef_macro = 0;
1839 bf->ifdef_stack_ptr = s1->ifdef_stack_ptr;
1840 // printf("opening '%s'\n", filename);
1841 return bf;
1844 void tcc_close(BufferedFile *bf)
1846 total_lines += bf->line_num;
1847 close(bf->fd);
1848 tcc_free(bf);
1851 /* fill input buffer and peek next char */
1852 static int tcc_peekc_slow(BufferedFile *bf)
1854 int len;
1855 /* only tries to read if really end of buffer */
1856 if (bf->buf_ptr >= bf->buf_end) {
1857 if (bf->fd != -1) {
1858 #if defined(PARSE_DEBUG)
1859 len = 8;
1860 #else
1861 len = IO_BUF_SIZE;
1862 #endif
1863 len = read(bf->fd, bf->buffer, len);
1864 if (len < 0)
1865 len = 0;
1866 } else {
1867 len = 0;
1869 total_bytes += len;
1870 bf->buf_ptr = bf->buffer;
1871 bf->buf_end = bf->buffer + len;
1872 *bf->buf_end = CH_EOB;
1874 if (bf->buf_ptr < bf->buf_end) {
1875 return bf->buf_ptr[0];
1876 } else {
1877 bf->buf_ptr = bf->buf_end;
1878 return CH_EOF;
1882 /* return the current character, handling end of block if necessary
1883 (but not stray) */
1884 static int handle_eob(void)
1886 return tcc_peekc_slow(file);
1889 /* read next char from current input file and handle end of input buffer */
1890 static inline void inp(void)
1892 ch = *(++(file->buf_ptr));
1893 /* end of buffer/file handling */
1894 if (ch == CH_EOB)
1895 ch = handle_eob();
1898 /* handle '\[\r]\n' */
1899 static void handle_stray(void)
1901 while (ch == '\\') {
1902 inp();
1903 if (ch == '\n') {
1904 file->line_num++;
1905 inp();
1906 } else if (ch == '\r') {
1907 inp();
1908 if (ch != '\n')
1909 goto fail;
1910 file->line_num++;
1911 inp();
1912 } else {
1913 fail:
1914 error("stray '\\' in program");
1919 /* skip the stray and handle the \\n case. Output an error if
1920 incorrect char after the stray */
1921 static int handle_stray1(uint8_t *p)
1923 int c;
1925 if (p >= file->buf_end) {
1926 file->buf_ptr = p;
1927 c = handle_eob();
1928 p = file->buf_ptr;
1929 if (c == '\\')
1930 goto parse_stray;
1931 } else {
1932 parse_stray:
1933 file->buf_ptr = p;
1934 ch = *p;
1935 handle_stray();
1936 p = file->buf_ptr;
1937 c = *p;
1939 return c;
1942 /* handle just the EOB case, but not stray */
1943 #define PEEKC_EOB(c, p)\
1945 p++;\
1946 c = *p;\
1947 if (c == '\\') {\
1948 file->buf_ptr = p;\
1949 c = handle_eob();\
1950 p = file->buf_ptr;\
1954 /* handle the complicated stray case */
1955 #define PEEKC(c, p)\
1957 p++;\
1958 c = *p;\
1959 if (c == '\\') {\
1960 c = handle_stray1(p);\
1961 p = file->buf_ptr;\
1965 /* input with '\[\r]\n' handling. Note that this function cannot
1966 handle other characters after '\', so you cannot call it inside
1967 strings or comments */
1968 static void minp(void)
1970 inp();
1971 if (ch == '\\')
1972 handle_stray();
1976 /* single line C++ comments */
1977 static uint8_t *parse_line_comment(uint8_t *p)
1979 int c;
1981 p++;
1982 for(;;) {
1983 c = *p;
1984 redo:
1985 if (c == '\n' || c == CH_EOF) {
1986 break;
1987 } else if (c == '\\') {
1988 file->buf_ptr = p;
1989 c = handle_eob();
1990 p = file->buf_ptr;
1991 if (c == '\\') {
1992 PEEKC_EOB(c, p);
1993 if (c == '\n') {
1994 file->line_num++;
1995 PEEKC_EOB(c, p);
1996 } else if (c == '\r') {
1997 PEEKC_EOB(c, p);
1998 if (c == '\n') {
1999 file->line_num++;
2000 PEEKC_EOB(c, p);
2003 } else {
2004 goto redo;
2006 } else {
2007 p++;
2010 return p;
2013 /* C comments */
2014 static uint8_t *parse_comment(uint8_t *p)
2016 int c;
2018 p++;
2019 for(;;) {
2020 /* fast skip loop */
2021 for(;;) {
2022 c = *p;
2023 if (c == '\n' || c == '*' || c == '\\')
2024 break;
2025 p++;
2026 c = *p;
2027 if (c == '\n' || c == '*' || c == '\\')
2028 break;
2029 p++;
2031 /* now we can handle all the cases */
2032 if (c == '\n') {
2033 file->line_num++;
2034 p++;
2035 } else if (c == '*') {
2036 p++;
2037 for(;;) {
2038 c = *p;
2039 if (c == '*') {
2040 p++;
2041 } else if (c == '/') {
2042 goto end_of_comment;
2043 } else if (c == '\\') {
2044 file->buf_ptr = p;
2045 c = handle_eob();
2046 p = file->buf_ptr;
2047 if (c == '\\') {
2048 /* skip '\[\r]\n', otherwise just skip the stray */
2049 while (c == '\\') {
2050 PEEKC_EOB(c, p);
2051 if (c == '\n') {
2052 file->line_num++;
2053 PEEKC_EOB(c, p);
2054 } else if (c == '\r') {
2055 PEEKC_EOB(c, p);
2056 if (c == '\n') {
2057 file->line_num++;
2058 PEEKC_EOB(c, p);
2060 } else {
2061 goto after_star;
2065 } else {
2066 break;
2069 after_star: ;
2070 } else {
2071 /* stray, eob or eof */
2072 file->buf_ptr = p;
2073 c = handle_eob();
2074 p = file->buf_ptr;
2075 if (c == CH_EOF) {
2076 error("unexpected end of file in comment");
2077 } else if (c == '\\') {
2078 p++;
2082 end_of_comment:
2083 p++;
2084 return p;
2087 #define cinp minp
2089 /* space exlcuding newline */
2090 static inline int is_space(int ch)
2092 return ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f' || ch == '\r';
2095 static inline void skip_spaces(void)
2097 while (is_space(ch))
2098 cinp();
2101 /* parse a string without interpreting escapes */
2102 static uint8_t *parse_pp_string(uint8_t *p,
2103 int sep, CString *str)
2105 int c;
2106 p++;
2107 for(;;) {
2108 c = *p;
2109 if (c == sep) {
2110 break;
2111 } else if (c == '\\') {
2112 file->buf_ptr = p;
2113 c = handle_eob();
2114 p = file->buf_ptr;
2115 if (c == CH_EOF) {
2116 unterminated_string:
2117 /* XXX: indicate line number of start of string */
2118 error("missing terminating %c character", sep);
2119 } else if (c == '\\') {
2120 /* escape : just skip \[\r]\n */
2121 PEEKC_EOB(c, p);
2122 if (c == '\n') {
2123 file->line_num++;
2124 p++;
2125 } else if (c == '\r') {
2126 PEEKC_EOB(c, p);
2127 if (c != '\n')
2128 expect("'\n' after '\r'");
2129 file->line_num++;
2130 p++;
2131 } else if (c == CH_EOF) {
2132 goto unterminated_string;
2133 } else {
2134 if (str) {
2135 cstr_ccat(str, '\\');
2136 cstr_ccat(str, c);
2138 p++;
2141 } else if (c == '\n') {
2142 file->line_num++;
2143 goto add_char;
2144 } else if (c == '\r') {
2145 PEEKC_EOB(c, p);
2146 if (c != '\n') {
2147 if (str)
2148 cstr_ccat(str, '\r');
2149 } else {
2150 file->line_num++;
2151 goto add_char;
2153 } else {
2154 add_char:
2155 if (str)
2156 cstr_ccat(str, c);
2157 p++;
2160 p++;
2161 return p;
2164 /* skip block of text until #else, #elif or #endif. skip also pairs of
2165 #if/#endif */
2166 void preprocess_skip(void)
2168 int a, start_of_line, c;
2169 uint8_t *p;
2171 p = file->buf_ptr;
2172 start_of_line = 1;
2173 a = 0;
2174 for(;;) {
2175 redo_no_start:
2176 c = *p;
2177 switch(c) {
2178 case ' ':
2179 case '\t':
2180 case '\f':
2181 case '\v':
2182 case '\r':
2183 p++;
2184 goto redo_no_start;
2185 case '\n':
2186 start_of_line = 1;
2187 file->line_num++;
2188 p++;
2189 goto redo_no_start;
2190 case '\\':
2191 file->buf_ptr = p;
2192 c = handle_eob();
2193 if (c == CH_EOF) {
2194 expect("#endif");
2195 } else if (c == '\\') {
2196 /* XXX: incorrect: should not give an error */
2197 ch = file->buf_ptr[0];
2198 handle_stray();
2200 p = file->buf_ptr;
2201 goto redo_no_start;
2202 /* skip strings */
2203 case '\"':
2204 case '\'':
2205 p = parse_pp_string(p, c, NULL);
2206 break;
2207 /* skip comments */
2208 case '/':
2209 file->buf_ptr = p;
2210 ch = *p;
2211 minp();
2212 p = file->buf_ptr;
2213 if (ch == '*') {
2214 p = parse_comment(p);
2215 } else if (ch == '/') {
2216 p = parse_line_comment(p);
2218 break;
2220 case '#':
2221 p++;
2222 if (start_of_line) {
2223 file->buf_ptr = p;
2224 next_nomacro();
2225 p = file->buf_ptr;
2226 if (a == 0 &&
2227 (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
2228 goto the_end;
2229 if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
2230 a++;
2231 else if (tok == TOK_ENDIF)
2232 a--;
2234 break;
2235 default:
2236 p++;
2237 break;
2239 start_of_line = 0;
2241 the_end: ;
2242 file->buf_ptr = p;
2245 /* ParseState handling */
2247 /* XXX: currently, no include file info is stored. Thus, we cannot display
2248 accurate messages if the function or data definition spans multiple
2249 files */
2251 /* save current parse state in 's' */
2252 void save_parse_state(ParseState *s)
2254 s->line_num = file->line_num;
2255 s->macro_ptr = macro_ptr;
2256 s->tok = tok;
2257 s->tokc = tokc;
2260 /* restore parse state from 's' */
2261 void restore_parse_state(ParseState *s)
2263 file->line_num = s->line_num;
2264 macro_ptr = s->macro_ptr;
2265 tok = s->tok;
2266 tokc = s->tokc;
2269 /* return the number of additional 'ints' necessary to store the
2270 token */
2271 static inline int tok_ext_size(int t)
2273 switch(t) {
2274 /* 4 bytes */
2275 case TOK_CINT:
2276 case TOK_CUINT:
2277 case TOK_CCHAR:
2278 case TOK_LCHAR:
2279 case TOK_CFLOAT:
2280 case TOK_LINENUM:
2281 return 1;
2282 case TOK_STR:
2283 case TOK_LSTR:
2284 case TOK_PPNUM:
2285 error("unsupported token");
2286 return 1;
2287 case TOK_CDOUBLE:
2288 case TOK_CLLONG:
2289 case TOK_CULLONG:
2290 return 2;
2291 case TOK_CLDOUBLE:
2292 return LDOUBLE_SIZE / 4;
2293 default:
2294 return 0;
2298 /* token string handling */
2300 static inline void tok_str_new(TokenString *s)
2302 s->str = NULL;
2303 s->len = 0;
2304 s->allocated_len = 0;
2305 s->last_line_num = -1;
2308 static void tok_str_free(int *str)
2310 tcc_free(str);
2313 static int *tok_str_realloc(TokenString *s)
2315 int *str, len;
2317 if (s->allocated_len == 0) {
2318 len = 8;
2319 } else {
2320 len = s->allocated_len * 2;
2322 str = tcc_realloc(s->str, len * sizeof(int));
2323 if (!str)
2324 error("memory full");
2325 s->allocated_len = len;
2326 s->str = str;
2327 return str;
2330 static void tok_str_add(TokenString *s, int t)
2332 int len, *str;
2334 len = s->len;
2335 str = s->str;
2336 if (len >= s->allocated_len)
2337 str = tok_str_realloc(s);
2338 str[len++] = t;
2339 s->len = len;
2342 static void tok_str_add2(TokenString *s, int t, CValue *cv)
2344 int len, *str;
2346 len = s->len;
2347 str = s->str;
2349 /* allocate space for worst case */
2350 if (len + TOK_MAX_SIZE > s->allocated_len)
2351 str = tok_str_realloc(s);
2352 str[len++] = t;
2353 switch(t) {
2354 case TOK_CINT:
2355 case TOK_CUINT:
2356 case TOK_CCHAR:
2357 case TOK_LCHAR:
2358 case TOK_CFLOAT:
2359 case TOK_LINENUM:
2360 str[len++] = cv->tab[0];
2361 break;
2362 case TOK_PPNUM:
2363 case TOK_STR:
2364 case TOK_LSTR:
2366 int nb_words;
2367 CString *cstr;
2369 nb_words = (sizeof(CString) + cv->cstr->size + 3) >> 2;
2370 while ((len + nb_words) > s->allocated_len)
2371 str = tok_str_realloc(s);
2372 cstr = (CString *)(str + len);
2373 cstr->data = NULL;
2374 cstr->size = cv->cstr->size;
2375 cstr->data_allocated = NULL;
2376 cstr->size_allocated = cstr->size;
2377 memcpy((char *)cstr + sizeof(CString),
2378 cv->cstr->data, cstr->size);
2379 len += nb_words;
2381 break;
2382 case TOK_CDOUBLE:
2383 case TOK_CLLONG:
2384 case TOK_CULLONG:
2385 #if LDOUBLE_SIZE == 8
2386 case TOK_CLDOUBLE:
2387 #endif
2388 str[len++] = cv->tab[0];
2389 str[len++] = cv->tab[1];
2390 break;
2391 #if LDOUBLE_SIZE == 12
2392 case TOK_CLDOUBLE:
2393 str[len++] = cv->tab[0];
2394 str[len++] = cv->tab[1];
2395 str[len++] = cv->tab[2];
2396 #elif LDOUBLE_SIZE != 8
2397 #error add long double size support
2398 #endif
2399 break;
2400 default:
2401 break;
2403 s->len = len;
2406 /* add the current parse token in token string 's' */
2407 static void tok_str_add_tok(TokenString *s)
2409 CValue cval;
2411 /* save line number info */
2412 if (file->line_num != s->last_line_num) {
2413 s->last_line_num = file->line_num;
2414 cval.i = s->last_line_num;
2415 tok_str_add2(s, TOK_LINENUM, &cval);
2417 tok_str_add2(s, tok, &tokc);
2420 #if LDOUBLE_SIZE == 12
2421 #define LDOUBLE_GET(p, cv) \
2422 cv.tab[0] = p[0]; \
2423 cv.tab[1] = p[1]; \
2424 cv.tab[2] = p[2];
2425 #elif LDOUBLE_SIZE == 8
2426 #define LDOUBLE_GET(p, cv) \
2427 cv.tab[0] = p[0]; \
2428 cv.tab[1] = p[1];
2429 #else
2430 #error add long double size support
2431 #endif
2434 /* get a token from an integer array and increment pointer
2435 accordingly. we code it as a macro to avoid pointer aliasing. */
2436 #define TOK_GET(t, p, cv) \
2438 t = *p++; \
2439 switch(t) { \
2440 case TOK_CINT: \
2441 case TOK_CUINT: \
2442 case TOK_CCHAR: \
2443 case TOK_LCHAR: \
2444 case TOK_CFLOAT: \
2445 case TOK_LINENUM: \
2446 cv.tab[0] = *p++; \
2447 break; \
2448 case TOK_STR: \
2449 case TOK_LSTR: \
2450 case TOK_PPNUM: \
2451 cv.cstr = (CString *)p; \
2452 cv.cstr->data = (char *)p + sizeof(CString);\
2453 p += (sizeof(CString) + cv.cstr->size + 3) >> 2;\
2454 break; \
2455 case TOK_CDOUBLE: \
2456 case TOK_CLLONG: \
2457 case TOK_CULLONG: \
2458 cv.tab[0] = p[0]; \
2459 cv.tab[1] = p[1]; \
2460 p += 2; \
2461 break; \
2462 case TOK_CLDOUBLE: \
2463 LDOUBLE_GET(p, cv); \
2464 p += LDOUBLE_SIZE / 4; \
2465 break; \
2466 default: \
2467 break; \
2471 /* defines handling */
2472 static inline void define_push(int v, int macro_type, int *str, Sym *first_arg)
2474 Sym *s;
2476 s = sym_push2(&define_stack, v, macro_type, (int)str);
2477 s->next = first_arg;
2478 table_ident[v - TOK_IDENT]->sym_define = s;
2481 /* undefined a define symbol. Its name is just set to zero */
2482 static void define_undef(Sym *s)
2484 int v;
2485 v = s->v;
2486 if (v >= TOK_IDENT && v < tok_ident)
2487 table_ident[v - TOK_IDENT]->sym_define = NULL;
2488 s->v = 0;
2491 static inline Sym *define_find(int v)
2493 v -= TOK_IDENT;
2494 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2495 return NULL;
2496 return table_ident[v]->sym_define;
2499 /* free define stack until top reaches 'b' */
2500 static void free_defines(Sym *b)
2502 Sym *top, *top1;
2503 int v;
2505 top = define_stack;
2506 while (top != b) {
2507 top1 = top->prev;
2508 /* do not free args or predefined defines */
2509 if (top->c)
2510 tok_str_free((int *)top->c);
2511 v = top->v;
2512 if (v >= TOK_IDENT && v < tok_ident)
2513 table_ident[v - TOK_IDENT]->sym_define = NULL;
2514 sym_free(top);
2515 top = top1;
2517 define_stack = b;
2520 /* label lookup */
2521 static Sym *label_find(int v)
2523 v -= TOK_IDENT;
2524 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2525 return NULL;
2526 return table_ident[v]->sym_label;
2529 static Sym *label_push(Sym **ptop, int v, int flags)
2531 Sym *s, **ps;
2532 s = sym_push2(ptop, v, 0, 0);
2533 s->r = flags;
2534 ps = &table_ident[v - TOK_IDENT]->sym_label;
2535 if (ptop == &global_label_stack) {
2536 /* modify the top most local identifier, so that
2537 sym_identifier will point to 's' when popped */
2538 while (*ps != NULL)
2539 ps = &(*ps)->prev_tok;
2541 s->prev_tok = *ps;
2542 *ps = s;
2543 return s;
2546 /* pop labels until element last is reached. Look if any labels are
2547 undefined. Define symbols if '&&label' was used. */
2548 static void label_pop(Sym **ptop, Sym *slast)
2550 Sym *s, *s1;
2551 for(s = *ptop; s != slast; s = s1) {
2552 s1 = s->prev;
2553 if (s->r == LABEL_DECLARED) {
2554 warning("label '%s' declared but not used", get_tok_str(s->v, NULL));
2555 } else if (s->r == LABEL_FORWARD) {
2556 error("label '%s' used but not defined",
2557 get_tok_str(s->v, NULL));
2558 } else {
2559 if (s->c) {
2560 /* define corresponding symbol. A size of
2561 1 is put. */
2562 put_extern_sym(s, cur_text_section, (long)s->next, 1);
2565 /* remove label */
2566 table_ident[s->v - TOK_IDENT]->sym_label = s->prev_tok;
2567 sym_free(s);
2569 *ptop = slast;
2572 /* eval an expression for #if/#elif */
2573 static int expr_preprocess(void)
2575 int c, t;
2576 TokenString str;
2578 tok_str_new(&str);
2579 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2580 next(); /* do macro subst */
2581 if (tok == TOK_DEFINED) {
2582 next_nomacro();
2583 t = tok;
2584 if (t == '(')
2585 next_nomacro();
2586 c = define_find(tok) != 0;
2587 if (t == '(')
2588 next_nomacro();
2589 tok = TOK_CINT;
2590 tokc.i = c;
2591 } else if (tok >= TOK_IDENT) {
2592 /* if undefined macro */
2593 tok = TOK_CINT;
2594 tokc.i = 0;
2596 tok_str_add_tok(&str);
2598 tok_str_add(&str, -1); /* simulate end of file */
2599 tok_str_add(&str, 0);
2600 /* now evaluate C constant expression */
2601 macro_ptr = str.str;
2602 next();
2603 c = expr_const();
2604 macro_ptr = NULL;
2605 tok_str_free(str.str);
2606 return c != 0;
2609 #if defined(PARSE_DEBUG) || defined(PP_DEBUG)
2610 static void tok_print(int *str)
2612 int t;
2613 CValue cval;
2615 while (1) {
2616 TOK_GET(t, str, cval);
2617 if (!t)
2618 break;
2619 printf(" %s", get_tok_str(t, &cval));
2621 printf("\n");
2623 #endif
2625 /* parse after #define */
2626 static void parse_define(void)
2628 Sym *s, *first, **ps;
2629 int v, t, varg, is_vaargs, c;
2630 TokenString str;
2632 v = tok;
2633 if (v < TOK_IDENT)
2634 error("invalid macro name '%s'", get_tok_str(tok, &tokc));
2635 /* XXX: should check if same macro (ANSI) */
2636 first = NULL;
2637 t = MACRO_OBJ;
2638 /* '(' must be just after macro definition for MACRO_FUNC */
2639 c = file->buf_ptr[0];
2640 if (c == '\\')
2641 c = handle_stray1(file->buf_ptr);
2642 if (c == '(') {
2643 next_nomacro();
2644 next_nomacro();
2645 ps = &first;
2646 while (tok != ')') {
2647 varg = tok;
2648 next_nomacro();
2649 is_vaargs = 0;
2650 if (varg == TOK_DOTS) {
2651 varg = TOK___VA_ARGS__;
2652 is_vaargs = 1;
2653 } else if (tok == TOK_DOTS && gnu_ext) {
2654 is_vaargs = 1;
2655 next_nomacro();
2657 if (varg < TOK_IDENT)
2658 error("badly punctuated parameter list");
2659 s = sym_push2(&define_stack, varg | SYM_FIELD, is_vaargs, 0);
2660 *ps = s;
2661 ps = &s->next;
2662 if (tok != ',')
2663 break;
2664 next_nomacro();
2666 t = MACRO_FUNC;
2668 tok_str_new(&str);
2669 next_nomacro();
2670 /* EOF testing necessary for '-D' handling */
2671 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2672 tok_str_add2(&str, tok, &tokc);
2673 next_nomacro();
2675 tok_str_add(&str, 0);
2676 #ifdef PP_DEBUG
2677 printf("define %s %d: ", get_tok_str(v, NULL), t);
2678 tok_print(str.str);
2679 #endif
2680 define_push(v, t, str.str, first);
2683 static inline int hash_cached_include(int type, const char *filename)
2685 const unsigned char *s;
2686 unsigned int h;
2688 h = TOK_HASH_INIT;
2689 h = TOK_HASH_FUNC(h, type);
2690 s = filename;
2691 while (*s) {
2692 h = TOK_HASH_FUNC(h, *s);
2693 s++;
2695 h &= (CACHED_INCLUDES_HASH_SIZE - 1);
2696 return h;
2699 /* XXX: use a token or a hash table to accelerate matching ? */
2700 static CachedInclude *search_cached_include(TCCState *s1,
2701 int type, const char *filename)
2703 CachedInclude *e;
2704 int i, h;
2705 h = hash_cached_include(type, filename);
2706 i = s1->cached_includes_hash[h];
2707 for(;;) {
2708 if (i == 0)
2709 break;
2710 e = s1->cached_includes[i - 1];
2711 if (e->type == type && !strcmp(e->filename, filename))
2712 return e;
2713 i = e->hash_next;
2715 return NULL;
2718 static inline void add_cached_include(TCCState *s1, int type,
2719 const char *filename, int ifndef_macro)
2721 CachedInclude *e;
2722 int h;
2724 if (search_cached_include(s1, type, filename))
2725 return;
2726 #ifdef INC_DEBUG
2727 printf("adding cached '%s' %s\n", filename, get_tok_str(ifndef_macro, NULL));
2728 #endif
2729 e = tcc_malloc(sizeof(CachedInclude) + strlen(filename));
2730 if (!e)
2731 return;
2732 e->type = type;
2733 strcpy(e->filename, filename);
2734 e->ifndef_macro = ifndef_macro;
2735 dynarray_add((void ***)&s1->cached_includes, &s1->nb_cached_includes, e);
2736 /* add in hash table */
2737 h = hash_cached_include(type, filename);
2738 e->hash_next = s1->cached_includes_hash[h];
2739 s1->cached_includes_hash[h] = s1->nb_cached_includes;
2742 static void pragma_parse(TCCState *s1)
2744 int val;
2746 next();
2747 if (tok == TOK_pack) {
2749 This may be:
2750 #pragma pack(1) // set
2751 #pragma pack() // reset to default
2752 #pragma pack(push,1) // push & set
2753 #pragma pack(pop) // restore previous
2755 next();
2756 skip('(');
2757 if (tok == TOK_ASM_pop) {
2758 next();
2759 if (s1->pack_stack_ptr <= s1->pack_stack) {
2760 stk_error:
2761 error("out of pack stack");
2763 s1->pack_stack_ptr--;
2764 } else {
2765 val = 0;
2766 if (tok != ')') {
2767 if (tok == TOK_ASM_push) {
2768 next();
2769 if (s1->pack_stack_ptr >= s1->pack_stack + PACK_STACK_SIZE - 1)
2770 goto stk_error;
2771 s1->pack_stack_ptr++;
2772 skip(',');
2774 if (tok != TOK_CINT) {
2775 pack_error:
2776 error("invalid pack pragma");
2778 val = tokc.i;
2779 if (val < 1 || val > 16 || (val & (val - 1)) != 0)
2780 goto pack_error;
2781 next();
2783 *s1->pack_stack_ptr = val;
2784 skip(')');
2789 /* is_bof is true if first non space token at beginning of file */
2790 static void preprocess(int is_bof)
2792 TCCState *s1 = tcc_state;
2793 int size, i, c, n, saved_parse_flags;
2794 char buf[1024], *q, *p;
2795 char buf1[1024];
2796 BufferedFile *f;
2797 Sym *s;
2798 CachedInclude *e;
2800 saved_parse_flags = parse_flags;
2801 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM |
2802 PARSE_FLAG_LINEFEED;
2803 next_nomacro();
2804 redo:
2805 switch(tok) {
2806 case TOK_DEFINE:
2807 next_nomacro();
2808 parse_define();
2809 break;
2810 case TOK_UNDEF:
2811 next_nomacro();
2812 s = define_find(tok);
2813 /* undefine symbol by putting an invalid name */
2814 if (s)
2815 define_undef(s);
2816 break;
2817 case TOK_INCLUDE:
2818 case TOK_INCLUDE_NEXT:
2819 ch = file->buf_ptr[0];
2820 /* XXX: incorrect if comments : use next_nomacro with a special mode */
2821 skip_spaces();
2822 if (ch == '<') {
2823 c = '>';
2824 goto read_name;
2825 } else if (ch == '\"') {
2826 c = ch;
2827 read_name:
2828 /* XXX: better stray handling */
2829 minp();
2830 q = buf;
2831 while (ch != c && ch != '\n' && ch != CH_EOF) {
2832 if ((q - buf) < sizeof(buf) - 1)
2833 *q++ = ch;
2834 minp();
2836 *q = '\0';
2837 minp();
2838 #if 0
2839 /* eat all spaces and comments after include */
2840 /* XXX: slightly incorrect */
2841 while (ch1 != '\n' && ch1 != CH_EOF)
2842 inp();
2843 #endif
2844 } else {
2845 /* computed #include : either we have only strings or
2846 we have anything enclosed in '<>' */
2847 next();
2848 buf[0] = '\0';
2849 if (tok == TOK_STR) {
2850 while (tok != TOK_LINEFEED) {
2851 if (tok != TOK_STR) {
2852 include_syntax:
2853 error("'#include' expects \"FILENAME\" or <FILENAME>");
2855 pstrcat(buf, sizeof(buf), (char *)tokc.cstr->data);
2856 next();
2858 c = '\"';
2859 } else {
2860 int len;
2861 while (tok != TOK_LINEFEED) {
2862 pstrcat(buf, sizeof(buf), get_tok_str(tok, &tokc));
2863 next();
2865 len = strlen(buf);
2866 /* check syntax and remove '<>' */
2867 if (len < 2 || buf[0] != '<' || buf[len - 1] != '>')
2868 goto include_syntax;
2869 memmove(buf, buf + 1, len - 2);
2870 buf[len - 2] = '\0';
2871 c = '>';
2875 e = search_cached_include(s1, c, buf);
2876 if (e && define_find(e->ifndef_macro)) {
2877 /* no need to parse the include because the 'ifndef macro'
2878 is defined */
2879 #ifdef INC_DEBUG
2880 printf("%s: skipping %s\n", file->filename, buf);
2881 #endif
2882 } else {
2883 if (c == '\"') {
2884 /* first search in current dir if "header.h" */
2885 size = 0;
2886 p = strrchr(file->filename, '/');
2887 if (p)
2888 size = p + 1 - file->filename;
2889 if (size > sizeof(buf1) - 1)
2890 size = sizeof(buf1) - 1;
2891 memcpy(buf1, file->filename, size);
2892 buf1[size] = '\0';
2893 pstrcat(buf1, sizeof(buf1), buf);
2894 f = tcc_open(s1, buf1);
2895 if (f) {
2896 if (tok == TOK_INCLUDE_NEXT)
2897 tok = TOK_INCLUDE;
2898 else
2899 goto found;
2902 if (s1->include_stack_ptr >= s1->include_stack + INCLUDE_STACK_SIZE)
2903 error("#include recursion too deep");
2904 /* now search in all the include paths */
2905 n = s1->nb_include_paths + s1->nb_sysinclude_paths;
2906 for(i = 0; i < n; i++) {
2907 const char *path;
2908 if (i < s1->nb_include_paths)
2909 path = s1->include_paths[i];
2910 else
2911 path = s1->sysinclude_paths[i - s1->nb_include_paths];
2912 pstrcpy(buf1, sizeof(buf1), path);
2913 pstrcat(buf1, sizeof(buf1), "/");
2914 pstrcat(buf1, sizeof(buf1), buf);
2915 f = tcc_open(s1, buf1);
2916 if (f) {
2917 if (tok == TOK_INCLUDE_NEXT)
2918 tok = TOK_INCLUDE;
2919 else
2920 goto found;
2923 error("include file '%s' not found", buf);
2924 f = NULL;
2925 found:
2926 #ifdef INC_DEBUG
2927 printf("%s: including %s\n", file->filename, buf1);
2928 #endif
2929 f->inc_type = c;
2930 pstrcpy(f->inc_filename, sizeof(f->inc_filename), buf);
2931 /* push current file in stack */
2932 /* XXX: fix current line init */
2933 *s1->include_stack_ptr++ = file;
2934 file = f;
2935 /* add include file debug info */
2936 if (do_debug) {
2937 put_stabs(file->filename, N_BINCL, 0, 0, 0);
2939 tok_flags |= TOK_FLAG_BOF | TOK_FLAG_BOL;
2940 ch = file->buf_ptr[0];
2941 goto the_end;
2943 break;
2944 case TOK_IFNDEF:
2945 c = 1;
2946 goto do_ifdef;
2947 case TOK_IF:
2948 c = expr_preprocess();
2949 goto do_if;
2950 case TOK_IFDEF:
2951 c = 0;
2952 do_ifdef:
2953 next_nomacro();
2954 if (tok < TOK_IDENT)
2955 error("invalid argument for '#if%sdef'", c ? "n" : "");
2956 if (is_bof) {
2957 if (c) {
2958 #ifdef INC_DEBUG
2959 printf("#ifndef %s\n", get_tok_str(tok, NULL));
2960 #endif
2961 file->ifndef_macro = tok;
2964 c = (define_find(tok) != 0) ^ c;
2965 do_if:
2966 if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE)
2967 error("memory full");
2968 *s1->ifdef_stack_ptr++ = c;
2969 goto test_skip;
2970 case TOK_ELSE:
2971 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
2972 error("#else without matching #if");
2973 if (s1->ifdef_stack_ptr[-1] & 2)
2974 error("#else after #else");
2975 c = (s1->ifdef_stack_ptr[-1] ^= 3);
2976 goto test_skip;
2977 case TOK_ELIF:
2978 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
2979 error("#elif without matching #if");
2980 c = s1->ifdef_stack_ptr[-1];
2981 if (c > 1)
2982 error("#elif after #else");
2983 /* last #if/#elif expression was true: we skip */
2984 if (c == 1)
2985 goto skip;
2986 c = expr_preprocess();
2987 s1->ifdef_stack_ptr[-1] = c;
2988 test_skip:
2989 if (!(c & 1)) {
2990 skip:
2991 preprocess_skip();
2992 is_bof = 0;
2993 goto redo;
2995 break;
2996 case TOK_ENDIF:
2997 if (s1->ifdef_stack_ptr <= file->ifdef_stack_ptr)
2998 error("#endif without matching #if");
2999 s1->ifdef_stack_ptr--;
3000 /* '#ifndef macro' was at the start of file. Now we check if
3001 an '#endif' is exactly at the end of file */
3002 if (file->ifndef_macro &&
3003 s1->ifdef_stack_ptr == file->ifdef_stack_ptr) {
3004 file->ifndef_macro_saved = file->ifndef_macro;
3005 /* need to set to zero to avoid false matches if another
3006 #ifndef at middle of file */
3007 file->ifndef_macro = 0;
3008 while (tok != TOK_LINEFEED)
3009 next_nomacro();
3010 tok_flags |= TOK_FLAG_ENDIF;
3011 goto the_end;
3013 break;
3014 case TOK_LINE:
3015 next();
3016 if (tok != TOK_CINT)
3017 error("#line");
3018 file->line_num = tokc.i - 1; /* the line number will be incremented after */
3019 next();
3020 if (tok != TOK_LINEFEED) {
3021 if (tok != TOK_STR)
3022 error("#line");
3023 pstrcpy(file->filename, sizeof(file->filename),
3024 (char *)tokc.cstr->data);
3026 break;
3027 case TOK_ERROR:
3028 case TOK_WARNING:
3029 c = tok;
3030 ch = file->buf_ptr[0];
3031 skip_spaces();
3032 q = buf;
3033 while (ch != '\n' && ch != CH_EOF) {
3034 if ((q - buf) < sizeof(buf) - 1)
3035 *q++ = ch;
3036 minp();
3038 *q = '\0';
3039 if (c == TOK_ERROR)
3040 error("#error %s", buf);
3041 else
3042 warning("#warning %s", buf);
3043 break;
3044 case TOK_PRAGMA:
3045 pragma_parse(s1);
3046 break;
3047 default:
3048 if (tok == TOK_LINEFEED || tok == '!' || tok == TOK_CINT) {
3049 /* '!' is ignored to allow C scripts. numbers are ignored
3050 to emulate cpp behaviour */
3051 } else {
3052 if (!(saved_parse_flags & PARSE_FLAG_ASM_COMMENTS))
3053 error("invalid preprocessing directive #%s", get_tok_str(tok, &tokc));
3055 break;
3057 /* ignore other preprocess commands or #! for C scripts */
3058 while (tok != TOK_LINEFEED)
3059 next_nomacro();
3060 the_end:
3061 parse_flags = saved_parse_flags;
3064 /* evaluate escape codes in a string. */
3065 static void parse_escape_string(CString *outstr, const uint8_t *buf, int is_long)
3067 int c, n;
3068 const uint8_t *p;
3070 p = buf;
3071 for(;;) {
3072 c = *p;
3073 if (c == '\0')
3074 break;
3075 if (c == '\\') {
3076 p++;
3077 /* escape */
3078 c = *p;
3079 switch(c) {
3080 case '0': case '1': case '2': case '3':
3081 case '4': case '5': case '6': case '7':
3082 /* at most three octal digits */
3083 n = c - '0';
3084 p++;
3085 c = *p;
3086 if (isoct(c)) {
3087 n = n * 8 + c - '0';
3088 p++;
3089 c = *p;
3090 if (isoct(c)) {
3091 n = n * 8 + c - '0';
3092 p++;
3095 c = n;
3096 goto add_char_nonext;
3097 case 'x':
3098 p++;
3099 n = 0;
3100 for(;;) {
3101 c = *p;
3102 if (c >= 'a' && c <= 'f')
3103 c = c - 'a' + 10;
3104 else if (c >= 'A' && c <= 'F')
3105 c = c - 'A' + 10;
3106 else if (isnum(c))
3107 c = c - '0';
3108 else
3109 break;
3110 n = n * 16 + c;
3111 p++;
3113 c = n;
3114 goto add_char_nonext;
3115 case 'a':
3116 c = '\a';
3117 break;
3118 case 'b':
3119 c = '\b';
3120 break;
3121 case 'f':
3122 c = '\f';
3123 break;
3124 case 'n':
3125 c = '\n';
3126 break;
3127 case 'r':
3128 c = '\r';
3129 break;
3130 case 't':
3131 c = '\t';
3132 break;
3133 case 'v':
3134 c = '\v';
3135 break;
3136 case 'e':
3137 if (!gnu_ext)
3138 goto invalid_escape;
3139 c = 27;
3140 break;
3141 case '\'':
3142 case '\"':
3143 case '\\':
3144 case '?':
3145 break;
3146 default:
3147 invalid_escape:
3148 if (c >= '!' && c <= '~')
3149 warning("unknown escape sequence: \'\\%c\'", c);
3150 else
3151 warning("unknown escape sequence: \'\\x%x\'", c);
3152 break;
3155 p++;
3156 add_char_nonext:
3157 if (!is_long)
3158 cstr_ccat(outstr, c);
3159 else
3160 cstr_wccat(outstr, c);
3162 /* add a trailing '\0' */
3163 if (!is_long)
3164 cstr_ccat(outstr, '\0');
3165 else
3166 cstr_wccat(outstr, '\0');
3169 /* we use 64 bit numbers */
3170 #define BN_SIZE 2
3172 /* bn = (bn << shift) | or_val */
3173 void bn_lshift(unsigned int *bn, int shift, int or_val)
3175 int i;
3176 unsigned int v;
3177 for(i=0;i<BN_SIZE;i++) {
3178 v = bn[i];
3179 bn[i] = (v << shift) | or_val;
3180 or_val = v >> (32 - shift);
3184 void bn_zero(unsigned int *bn)
3186 int i;
3187 for(i=0;i<BN_SIZE;i++) {
3188 bn[i] = 0;
3192 /* parse number in null terminated string 'p' and return it in the
3193 current token */
3194 void parse_number(const char *p)
3196 int b, t, shift, frac_bits, s, exp_val, ch;
3197 char *q;
3198 unsigned int bn[BN_SIZE];
3199 double d;
3201 /* number */
3202 q = token_buf;
3203 ch = *p++;
3204 t = ch;
3205 ch = *p++;
3206 *q++ = t;
3207 b = 10;
3208 if (t == '.') {
3209 goto float_frac_parse;
3210 } else if (t == '0') {
3211 if (ch == 'x' || ch == 'X') {
3212 q--;
3213 ch = *p++;
3214 b = 16;
3215 } else if (tcc_ext && (ch == 'b' || ch == 'B')) {
3216 q--;
3217 ch = *p++;
3218 b = 2;
3221 /* parse all digits. cannot check octal numbers at this stage
3222 because of floating point constants */
3223 while (1) {
3224 if (ch >= 'a' && ch <= 'f')
3225 t = ch - 'a' + 10;
3226 else if (ch >= 'A' && ch <= 'F')
3227 t = ch - 'A' + 10;
3228 else if (isnum(ch))
3229 t = ch - '0';
3230 else
3231 break;
3232 if (t >= b)
3233 break;
3234 if (q >= token_buf + STRING_MAX_SIZE) {
3235 num_too_long:
3236 error("number too long");
3238 *q++ = ch;
3239 ch = *p++;
3241 if (ch == '.' ||
3242 ((ch == 'e' || ch == 'E') && b == 10) ||
3243 ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
3244 if (b != 10) {
3245 /* NOTE: strtox should support that for hexa numbers, but
3246 non ISOC99 libcs do not support it, so we prefer to do
3247 it by hand */
3248 /* hexadecimal or binary floats */
3249 /* XXX: handle overflows */
3250 *q = '\0';
3251 if (b == 16)
3252 shift = 4;
3253 else
3254 shift = 2;
3255 bn_zero(bn);
3256 q = token_buf;
3257 while (1) {
3258 t = *q++;
3259 if (t == '\0') {
3260 break;
3261 } else if (t >= 'a') {
3262 t = t - 'a' + 10;
3263 } else if (t >= 'A') {
3264 t = t - 'A' + 10;
3265 } else {
3266 t = t - '0';
3268 bn_lshift(bn, shift, t);
3270 frac_bits = 0;
3271 if (ch == '.') {
3272 ch = *p++;
3273 while (1) {
3274 t = ch;
3275 if (t >= 'a' && t <= 'f') {
3276 t = t - 'a' + 10;
3277 } else if (t >= 'A' && t <= 'F') {
3278 t = t - 'A' + 10;
3279 } else if (t >= '0' && t <= '9') {
3280 t = t - '0';
3281 } else {
3282 break;
3284 if (t >= b)
3285 error("invalid digit");
3286 bn_lshift(bn, shift, t);
3287 frac_bits += shift;
3288 ch = *p++;
3291 if (ch != 'p' && ch != 'P')
3292 expect("exponent");
3293 ch = *p++;
3294 s = 1;
3295 exp_val = 0;
3296 if (ch == '+') {
3297 ch = *p++;
3298 } else if (ch == '-') {
3299 s = -1;
3300 ch = *p++;
3302 if (ch < '0' || ch > '9')
3303 expect("exponent digits");
3304 while (ch >= '0' && ch <= '9') {
3305 exp_val = exp_val * 10 + ch - '0';
3306 ch = *p++;
3308 exp_val = exp_val * s;
3310 /* now we can generate the number */
3311 /* XXX: should patch directly float number */
3312 d = (double)bn[1] * 4294967296.0 + (double)bn[0];
3313 d = ldexp(d, exp_val - frac_bits);
3314 t = toup(ch);
3315 if (t == 'F') {
3316 ch = *p++;
3317 tok = TOK_CFLOAT;
3318 /* float : should handle overflow */
3319 tokc.f = (float)d;
3320 } else if (t == 'L') {
3321 ch = *p++;
3322 tok = TOK_CLDOUBLE;
3323 /* XXX: not large enough */
3324 tokc.ld = (long double)d;
3325 } else {
3326 tok = TOK_CDOUBLE;
3327 tokc.d = d;
3329 } else {
3330 /* decimal floats */
3331 if (ch == '.') {
3332 if (q >= token_buf + STRING_MAX_SIZE)
3333 goto num_too_long;
3334 *q++ = ch;
3335 ch = *p++;
3336 float_frac_parse:
3337 while (ch >= '0' && ch <= '9') {
3338 if (q >= token_buf + STRING_MAX_SIZE)
3339 goto num_too_long;
3340 *q++ = ch;
3341 ch = *p++;
3344 if (ch == 'e' || ch == 'E') {
3345 if (q >= token_buf + STRING_MAX_SIZE)
3346 goto num_too_long;
3347 *q++ = ch;
3348 ch = *p++;
3349 if (ch == '-' || ch == '+') {
3350 if (q >= token_buf + STRING_MAX_SIZE)
3351 goto num_too_long;
3352 *q++ = ch;
3353 ch = *p++;
3355 if (ch < '0' || ch > '9')
3356 expect("exponent digits");
3357 while (ch >= '0' && ch <= '9') {
3358 if (q >= token_buf + STRING_MAX_SIZE)
3359 goto num_too_long;
3360 *q++ = ch;
3361 ch = *p++;
3364 *q = '\0';
3365 t = toup(ch);
3366 errno = 0;
3367 if (t == 'F') {
3368 ch = *p++;
3369 tok = TOK_CFLOAT;
3370 tokc.f = strtof(token_buf, NULL);
3371 } else if (t == 'L') {
3372 ch = *p++;
3373 tok = TOK_CLDOUBLE;
3374 tokc.ld = strtold(token_buf, NULL);
3375 } else {
3376 tok = TOK_CDOUBLE;
3377 tokc.d = strtod(token_buf, NULL);
3380 } else {
3381 unsigned long long n, n1;
3382 int lcount, ucount;
3384 /* integer number */
3385 *q = '\0';
3386 q = token_buf;
3387 if (b == 10 && *q == '0') {
3388 b = 8;
3389 q++;
3391 n = 0;
3392 while(1) {
3393 t = *q++;
3394 /* no need for checks except for base 10 / 8 errors */
3395 if (t == '\0') {
3396 break;
3397 } else if (t >= 'a') {
3398 t = t - 'a' + 10;
3399 } else if (t >= 'A') {
3400 t = t - 'A' + 10;
3401 } else {
3402 t = t - '0';
3403 if (t >= b)
3404 error("invalid digit");
3406 n1 = n;
3407 n = n * b + t;
3408 /* detect overflow */
3409 /* XXX: this test is not reliable */
3410 if (n < n1)
3411 error("integer constant overflow");
3414 /* XXX: not exactly ANSI compliant */
3415 if ((n & 0xffffffff00000000LL) != 0) {
3416 if ((n >> 63) != 0)
3417 tok = TOK_CULLONG;
3418 else
3419 tok = TOK_CLLONG;
3420 } else if (n > 0x7fffffff) {
3421 tok = TOK_CUINT;
3422 } else {
3423 tok = TOK_CINT;
3425 lcount = 0;
3426 ucount = 0;
3427 for(;;) {
3428 t = toup(ch);
3429 if (t == 'L') {
3430 if (lcount >= 2)
3431 error("three 'l's in integer constant");
3432 lcount++;
3433 if (lcount == 2) {
3434 if (tok == TOK_CINT)
3435 tok = TOK_CLLONG;
3436 else if (tok == TOK_CUINT)
3437 tok = TOK_CULLONG;
3439 ch = *p++;
3440 } else if (t == 'U') {
3441 if (ucount >= 1)
3442 error("two 'u's in integer constant");
3443 ucount++;
3444 if (tok == TOK_CINT)
3445 tok = TOK_CUINT;
3446 else if (tok == TOK_CLLONG)
3447 tok = TOK_CULLONG;
3448 ch = *p++;
3449 } else {
3450 break;
3453 if (tok == TOK_CINT || tok == TOK_CUINT)
3454 tokc.ui = n;
3455 else
3456 tokc.ull = n;
3461 #define PARSE2(c1, tok1, c2, tok2) \
3462 case c1: \
3463 PEEKC(c, p); \
3464 if (c == c2) { \
3465 p++; \
3466 tok = tok2; \
3467 } else { \
3468 tok = tok1; \
3470 break;
3472 /* return next token without macro substitution */
3473 static inline void next_nomacro1(void)
3475 int t, c, is_long;
3476 TokenSym *ts;
3477 uint8_t *p, *p1;
3478 unsigned int h;
3480 p = file->buf_ptr;
3481 redo_no_start:
3482 c = *p;
3483 switch(c) {
3484 case ' ':
3485 case '\t':
3486 case '\f':
3487 case '\v':
3488 case '\r':
3489 p++;
3490 goto redo_no_start;
3492 case '\\':
3493 /* first look if it is in fact an end of buffer */
3494 if (p >= file->buf_end) {
3495 file->buf_ptr = p;
3496 handle_eob();
3497 p = file->buf_ptr;
3498 if (p >= file->buf_end)
3499 goto parse_eof;
3500 else
3501 goto redo_no_start;
3502 } else {
3503 file->buf_ptr = p;
3504 ch = *p;
3505 handle_stray();
3506 p = file->buf_ptr;
3507 goto redo_no_start;
3509 parse_eof:
3511 TCCState *s1 = tcc_state;
3512 if (parse_flags & PARSE_FLAG_LINEFEED) {
3513 tok = TOK_LINEFEED;
3514 } else if (s1->include_stack_ptr == s1->include_stack ||
3515 !(parse_flags & PARSE_FLAG_PREPROCESS)) {
3516 /* no include left : end of file. */
3517 tok = TOK_EOF;
3518 } else {
3519 /* pop include file */
3521 /* test if previous '#endif' was after a #ifdef at
3522 start of file */
3523 if (tok_flags & TOK_FLAG_ENDIF) {
3524 #ifdef INC_DEBUG
3525 printf("#endif %s\n", get_tok_str(file->ifndef_macro_saved, NULL));
3526 #endif
3527 add_cached_include(s1, file->inc_type, file->inc_filename,
3528 file->ifndef_macro_saved);
3531 /* add end of include file debug info */
3532 if (do_debug) {
3533 put_stabd(N_EINCL, 0, 0);
3535 /* pop include stack */
3536 tcc_close(file);
3537 s1->include_stack_ptr--;
3538 file = *s1->include_stack_ptr;
3539 p = file->buf_ptr;
3540 goto redo_no_start;
3543 break;
3545 case '\n':
3546 if (parse_flags & PARSE_FLAG_LINEFEED) {
3547 tok = TOK_LINEFEED;
3548 } else {
3549 file->line_num++;
3550 tok_flags |= TOK_FLAG_BOL;
3551 p++;
3552 goto redo_no_start;
3554 break;
3556 case '#':
3557 /* XXX: simplify */
3558 PEEKC(c, p);
3559 if ((tok_flags & TOK_FLAG_BOL) &&
3560 (parse_flags & PARSE_FLAG_PREPROCESS)) {
3561 file->buf_ptr = p;
3562 preprocess(tok_flags & TOK_FLAG_BOF);
3563 p = file->buf_ptr;
3564 goto redo_no_start;
3565 } else {
3566 if (c == '#') {
3567 p++;
3568 tok = TOK_TWOSHARPS;
3569 } else {
3570 if (parse_flags & PARSE_FLAG_ASM_COMMENTS) {
3571 p = parse_line_comment(p - 1);
3572 goto redo_no_start;
3573 } else {
3574 tok = '#';
3578 break;
3580 case 'a': case 'b': case 'c': case 'd':
3581 case 'e': case 'f': case 'g': case 'h':
3582 case 'i': case 'j': case 'k': case 'l':
3583 case 'm': case 'n': case 'o': case 'p':
3584 case 'q': case 'r': case 's': case 't':
3585 case 'u': case 'v': case 'w': case 'x':
3586 case 'y': case 'z':
3587 case 'A': case 'B': case 'C': case 'D':
3588 case 'E': case 'F': case 'G': case 'H':
3589 case 'I': case 'J': case 'K':
3590 case 'M': case 'N': case 'O': case 'P':
3591 case 'Q': case 'R': case 'S': case 'T':
3592 case 'U': case 'V': case 'W': case 'X':
3593 case 'Y': case 'Z':
3594 case '_':
3595 parse_ident_fast:
3596 p1 = p;
3597 h = TOK_HASH_INIT;
3598 h = TOK_HASH_FUNC(h, c);
3599 p++;
3600 for(;;) {
3601 c = *p;
3602 if (!isidnum_table[c])
3603 break;
3604 h = TOK_HASH_FUNC(h, c);
3605 p++;
3607 if (c != '\\') {
3608 TokenSym **pts;
3609 int len;
3611 /* fast case : no stray found, so we have the full token
3612 and we have already hashed it */
3613 len = p - p1;
3614 h &= (TOK_HASH_SIZE - 1);
3615 pts = &hash_ident[h];
3616 for(;;) {
3617 ts = *pts;
3618 if (!ts)
3619 break;
3620 if (ts->len == len && !memcmp(ts->str, p1, len))
3621 goto token_found;
3622 pts = &(ts->hash_next);
3624 ts = tok_alloc_new(pts, p1, len);
3625 token_found: ;
3626 } else {
3627 /* slower case */
3628 cstr_reset(&tokcstr);
3630 while (p1 < p) {
3631 cstr_ccat(&tokcstr, *p1);
3632 p1++;
3634 p--;
3635 PEEKC(c, p);
3636 parse_ident_slow:
3637 while (isidnum_table[c]) {
3638 cstr_ccat(&tokcstr, c);
3639 PEEKC(c, p);
3641 ts = tok_alloc(tokcstr.data, tokcstr.size);
3643 tok = ts->tok;
3644 break;
3645 case 'L':
3646 t = p[1];
3647 if (t != '\\' && t != '\'' && t != '\"') {
3648 /* fast case */
3649 goto parse_ident_fast;
3650 } else {
3651 PEEKC(c, p);
3652 if (c == '\'' || c == '\"') {
3653 is_long = 1;
3654 goto str_const;
3655 } else {
3656 cstr_reset(&tokcstr);
3657 cstr_ccat(&tokcstr, 'L');
3658 goto parse_ident_slow;
3661 break;
3662 case '0': case '1': case '2': case '3':
3663 case '4': case '5': case '6': case '7':
3664 case '8': case '9':
3666 cstr_reset(&tokcstr);
3667 /* after the first digit, accept digits, alpha, '.' or sign if
3668 prefixed by 'eEpP' */
3669 parse_num:
3670 for(;;) {
3671 t = c;
3672 cstr_ccat(&tokcstr, c);
3673 PEEKC(c, p);
3674 if (!(isnum(c) || isid(c) || c == '.' ||
3675 ((c == '+' || c == '-') &&
3676 (t == 'e' || t == 'E' || t == 'p' || t == 'P'))))
3677 break;
3679 /* We add a trailing '\0' to ease parsing */
3680 cstr_ccat(&tokcstr, '\0');
3681 tokc.cstr = &tokcstr;
3682 tok = TOK_PPNUM;
3683 break;
3684 case '.':
3685 /* special dot handling because it can also start a number */
3686 PEEKC(c, p);
3687 if (isnum(c)) {
3688 cstr_reset(&tokcstr);
3689 cstr_ccat(&tokcstr, '.');
3690 goto parse_num;
3691 } else if (c == '.') {
3692 PEEKC(c, p);
3693 if (c != '.')
3694 expect("'.'");
3695 PEEKC(c, p);
3696 tok = TOK_DOTS;
3697 } else {
3698 tok = '.';
3700 break;
3701 case '\'':
3702 case '\"':
3703 is_long = 0;
3704 str_const:
3706 CString str;
3707 int sep;
3709 sep = c;
3711 /* parse the string */
3712 cstr_new(&str);
3713 p = parse_pp_string(p, sep, &str);
3714 cstr_ccat(&str, '\0');
3716 /* eval the escape (should be done as TOK_PPNUM) */
3717 cstr_reset(&tokcstr);
3718 parse_escape_string(&tokcstr, str.data, is_long);
3719 cstr_free(&str);
3721 if (sep == '\'') {
3722 int char_size;
3723 /* XXX: make it portable */
3724 if (!is_long)
3725 char_size = 1;
3726 else
3727 char_size = sizeof(int);
3728 if (tokcstr.size <= char_size)
3729 error("empty character constant");
3730 if (tokcstr.size > 2 * char_size)
3731 warning("multi-character character constant");
3732 if (!is_long) {
3733 tokc.i = *(int8_t *)tokcstr.data;
3734 tok = TOK_CCHAR;
3735 } else {
3736 tokc.i = *(int *)tokcstr.data;
3737 tok = TOK_LCHAR;
3739 } else {
3740 tokc.cstr = &tokcstr;
3741 if (!is_long)
3742 tok = TOK_STR;
3743 else
3744 tok = TOK_LSTR;
3747 break;
3749 case '<':
3750 PEEKC(c, p);
3751 if (c == '=') {
3752 p++;
3753 tok = TOK_LE;
3754 } else if (c == '<') {
3755 PEEKC(c, p);
3756 if (c == '=') {
3757 p++;
3758 tok = TOK_A_SHL;
3759 } else {
3760 tok = TOK_SHL;
3762 } else {
3763 tok = TOK_LT;
3765 break;
3767 case '>':
3768 PEEKC(c, p);
3769 if (c == '=') {
3770 p++;
3771 tok = TOK_GE;
3772 } else if (c == '>') {
3773 PEEKC(c, p);
3774 if (c == '=') {
3775 p++;
3776 tok = TOK_A_SAR;
3777 } else {
3778 tok = TOK_SAR;
3780 } else {
3781 tok = TOK_GT;
3783 break;
3785 case '&':
3786 PEEKC(c, p);
3787 if (c == '&') {
3788 p++;
3789 tok = TOK_LAND;
3790 } else if (c == '=') {
3791 p++;
3792 tok = TOK_A_AND;
3793 } else {
3794 tok = '&';
3796 break;
3798 case '|':
3799 PEEKC(c, p);
3800 if (c == '|') {
3801 p++;
3802 tok = TOK_LOR;
3803 } else if (c == '=') {
3804 p++;
3805 tok = TOK_A_OR;
3806 } else {
3807 tok = '|';
3809 break;
3811 case '+':
3812 PEEKC(c, p);
3813 if (c == '+') {
3814 p++;
3815 tok = TOK_INC;
3816 } else if (c == '=') {
3817 p++;
3818 tok = TOK_A_ADD;
3819 } else {
3820 tok = '+';
3822 break;
3824 case '-':
3825 PEEKC(c, p);
3826 if (c == '-') {
3827 p++;
3828 tok = TOK_DEC;
3829 } else if (c == '=') {
3830 p++;
3831 tok = TOK_A_SUB;
3832 } else if (c == '>') {
3833 p++;
3834 tok = TOK_ARROW;
3835 } else {
3836 tok = '-';
3838 break;
3840 PARSE2('!', '!', '=', TOK_NE)
3841 PARSE2('=', '=', '=', TOK_EQ)
3842 PARSE2('*', '*', '=', TOK_A_MUL)
3843 PARSE2('%', '%', '=', TOK_A_MOD)
3844 PARSE2('^', '^', '=', TOK_A_XOR)
3846 /* comments or operator */
3847 case '/':
3848 PEEKC(c, p);
3849 if (c == '*') {
3850 p = parse_comment(p);
3851 goto redo_no_start;
3852 } else if (c == '/') {
3853 p = parse_line_comment(p);
3854 goto redo_no_start;
3855 } else if (c == '=') {
3856 p++;
3857 tok = TOK_A_DIV;
3858 } else {
3859 tok = '/';
3861 break;
3863 /* simple tokens */
3864 case '(':
3865 case ')':
3866 case '[':
3867 case ']':
3868 case '{':
3869 case '}':
3870 case ',':
3871 case ';':
3872 case ':':
3873 case '?':
3874 case '~':
3875 case '$': /* only used in assembler */
3876 case '@': /* dito */
3877 tok = c;
3878 p++;
3879 break;
3880 default:
3881 error("unrecognized character \\x%02x", c);
3882 break;
3884 file->buf_ptr = p;
3885 tok_flags = 0;
3886 #if defined(PARSE_DEBUG)
3887 printf("token = %s\n", get_tok_str(tok, &tokc));
3888 #endif
3891 /* return next token without macro substitution. Can read input from
3892 macro_ptr buffer */
3893 static void next_nomacro(void)
3895 if (macro_ptr) {
3896 redo:
3897 tok = *macro_ptr;
3898 if (tok) {
3899 TOK_GET(tok, macro_ptr, tokc);
3900 if (tok == TOK_LINENUM) {
3901 file->line_num = tokc.i;
3902 goto redo;
3905 } else {
3906 next_nomacro1();
3910 /* substitute args in macro_str and return allocated string */
3911 static int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
3913 int *st, last_tok, t, notfirst;
3914 Sym *s;
3915 CValue cval;
3916 TokenString str;
3917 CString cstr;
3919 tok_str_new(&str);
3920 last_tok = 0;
3921 while(1) {
3922 TOK_GET(t, macro_str, cval);
3923 if (!t)
3924 break;
3925 if (t == '#') {
3926 /* stringize */
3927 TOK_GET(t, macro_str, cval);
3928 if (!t)
3929 break;
3930 s = sym_find2(args, t);
3931 if (s) {
3932 cstr_new(&cstr);
3933 st = (int *)s->c;
3934 notfirst = 0;
3935 while (*st) {
3936 if (notfirst)
3937 cstr_ccat(&cstr, ' ');
3938 TOK_GET(t, st, cval);
3939 cstr_cat(&cstr, get_tok_str(t, &cval));
3940 notfirst = 1;
3942 cstr_ccat(&cstr, '\0');
3943 #ifdef PP_DEBUG
3944 printf("stringize: %s\n", (char *)cstr.data);
3945 #endif
3946 /* add string */
3947 cval.cstr = &cstr;
3948 tok_str_add2(&str, TOK_STR, &cval);
3949 cstr_free(&cstr);
3950 } else {
3951 tok_str_add2(&str, t, &cval);
3953 } else if (t >= TOK_IDENT) {
3954 s = sym_find2(args, t);
3955 if (s) {
3956 st = (int *)s->c;
3957 /* if '##' is present before or after, no arg substitution */
3958 if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) {
3959 /* special case for var arg macros : ## eats the
3960 ',' if empty VA_ARGS variable. */
3961 /* XXX: test of the ',' is not 100%
3962 reliable. should fix it to avoid security
3963 problems */
3964 if (gnu_ext && s->type.t &&
3965 last_tok == TOK_TWOSHARPS &&
3966 str.len >= 2 && str.str[str.len - 2] == ',') {
3967 if (*st == 0) {
3968 /* suppress ',' '##' */
3969 str.len -= 2;
3970 } else {
3971 /* suppress '##' and add variable */
3972 str.len--;
3973 goto add_var;
3975 } else {
3976 int t1;
3977 add_var:
3978 for(;;) {
3979 TOK_GET(t1, st, cval);
3980 if (!t1)
3981 break;
3982 tok_str_add2(&str, t1, &cval);
3985 } else {
3986 /* NOTE: the stream cannot be read when macro
3987 substituing an argument */
3988 macro_subst(&str, nested_list, st, NULL);
3990 } else {
3991 tok_str_add(&str, t);
3993 } else {
3994 tok_str_add2(&str, t, &cval);
3996 last_tok = t;
3998 tok_str_add(&str, 0);
3999 return str.str;
4002 static char const ab_month_name[12][4] =
4004 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
4005 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
4008 /* do macro substitution of current token with macro 's' and add
4009 result to (tok_str,tok_len). 'nested_list' is the list of all
4010 macros we got inside to avoid recursing. Return non zero if no
4011 substitution needs to be done */
4012 static int macro_subst_tok(TokenString *tok_str,
4013 Sym **nested_list, Sym *s, struct macro_level **can_read_stream)
4015 Sym *args, *sa, *sa1;
4016 int mstr_allocated, parlevel, *mstr, t, t1;
4017 TokenString str;
4018 char *cstrval;
4019 CValue cval;
4020 CString cstr;
4021 char buf[32];
4023 /* if symbol is a macro, prepare substitution */
4024 /* special macros */
4025 if (tok == TOK___LINE__) {
4026 snprintf(buf, sizeof(buf), "%d", file->line_num);
4027 cstrval = buf;
4028 t1 = TOK_PPNUM;
4029 goto add_cstr1;
4030 } else if (tok == TOK___FILE__) {
4031 cstrval = file->filename;
4032 goto add_cstr;
4033 } else if (tok == TOK___DATE__ || tok == TOK___TIME__) {
4034 time_t ti;
4035 struct tm *tm;
4037 time(&ti);
4038 tm = localtime(&ti);
4039 if (tok == TOK___DATE__) {
4040 snprintf(buf, sizeof(buf), "%s %2d %d",
4041 ab_month_name[tm->tm_mon], tm->tm_mday, tm->tm_year + 1900);
4042 } else {
4043 snprintf(buf, sizeof(buf), "%02d:%02d:%02d",
4044 tm->tm_hour, tm->tm_min, tm->tm_sec);
4046 cstrval = buf;
4047 add_cstr:
4048 t1 = TOK_STR;
4049 add_cstr1:
4050 cstr_new(&cstr);
4051 cstr_cat(&cstr, cstrval);
4052 cstr_ccat(&cstr, '\0');
4053 cval.cstr = &cstr;
4054 tok_str_add2(tok_str, t1, &cval);
4055 cstr_free(&cstr);
4056 } else {
4057 mstr = (int *)s->c;
4058 mstr_allocated = 0;
4059 if (s->type.t == MACRO_FUNC) {
4060 /* NOTE: we do not use next_nomacro to avoid eating the
4061 next token. XXX: find better solution */
4062 redo:
4063 if (macro_ptr) {
4064 t = *macro_ptr;
4065 if (t == 0 && can_read_stream) {
4066 /* end of macro stream: we must look at the token
4067 after in the file */
4068 struct macro_level *ml = *can_read_stream;
4069 macro_ptr = NULL;
4070 if (ml)
4072 macro_ptr = ml->p;
4073 ml->p = NULL;
4074 *can_read_stream = ml -> prev;
4076 goto redo;
4078 } else {
4079 /* XXX: incorrect with comments */
4080 ch = file->buf_ptr[0];
4081 while (is_space(ch) || ch == '\n')
4082 cinp();
4083 t = ch;
4085 if (t != '(') /* no macro subst */
4086 return -1;
4088 /* argument macro */
4089 next_nomacro();
4090 next_nomacro();
4091 args = NULL;
4092 sa = s->next;
4093 /* NOTE: empty args are allowed, except if no args */
4094 for(;;) {
4095 /* handle '()' case */
4096 if (!args && !sa && tok == ')')
4097 break;
4098 if (!sa)
4099 error("macro '%s' used with too many args",
4100 get_tok_str(s->v, 0));
4101 tok_str_new(&str);
4102 parlevel = 0;
4103 /* NOTE: non zero sa->t indicates VA_ARGS */
4104 while ((parlevel > 0 ||
4105 (tok != ')' &&
4106 (tok != ',' || sa->type.t))) &&
4107 tok != -1) {
4108 if (tok == '(')
4109 parlevel++;
4110 else if (tok == ')')
4111 parlevel--;
4112 tok_str_add2(&str, tok, &tokc);
4113 next_nomacro();
4115 tok_str_add(&str, 0);
4116 sym_push2(&args, sa->v & ~SYM_FIELD, sa->type.t, (int)str.str);
4117 sa = sa->next;
4118 if (tok == ')') {
4119 /* special case for gcc var args: add an empty
4120 var arg argument if it is omitted */
4121 if (sa && sa->type.t && gnu_ext)
4122 continue;
4123 else
4124 break;
4126 if (tok != ',')
4127 expect(",");
4128 next_nomacro();
4130 if (sa) {
4131 error("macro '%s' used with too few args",
4132 get_tok_str(s->v, 0));
4135 /* now subst each arg */
4136 mstr = macro_arg_subst(nested_list, mstr, args);
4137 /* free memory */
4138 sa = args;
4139 while (sa) {
4140 sa1 = sa->prev;
4141 tok_str_free((int *)sa->c);
4142 sym_free(sa);
4143 sa = sa1;
4145 mstr_allocated = 1;
4147 sym_push2(nested_list, s->v, 0, 0);
4148 macro_subst(tok_str, nested_list, mstr, can_read_stream);
4149 /* pop nested defined symbol */
4150 sa1 = *nested_list;
4151 *nested_list = sa1->prev;
4152 sym_free(sa1);
4153 if (mstr_allocated)
4154 tok_str_free(mstr);
4156 return 0;
4159 /* handle the '##' operator. Return NULL if no '##' seen. Otherwise
4160 return the resulting string (which must be freed). */
4161 static inline int *macro_twosharps(const int *macro_str)
4163 TokenSym *ts;
4164 const int *macro_ptr1, *start_macro_ptr, *ptr, *saved_macro_ptr;
4165 int t;
4166 const char *p1, *p2;
4167 CValue cval;
4168 TokenString macro_str1;
4169 CString cstr;
4171 start_macro_ptr = macro_str;
4172 /* we search the first '##' */
4173 for(;;) {
4174 macro_ptr1 = macro_str;
4175 TOK_GET(t, macro_str, cval);
4176 /* nothing more to do if end of string */
4177 if (t == 0)
4178 return NULL;
4179 if (*macro_str == TOK_TWOSHARPS)
4180 break;
4183 /* we saw '##', so we need more processing to handle it */
4184 cstr_new(&cstr);
4185 tok_str_new(&macro_str1);
4186 tok = t;
4187 tokc = cval;
4189 /* add all tokens seen so far */
4190 for(ptr = start_macro_ptr; ptr < macro_ptr1;) {
4191 TOK_GET(t, ptr, cval);
4192 tok_str_add2(&macro_str1, t, &cval);
4194 saved_macro_ptr = macro_ptr;
4195 /* XXX: get rid of the use of macro_ptr here */
4196 macro_ptr = (int *)macro_str;
4197 for(;;) {
4198 while (*macro_ptr == TOK_TWOSHARPS) {
4199 macro_ptr++;
4200 macro_ptr1 = macro_ptr;
4201 t = *macro_ptr;
4202 if (t) {
4203 TOK_GET(t, macro_ptr, cval);
4204 /* We concatenate the two tokens if we have an
4205 identifier or a preprocessing number */
4206 cstr_reset(&cstr);
4207 p1 = get_tok_str(tok, &tokc);
4208 cstr_cat(&cstr, p1);
4209 p2 = get_tok_str(t, &cval);
4210 cstr_cat(&cstr, p2);
4211 cstr_ccat(&cstr, '\0');
4213 if ((tok >= TOK_IDENT || tok == TOK_PPNUM) &&
4214 (t >= TOK_IDENT || t == TOK_PPNUM)) {
4215 if (tok == TOK_PPNUM) {
4216 /* if number, then create a number token */
4217 /* NOTE: no need to allocate because
4218 tok_str_add2() does it */
4219 tokc.cstr = &cstr;
4220 } else {
4221 /* if identifier, we must do a test to
4222 validate we have a correct identifier */
4223 if (t == TOK_PPNUM) {
4224 const char *p;
4225 int c;
4227 p = p2;
4228 for(;;) {
4229 c = *p;
4230 if (c == '\0')
4231 break;
4232 p++;
4233 if (!isnum(c) && !isid(c))
4234 goto error_pasting;
4237 ts = tok_alloc(cstr.data, strlen(cstr.data));
4238 tok = ts->tok; /* modify current token */
4240 } else {
4241 const char *str = cstr.data;
4242 const unsigned char *q;
4244 /* we look for a valid token */
4245 /* XXX: do more extensive checks */
4246 if (!strcmp(str, ">>=")) {
4247 tok = TOK_A_SAR;
4248 } else if (!strcmp(str, "<<=")) {
4249 tok = TOK_A_SHL;
4250 } else if (strlen(str) == 2) {
4251 /* search in two bytes table */
4252 q = tok_two_chars;
4253 for(;;) {
4254 if (!*q)
4255 goto error_pasting;
4256 if (q[0] == str[0] && q[1] == str[1])
4257 break;
4258 q += 3;
4260 tok = q[2];
4261 } else {
4262 error_pasting:
4263 /* NOTE: because get_tok_str use a static buffer,
4264 we must save it */
4265 cstr_reset(&cstr);
4266 p1 = get_tok_str(tok, &tokc);
4267 cstr_cat(&cstr, p1);
4268 cstr_ccat(&cstr, '\0');
4269 p2 = get_tok_str(t, &cval);
4270 warning("pasting \"%s\" and \"%s\" does not give a valid preprocessing token", cstr.data, p2);
4271 /* cannot merge tokens: just add them separately */
4272 tok_str_add2(&macro_str1, tok, &tokc);
4273 /* XXX: free associated memory ? */
4274 tok = t;
4275 tokc = cval;
4280 tok_str_add2(&macro_str1, tok, &tokc);
4281 next_nomacro();
4282 if (tok == 0)
4283 break;
4285 macro_ptr = (int *)saved_macro_ptr;
4286 cstr_free(&cstr);
4287 tok_str_add(&macro_str1, 0);
4288 return macro_str1.str;
4292 /* do macro substitution of macro_str and add result to
4293 (tok_str,tok_len). 'nested_list' is the list of all macros we got
4294 inside to avoid recursing. */
4295 static void macro_subst(TokenString *tok_str, Sym **nested_list,
4296 const int *macro_str, struct macro_level ** can_read_stream)
4298 Sym *s;
4299 int *macro_str1;
4300 const int *ptr;
4301 int t, ret;
4302 CValue cval;
4303 struct macro_level ml;
4305 /* first scan for '##' operator handling */
4306 ptr = macro_str;
4307 macro_str1 = macro_twosharps(ptr);
4308 if (macro_str1)
4309 ptr = macro_str1;
4310 while (1) {
4311 /* NOTE: ptr == NULL can only happen if tokens are read from
4312 file stream due to a macro function call */
4313 if (ptr == NULL)
4314 break;
4315 TOK_GET(t, ptr, cval);
4316 if (t == 0)
4317 break;
4318 s = define_find(t);
4319 if (s != NULL) {
4320 /* if nested substitution, do nothing */
4321 if (sym_find2(*nested_list, t))
4322 goto no_subst;
4323 ml.p = macro_ptr;
4324 if (can_read_stream)
4325 ml.prev = *can_read_stream, *can_read_stream = &ml;
4326 macro_ptr = (int *)ptr;
4327 tok = t;
4328 ret = macro_subst_tok(tok_str, nested_list, s, can_read_stream);
4329 ptr = (int *)macro_ptr;
4330 macro_ptr = ml.p;
4331 if (can_read_stream && *can_read_stream == &ml)
4332 *can_read_stream = ml.prev;
4333 if (ret != 0)
4334 goto no_subst;
4335 } else {
4336 no_subst:
4337 tok_str_add2(tok_str, t, &cval);
4340 if (macro_str1)
4341 tok_str_free(macro_str1);
4344 /* return next token with macro substitution */
4345 static void next(void)
4347 Sym *nested_list, *s;
4348 TokenString str;
4349 struct macro_level *ml;
4351 redo:
4352 next_nomacro();
4353 if (!macro_ptr) {
4354 /* if not reading from macro substituted string, then try
4355 to substitute macros */
4356 if (tok >= TOK_IDENT &&
4357 (parse_flags & PARSE_FLAG_PREPROCESS)) {
4358 s = define_find(tok);
4359 if (s) {
4360 /* we have a macro: we try to substitute */
4361 tok_str_new(&str);
4362 nested_list = NULL;
4363 ml = NULL;
4364 if (macro_subst_tok(&str, &nested_list, s, &ml) == 0) {
4365 /* substitution done, NOTE: maybe empty */
4366 tok_str_add(&str, 0);
4367 macro_ptr = str.str;
4368 macro_ptr_allocated = str.str;
4369 goto redo;
4373 } else {
4374 if (tok == 0) {
4375 /* end of macro or end of unget buffer */
4376 if (unget_buffer_enabled) {
4377 macro_ptr = unget_saved_macro_ptr;
4378 unget_buffer_enabled = 0;
4379 } else {
4380 /* end of macro string: free it */
4381 tok_str_free(macro_ptr_allocated);
4382 macro_ptr = NULL;
4384 goto redo;
4388 /* convert preprocessor tokens into C tokens */
4389 if (tok == TOK_PPNUM &&
4390 (parse_flags & PARSE_FLAG_TOK_NUM)) {
4391 parse_number((char *)tokc.cstr->data);
4395 /* push back current token and set current token to 'last_tok'. Only
4396 identifier case handled for labels. */
4397 static inline void unget_tok(int last_tok)
4399 int i, n;
4400 int *q;
4401 unget_saved_macro_ptr = macro_ptr;
4402 unget_buffer_enabled = 1;
4403 q = unget_saved_buffer;
4404 macro_ptr = q;
4405 *q++ = tok;
4406 n = tok_ext_size(tok) - 1;
4407 for(i=0;i<n;i++)
4408 *q++ = tokc.tab[i];
4409 *q = 0; /* end of token string */
4410 tok = last_tok;
4414 void swap(int *p, int *q)
4416 int t;
4417 t = *p;
4418 *p = *q;
4419 *q = t;
4422 void vsetc(CType *type, int r, CValue *vc)
4424 int v;
4426 if (vtop >= vstack + (VSTACK_SIZE - 1))
4427 error("memory full");
4428 /* cannot let cpu flags if other instruction are generated. Also
4429 avoid leaving VT_JMP anywhere except on the top of the stack
4430 because it would complicate the code generator. */
4431 if (vtop >= vstack) {
4432 v = vtop->r & VT_VALMASK;
4433 if (v == VT_CMP || (v & ~1) == VT_JMP)
4434 gv(RC_INT);
4436 vtop++;
4437 vtop->type = *type;
4438 vtop->r = r;
4439 vtop->r2 = VT_CONST;
4440 vtop->c = *vc;
4443 /* push integer constant */
4444 void vpushi(int v)
4446 CValue cval;
4447 cval.i = v;
4448 vsetc(&int_type, VT_CONST, &cval);
4451 /* Return a static symbol pointing to a section */
4452 static Sym *get_sym_ref(CType *type, Section *sec,
4453 unsigned long offset, unsigned long size)
4455 int v;
4456 Sym *sym;
4458 v = anon_sym++;
4459 sym = global_identifier_push(v, type->t | VT_STATIC, 0);
4460 sym->type.ref = type->ref;
4461 sym->r = VT_CONST | VT_SYM;
4462 put_extern_sym(sym, sec, offset, size);
4463 return sym;
4466 /* push a reference to a section offset by adding a dummy symbol */
4467 static void vpush_ref(CType *type, Section *sec, unsigned long offset, unsigned long size)
4469 CValue cval;
4471 cval.ul = 0;
4472 vsetc(type, VT_CONST | VT_SYM, &cval);
4473 vtop->sym = get_sym_ref(type, sec, offset, size);
4476 /* define a new external reference to a symbol 'v' of type 'u' */
4477 static Sym *external_global_sym(int v, CType *type, int r)
4479 Sym *s;
4481 s = sym_find(v);
4482 if (!s) {
4483 /* push forward reference */
4484 s = global_identifier_push(v, type->t | VT_EXTERN, 0);
4485 s->type.ref = type->ref;
4486 s->r = r | VT_CONST | VT_SYM;
4488 return s;
4491 /* define a new external reference to a symbol 'v' of type 'u' */
4492 static Sym *external_sym(int v, CType *type, int r)
4494 Sym *s;
4496 s = sym_find(v);
4497 if (!s) {
4498 /* push forward reference */
4499 s = sym_push(v, type, r | VT_CONST | VT_SYM, 0);
4500 s->type.t |= VT_EXTERN;
4501 } else {
4502 if (!is_compatible_types(&s->type, type))
4503 error("incompatible types for redefinition of '%s'",
4504 get_tok_str(v, NULL));
4506 return s;
4509 /* push a reference to global symbol v */
4510 static void vpush_global_sym(CType *type, int v)
4512 Sym *sym;
4513 CValue cval;
4515 sym = external_global_sym(v, type, 0);
4516 cval.ul = 0;
4517 vsetc(type, VT_CONST | VT_SYM, &cval);
4518 vtop->sym = sym;
4521 void vset(CType *type, int r, int v)
4523 CValue cval;
4525 cval.i = v;
4526 vsetc(type, r, &cval);
4529 void vseti(int r, int v)
4531 CType type;
4532 type.t = VT_INT;
4533 vset(&type, r, v);
4536 void vswap(void)
4538 SValue tmp;
4540 tmp = vtop[0];
4541 vtop[0] = vtop[-1];
4542 vtop[-1] = tmp;
4545 void vpushv(SValue *v)
4547 if (vtop >= vstack + (VSTACK_SIZE - 1))
4548 error("memory full");
4549 vtop++;
4550 *vtop = *v;
4553 void vdup(void)
4555 vpushv(vtop);
4558 /* save r to the memory stack, and mark it as being free */
4559 void save_reg(int r)
4561 int l, saved, size, align;
4562 SValue *p, sv;
4563 CType *type;
4565 /* modify all stack values */
4566 saved = 0;
4567 l = 0;
4568 for(p=vstack;p<=vtop;p++) {
4569 if ((p->r & VT_VALMASK) == r ||
4570 (p->r2 & VT_VALMASK) == r) {
4571 /* must save value on stack if not already done */
4572 if (!saved) {
4573 /* NOTE: must reload 'r' because r might be equal to r2 */
4574 r = p->r & VT_VALMASK;
4575 /* store register in the stack */
4576 type = &p->type;
4577 if ((p->r & VT_LVAL) ||
4578 (!is_float(type->t) && (type->t & VT_BTYPE) != VT_LLONG))
4579 type = &int_type;
4580 size = type_size(type, &align);
4581 loc = (loc - size) & -align;
4582 sv.type.t = type->t;
4583 sv.r = VT_LOCAL | VT_LVAL;
4584 sv.c.ul = loc;
4585 store(r, &sv);
4586 #ifdef TCC_TARGET_I386
4587 /* x86 specific: need to pop fp register ST0 if saved */
4588 if (r == TREG_ST0) {
4589 o(0xd9dd); /* fstp %st(1) */
4591 #endif
4592 /* special long long case */
4593 if ((type->t & VT_BTYPE) == VT_LLONG) {
4594 sv.c.ul += 4;
4595 store(p->r2, &sv);
4597 l = loc;
4598 saved = 1;
4600 /* mark that stack entry as being saved on the stack */
4601 if (p->r & VT_LVAL) {
4602 /* also clear the bounded flag because the
4603 relocation address of the function was stored in
4604 p->c.ul */
4605 p->r = (p->r & ~(VT_VALMASK | VT_BOUNDED)) | VT_LLOCAL;
4606 } else {
4607 p->r = lvalue_type(p->type.t) | VT_LOCAL;
4609 p->r2 = VT_CONST;
4610 p->c.ul = l;
4615 /* find a register of class 'rc2' with at most one reference on stack.
4616 * If none, call get_reg(rc) */
4617 int get_reg_ex(int rc, int rc2)
4619 int r;
4620 SValue *p;
4622 for(r=0;r<NB_REGS;r++) {
4623 if (reg_classes[r] & rc2) {
4624 int n;
4625 n=0;
4626 for(p = vstack; p <= vtop; p++) {
4627 if ((p->r & VT_VALMASK) == r ||
4628 (p->r2 & VT_VALMASK) == r)
4629 n++;
4631 if (n <= 1)
4632 return r;
4635 return get_reg(rc);
4638 /* find a free register of class 'rc'. If none, save one register */
4639 int get_reg(int rc)
4641 int r;
4642 SValue *p;
4644 /* find a free register */
4645 for(r=0;r<NB_REGS;r++) {
4646 if (reg_classes[r] & rc) {
4647 for(p=vstack;p<=vtop;p++) {
4648 if ((p->r & VT_VALMASK) == r ||
4649 (p->r2 & VT_VALMASK) == r)
4650 goto notfound;
4652 return r;
4654 notfound: ;
4657 /* no register left : free the first one on the stack (VERY
4658 IMPORTANT to start from the bottom to ensure that we don't
4659 spill registers used in gen_opi()) */
4660 for(p=vstack;p<=vtop;p++) {
4661 r = p->r & VT_VALMASK;
4662 if (r < VT_CONST && (reg_classes[r] & rc))
4663 goto save_found;
4664 /* also look at second register (if long long) */
4665 r = p->r2 & VT_VALMASK;
4666 if (r < VT_CONST && (reg_classes[r] & rc)) {
4667 save_found:
4668 save_reg(r);
4669 return r;
4672 /* Should never comes here */
4673 return -1;
4676 /* save registers up to (vtop - n) stack entry */
4677 void save_regs(int n)
4679 int r;
4680 SValue *p, *p1;
4681 p1 = vtop - n;
4682 for(p = vstack;p <= p1; p++) {
4683 r = p->r & VT_VALMASK;
4684 if (r < VT_CONST) {
4685 save_reg(r);
4690 /* move register 's' to 'r', and flush previous value of r to memory
4691 if needed */
4692 void move_reg(int r, int s)
4694 SValue sv;
4696 if (r != s) {
4697 save_reg(r);
4698 sv.type.t = VT_INT;
4699 sv.r = s;
4700 sv.c.ul = 0;
4701 load(r, &sv);
4705 /* get address of vtop (vtop MUST BE an lvalue) */
4706 void gaddrof(void)
4708 vtop->r &= ~VT_LVAL;
4709 /* tricky: if saved lvalue, then we can go back to lvalue */
4710 if ((vtop->r & VT_VALMASK) == VT_LLOCAL)
4711 vtop->r = (vtop->r & ~(VT_VALMASK | VT_LVAL_TYPE)) | VT_LOCAL | VT_LVAL;
4714 #ifdef CONFIG_TCC_BCHECK
4715 /* generate lvalue bound code */
4716 void gbound(void)
4718 int lval_type;
4719 CType type1;
4721 vtop->r &= ~VT_MUSTBOUND;
4722 /* if lvalue, then use checking code before dereferencing */
4723 if (vtop->r & VT_LVAL) {
4724 /* if not VT_BOUNDED value, then make one */
4725 if (!(vtop->r & VT_BOUNDED)) {
4726 lval_type = vtop->r & (VT_LVAL_TYPE | VT_LVAL);
4727 /* must save type because we must set it to int to get pointer */
4728 type1 = vtop->type;
4729 vtop->type.t = VT_INT;
4730 gaddrof();
4731 vpushi(0);
4732 gen_bounded_ptr_add();
4733 vtop->r |= lval_type;
4734 vtop->type = type1;
4736 /* then check for dereferencing */
4737 gen_bounded_ptr_deref();
4740 #endif
4742 /* store vtop a register belonging to class 'rc'. lvalues are
4743 converted to values. Cannot be used if cannot be converted to
4744 register value (such as structures). */
4745 int gv(int rc)
4747 int r, r2, rc2, bit_pos, bit_size, size, align, i;
4748 unsigned long long ll;
4750 /* NOTE: get_reg can modify vstack[] */
4751 if (vtop->type.t & VT_BITFIELD) {
4752 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
4753 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
4754 /* remove bit field info to avoid loops */
4755 vtop->type.t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
4756 /* generate shifts */
4757 vpushi(32 - (bit_pos + bit_size));
4758 gen_op(TOK_SHL);
4759 vpushi(32 - bit_size);
4760 /* NOTE: transformed to SHR if unsigned */
4761 gen_op(TOK_SAR);
4762 r = gv(rc);
4763 } else {
4764 if (is_float(vtop->type.t) &&
4765 (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4766 Sym *sym;
4767 int *ptr;
4768 unsigned long offset;
4770 /* XXX: unify with initializers handling ? */
4771 /* CPUs usually cannot use float constants, so we store them
4772 generically in data segment */
4773 size = type_size(&vtop->type, &align);
4774 offset = (data_section->data_offset + align - 1) & -align;
4775 data_section->data_offset = offset;
4776 /* XXX: not portable yet */
4777 ptr = section_ptr_add(data_section, size);
4778 size = size >> 2;
4779 for(i=0;i<size;i++)
4780 ptr[i] = vtop->c.tab[i];
4781 sym = get_sym_ref(&vtop->type, data_section, offset, size << 2);
4782 vtop->r |= VT_LVAL | VT_SYM;
4783 vtop->sym = sym;
4784 vtop->c.ul = 0;
4786 #ifdef CONFIG_TCC_BCHECK
4787 if (vtop->r & VT_MUSTBOUND)
4788 gbound();
4789 #endif
4791 r = vtop->r & VT_VALMASK;
4792 /* need to reload if:
4793 - constant
4794 - lvalue (need to dereference pointer)
4795 - already a register, but not in the right class */
4796 if (r >= VT_CONST ||
4797 (vtop->r & VT_LVAL) ||
4798 !(reg_classes[r] & rc) ||
4799 ((vtop->type.t & VT_BTYPE) == VT_LLONG &&
4800 !(reg_classes[vtop->r2] & rc))) {
4801 r = get_reg(rc);
4802 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
4803 /* two register type load : expand to two words
4804 temporarily */
4805 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4806 /* load constant */
4807 ll = vtop->c.ull;
4808 vtop->c.ui = ll; /* first word */
4809 load(r, vtop);
4810 vtop->r = r; /* save register value */
4811 vpushi(ll >> 32); /* second word */
4812 } else if (r >= VT_CONST || /* XXX: test to VT_CONST incorrect ? */
4813 (vtop->r & VT_LVAL)) {
4814 /* We do not want to modifier the long long
4815 pointer here, so the safest (and less
4816 efficient) is to save all the other registers
4817 in the stack. XXX: totally inefficient. */
4818 save_regs(1);
4819 /* load from memory */
4820 load(r, vtop);
4821 vdup();
4822 vtop[-1].r = r; /* save register value */
4823 /* increment pointer to get second word */
4824 vtop->type.t = VT_INT;
4825 gaddrof();
4826 vpushi(4);
4827 gen_op('+');
4828 vtop->r |= VT_LVAL;
4829 } else {
4830 /* move registers */
4831 load(r, vtop);
4832 vdup();
4833 vtop[-1].r = r; /* save register value */
4834 vtop->r = vtop[-1].r2;
4836 /* allocate second register */
4837 rc2 = RC_INT;
4838 if (rc == RC_IRET)
4839 rc2 = RC_LRET;
4840 r2 = get_reg(rc2);
4841 load(r2, vtop);
4842 vpop();
4843 /* write second register */
4844 vtop->r2 = r2;
4845 } else if ((vtop->r & VT_LVAL) && !is_float(vtop->type.t)) {
4846 int t1, t;
4847 /* lvalue of scalar type : need to use lvalue type
4848 because of possible cast */
4849 t = vtop->type.t;
4850 t1 = t;
4851 /* compute memory access type */
4852 if (vtop->r & VT_LVAL_BYTE)
4853 t = VT_BYTE;
4854 else if (vtop->r & VT_LVAL_SHORT)
4855 t = VT_SHORT;
4856 if (vtop->r & VT_LVAL_UNSIGNED)
4857 t |= VT_UNSIGNED;
4858 vtop->type.t = t;
4859 load(r, vtop);
4860 /* restore wanted type */
4861 vtop->type.t = t1;
4862 } else {
4863 /* one register type load */
4864 load(r, vtop);
4867 vtop->r = r;
4868 #ifdef TCC_TARGET_C67
4869 /* uses register pairs for doubles */
4870 if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE)
4871 vtop->r2 = r+1;
4872 #endif
4874 return r;
4877 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
4878 void gv2(int rc1, int rc2)
4880 int v;
4882 /* generate more generic register first. But VT_JMP or VT_CMP
4883 values must be generated first in all cases to avoid possible
4884 reload errors */
4885 v = vtop[0].r & VT_VALMASK;
4886 if (v != VT_CMP && (v & ~1) != VT_JMP && rc1 <= rc2) {
4887 vswap();
4888 gv(rc1);
4889 vswap();
4890 gv(rc2);
4891 /* test if reload is needed for first register */
4892 if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
4893 vswap();
4894 gv(rc1);
4895 vswap();
4897 } else {
4898 gv(rc2);
4899 vswap();
4900 gv(rc1);
4901 vswap();
4902 /* test if reload is needed for first register */
4903 if ((vtop[0].r & VT_VALMASK) >= VT_CONST) {
4904 gv(rc2);
4909 /* expand long long on stack in two int registers */
4910 void lexpand(void)
4912 int u;
4914 u = vtop->type.t & VT_UNSIGNED;
4915 gv(RC_INT);
4916 vdup();
4917 vtop[0].r = vtop[-1].r2;
4918 vtop[0].r2 = VT_CONST;
4919 vtop[-1].r2 = VT_CONST;
4920 vtop[0].type.t = VT_INT | u;
4921 vtop[-1].type.t = VT_INT | u;
4924 #ifdef TCC_TARGET_ARM
4925 /* expand long long on stack */
4926 void lexpand_nr(void)
4928 int u,v;
4930 u = vtop->type.t & VT_UNSIGNED;
4931 vdup();
4932 vtop->r2 = VT_CONST;
4933 vtop->type.t = VT_INT | u;
4934 v=vtop[-1].r & (VT_VALMASK | VT_LVAL);
4935 if (v == VT_CONST) {
4936 vtop[-1].c.ui = vtop->c.ull;
4937 vtop->c.ui = vtop->c.ull >> 32;
4938 vtop->r = VT_CONST;
4939 } else if (v == (VT_LVAL|VT_CONST) || v == (VT_LVAL|VT_LOCAL)) {
4940 vtop->c.ui += 4;
4941 vtop->r = vtop[-1].r;
4942 } else if (v > VT_CONST) {
4943 vtop--;
4944 lexpand();
4945 } else
4946 vtop->r = vtop[-1].r2;
4947 vtop[-1].r2 = VT_CONST;
4948 vtop[-1].type.t = VT_INT | u;
4950 #endif
4952 /* build a long long from two ints */
4953 void lbuild(int t)
4955 gv2(RC_INT, RC_INT);
4956 vtop[-1].r2 = vtop[0].r;
4957 vtop[-1].type.t = t;
4958 vpop();
4961 /* rotate n first stack elements to the bottom
4962 I1 ... In -> I2 ... In I1 [top is right]
4964 void vrotb(int n)
4966 int i;
4967 SValue tmp;
4969 tmp = vtop[-n + 1];
4970 for(i=-n+1;i!=0;i++)
4971 vtop[i] = vtop[i+1];
4972 vtop[0] = tmp;
4975 /* rotate n first stack elements to the top
4976 I1 ... In -> In I1 ... I(n-1) [top is right]
4978 void vrott(int n)
4980 int i;
4981 SValue tmp;
4983 tmp = vtop[0];
4984 for(i = 0;i < n - 1; i++)
4985 vtop[-i] = vtop[-i - 1];
4986 vtop[-n + 1] = tmp;
4989 #ifdef TCC_TARGET_ARM
4990 /* like vrott but in other direction
4991 In ... I1 -> I(n-1) ... I1 In [top is right]
4993 void vnrott(int n)
4995 int i;
4996 SValue tmp;
4998 tmp = vtop[-n + 1];
4999 for(i = n - 1; i > 0; i--)
5000 vtop[-i] = vtop[-i + 1];
5001 vtop[0] = tmp;
5003 #endif
5005 /* pop stack value */
5006 void vpop(void)
5008 int v;
5009 v = vtop->r & VT_VALMASK;
5010 #ifdef TCC_TARGET_I386
5011 /* for x86, we need to pop the FP stack */
5012 if (v == TREG_ST0 && !nocode_wanted) {
5013 o(0xd9dd); /* fstp %st(1) */
5014 } else
5015 #endif
5016 if (v == VT_JMP || v == VT_JMPI) {
5017 /* need to put correct jump if && or || without test */
5018 gsym(vtop->c.ul);
5020 vtop--;
5023 /* convert stack entry to register and duplicate its value in another
5024 register */
5025 void gv_dup(void)
5027 int rc, t, r, r1;
5028 SValue sv;
5030 t = vtop->type.t;
5031 if ((t & VT_BTYPE) == VT_LLONG) {
5032 lexpand();
5033 gv_dup();
5034 vswap();
5035 vrotb(3);
5036 gv_dup();
5037 vrotb(4);
5038 /* stack: H L L1 H1 */
5039 lbuild(t);
5040 vrotb(3);
5041 vrotb(3);
5042 vswap();
5043 lbuild(t);
5044 vswap();
5045 } else {
5046 /* duplicate value */
5047 rc = RC_INT;
5048 sv.type.t = VT_INT;
5049 if (is_float(t)) {
5050 rc = RC_FLOAT;
5051 sv.type.t = t;
5053 r = gv(rc);
5054 r1 = get_reg(rc);
5055 sv.r = r;
5056 sv.c.ul = 0;
5057 load(r1, &sv); /* move r to r1 */
5058 vdup();
5059 /* duplicates value */
5060 vtop->r = r1;
5064 /* generate CPU independent (unsigned) long long operations */
5065 void gen_opl(int op)
5067 int t, a, b, op1, c, i;
5068 int func;
5069 SValue tmp;
5071 switch(op) {
5072 case '/':
5073 case TOK_PDIV:
5074 func = TOK___divdi3;
5075 goto gen_func;
5076 case TOK_UDIV:
5077 func = TOK___udivdi3;
5078 goto gen_func;
5079 case '%':
5080 func = TOK___moddi3;
5081 goto gen_func;
5082 case TOK_UMOD:
5083 func = TOK___umoddi3;
5084 gen_func:
5085 /* call generic long long function */
5086 vpush_global_sym(&func_old_type, func);
5087 vrott(3);
5088 gfunc_call(2);
5089 vpushi(0);
5090 vtop->r = REG_IRET;
5091 vtop->r2 = REG_LRET;
5092 break;
5093 case '^':
5094 case '&':
5095 case '|':
5096 case '*':
5097 case '+':
5098 case '-':
5099 t = vtop->type.t;
5100 vswap();
5101 lexpand();
5102 vrotb(3);
5103 lexpand();
5104 /* stack: L1 H1 L2 H2 */
5105 tmp = vtop[0];
5106 vtop[0] = vtop[-3];
5107 vtop[-3] = tmp;
5108 tmp = vtop[-2];
5109 vtop[-2] = vtop[-3];
5110 vtop[-3] = tmp;
5111 vswap();
5112 /* stack: H1 H2 L1 L2 */
5113 if (op == '*') {
5114 vpushv(vtop - 1);
5115 vpushv(vtop - 1);
5116 gen_op(TOK_UMULL);
5117 lexpand();
5118 /* stack: H1 H2 L1 L2 ML MH */
5119 for(i=0;i<4;i++)
5120 vrotb(6);
5121 /* stack: ML MH H1 H2 L1 L2 */
5122 tmp = vtop[0];
5123 vtop[0] = vtop[-2];
5124 vtop[-2] = tmp;
5125 /* stack: ML MH H1 L2 H2 L1 */
5126 gen_op('*');
5127 vrotb(3);
5128 vrotb(3);
5129 gen_op('*');
5130 /* stack: ML MH M1 M2 */
5131 gen_op('+');
5132 gen_op('+');
5133 } else if (op == '+' || op == '-') {
5134 /* XXX: add non carry method too (for MIPS or alpha) */
5135 if (op == '+')
5136 op1 = TOK_ADDC1;
5137 else
5138 op1 = TOK_SUBC1;
5139 gen_op(op1);
5140 /* stack: H1 H2 (L1 op L2) */
5141 vrotb(3);
5142 vrotb(3);
5143 gen_op(op1 + 1); /* TOK_xxxC2 */
5144 } else {
5145 gen_op(op);
5146 /* stack: H1 H2 (L1 op L2) */
5147 vrotb(3);
5148 vrotb(3);
5149 /* stack: (L1 op L2) H1 H2 */
5150 gen_op(op);
5151 /* stack: (L1 op L2) (H1 op H2) */
5153 /* stack: L H */
5154 lbuild(t);
5155 break;
5156 case TOK_SAR:
5157 case TOK_SHR:
5158 case TOK_SHL:
5159 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
5160 t = vtop[-1].type.t;
5161 vswap();
5162 lexpand();
5163 vrotb(3);
5164 /* stack: L H shift */
5165 c = (int)vtop->c.i;
5166 /* constant: simpler */
5167 /* NOTE: all comments are for SHL. the other cases are
5168 done by swaping words */
5169 vpop();
5170 if (op != TOK_SHL)
5171 vswap();
5172 if (c >= 32) {
5173 /* stack: L H */
5174 vpop();
5175 if (c > 32) {
5176 vpushi(c - 32);
5177 gen_op(op);
5179 if (op != TOK_SAR) {
5180 vpushi(0);
5181 } else {
5182 gv_dup();
5183 vpushi(31);
5184 gen_op(TOK_SAR);
5186 vswap();
5187 } else {
5188 vswap();
5189 gv_dup();
5190 /* stack: H L L */
5191 vpushi(c);
5192 gen_op(op);
5193 vswap();
5194 vpushi(32 - c);
5195 if (op == TOK_SHL)
5196 gen_op(TOK_SHR);
5197 else
5198 gen_op(TOK_SHL);
5199 vrotb(3);
5200 /* stack: L L H */
5201 vpushi(c);
5202 if (op == TOK_SHL)
5203 gen_op(TOK_SHL);
5204 else
5205 gen_op(TOK_SHR);
5206 gen_op('|');
5208 if (op != TOK_SHL)
5209 vswap();
5210 lbuild(t);
5211 } else {
5212 /* XXX: should provide a faster fallback on x86 ? */
5213 switch(op) {
5214 case TOK_SAR:
5215 func = TOK___sardi3;
5216 goto gen_func;
5217 case TOK_SHR:
5218 func = TOK___shrdi3;
5219 goto gen_func;
5220 case TOK_SHL:
5221 func = TOK___shldi3;
5222 goto gen_func;
5225 break;
5226 default:
5227 /* compare operations */
5228 t = vtop->type.t;
5229 vswap();
5230 lexpand();
5231 vrotb(3);
5232 lexpand();
5233 /* stack: L1 H1 L2 H2 */
5234 tmp = vtop[-1];
5235 vtop[-1] = vtop[-2];
5236 vtop[-2] = tmp;
5237 /* stack: L1 L2 H1 H2 */
5238 /* compare high */
5239 op1 = op;
5240 /* when values are equal, we need to compare low words. since
5241 the jump is inverted, we invert the test too. */
5242 if (op1 == TOK_LT)
5243 op1 = TOK_LE;
5244 else if (op1 == TOK_GT)
5245 op1 = TOK_GE;
5246 else if (op1 == TOK_ULT)
5247 op1 = TOK_ULE;
5248 else if (op1 == TOK_UGT)
5249 op1 = TOK_UGE;
5250 a = 0;
5251 b = 0;
5252 gen_op(op1);
5253 if (op1 != TOK_NE) {
5254 a = gtst(1, 0);
5256 if (op != TOK_EQ) {
5257 /* generate non equal test */
5258 /* XXX: NOT PORTABLE yet */
5259 if (a == 0) {
5260 b = gtst(0, 0);
5261 } else {
5262 #if defined(TCC_TARGET_I386)
5263 b = psym(0x850f, 0);
5264 #elif defined(TCC_TARGET_ARM)
5265 b = ind;
5266 o(0x1A000000 | encbranch(ind, 0, 1));
5267 #elif defined(TCC_TARGET_C67)
5268 error("not implemented");
5269 #else
5270 #error not supported
5271 #endif
5274 /* compare low. Always unsigned */
5275 op1 = op;
5276 if (op1 == TOK_LT)
5277 op1 = TOK_ULT;
5278 else if (op1 == TOK_LE)
5279 op1 = TOK_ULE;
5280 else if (op1 == TOK_GT)
5281 op1 = TOK_UGT;
5282 else if (op1 == TOK_GE)
5283 op1 = TOK_UGE;
5284 gen_op(op1);
5285 a = gtst(1, a);
5286 gsym(b);
5287 vseti(VT_JMPI, a);
5288 break;
5292 /* handle integer constant optimizations and various machine
5293 independent opt */
5294 void gen_opic(int op)
5296 int fc, c1, c2, n;
5297 SValue *v1, *v2;
5299 v1 = vtop - 1;
5300 v2 = vtop;
5301 /* currently, we cannot do computations with forward symbols */
5302 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5303 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5304 if (c1 && c2) {
5305 fc = v2->c.i;
5306 switch(op) {
5307 case '+': v1->c.i += fc; break;
5308 case '-': v1->c.i -= fc; break;
5309 case '&': v1->c.i &= fc; break;
5310 case '^': v1->c.i ^= fc; break;
5311 case '|': v1->c.i |= fc; break;
5312 case '*': v1->c.i *= fc; break;
5314 case TOK_PDIV:
5315 case '/':
5316 case '%':
5317 case TOK_UDIV:
5318 case TOK_UMOD:
5319 /* if division by zero, generate explicit division */
5320 if (fc == 0) {
5321 if (const_wanted)
5322 error("division by zero in constant");
5323 goto general_case;
5325 switch(op) {
5326 default: v1->c.i /= fc; break;
5327 case '%': v1->c.i %= fc; break;
5328 case TOK_UDIV: v1->c.i = (unsigned)v1->c.i / fc; break;
5329 case TOK_UMOD: v1->c.i = (unsigned)v1->c.i % fc; break;
5331 break;
5332 case TOK_SHL: v1->c.i <<= fc; break;
5333 case TOK_SHR: v1->c.i = (unsigned)v1->c.i >> fc; break;
5334 case TOK_SAR: v1->c.i >>= fc; break;
5335 /* tests */
5336 case TOK_ULT: v1->c.i = (unsigned)v1->c.i < (unsigned)fc; break;
5337 case TOK_UGE: v1->c.i = (unsigned)v1->c.i >= (unsigned)fc; break;
5338 case TOK_EQ: v1->c.i = v1->c.i == fc; break;
5339 case TOK_NE: v1->c.i = v1->c.i != fc; break;
5340 case TOK_ULE: v1->c.i = (unsigned)v1->c.i <= (unsigned)fc; break;
5341 case TOK_UGT: v1->c.i = (unsigned)v1->c.i > (unsigned)fc; break;
5342 case TOK_LT: v1->c.i = v1->c.i < fc; break;
5343 case TOK_GE: v1->c.i = v1->c.i >= fc; break;
5344 case TOK_LE: v1->c.i = v1->c.i <= fc; break;
5345 case TOK_GT: v1->c.i = v1->c.i > fc; break;
5346 /* logical */
5347 case TOK_LAND: v1->c.i = v1->c.i && fc; break;
5348 case TOK_LOR: v1->c.i = v1->c.i || fc; break;
5349 default:
5350 goto general_case;
5352 vtop--;
5353 } else {
5354 /* if commutative ops, put c2 as constant */
5355 if (c1 && (op == '+' || op == '&' || op == '^' ||
5356 op == '|' || op == '*')) {
5357 vswap();
5358 swap(&c1, &c2);
5360 fc = vtop->c.i;
5361 if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
5362 op == TOK_PDIV) &&
5363 fc == 1) ||
5364 ((op == '+' || op == '-' || op == '|' || op == '^' ||
5365 op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
5366 fc == 0) ||
5367 (op == '&' &&
5368 fc == -1))) {
5369 /* nothing to do */
5370 vtop--;
5371 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
5372 /* try to use shifts instead of muls or divs */
5373 if (fc > 0 && (fc & (fc - 1)) == 0) {
5374 n = -1;
5375 while (fc) {
5376 fc >>= 1;
5377 n++;
5379 vtop->c.i = n;
5380 if (op == '*')
5381 op = TOK_SHL;
5382 else if (op == TOK_PDIV)
5383 op = TOK_SAR;
5384 else
5385 op = TOK_SHR;
5387 goto general_case;
5388 } else if (c2 && (op == '+' || op == '-') &&
5389 (vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) ==
5390 (VT_CONST | VT_SYM)) {
5391 /* symbol + constant case */
5392 if (op == '-')
5393 fc = -fc;
5394 vtop--;
5395 vtop->c.i += fc;
5396 } else {
5397 general_case:
5398 if (!nocode_wanted) {
5399 /* call low level op generator */
5400 gen_opi(op);
5401 } else {
5402 vtop--;
5408 /* generate a floating point operation with constant propagation */
5409 void gen_opif(int op)
5411 int c1, c2;
5412 SValue *v1, *v2;
5413 long double f1, f2;
5415 v1 = vtop - 1;
5416 v2 = vtop;
5417 /* currently, we cannot do computations with forward symbols */
5418 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5419 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5420 if (c1 && c2) {
5421 if (v1->type.t == VT_FLOAT) {
5422 f1 = v1->c.f;
5423 f2 = v2->c.f;
5424 } else if (v1->type.t == VT_DOUBLE) {
5425 f1 = v1->c.d;
5426 f2 = v2->c.d;
5427 } else {
5428 f1 = v1->c.ld;
5429 f2 = v2->c.ld;
5432 /* NOTE: we only do constant propagation if finite number (not
5433 NaN or infinity) (ANSI spec) */
5434 if (!ieee_finite(f1) || !ieee_finite(f2))
5435 goto general_case;
5437 switch(op) {
5438 case '+': f1 += f2; break;
5439 case '-': f1 -= f2; break;
5440 case '*': f1 *= f2; break;
5441 case '/':
5442 if (f2 == 0.0) {
5443 if (const_wanted)
5444 error("division by zero in constant");
5445 goto general_case;
5447 f1 /= f2;
5448 break;
5449 /* XXX: also handles tests ? */
5450 default:
5451 goto general_case;
5453 /* XXX: overflow test ? */
5454 if (v1->type.t == VT_FLOAT) {
5455 v1->c.f = f1;
5456 } else if (v1->type.t == VT_DOUBLE) {
5457 v1->c.d = f1;
5458 } else {
5459 v1->c.ld = f1;
5461 vtop--;
5462 } else {
5463 general_case:
5464 if (!nocode_wanted) {
5465 gen_opf(op);
5466 } else {
5467 vtop--;
5472 static int pointed_size(CType *type)
5474 int align;
5475 return type_size(pointed_type(type), &align);
5478 static inline int is_null_pointer(SValue *p)
5480 if ((p->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
5481 return 0;
5482 return ((p->type.t & VT_BTYPE) == VT_INT && p->c.i == 0) ||
5483 ((p->type.t & VT_BTYPE) == VT_LLONG && p->c.ll == 0);
5486 static inline int is_integer_btype(int bt)
5488 return (bt == VT_BYTE || bt == VT_SHORT ||
5489 bt == VT_INT || bt == VT_LLONG);
5492 /* check types for comparison or substraction of pointers */
5493 static void check_comparison_pointer_types(SValue *p1, SValue *p2, int op)
5495 CType *type1, *type2, tmp_type1, tmp_type2;
5496 int bt1, bt2;
5498 /* null pointers are accepted for all comparisons as gcc */
5499 if (is_null_pointer(p1) || is_null_pointer(p2))
5500 return;
5501 type1 = &p1->type;
5502 type2 = &p2->type;
5503 bt1 = type1->t & VT_BTYPE;
5504 bt2 = type2->t & VT_BTYPE;
5505 /* accept comparison between pointer and integer with a warning */
5506 if ((is_integer_btype(bt1) || is_integer_btype(bt2)) && op != '-') {
5507 warning("comparison between pointer and integer");
5508 return;
5511 /* both must be pointers or implicit function pointers */
5512 if (bt1 == VT_PTR) {
5513 type1 = pointed_type(type1);
5514 } else if (bt1 != VT_FUNC)
5515 goto invalid_operands;
5517 if (bt2 == VT_PTR) {
5518 type2 = pointed_type(type2);
5519 } else if (bt2 != VT_FUNC) {
5520 invalid_operands:
5521 error("invalid operands to binary %s", get_tok_str(op, NULL));
5523 if ((type1->t & VT_BTYPE) == VT_VOID ||
5524 (type2->t & VT_BTYPE) == VT_VOID)
5525 return;
5526 tmp_type1 = *type1;
5527 tmp_type2 = *type2;
5528 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5529 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5530 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
5531 /* gcc-like error if '-' is used */
5532 if (op == '-')
5533 goto invalid_operands;
5534 else
5535 warning("comparison of distinct pointer types lacks a cast");
5539 /* generic gen_op: handles types problems */
5540 void gen_op(int op)
5542 int u, t1, t2, bt1, bt2, t;
5543 CType type1;
5545 t1 = vtop[-1].type.t;
5546 t2 = vtop[0].type.t;
5547 bt1 = t1 & VT_BTYPE;
5548 bt2 = t2 & VT_BTYPE;
5550 if (bt1 == VT_PTR || bt2 == VT_PTR) {
5551 /* at least one operand is a pointer */
5552 /* relationnal op: must be both pointers */
5553 if (op >= TOK_ULT && op <= TOK_GT) {
5554 check_comparison_pointer_types(vtop - 1, vtop, op);
5555 /* pointers are handled are unsigned */
5556 t = VT_INT | VT_UNSIGNED;
5557 goto std_op;
5559 /* if both pointers, then it must be the '-' op */
5560 if (bt1 == VT_PTR && bt2 == VT_PTR) {
5561 if (op != '-')
5562 error("cannot use pointers here");
5563 check_comparison_pointer_types(vtop - 1, vtop, op);
5564 /* XXX: check that types are compatible */
5565 u = pointed_size(&vtop[-1].type);
5566 gen_opic(op);
5567 /* set to integer type */
5568 vtop->type.t = VT_INT;
5569 vpushi(u);
5570 gen_op(TOK_PDIV);
5571 } else {
5572 /* exactly one pointer : must be '+' or '-'. */
5573 if (op != '-' && op != '+')
5574 error("cannot use pointers here");
5575 /* Put pointer as first operand */
5576 if (bt2 == VT_PTR) {
5577 vswap();
5578 swap(&t1, &t2);
5580 type1 = vtop[-1].type;
5581 /* XXX: cast to int ? (long long case) */
5582 vpushi(pointed_size(&vtop[-1].type));
5583 gen_op('*');
5584 #ifdef CONFIG_TCC_BCHECK
5585 /* if evaluating constant expression, no code should be
5586 generated, so no bound check */
5587 if (do_bounds_check && !const_wanted) {
5588 /* if bounded pointers, we generate a special code to
5589 test bounds */
5590 if (op == '-') {
5591 vpushi(0);
5592 vswap();
5593 gen_op('-');
5595 gen_bounded_ptr_add();
5596 } else
5597 #endif
5599 gen_opic(op);
5601 /* put again type if gen_opic() swaped operands */
5602 vtop->type = type1;
5604 } else if (is_float(bt1) || is_float(bt2)) {
5605 /* compute bigger type and do implicit casts */
5606 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
5607 t = VT_LDOUBLE;
5608 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
5609 t = VT_DOUBLE;
5610 } else {
5611 t = VT_FLOAT;
5613 /* floats can only be used for a few operations */
5614 if (op != '+' && op != '-' && op != '*' && op != '/' &&
5615 (op < TOK_ULT || op > TOK_GT))
5616 error("invalid operands for binary operation");
5617 goto std_op;
5618 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
5619 /* cast to biggest op */
5620 t = VT_LLONG;
5621 /* convert to unsigned if it does not fit in a long long */
5622 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
5623 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
5624 t |= VT_UNSIGNED;
5625 goto std_op;
5626 } else {
5627 /* integer operations */
5628 t = VT_INT;
5629 /* convert to unsigned if it does not fit in an integer */
5630 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
5631 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
5632 t |= VT_UNSIGNED;
5633 std_op:
5634 /* XXX: currently, some unsigned operations are explicit, so
5635 we modify them here */
5636 if (t & VT_UNSIGNED) {
5637 if (op == TOK_SAR)
5638 op = TOK_SHR;
5639 else if (op == '/')
5640 op = TOK_UDIV;
5641 else if (op == '%')
5642 op = TOK_UMOD;
5643 else if (op == TOK_LT)
5644 op = TOK_ULT;
5645 else if (op == TOK_GT)
5646 op = TOK_UGT;
5647 else if (op == TOK_LE)
5648 op = TOK_ULE;
5649 else if (op == TOK_GE)
5650 op = TOK_UGE;
5652 vswap();
5653 type1.t = t;
5654 gen_cast(&type1);
5655 vswap();
5656 /* special case for shifts and long long: we keep the shift as
5657 an integer */
5658 if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL)
5659 type1.t = VT_INT;
5660 gen_cast(&type1);
5661 if (is_float(t))
5662 gen_opif(op);
5663 else if ((t & VT_BTYPE) == VT_LLONG)
5664 gen_opl(op);
5665 else
5666 gen_opic(op);
5667 if (op >= TOK_ULT && op <= TOK_GT) {
5668 /* relationnal op: the result is an int */
5669 vtop->type.t = VT_INT;
5670 } else {
5671 vtop->type.t = t;
5676 /* generic itof for unsigned long long case */
5677 void gen_cvt_itof1(int t)
5679 if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
5680 (VT_LLONG | VT_UNSIGNED)) {
5682 if (t == VT_FLOAT)
5683 vpush_global_sym(&func_old_type, TOK___ulltof);
5684 else if (t == VT_DOUBLE)
5685 vpush_global_sym(&func_old_type, TOK___ulltod);
5686 else
5687 vpush_global_sym(&func_old_type, TOK___ulltold);
5688 vrott(2);
5689 gfunc_call(1);
5690 vpushi(0);
5691 vtop->r = REG_FRET;
5692 } else {
5693 gen_cvt_itof(t);
5697 /* generic ftoi for unsigned long long case */
5698 void gen_cvt_ftoi1(int t)
5700 int st;
5702 if (t == (VT_LLONG | VT_UNSIGNED)) {
5703 /* not handled natively */
5704 st = vtop->type.t & VT_BTYPE;
5705 if (st == VT_FLOAT)
5706 vpush_global_sym(&func_old_type, TOK___fixunssfdi);
5707 else if (st == VT_DOUBLE)
5708 vpush_global_sym(&func_old_type, TOK___fixunsdfdi);
5709 else
5710 vpush_global_sym(&func_old_type, TOK___fixunsxfdi);
5711 vrott(2);
5712 gfunc_call(1);
5713 vpushi(0);
5714 vtop->r = REG_IRET;
5715 vtop->r2 = REG_LRET;
5716 } else {
5717 gen_cvt_ftoi(t);
5721 /* force char or short cast */
5722 void force_charshort_cast(int t)
5724 int bits, dbt;
5725 dbt = t & VT_BTYPE;
5726 /* XXX: add optimization if lvalue : just change type and offset */
5727 if (dbt == VT_BYTE)
5728 bits = 8;
5729 else
5730 bits = 16;
5731 if (t & VT_UNSIGNED) {
5732 vpushi((1 << bits) - 1);
5733 gen_op('&');
5734 } else {
5735 bits = 32 - bits;
5736 vpushi(bits);
5737 gen_op(TOK_SHL);
5738 vpushi(bits);
5739 gen_op(TOK_SAR);
5743 /* cast 'vtop' to 'type'. Casting to bitfields is forbidden. */
5744 static void gen_cast(CType *type)
5746 int sbt, dbt, sf, df, c;
5748 /* special delayed cast for char/short */
5749 /* XXX: in some cases (multiple cascaded casts), it may still
5750 be incorrect */
5751 if (vtop->r & VT_MUSTCAST) {
5752 vtop->r &= ~VT_MUSTCAST;
5753 force_charshort_cast(vtop->type.t);
5756 /* bitfields first get cast to ints */
5757 if (vtop->type.t & VT_BITFIELD) {
5758 gv(RC_INT);
5761 dbt = type->t & (VT_BTYPE | VT_UNSIGNED);
5762 sbt = vtop->type.t & (VT_BTYPE | VT_UNSIGNED);
5764 if (sbt != dbt && !nocode_wanted) {
5765 sf = is_float(sbt);
5766 df = is_float(dbt);
5767 c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5768 if (sf && df) {
5769 /* convert from fp to fp */
5770 if (c) {
5771 /* constant case: we can do it now */
5772 /* XXX: in ISOC, cannot do it if error in convert */
5773 if (dbt == VT_FLOAT && sbt == VT_DOUBLE)
5774 vtop->c.f = (float)vtop->c.d;
5775 else if (dbt == VT_FLOAT && sbt == VT_LDOUBLE)
5776 vtop->c.f = (float)vtop->c.ld;
5777 else if (dbt == VT_DOUBLE && sbt == VT_FLOAT)
5778 vtop->c.d = (double)vtop->c.f;
5779 else if (dbt == VT_DOUBLE && sbt == VT_LDOUBLE)
5780 vtop->c.d = (double)vtop->c.ld;
5781 else if (dbt == VT_LDOUBLE && sbt == VT_FLOAT)
5782 vtop->c.ld = (long double)vtop->c.f;
5783 else if (dbt == VT_LDOUBLE && sbt == VT_DOUBLE)
5784 vtop->c.ld = (long double)vtop->c.d;
5785 } else {
5786 /* non constant case: generate code */
5787 gen_cvt_ftof(dbt);
5789 } else if (df) {
5790 /* convert int to fp */
5791 if (c) {
5792 switch(sbt) {
5793 case VT_LLONG | VT_UNSIGNED:
5794 case VT_LLONG:
5795 /* XXX: add const cases for long long */
5796 goto do_itof;
5797 case VT_INT | VT_UNSIGNED:
5798 switch(dbt) {
5799 case VT_FLOAT: vtop->c.f = (float)vtop->c.ui; break;
5800 case VT_DOUBLE: vtop->c.d = (double)vtop->c.ui; break;
5801 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.ui; break;
5803 break;
5804 default:
5805 switch(dbt) {
5806 case VT_FLOAT: vtop->c.f = (float)vtop->c.i; break;
5807 case VT_DOUBLE: vtop->c.d = (double)vtop->c.i; break;
5808 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.i; break;
5810 break;
5812 } else {
5813 do_itof:
5814 #if !defined(TCC_TARGET_ARM)
5815 gen_cvt_itof1(dbt);
5816 #else
5817 gen_cvt_itof(dbt);
5818 #endif
5820 } else if (sf) {
5821 /* convert fp to int */
5822 /* we handle char/short/etc... with generic code */
5823 if (dbt != (VT_INT | VT_UNSIGNED) &&
5824 dbt != (VT_LLONG | VT_UNSIGNED) &&
5825 dbt != VT_LLONG)
5826 dbt = VT_INT;
5827 if (c) {
5828 switch(dbt) {
5829 case VT_LLONG | VT_UNSIGNED:
5830 case VT_LLONG:
5831 /* XXX: add const cases for long long */
5832 goto do_ftoi;
5833 case VT_INT | VT_UNSIGNED:
5834 switch(sbt) {
5835 case VT_FLOAT: vtop->c.ui = (unsigned int)vtop->c.d; break;
5836 case VT_DOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
5837 case VT_LDOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
5839 break;
5840 default:
5841 /* int case */
5842 switch(sbt) {
5843 case VT_FLOAT: vtop->c.i = (int)vtop->c.d; break;
5844 case VT_DOUBLE: vtop->c.i = (int)vtop->c.d; break;
5845 case VT_LDOUBLE: vtop->c.i = (int)vtop->c.d; break;
5847 break;
5849 } else {
5850 do_ftoi:
5851 gen_cvt_ftoi1(dbt);
5853 if (dbt == VT_INT && (type->t & (VT_BTYPE | VT_UNSIGNED)) != dbt) {
5854 /* additional cast for char/short/bool... */
5855 vtop->type.t = dbt;
5856 gen_cast(type);
5858 } else if ((dbt & VT_BTYPE) == VT_LLONG) {
5859 if ((sbt & VT_BTYPE) != VT_LLONG) {
5860 /* scalar to long long */
5861 if (c) {
5862 if (sbt == (VT_INT | VT_UNSIGNED))
5863 vtop->c.ll = vtop->c.ui;
5864 else
5865 vtop->c.ll = vtop->c.i;
5866 } else {
5867 /* machine independent conversion */
5868 gv(RC_INT);
5869 /* generate high word */
5870 if (sbt == (VT_INT | VT_UNSIGNED)) {
5871 vpushi(0);
5872 gv(RC_INT);
5873 } else {
5874 gv_dup();
5875 vpushi(31);
5876 gen_op(TOK_SAR);
5878 /* patch second register */
5879 vtop[-1].r2 = vtop->r;
5880 vpop();
5883 } else if (dbt == VT_BOOL) {
5884 /* scalar to bool */
5885 vpushi(0);
5886 gen_op(TOK_NE);
5887 } else if ((dbt & VT_BTYPE) == VT_BYTE ||
5888 (dbt & VT_BTYPE) == VT_SHORT) {
5889 force_charshort_cast(dbt);
5890 } else if ((dbt & VT_BTYPE) == VT_INT) {
5891 /* scalar to int */
5892 if (sbt == VT_LLONG) {
5893 /* from long long: just take low order word */
5894 lexpand();
5895 vpop();
5897 /* if lvalue and single word type, nothing to do because
5898 the lvalue already contains the real type size (see
5899 VT_LVAL_xxx constants) */
5902 vtop->type = *type;
5905 /* return type size. Put alignment at 'a' */
5906 static int type_size(CType *type, int *a)
5908 Sym *s;
5909 int bt;
5911 bt = type->t & VT_BTYPE;
5912 if (bt == VT_STRUCT) {
5913 /* struct/union */
5914 s = type->ref;
5915 *a = s->r;
5916 return s->c;
5917 } else if (bt == VT_PTR) {
5918 if (type->t & VT_ARRAY) {
5919 s = type->ref;
5920 return type_size(&s->type, a) * s->c;
5921 } else {
5922 *a = PTR_SIZE;
5923 return PTR_SIZE;
5925 } else if (bt == VT_LDOUBLE) {
5926 *a = LDOUBLE_ALIGN;
5927 return LDOUBLE_SIZE;
5928 } else if (bt == VT_DOUBLE || bt == VT_LLONG) {
5929 #ifdef TCC_TARGET_I386
5930 *a = 4;
5931 #else
5932 *a = 8;
5933 #endif
5934 return 8;
5935 } else if (bt == VT_INT || bt == VT_ENUM || bt == VT_FLOAT) {
5936 *a = 4;
5937 return 4;
5938 } else if (bt == VT_SHORT) {
5939 *a = 2;
5940 return 2;
5941 } else {
5942 /* char, void, function, _Bool */
5943 *a = 1;
5944 return 1;
5948 /* return the pointed type of t */
5949 static inline CType *pointed_type(CType *type)
5951 return &type->ref->type;
5954 /* modify type so that its it is a pointer to type. */
5955 static void mk_pointer(CType *type)
5957 Sym *s;
5958 s = sym_push(SYM_FIELD, type, 0, -1);
5959 type->t = VT_PTR | (type->t & ~VT_TYPE);
5960 type->ref = s;
5963 /* compare function types. OLD functions match any new functions */
5964 static int is_compatible_func(CType *type1, CType *type2)
5966 Sym *s1, *s2;
5968 s1 = type1->ref;
5969 s2 = type2->ref;
5970 if (!is_compatible_types(&s1->type, &s2->type))
5971 return 0;
5972 /* check func_call */
5973 if (s1->r != s2->r)
5974 return 0;
5975 /* XXX: not complete */
5976 if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
5977 return 1;
5978 if (s1->c != s2->c)
5979 return 0;
5980 while (s1 != NULL) {
5981 if (s2 == NULL)
5982 return 0;
5983 if (!is_compatible_types(&s1->type, &s2->type))
5984 return 0;
5985 s1 = s1->next;
5986 s2 = s2->next;
5988 if (s2)
5989 return 0;
5990 return 1;
5993 /* return true if type1 and type2 are exactly the same (including
5994 qualifiers).
5996 - enums are not checked as gcc __builtin_types_compatible_p ()
5998 static int is_compatible_types(CType *type1, CType *type2)
6000 int bt1, t1, t2;
6002 t1 = type1->t & VT_TYPE;
6003 t2 = type2->t & VT_TYPE;
6004 /* XXX: bitfields ? */
6005 if (t1 != t2)
6006 return 0;
6007 /* test more complicated cases */
6008 bt1 = t1 & VT_BTYPE;
6009 if (bt1 == VT_PTR) {
6010 type1 = pointed_type(type1);
6011 type2 = pointed_type(type2);
6012 return is_compatible_types(type1, type2);
6013 } else if (bt1 == VT_STRUCT) {
6014 return (type1->ref == type2->ref);
6015 } else if (bt1 == VT_FUNC) {
6016 return is_compatible_func(type1, type2);
6017 } else {
6018 return 1;
6022 /* print a type. If 'varstr' is not NULL, then the variable is also
6023 printed in the type */
6024 /* XXX: union */
6025 /* XXX: add array and function pointers */
6026 void type_to_str(char *buf, int buf_size,
6027 CType *type, const char *varstr)
6029 int bt, v, t;
6030 Sym *s, *sa;
6031 char buf1[256];
6032 const char *tstr;
6034 t = type->t & VT_TYPE;
6035 bt = t & VT_BTYPE;
6036 buf[0] = '\0';
6037 if (t & VT_CONSTANT)
6038 pstrcat(buf, buf_size, "const ");
6039 if (t & VT_VOLATILE)
6040 pstrcat(buf, buf_size, "volatile ");
6041 if (t & VT_UNSIGNED)
6042 pstrcat(buf, buf_size, "unsigned ");
6043 switch(bt) {
6044 case VT_VOID:
6045 tstr = "void";
6046 goto add_tstr;
6047 case VT_BOOL:
6048 tstr = "_Bool";
6049 goto add_tstr;
6050 case VT_BYTE:
6051 tstr = "char";
6052 goto add_tstr;
6053 case VT_SHORT:
6054 tstr = "short";
6055 goto add_tstr;
6056 case VT_INT:
6057 tstr = "int";
6058 goto add_tstr;
6059 case VT_LONG:
6060 tstr = "long";
6061 goto add_tstr;
6062 case VT_LLONG:
6063 tstr = "long long";
6064 goto add_tstr;
6065 case VT_FLOAT:
6066 tstr = "float";
6067 goto add_tstr;
6068 case VT_DOUBLE:
6069 tstr = "double";
6070 goto add_tstr;
6071 case VT_LDOUBLE:
6072 tstr = "long double";
6073 add_tstr:
6074 pstrcat(buf, buf_size, tstr);
6075 break;
6076 case VT_ENUM:
6077 case VT_STRUCT:
6078 if (bt == VT_STRUCT)
6079 tstr = "struct ";
6080 else
6081 tstr = "enum ";
6082 pstrcat(buf, buf_size, tstr);
6083 v = type->ref->v & ~SYM_STRUCT;
6084 if (v >= SYM_FIRST_ANOM)
6085 pstrcat(buf, buf_size, "<anonymous>");
6086 else
6087 pstrcat(buf, buf_size, get_tok_str(v, NULL));
6088 break;
6089 case VT_FUNC:
6090 s = type->ref;
6091 type_to_str(buf, buf_size, &s->type, varstr);
6092 pstrcat(buf, buf_size, "(");
6093 sa = s->next;
6094 while (sa != NULL) {
6095 type_to_str(buf1, sizeof(buf1), &sa->type, NULL);
6096 pstrcat(buf, buf_size, buf1);
6097 sa = sa->next;
6098 if (sa)
6099 pstrcat(buf, buf_size, ", ");
6101 pstrcat(buf, buf_size, ")");
6102 goto no_var;
6103 case VT_PTR:
6104 s = type->ref;
6105 pstrcpy(buf1, sizeof(buf1), "*");
6106 if (varstr)
6107 pstrcat(buf1, sizeof(buf1), varstr);
6108 type_to_str(buf, buf_size, &s->type, buf1);
6109 goto no_var;
6111 if (varstr) {
6112 pstrcat(buf, buf_size, " ");
6113 pstrcat(buf, buf_size, varstr);
6115 no_var: ;
6118 /* verify type compatibility to store vtop in 'dt' type, and generate
6119 casts if needed. */
6120 static void gen_assign_cast(CType *dt)
6122 CType *st, *type1, *type2, tmp_type1, tmp_type2;
6123 char buf1[256], buf2[256];
6124 int dbt, sbt;
6126 st = &vtop->type; /* source type */
6127 dbt = dt->t & VT_BTYPE;
6128 sbt = st->t & VT_BTYPE;
6129 if (dt->t & VT_CONSTANT)
6130 warning("assignment of read-only location");
6131 switch(dbt) {
6132 case VT_PTR:
6133 /* special cases for pointers */
6134 /* '0' can also be a pointer */
6135 if (is_null_pointer(vtop))
6136 goto type_ok;
6137 /* accept implicit pointer to integer cast with warning */
6138 if (is_integer_btype(sbt)) {
6139 warning("assignment makes pointer from integer without a cast");
6140 goto type_ok;
6142 type1 = pointed_type(dt);
6143 /* a function is implicitely a function pointer */
6144 if (sbt == VT_FUNC) {
6145 if ((type1->t & VT_BTYPE) != VT_VOID &&
6146 !is_compatible_types(pointed_type(dt), st))
6147 goto error;
6148 else
6149 goto type_ok;
6151 if (sbt != VT_PTR)
6152 goto error;
6153 type2 = pointed_type(st);
6154 if ((type1->t & VT_BTYPE) == VT_VOID ||
6155 (type2->t & VT_BTYPE) == VT_VOID) {
6156 /* void * can match anything */
6157 } else {
6158 /* exact type match, except for unsigned */
6159 tmp_type1 = *type1;
6160 tmp_type2 = *type2;
6161 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
6162 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
6163 if (!is_compatible_types(&tmp_type1, &tmp_type2))
6164 goto error;
6166 /* check const and volatile */
6167 if ((!(type1->t & VT_CONSTANT) && (type2->t & VT_CONSTANT)) ||
6168 (!(type1->t & VT_VOLATILE) && (type2->t & VT_VOLATILE)))
6169 warning("assignment discards qualifiers from pointer target type");
6170 break;
6171 case VT_BYTE:
6172 case VT_SHORT:
6173 case VT_INT:
6174 case VT_LLONG:
6175 if (sbt == VT_PTR || sbt == VT_FUNC) {
6176 warning("assignment makes integer from pointer without a cast");
6178 /* XXX: more tests */
6179 break;
6180 case VT_STRUCT:
6181 tmp_type1 = *dt;
6182 tmp_type2 = *st;
6183 tmp_type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
6184 tmp_type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
6185 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
6186 error:
6187 type_to_str(buf1, sizeof(buf1), st, NULL);
6188 type_to_str(buf2, sizeof(buf2), dt, NULL);
6189 error("cannot cast '%s' to '%s'", buf1, buf2);
6191 break;
6193 type_ok:
6194 gen_cast(dt);
6197 /* store vtop in lvalue pushed on stack */
6198 void vstore(void)
6200 int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
6202 ft = vtop[-1].type.t;
6203 sbt = vtop->type.t & VT_BTYPE;
6204 dbt = ft & VT_BTYPE;
6205 if (((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
6206 (sbt == VT_INT && dbt == VT_SHORT)) {
6207 /* optimize char/short casts */
6208 delayed_cast = VT_MUSTCAST;
6209 vtop->type.t = ft & VT_TYPE;
6210 /* XXX: factorize */
6211 if (ft & VT_CONSTANT)
6212 warning("assignment of read-only location");
6213 } else {
6214 delayed_cast = 0;
6215 if (!(ft & VT_BITFIELD))
6216 gen_assign_cast(&vtop[-1].type);
6219 if (sbt == VT_STRUCT) {
6220 /* if structure, only generate pointer */
6221 /* structure assignment : generate memcpy */
6222 /* XXX: optimize if small size */
6223 if (!nocode_wanted) {
6224 size = type_size(&vtop->type, &align);
6226 vpush_global_sym(&func_old_type, TOK_memcpy);
6228 /* destination */
6229 vpushv(vtop - 2);
6230 vtop->type.t = VT_INT;
6231 gaddrof();
6232 /* source */
6233 vpushv(vtop - 2);
6234 vtop->type.t = VT_INT;
6235 gaddrof();
6236 /* type size */
6237 vpushi(size);
6238 gfunc_call(3);
6240 vswap();
6241 vpop();
6242 } else {
6243 vswap();
6244 vpop();
6246 /* leave source on stack */
6247 } else if (ft & VT_BITFIELD) {
6248 /* bitfield store handling */
6249 bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
6250 bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
6251 /* remove bit field info to avoid loops */
6252 vtop[-1].type.t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
6254 /* duplicate destination */
6255 vdup();
6256 vtop[-1] = vtop[-2];
6258 /* mask and shift source */
6259 vpushi((1 << bit_size) - 1);
6260 gen_op('&');
6261 vpushi(bit_pos);
6262 gen_op(TOK_SHL);
6263 /* load destination, mask and or with source */
6264 vswap();
6265 vpushi(~(((1 << bit_size) - 1) << bit_pos));
6266 gen_op('&');
6267 gen_op('|');
6268 /* store result */
6269 vstore();
6270 } else {
6271 #ifdef CONFIG_TCC_BCHECK
6272 /* bound check case */
6273 if (vtop[-1].r & VT_MUSTBOUND) {
6274 vswap();
6275 gbound();
6276 vswap();
6278 #endif
6279 if (!nocode_wanted) {
6280 rc = RC_INT;
6281 if (is_float(ft))
6282 rc = RC_FLOAT;
6283 r = gv(rc); /* generate value */
6284 /* if lvalue was saved on stack, must read it */
6285 if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
6286 SValue sv;
6287 t = get_reg(RC_INT);
6288 sv.type.t = VT_INT;
6289 sv.r = VT_LOCAL | VT_LVAL;
6290 sv.c.ul = vtop[-1].c.ul;
6291 load(t, &sv);
6292 vtop[-1].r = t | VT_LVAL;
6294 store(r, vtop - 1);
6295 /* two word case handling : store second register at word + 4 */
6296 if ((ft & VT_BTYPE) == VT_LLONG) {
6297 vswap();
6298 /* convert to int to increment easily */
6299 vtop->type.t = VT_INT;
6300 gaddrof();
6301 vpushi(4);
6302 gen_op('+');
6303 vtop->r |= VT_LVAL;
6304 vswap();
6305 /* XXX: it works because r2 is spilled last ! */
6306 store(vtop->r2, vtop - 1);
6309 vswap();
6310 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
6311 vtop->r |= delayed_cast;
6315 /* post defines POST/PRE add. c is the token ++ or -- */
6316 void inc(int post, int c)
6318 test_lvalue();
6319 vdup(); /* save lvalue */
6320 if (post) {
6321 gv_dup(); /* duplicate value */
6322 vrotb(3);
6323 vrotb(3);
6325 /* add constant */
6326 vpushi(c - TOK_MID);
6327 gen_op('+');
6328 vstore(); /* store value */
6329 if (post)
6330 vpop(); /* if post op, return saved value */
6333 /* Parse GNUC __attribute__ extension. Currently, the following
6334 extensions are recognized:
6335 - aligned(n) : set data/function alignment.
6336 - packed : force data alignment to 1
6337 - section(x) : generate data/code in this section.
6338 - unused : currently ignored, but may be used someday.
6339 - regparm(n) : pass function parameters in registers (i386 only)
6341 static void parse_attribute(AttributeDef *ad)
6343 int t, n;
6345 while (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) {
6346 next();
6347 skip('(');
6348 skip('(');
6349 while (tok != ')') {
6350 if (tok < TOK_IDENT)
6351 expect("attribute name");
6352 t = tok;
6353 next();
6354 switch(t) {
6355 case TOK_SECTION1:
6356 case TOK_SECTION2:
6357 skip('(');
6358 if (tok != TOK_STR)
6359 expect("section name");
6360 ad->section = find_section(tcc_state, (char *)tokc.cstr->data);
6361 next();
6362 skip(')');
6363 break;
6364 case TOK_ALIGNED1:
6365 case TOK_ALIGNED2:
6366 if (tok == '(') {
6367 next();
6368 n = expr_const();
6369 if (n <= 0 || (n & (n - 1)) != 0)
6370 error("alignment must be a positive power of two");
6371 skip(')');
6372 } else {
6373 n = MAX_ALIGN;
6375 ad->aligned = n;
6376 break;
6377 case TOK_PACKED1:
6378 case TOK_PACKED2:
6379 ad->packed = 1;
6380 break;
6381 case TOK_UNUSED1:
6382 case TOK_UNUSED2:
6383 /* currently, no need to handle it because tcc does not
6384 track unused objects */
6385 break;
6386 case TOK_NORETURN1:
6387 case TOK_NORETURN2:
6388 /* currently, no need to handle it because tcc does not
6389 track unused objects */
6390 break;
6391 case TOK_CDECL1:
6392 case TOK_CDECL2:
6393 case TOK_CDECL3:
6394 ad->func_call = FUNC_CDECL;
6395 break;
6396 case TOK_STDCALL1:
6397 case TOK_STDCALL2:
6398 case TOK_STDCALL3:
6399 ad->func_call = FUNC_STDCALL;
6400 break;
6401 #ifdef TCC_TARGET_I386
6402 case TOK_REGPARM1:
6403 case TOK_REGPARM2:
6404 skip('(');
6405 n = expr_const();
6406 if (n > 3)
6407 n = 3;
6408 else if (n < 0)
6409 n = 0;
6410 if (n > 0)
6411 ad->func_call = FUNC_FASTCALL1 + n - 1;
6412 skip(')');
6413 break;
6414 #endif
6415 case TOK_DLLEXPORT:
6416 ad->dllexport = 1;
6417 break;
6418 default:
6419 if (tcc_state->warn_unsupported)
6420 warning("'%s' attribute ignored", get_tok_str(t, NULL));
6421 /* skip parameters */
6422 /* XXX: skip parenthesis too */
6423 if (tok == '(') {
6424 next();
6425 while (tok != ')' && tok != -1)
6426 next();
6427 next();
6429 break;
6431 if (tok != ',')
6432 break;
6433 next();
6435 skip(')');
6436 skip(')');
6440 /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
6441 static void struct_decl(CType *type, int u)
6443 int a, v, size, align, maxalign, c, offset;
6444 int bit_size, bit_pos, bsize, bt, lbit_pos;
6445 Sym *s, *ss, **ps;
6446 AttributeDef ad;
6447 CType type1, btype;
6449 a = tok; /* save decl type */
6450 next();
6451 if (tok != '{') {
6452 v = tok;
6453 next();
6454 /* struct already defined ? return it */
6455 if (v < TOK_IDENT)
6456 expect("struct/union/enum name");
6457 s = struct_find(v);
6458 if (s) {
6459 if (s->type.t != a)
6460 error("invalid type");
6461 goto do_decl;
6463 } else {
6464 v = anon_sym++;
6466 type1.t = a;
6467 /* we put an undefined size for struct/union */
6468 s = sym_push(v | SYM_STRUCT, &type1, 0, -1);
6469 s->r = 0; /* default alignment is zero as gcc */
6470 /* put struct/union/enum name in type */
6471 do_decl:
6472 type->t = u;
6473 type->ref = s;
6475 if (tok == '{') {
6476 next();
6477 if (s->c != -1)
6478 error("struct/union/enum already defined");
6479 /* cannot be empty */
6480 c = 0;
6481 /* non empty enums are not allowed */
6482 if (a == TOK_ENUM) {
6483 for(;;) {
6484 v = tok;
6485 if (v < TOK_UIDENT)
6486 expect("identifier");
6487 next();
6488 if (tok == '=') {
6489 next();
6490 c = expr_const();
6492 /* enum symbols have static storage */
6493 ss = sym_push(v, &int_type, VT_CONST, c);
6494 ss->type.t |= VT_STATIC;
6495 if (tok != ',')
6496 break;
6497 next();
6498 c++;
6499 /* NOTE: we accept a trailing comma */
6500 if (tok == '}')
6501 break;
6503 skip('}');
6504 } else {
6505 maxalign = 1;
6506 ps = &s->next;
6507 bit_pos = 0;
6508 offset = 0;
6509 while (tok != '}') {
6510 parse_btype(&btype, &ad);
6511 while (1) {
6512 bit_size = -1;
6513 v = 0;
6514 type1 = btype;
6515 if (tok != ':') {
6516 type_decl(&type1, &ad, &v, TYPE_DIRECT);
6517 if ((type1.t & VT_BTYPE) == VT_FUNC ||
6518 (type1.t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN | VT_INLINE)))
6519 error("invalid type for '%s'",
6520 get_tok_str(v, NULL));
6522 if (tok == ':') {
6523 next();
6524 bit_size = expr_const();
6525 /* XXX: handle v = 0 case for messages */
6526 if (bit_size < 0)
6527 error("negative width in bit-field '%s'",
6528 get_tok_str(v, NULL));
6529 if (v && bit_size == 0)
6530 error("zero width for bit-field '%s'",
6531 get_tok_str(v, NULL));
6533 size = type_size(&type1, &align);
6534 if (ad.aligned) {
6535 if (align < ad.aligned)
6536 align = ad.aligned;
6537 } else if (ad.packed) {
6538 align = 1;
6539 } else if (*tcc_state->pack_stack_ptr) {
6540 if (align > *tcc_state->pack_stack_ptr)
6541 align = *tcc_state->pack_stack_ptr;
6543 lbit_pos = 0;
6544 if (bit_size >= 0) {
6545 bt = type1.t & VT_BTYPE;
6546 if (bt != VT_INT &&
6547 bt != VT_BYTE &&
6548 bt != VT_SHORT &&
6549 bt != VT_BOOL &&
6550 bt != VT_ENUM)
6551 error("bitfields must have scalar type");
6552 bsize = size * 8;
6553 if (bit_size > bsize) {
6554 error("width of '%s' exceeds its type",
6555 get_tok_str(v, NULL));
6556 } else if (bit_size == bsize) {
6557 /* no need for bit fields */
6558 bit_pos = 0;
6559 } else if (bit_size == 0) {
6560 /* XXX: what to do if only padding in a
6561 structure ? */
6562 /* zero size: means to pad */
6563 if (bit_pos > 0)
6564 bit_pos = bsize;
6565 } else {
6566 /* we do not have enough room ? */
6567 if ((bit_pos + bit_size) > bsize)
6568 bit_pos = 0;
6569 lbit_pos = bit_pos;
6570 /* XXX: handle LSB first */
6571 type1.t |= VT_BITFIELD |
6572 (bit_pos << VT_STRUCT_SHIFT) |
6573 (bit_size << (VT_STRUCT_SHIFT + 6));
6574 bit_pos += bit_size;
6576 } else {
6577 bit_pos = 0;
6579 if (v) {
6580 /* add new memory data only if starting
6581 bit field */
6582 if (lbit_pos == 0) {
6583 if (a == TOK_STRUCT) {
6584 c = (c + align - 1) & -align;
6585 offset = c;
6586 c += size;
6587 } else {
6588 offset = 0;
6589 if (size > c)
6590 c = size;
6592 if (align > maxalign)
6593 maxalign = align;
6595 #if 0
6596 printf("add field %s offset=%d",
6597 get_tok_str(v, NULL), offset);
6598 if (type1.t & VT_BITFIELD) {
6599 printf(" pos=%d size=%d",
6600 (type1.t >> VT_STRUCT_SHIFT) & 0x3f,
6601 (type1.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
6603 printf("\n");
6604 #endif
6605 ss = sym_push(v | SYM_FIELD, &type1, 0, offset);
6606 *ps = ss;
6607 ps = &ss->next;
6609 if (tok == ';' || tok == TOK_EOF)
6610 break;
6611 skip(',');
6613 skip(';');
6615 skip('}');
6616 /* store size and alignment */
6617 s->c = (c + maxalign - 1) & -maxalign;
6618 s->r = maxalign;
6623 /* return 0 if no type declaration. otherwise, return the basic type
6624 and skip it.
6626 static int parse_btype(CType *type, AttributeDef *ad)
6628 int t, u, type_found, typespec_found;
6629 Sym *s;
6630 CType type1;
6632 memset(ad, 0, sizeof(AttributeDef));
6633 type_found = 0;
6634 typespec_found = 0;
6635 t = 0;
6636 while(1) {
6637 switch(tok) {
6638 case TOK_EXTENSION:
6639 /* currently, we really ignore extension */
6640 next();
6641 continue;
6643 /* basic types */
6644 case TOK_CHAR:
6645 u = VT_BYTE;
6646 basic_type:
6647 next();
6648 basic_type1:
6649 if ((t & VT_BTYPE) != 0)
6650 error("too many basic types");
6651 t |= u;
6652 typespec_found = 1;
6653 break;
6654 case TOK_VOID:
6655 u = VT_VOID;
6656 goto basic_type;
6657 case TOK_SHORT:
6658 u = VT_SHORT;
6659 goto basic_type;
6660 case TOK_INT:
6661 next();
6662 typespec_found = 1;
6663 break;
6664 case TOK_LONG:
6665 next();
6666 if ((t & VT_BTYPE) == VT_DOUBLE) {
6667 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6668 } else if ((t & VT_BTYPE) == VT_LONG) {
6669 t = (t & ~VT_BTYPE) | VT_LLONG;
6670 } else {
6671 u = VT_LONG;
6672 goto basic_type1;
6674 break;
6675 case TOK_BOOL:
6676 u = VT_BOOL;
6677 goto basic_type;
6678 case TOK_FLOAT:
6679 u = VT_FLOAT;
6680 goto basic_type;
6681 case TOK_DOUBLE:
6682 next();
6683 if ((t & VT_BTYPE) == VT_LONG) {
6684 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6685 } else {
6686 u = VT_DOUBLE;
6687 goto basic_type1;
6689 break;
6690 case TOK_ENUM:
6691 struct_decl(&type1, VT_ENUM);
6692 basic_type2:
6693 u = type1.t;
6694 type->ref = type1.ref;
6695 goto basic_type1;
6696 case TOK_STRUCT:
6697 case TOK_UNION:
6698 struct_decl(&type1, VT_STRUCT);
6699 goto basic_type2;
6701 /* type modifiers */
6702 case TOK_CONST1:
6703 case TOK_CONST2:
6704 case TOK_CONST3:
6705 t |= VT_CONSTANT;
6706 next();
6707 break;
6708 case TOK_VOLATILE1:
6709 case TOK_VOLATILE2:
6710 case TOK_VOLATILE3:
6711 t |= VT_VOLATILE;
6712 next();
6713 break;
6714 case TOK_SIGNED1:
6715 case TOK_SIGNED2:
6716 case TOK_SIGNED3:
6717 typespec_found = 1;
6718 t |= VT_SIGNED;
6719 next();
6720 break;
6721 case TOK_REGISTER:
6722 case TOK_AUTO:
6723 case TOK_RESTRICT1:
6724 case TOK_RESTRICT2:
6725 case TOK_RESTRICT3:
6726 next();
6727 break;
6728 case TOK_UNSIGNED:
6729 t |= VT_UNSIGNED;
6730 next();
6731 typespec_found = 1;
6732 break;
6734 /* storage */
6735 case TOK_EXTERN:
6736 t |= VT_EXTERN;
6737 next();
6738 break;
6739 case TOK_STATIC:
6740 t |= VT_STATIC;
6741 next();
6742 break;
6743 case TOK_TYPEDEF:
6744 t |= VT_TYPEDEF;
6745 next();
6746 break;
6747 case TOK_INLINE1:
6748 case TOK_INLINE2:
6749 case TOK_INLINE3:
6750 t |= VT_INLINE;
6751 next();
6752 break;
6754 /* GNUC attribute */
6755 case TOK_ATTRIBUTE1:
6756 case TOK_ATTRIBUTE2:
6757 parse_attribute(ad);
6758 break;
6759 /* GNUC typeof */
6760 case TOK_TYPEOF1:
6761 case TOK_TYPEOF2:
6762 case TOK_TYPEOF3:
6763 next();
6764 parse_expr_type(&type1);
6765 goto basic_type2;
6766 default:
6767 if (typespec_found)
6768 goto the_end;
6769 s = sym_find(tok);
6770 if (!s || !(s->type.t & VT_TYPEDEF))
6771 goto the_end;
6772 t |= (s->type.t & ~VT_TYPEDEF);
6773 type->ref = s->type.ref;
6774 next();
6775 break;
6777 type_found = 1;
6779 the_end:
6780 if ((t & (VT_SIGNED|VT_UNSIGNED)) == (VT_SIGNED|VT_UNSIGNED))
6781 error("signed and unsigned modifier");
6782 if (tcc_state->char_is_unsigned) {
6783 if ((t & (VT_SIGNED|VT_UNSIGNED|VT_BTYPE)) == VT_BYTE)
6784 t |= VT_UNSIGNED;
6786 t &= ~VT_SIGNED;
6788 /* long is never used as type */
6789 if ((t & VT_BTYPE) == VT_LONG)
6790 t = (t & ~VT_BTYPE) | VT_INT;
6791 type->t = t;
6792 return type_found;
6795 /* convert a function parameter type (array to pointer and function to
6796 function pointer) */
6797 static inline void convert_parameter_type(CType *pt)
6799 /* remove const and volatile qualifiers (XXX: const could be used
6800 to indicate a const function parameter */
6801 pt->t &= ~(VT_CONSTANT | VT_VOLATILE);
6802 /* array must be transformed to pointer according to ANSI C */
6803 pt->t &= ~VT_ARRAY;
6804 if ((pt->t & VT_BTYPE) == VT_FUNC) {
6805 mk_pointer(pt);
6809 static void post_type(CType *type, AttributeDef *ad)
6811 int n, l, t1;
6812 Sym **plast, *s, *first;
6813 AttributeDef ad1;
6814 CType pt;
6816 if (tok == '(') {
6817 /* function declaration */
6818 next();
6819 l = 0;
6820 first = NULL;
6821 plast = &first;
6822 while (tok != ')') {
6823 /* read param name and compute offset */
6824 if (l != FUNC_OLD) {
6825 if (!parse_btype(&pt, &ad1)) {
6826 if (l) {
6827 error("invalid type");
6828 } else {
6829 l = FUNC_OLD;
6830 goto old_proto;
6833 l = FUNC_NEW;
6834 if ((pt.t & VT_BTYPE) == VT_VOID && tok == ')')
6835 break;
6836 type_decl(&pt, &ad1, &n, TYPE_DIRECT | TYPE_ABSTRACT);
6837 if ((pt.t & VT_BTYPE) == VT_VOID)
6838 error("parameter declared as void");
6839 } else {
6840 old_proto:
6841 n = tok;
6842 pt.t = VT_INT;
6843 next();
6845 convert_parameter_type(&pt);
6846 s = sym_push(n | SYM_FIELD, &pt, 0, 0);
6847 *plast = s;
6848 plast = &s->next;
6849 if (tok == ',') {
6850 next();
6851 if (l == FUNC_NEW && tok == TOK_DOTS) {
6852 l = FUNC_ELLIPSIS;
6853 next();
6854 break;
6858 /* if no parameters, then old type prototype */
6859 if (l == 0)
6860 l = FUNC_OLD;
6861 skip(')');
6862 t1 = type->t & VT_STORAGE;
6863 /* NOTE: const is ignored in returned type as it has a special
6864 meaning in gcc / C++ */
6865 type->t &= ~(VT_STORAGE | VT_CONSTANT);
6866 post_type(type, ad);
6867 /* we push a anonymous symbol which will contain the function prototype */
6868 s = sym_push(SYM_FIELD, type, ad->func_call, l);
6869 s->next = first;
6870 type->t = t1 | VT_FUNC;
6871 type->ref = s;
6872 } else if (tok == '[') {
6873 /* array definition */
6874 next();
6875 n = -1;
6876 if (tok != ']') {
6877 n = expr_const();
6878 if (n < 0)
6879 error("invalid array size");
6881 skip(']');
6882 /* parse next post type */
6883 t1 = type->t & VT_STORAGE;
6884 type->t &= ~VT_STORAGE;
6885 post_type(type, ad);
6887 /* we push a anonymous symbol which will contain the array
6888 element type */
6889 s = sym_push(SYM_FIELD, type, 0, n);
6890 type->t = t1 | VT_ARRAY | VT_PTR;
6891 type->ref = s;
6895 /* Parse a type declaration (except basic type), and return the type
6896 in 'type'. 'td' is a bitmask indicating which kind of type decl is
6897 expected. 'type' should contain the basic type. 'ad' is the
6898 attribute definition of the basic type. It can be modified by
6899 type_decl().
6901 static void type_decl(CType *type, AttributeDef *ad, int *v, int td)
6903 Sym *s;
6904 CType type1, *type2;
6905 int qualifiers;
6907 while (tok == '*') {
6908 qualifiers = 0;
6909 redo:
6910 next();
6911 switch(tok) {
6912 case TOK_CONST1:
6913 case TOK_CONST2:
6914 case TOK_CONST3:
6915 qualifiers |= VT_CONSTANT;
6916 goto redo;
6917 case TOK_VOLATILE1:
6918 case TOK_VOLATILE2:
6919 case TOK_VOLATILE3:
6920 qualifiers |= VT_VOLATILE;
6921 goto redo;
6922 case TOK_RESTRICT1:
6923 case TOK_RESTRICT2:
6924 case TOK_RESTRICT3:
6925 goto redo;
6927 mk_pointer(type);
6928 type->t |= qualifiers;
6931 /* XXX: clarify attribute handling */
6932 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6933 parse_attribute(ad);
6935 /* recursive type */
6936 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
6937 type1.t = 0; /* XXX: same as int */
6938 if (tok == '(') {
6939 next();
6940 /* XXX: this is not correct to modify 'ad' at this point, but
6941 the syntax is not clear */
6942 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6943 parse_attribute(ad);
6944 type_decl(&type1, ad, v, td);
6945 skip(')');
6946 } else {
6947 /* type identifier */
6948 if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
6949 *v = tok;
6950 next();
6951 } else {
6952 if (!(td & TYPE_ABSTRACT))
6953 expect("identifier");
6954 *v = 0;
6957 post_type(type, ad);
6958 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6959 parse_attribute(ad);
6960 if (!type1.t)
6961 return;
6962 /* append type at the end of type1 */
6963 type2 = &type1;
6964 for(;;) {
6965 s = type2->ref;
6966 type2 = &s->type;
6967 if (!type2->t) {
6968 *type2 = *type;
6969 break;
6972 *type = type1;
6975 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
6976 static int lvalue_type(int t)
6978 int bt, r;
6979 r = VT_LVAL;
6980 bt = t & VT_BTYPE;
6981 if (bt == VT_BYTE || bt == VT_BOOL)
6982 r |= VT_LVAL_BYTE;
6983 else if (bt == VT_SHORT)
6984 r |= VT_LVAL_SHORT;
6985 else
6986 return r;
6987 if (t & VT_UNSIGNED)
6988 r |= VT_LVAL_UNSIGNED;
6989 return r;
6992 /* indirection with full error checking and bound check */
6993 static void indir(void)
6995 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
6996 expect("pointer");
6997 if ((vtop->r & VT_LVAL) && !nocode_wanted)
6998 gv(RC_INT);
6999 vtop->type = *pointed_type(&vtop->type);
7000 /* an array is never an lvalue */
7001 if (!(vtop->type.t & VT_ARRAY)) {
7002 vtop->r |= lvalue_type(vtop->type.t);
7003 /* if bound checking, the referenced pointer must be checked */
7004 if (do_bounds_check)
7005 vtop->r |= VT_MUSTBOUND;
7009 /* pass a parameter to a function and do type checking and casting */
7010 static void gfunc_param_typed(Sym *func, Sym *arg)
7012 int func_type;
7013 CType type;
7015 func_type = func->c;
7016 if (func_type == FUNC_OLD ||
7017 (func_type == FUNC_ELLIPSIS && arg == NULL)) {
7018 /* default casting : only need to convert float to double */
7019 if ((vtop->type.t & VT_BTYPE) == VT_FLOAT) {
7020 type.t = VT_DOUBLE;
7021 gen_cast(&type);
7023 } else if (arg == NULL) {
7024 error("too many arguments to function");
7025 } else {
7026 type = arg->type;
7027 type.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
7028 gen_assign_cast(&type);
7032 /* parse an expression of the form '(type)' or '(expr)' and return its
7033 type */
7034 static void parse_expr_type(CType *type)
7036 int n;
7037 AttributeDef ad;
7039 skip('(');
7040 if (parse_btype(type, &ad)) {
7041 type_decl(type, &ad, &n, TYPE_ABSTRACT);
7042 } else {
7043 expr_type(type);
7045 skip(')');
7048 static void parse_type(CType *type)
7050 AttributeDef ad;
7051 int n;
7053 if (!parse_btype(type, &ad)) {
7054 expect("type");
7056 type_decl(type, &ad, &n, TYPE_ABSTRACT);
7059 static void vpush_tokc(int t)
7061 CType type;
7062 type.t = t;
7063 vsetc(&type, VT_CONST, &tokc);
7066 static void unary(void)
7068 int n, t, align, size, r;
7069 CType type;
7070 Sym *s;
7071 AttributeDef ad;
7073 /* XXX: GCC 2.95.3 does not generate a table although it should be
7074 better here */
7075 tok_next:
7076 switch(tok) {
7077 case TOK_EXTENSION:
7078 next();
7079 goto tok_next;
7080 case TOK_CINT:
7081 case TOK_CCHAR:
7082 case TOK_LCHAR:
7083 vpushi(tokc.i);
7084 next();
7085 break;
7086 case TOK_CUINT:
7087 vpush_tokc(VT_INT | VT_UNSIGNED);
7088 next();
7089 break;
7090 case TOK_CLLONG:
7091 vpush_tokc(VT_LLONG);
7092 next();
7093 break;
7094 case TOK_CULLONG:
7095 vpush_tokc(VT_LLONG | VT_UNSIGNED);
7096 next();
7097 break;
7098 case TOK_CFLOAT:
7099 vpush_tokc(VT_FLOAT);
7100 next();
7101 break;
7102 case TOK_CDOUBLE:
7103 vpush_tokc(VT_DOUBLE);
7104 next();
7105 break;
7106 case TOK_CLDOUBLE:
7107 vpush_tokc(VT_LDOUBLE);
7108 next();
7109 break;
7110 case TOK___FUNCTION__:
7111 if (!gnu_ext)
7112 goto tok_identifier;
7113 /* fall thru */
7114 case TOK___FUNC__:
7116 void *ptr;
7117 int len;
7118 /* special function name identifier */
7119 len = strlen(funcname) + 1;
7120 /* generate char[len] type */
7121 type.t = VT_BYTE;
7122 mk_pointer(&type);
7123 type.t |= VT_ARRAY;
7124 type.ref->c = len;
7125 vpush_ref(&type, data_section, data_section->data_offset, len);
7126 ptr = section_ptr_add(data_section, len);
7127 memcpy(ptr, funcname, len);
7128 next();
7130 break;
7131 case TOK_LSTR:
7132 t = VT_INT;
7133 goto str_init;
7134 case TOK_STR:
7135 /* string parsing */
7136 t = VT_BYTE;
7137 str_init:
7138 if (tcc_state->warn_write_strings)
7139 t |= VT_CONSTANT;
7140 type.t = t;
7141 mk_pointer(&type);
7142 type.t |= VT_ARRAY;
7143 memset(&ad, 0, sizeof(AttributeDef));
7144 decl_initializer_alloc(&type, &ad, VT_CONST, 2, 0, 0);
7145 break;
7146 case '(':
7147 next();
7148 /* cast ? */
7149 if (parse_btype(&type, &ad)) {
7150 type_decl(&type, &ad, &n, TYPE_ABSTRACT);
7151 skip(')');
7152 /* check ISOC99 compound literal */
7153 if (tok == '{') {
7154 /* data is allocated locally by default */
7155 if (global_expr)
7156 r = VT_CONST;
7157 else
7158 r = VT_LOCAL;
7159 /* all except arrays are lvalues */
7160 if (!(type.t & VT_ARRAY))
7161 r |= lvalue_type(type.t);
7162 memset(&ad, 0, sizeof(AttributeDef));
7163 decl_initializer_alloc(&type, &ad, r, 1, 0, 0);
7164 } else {
7165 unary();
7166 gen_cast(&type);
7168 } else if (tok == '{') {
7169 /* save all registers */
7170 save_regs(0);
7171 /* statement expression : we do not accept break/continue
7172 inside as GCC does */
7173 block(NULL, NULL, NULL, NULL, 0, 1);
7174 skip(')');
7175 } else {
7176 gexpr();
7177 skip(')');
7179 break;
7180 case '*':
7181 next();
7182 unary();
7183 indir();
7184 break;
7185 case '&':
7186 next();
7187 unary();
7188 /* functions names must be treated as function pointers,
7189 except for unary '&' and sizeof. Since we consider that
7190 functions are not lvalues, we only have to handle it
7191 there and in function calls. */
7192 /* arrays can also be used although they are not lvalues */
7193 if ((vtop->type.t & VT_BTYPE) != VT_FUNC &&
7194 !(vtop->type.t & VT_ARRAY))
7195 test_lvalue();
7196 mk_pointer(&vtop->type);
7197 gaddrof();
7198 break;
7199 case '!':
7200 next();
7201 unary();
7202 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST)
7203 vtop->c.i = !vtop->c.i;
7204 else if ((vtop->r & VT_VALMASK) == VT_CMP)
7205 vtop->c.i = vtop->c.i ^ 1;
7206 else
7207 vseti(VT_JMP, gtst(1, 0));
7208 break;
7209 case '~':
7210 next();
7211 unary();
7212 vpushi(-1);
7213 gen_op('^');
7214 break;
7215 case '+':
7216 next();
7217 /* in order to force cast, we add zero */
7218 unary();
7219 if ((vtop->type.t & VT_BTYPE) == VT_PTR)
7220 error("pointer not accepted for unary plus");
7221 vpushi(0);
7222 gen_op('+');
7223 break;
7224 case TOK_SIZEOF:
7225 case TOK_ALIGNOF1:
7226 case TOK_ALIGNOF2:
7227 t = tok;
7228 next();
7229 if (tok == '(') {
7230 parse_expr_type(&type);
7231 } else {
7232 unary_type(&type);
7234 size = type_size(&type, &align);
7235 if (t == TOK_SIZEOF) {
7236 if (size < 0)
7237 error("sizeof applied to an incomplete type");
7238 vpushi(size);
7239 } else {
7240 vpushi(align);
7242 break;
7244 case TOK_builtin_types_compatible_p:
7246 CType type1, type2;
7247 next();
7248 skip('(');
7249 parse_type(&type1);
7250 skip(',');
7251 parse_type(&type2);
7252 skip(')');
7253 type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
7254 type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
7255 vpushi(is_compatible_types(&type1, &type2));
7257 break;
7258 case TOK_builtin_constant_p:
7260 int saved_nocode_wanted, res;
7261 next();
7262 skip('(');
7263 saved_nocode_wanted = nocode_wanted;
7264 nocode_wanted = 1;
7265 gexpr();
7266 res = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
7267 vpop();
7268 nocode_wanted = saved_nocode_wanted;
7269 skip(')');
7270 vpushi(res);
7272 break;
7273 case TOK_INC:
7274 case TOK_DEC:
7275 t = tok;
7276 next();
7277 unary();
7278 inc(0, t);
7279 break;
7280 case '-':
7281 next();
7282 vpushi(0);
7283 unary();
7284 gen_op('-');
7285 break;
7286 case TOK_LAND:
7287 if (!gnu_ext)
7288 goto tok_identifier;
7289 next();
7290 /* allow to take the address of a label */
7291 if (tok < TOK_UIDENT)
7292 expect("label identifier");
7293 s = label_find(tok);
7294 if (!s) {
7295 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
7296 } else {
7297 if (s->r == LABEL_DECLARED)
7298 s->r = LABEL_FORWARD;
7300 if (!s->type.t) {
7301 s->type.t = VT_VOID;
7302 mk_pointer(&s->type);
7303 s->type.t |= VT_STATIC;
7305 vset(&s->type, VT_CONST | VT_SYM, 0);
7306 vtop->sym = s;
7307 next();
7308 break;
7309 default:
7310 tok_identifier:
7311 t = tok;
7312 next();
7313 if (t < TOK_UIDENT)
7314 expect("identifier");
7315 s = sym_find(t);
7316 if (!s) {
7317 if (tok != '(')
7318 error("'%s' undeclared", get_tok_str(t, NULL));
7319 /* for simple function calls, we tolerate undeclared
7320 external reference to int() function */
7321 if (tcc_state->warn_implicit_function_declaration)
7322 warning("implicit declaration of function '%s'",
7323 get_tok_str(t, NULL));
7324 s = external_global_sym(t, &func_old_type, 0);
7326 if ((s->type.t & (VT_STATIC | VT_INLINE | VT_BTYPE)) ==
7327 (VT_STATIC | VT_INLINE | VT_FUNC)) {
7328 /* if referencing an inline function, then we generate a
7329 symbol to it if not already done. It will have the
7330 effect to generate code for it at the end of the
7331 compilation unit. Inline function as always
7332 generated in the text section. */
7333 if (!s->c)
7334 put_extern_sym(s, text_section, 0, 0);
7335 r = VT_SYM | VT_CONST;
7336 } else {
7337 r = s->r;
7339 vset(&s->type, r, s->c);
7340 /* if forward reference, we must point to s */
7341 if (vtop->r & VT_SYM) {
7342 vtop->sym = s;
7343 vtop->c.ul = 0;
7345 break;
7348 /* post operations */
7349 while (1) {
7350 if (tok == TOK_INC || tok == TOK_DEC) {
7351 inc(1, tok);
7352 next();
7353 } else if (tok == '.' || tok == TOK_ARROW) {
7354 /* field */
7355 if (tok == TOK_ARROW)
7356 indir();
7357 test_lvalue();
7358 gaddrof();
7359 next();
7360 /* expect pointer on structure */
7361 if ((vtop->type.t & VT_BTYPE) != VT_STRUCT)
7362 expect("struct or union");
7363 s = vtop->type.ref;
7364 /* find field */
7365 tok |= SYM_FIELD;
7366 while ((s = s->next) != NULL) {
7367 if (s->v == tok)
7368 break;
7370 if (!s)
7371 error("field not found");
7372 /* add field offset to pointer */
7373 vtop->type = char_pointer_type; /* change type to 'char *' */
7374 vpushi(s->c);
7375 gen_op('+');
7376 /* change type to field type, and set to lvalue */
7377 vtop->type = s->type;
7378 /* an array is never an lvalue */
7379 if (!(vtop->type.t & VT_ARRAY)) {
7380 vtop->r |= lvalue_type(vtop->type.t);
7381 /* if bound checking, the referenced pointer must be checked */
7382 if (do_bounds_check)
7383 vtop->r |= VT_MUSTBOUND;
7385 next();
7386 } else if (tok == '[') {
7387 next();
7388 gexpr();
7389 gen_op('+');
7390 indir();
7391 skip(']');
7392 } else if (tok == '(') {
7393 SValue ret;
7394 Sym *sa;
7395 int nb_args;
7397 /* function call */
7398 if ((vtop->type.t & VT_BTYPE) != VT_FUNC) {
7399 /* pointer test (no array accepted) */
7400 if ((vtop->type.t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
7401 vtop->type = *pointed_type(&vtop->type);
7402 if ((vtop->type.t & VT_BTYPE) != VT_FUNC)
7403 goto error_func;
7404 } else {
7405 error_func:
7406 expect("function pointer");
7408 } else {
7409 vtop->r &= ~VT_LVAL; /* no lvalue */
7411 /* get return type */
7412 s = vtop->type.ref;
7413 next();
7414 sa = s->next; /* first parameter */
7415 nb_args = 0;
7416 /* compute first implicit argument if a structure is returned */
7417 if ((s->type.t & VT_BTYPE) == VT_STRUCT) {
7418 /* get some space for the returned structure */
7419 size = type_size(&s->type, &align);
7420 loc = (loc - size) & -align;
7421 ret.type = s->type;
7422 ret.r = VT_LOCAL | VT_LVAL;
7423 /* pass it as 'int' to avoid structure arg passing
7424 problems */
7425 vseti(VT_LOCAL, loc);
7426 ret.c = vtop->c;
7427 nb_args++;
7428 } else {
7429 ret.type = s->type;
7430 ret.r2 = VT_CONST;
7431 /* return in register */
7432 if (is_float(ret.type.t)) {
7433 ret.r = REG_FRET;
7434 } else {
7435 if ((ret.type.t & VT_BTYPE) == VT_LLONG)
7436 ret.r2 = REG_LRET;
7437 ret.r = REG_IRET;
7439 ret.c.i = 0;
7441 if (tok != ')') {
7442 for(;;) {
7443 expr_eq();
7444 gfunc_param_typed(s, sa);
7445 nb_args++;
7446 if (sa)
7447 sa = sa->next;
7448 if (tok == ')')
7449 break;
7450 skip(',');
7453 if (sa)
7454 error("too few arguments to function");
7455 skip(')');
7456 if (!nocode_wanted) {
7457 gfunc_call(nb_args);
7458 } else {
7459 vtop -= (nb_args + 1);
7461 /* return value */
7462 vsetc(&ret.type, ret.r, &ret.c);
7463 vtop->r2 = ret.r2;
7464 } else {
7465 break;
7470 static void uneq(void)
7472 int t;
7474 unary();
7475 if (tok == '=' ||
7476 (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
7477 tok == TOK_A_XOR || tok == TOK_A_OR ||
7478 tok == TOK_A_SHL || tok == TOK_A_SAR) {
7479 test_lvalue();
7480 t = tok;
7481 next();
7482 if (t == '=') {
7483 expr_eq();
7484 } else {
7485 vdup();
7486 expr_eq();
7487 gen_op(t & 0x7f);
7489 vstore();
7493 static void expr_prod(void)
7495 int t;
7497 uneq();
7498 while (tok == '*' || tok == '/' || tok == '%') {
7499 t = tok;
7500 next();
7501 uneq();
7502 gen_op(t);
7506 static void expr_sum(void)
7508 int t;
7510 expr_prod();
7511 while (tok == '+' || tok == '-') {
7512 t = tok;
7513 next();
7514 expr_prod();
7515 gen_op(t);
7519 static void expr_shift(void)
7521 int t;
7523 expr_sum();
7524 while (tok == TOK_SHL || tok == TOK_SAR) {
7525 t = tok;
7526 next();
7527 expr_sum();
7528 gen_op(t);
7532 static void expr_cmp(void)
7534 int t;
7536 expr_shift();
7537 while ((tok >= TOK_ULE && tok <= TOK_GT) ||
7538 tok == TOK_ULT || tok == TOK_UGE) {
7539 t = tok;
7540 next();
7541 expr_shift();
7542 gen_op(t);
7546 static void expr_cmpeq(void)
7548 int t;
7550 expr_cmp();
7551 while (tok == TOK_EQ || tok == TOK_NE) {
7552 t = tok;
7553 next();
7554 expr_cmp();
7555 gen_op(t);
7559 static void expr_and(void)
7561 expr_cmpeq();
7562 while (tok == '&') {
7563 next();
7564 expr_cmpeq();
7565 gen_op('&');
7569 static void expr_xor(void)
7571 expr_and();
7572 while (tok == '^') {
7573 next();
7574 expr_and();
7575 gen_op('^');
7579 static void expr_or(void)
7581 expr_xor();
7582 while (tok == '|') {
7583 next();
7584 expr_xor();
7585 gen_op('|');
7589 /* XXX: fix this mess */
7590 static void expr_land_const(void)
7592 expr_or();
7593 while (tok == TOK_LAND) {
7594 next();
7595 expr_or();
7596 gen_op(TOK_LAND);
7600 /* XXX: fix this mess */
7601 static void expr_lor_const(void)
7603 expr_land_const();
7604 while (tok == TOK_LOR) {
7605 next();
7606 expr_land_const();
7607 gen_op(TOK_LOR);
7611 /* only used if non constant */
7612 static void expr_land(void)
7614 int t;
7616 expr_or();
7617 if (tok == TOK_LAND) {
7618 t = 0;
7619 for(;;) {
7620 t = gtst(1, t);
7621 if (tok != TOK_LAND) {
7622 vseti(VT_JMPI, t);
7623 break;
7625 next();
7626 expr_or();
7631 static void expr_lor(void)
7633 int t;
7635 expr_land();
7636 if (tok == TOK_LOR) {
7637 t = 0;
7638 for(;;) {
7639 t = gtst(0, t);
7640 if (tok != TOK_LOR) {
7641 vseti(VT_JMP, t);
7642 break;
7644 next();
7645 expr_land();
7650 /* XXX: better constant handling */
7651 static void expr_eq(void)
7653 int tt, u, r1, r2, rc, t1, t2, bt1, bt2;
7654 SValue sv;
7655 CType type, type1, type2;
7657 if (const_wanted) {
7658 int c1, c;
7659 expr_lor_const();
7660 if (tok == '?') {
7661 c = vtop->c.i;
7662 vpop();
7663 next();
7664 if (tok == ':' && gnu_ext) {
7665 c1 = c;
7666 } else {
7667 gexpr();
7668 c1 = vtop->c.i;
7669 vpop();
7671 skip(':');
7672 expr_eq();
7673 if (c)
7674 vtop->c.i = c1;
7676 } else {
7677 expr_lor();
7678 if (tok == '?') {
7679 next();
7680 if (vtop != vstack) {
7681 /* needed to avoid having different registers saved in
7682 each branch */
7683 if (is_float(vtop->type.t))
7684 rc = RC_FLOAT;
7685 else
7686 rc = RC_INT;
7687 gv(rc);
7688 save_regs(1);
7690 if (tok == ':' && gnu_ext) {
7691 gv_dup();
7692 tt = gtst(1, 0);
7693 } else {
7694 tt = gtst(1, 0);
7695 gexpr();
7697 type1 = vtop->type;
7698 sv = *vtop; /* save value to handle it later */
7699 vtop--; /* no vpop so that FP stack is not flushed */
7700 skip(':');
7701 u = gjmp(0);
7702 gsym(tt);
7703 expr_eq();
7704 type2 = vtop->type;
7706 t1 = type1.t;
7707 bt1 = t1 & VT_BTYPE;
7708 t2 = type2.t;
7709 bt2 = t2 & VT_BTYPE;
7710 /* cast operands to correct type according to ISOC rules */
7711 if (is_float(bt1) || is_float(bt2)) {
7712 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
7713 type.t = VT_LDOUBLE;
7714 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
7715 type.t = VT_DOUBLE;
7716 } else {
7717 type.t = VT_FLOAT;
7719 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
7720 /* cast to biggest op */
7721 type.t = VT_LLONG;
7722 /* convert to unsigned if it does not fit in a long long */
7723 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
7724 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
7725 type.t |= VT_UNSIGNED;
7726 } else if (bt1 == VT_PTR || bt2 == VT_PTR) {
7727 /* XXX: test pointer compatibility */
7728 type = type1;
7729 } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
7730 /* XXX: test structure compatibility */
7731 type = type1;
7732 } else if (bt1 == VT_VOID || bt2 == VT_VOID) {
7733 /* NOTE: as an extension, we accept void on only one side */
7734 type.t = VT_VOID;
7735 } else {
7736 /* integer operations */
7737 type.t = VT_INT;
7738 /* convert to unsigned if it does not fit in an integer */
7739 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
7740 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
7741 type.t |= VT_UNSIGNED;
7744 /* now we convert second operand */
7745 gen_cast(&type);
7746 rc = RC_INT;
7747 if (is_float(type.t)) {
7748 rc = RC_FLOAT;
7749 } else if ((type.t & VT_BTYPE) == VT_LLONG) {
7750 /* for long longs, we use fixed registers to avoid having
7751 to handle a complicated move */
7752 rc = RC_IRET;
7755 r2 = gv(rc);
7756 /* this is horrible, but we must also convert first
7757 operand */
7758 tt = gjmp(0);
7759 gsym(u);
7760 /* put again first value and cast it */
7761 *vtop = sv;
7762 gen_cast(&type);
7763 r1 = gv(rc);
7764 move_reg(r2, r1);
7765 vtop->r = r2;
7766 gsym(tt);
7771 static void gexpr(void)
7773 while (1) {
7774 expr_eq();
7775 if (tok != ',')
7776 break;
7777 vpop();
7778 next();
7782 /* parse an expression and return its type without any side effect. */
7783 static void expr_type(CType *type)
7785 int saved_nocode_wanted;
7787 saved_nocode_wanted = nocode_wanted;
7788 nocode_wanted = 1;
7789 gexpr();
7790 *type = vtop->type;
7791 vpop();
7792 nocode_wanted = saved_nocode_wanted;
7795 /* parse a unary expression and return its type without any side
7796 effect. */
7797 static void unary_type(CType *type)
7799 int a;
7801 a = nocode_wanted;
7802 nocode_wanted = 1;
7803 unary();
7804 *type = vtop->type;
7805 vpop();
7806 nocode_wanted = a;
7809 /* parse a constant expression and return value in vtop. */
7810 static void expr_const1(void)
7812 int a;
7813 a = const_wanted;
7814 const_wanted = 1;
7815 expr_eq();
7816 const_wanted = a;
7819 /* parse an integer constant and return its value. */
7820 static int expr_const(void)
7822 int c;
7823 expr_const1();
7824 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
7825 expect("constant expression");
7826 c = vtop->c.i;
7827 vpop();
7828 return c;
7831 /* return the label token if current token is a label, otherwise
7832 return zero */
7833 static int is_label(void)
7835 int last_tok;
7837 /* fast test first */
7838 if (tok < TOK_UIDENT)
7839 return 0;
7840 /* no need to save tokc because tok is an identifier */
7841 last_tok = tok;
7842 next();
7843 if (tok == ':') {
7844 next();
7845 return last_tok;
7846 } else {
7847 unget_tok(last_tok);
7848 return 0;
7852 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
7853 int case_reg, int is_expr)
7855 int a, b, c, d;
7856 Sym *s;
7858 /* generate line number info */
7859 if (do_debug &&
7860 (last_line_num != file->line_num || last_ind != ind)) {
7861 put_stabn(N_SLINE, 0, file->line_num, ind - func_ind);
7862 last_ind = ind;
7863 last_line_num = file->line_num;
7866 if (is_expr) {
7867 /* default return value is (void) */
7868 vpushi(0);
7869 vtop->type.t = VT_VOID;
7872 if (tok == TOK_IF) {
7873 /* if test */
7874 next();
7875 skip('(');
7876 gexpr();
7877 skip(')');
7878 a = gtst(1, 0);
7879 block(bsym, csym, case_sym, def_sym, case_reg, 0);
7880 c = tok;
7881 if (c == TOK_ELSE) {
7882 next();
7883 d = gjmp(0);
7884 gsym(a);
7885 block(bsym, csym, case_sym, def_sym, case_reg, 0);
7886 gsym(d); /* patch else jmp */
7887 } else
7888 gsym(a);
7889 } else if (tok == TOK_WHILE) {
7890 next();
7891 d = ind;
7892 skip('(');
7893 gexpr();
7894 skip(')');
7895 a = gtst(1, 0);
7896 b = 0;
7897 block(&a, &b, case_sym, def_sym, case_reg, 0);
7898 gjmp_addr(d);
7899 gsym(a);
7900 gsym_addr(b, d);
7901 } else if (tok == '{') {
7902 Sym *llabel;
7904 next();
7905 /* record local declaration stack position */
7906 s = local_stack;
7907 llabel = local_label_stack;
7908 /* handle local labels declarations */
7909 if (tok == TOK_LABEL) {
7910 next();
7911 for(;;) {
7912 if (tok < TOK_UIDENT)
7913 expect("label identifier");
7914 label_push(&local_label_stack, tok, LABEL_DECLARED);
7915 next();
7916 if (tok == ',') {
7917 next();
7918 } else {
7919 skip(';');
7920 break;
7924 while (tok != '}') {
7925 decl(VT_LOCAL);
7926 if (tok != '}') {
7927 if (is_expr)
7928 vpop();
7929 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
7932 /* pop locally defined labels */
7933 label_pop(&local_label_stack, llabel);
7934 /* pop locally defined symbols */
7935 sym_pop(&local_stack, s);
7936 next();
7937 } else if (tok == TOK_RETURN) {
7938 next();
7939 if (tok != ';') {
7940 gexpr();
7941 gen_assign_cast(&func_vt);
7942 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
7943 CType type;
7944 /* if returning structure, must copy it to implicit
7945 first pointer arg location */
7946 type = func_vt;
7947 mk_pointer(&type);
7948 vset(&type, VT_LOCAL | VT_LVAL, func_vc);
7949 indir();
7950 vswap();
7951 /* copy structure value to pointer */
7952 vstore();
7953 } else if (is_float(func_vt.t)) {
7954 gv(RC_FRET);
7955 } else {
7956 gv(RC_IRET);
7958 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
7960 skip(';');
7961 rsym = gjmp(rsym); /* jmp */
7962 } else if (tok == TOK_BREAK) {
7963 /* compute jump */
7964 if (!bsym)
7965 error("cannot break");
7966 *bsym = gjmp(*bsym);
7967 next();
7968 skip(';');
7969 } else if (tok == TOK_CONTINUE) {
7970 /* compute jump */
7971 if (!csym)
7972 error("cannot continue");
7973 *csym = gjmp(*csym);
7974 next();
7975 skip(';');
7976 } else if (tok == TOK_FOR) {
7977 int e;
7978 next();
7979 skip('(');
7980 if (tok != ';') {
7981 gexpr();
7982 vpop();
7984 skip(';');
7985 d = ind;
7986 c = ind;
7987 a = 0;
7988 b = 0;
7989 if (tok != ';') {
7990 gexpr();
7991 a = gtst(1, 0);
7993 skip(';');
7994 if (tok != ')') {
7995 e = gjmp(0);
7996 c = ind;
7997 gexpr();
7998 vpop();
7999 gjmp_addr(d);
8000 gsym(e);
8002 skip(')');
8003 block(&a, &b, case_sym, def_sym, case_reg, 0);
8004 gjmp_addr(c);
8005 gsym(a);
8006 gsym_addr(b, c);
8007 } else
8008 if (tok == TOK_DO) {
8009 next();
8010 a = 0;
8011 b = 0;
8012 d = ind;
8013 block(&a, &b, case_sym, def_sym, case_reg, 0);
8014 skip(TOK_WHILE);
8015 skip('(');
8016 gsym(b);
8017 gexpr();
8018 c = gtst(0, 0);
8019 gsym_addr(c, d);
8020 skip(')');
8021 gsym(a);
8022 skip(';');
8023 } else
8024 if (tok == TOK_SWITCH) {
8025 next();
8026 skip('(');
8027 gexpr();
8028 /* XXX: other types than integer */
8029 case_reg = gv(RC_INT);
8030 vpop();
8031 skip(')');
8032 a = 0;
8033 b = gjmp(0); /* jump to first case */
8034 c = 0;
8035 block(&a, csym, &b, &c, case_reg, 0);
8036 /* if no default, jmp after switch */
8037 if (c == 0)
8038 c = ind;
8039 /* default label */
8040 gsym_addr(b, c);
8041 /* break label */
8042 gsym(a);
8043 } else
8044 if (tok == TOK_CASE) {
8045 int v1, v2;
8046 if (!case_sym)
8047 expect("switch");
8048 next();
8049 v1 = expr_const();
8050 v2 = v1;
8051 if (gnu_ext && tok == TOK_DOTS) {
8052 next();
8053 v2 = expr_const();
8054 if (v2 < v1)
8055 warning("empty case range");
8057 /* since a case is like a label, we must skip it with a jmp */
8058 b = gjmp(0);
8059 gsym(*case_sym);
8060 vseti(case_reg, 0);
8061 vpushi(v1);
8062 if (v1 == v2) {
8063 gen_op(TOK_EQ);
8064 *case_sym = gtst(1, 0);
8065 } else {
8066 gen_op(TOK_GE);
8067 *case_sym = gtst(1, 0);
8068 vseti(case_reg, 0);
8069 vpushi(v2);
8070 gen_op(TOK_LE);
8071 *case_sym = gtst(1, *case_sym);
8073 gsym(b);
8074 skip(':');
8075 is_expr = 0;
8076 goto block_after_label;
8077 } else
8078 if (tok == TOK_DEFAULT) {
8079 next();
8080 skip(':');
8081 if (!def_sym)
8082 expect("switch");
8083 if (*def_sym)
8084 error("too many 'default'");
8085 *def_sym = ind;
8086 is_expr = 0;
8087 goto block_after_label;
8088 } else
8089 if (tok == TOK_GOTO) {
8090 next();
8091 if (tok == '*' && gnu_ext) {
8092 /* computed goto */
8093 next();
8094 gexpr();
8095 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
8096 expect("pointer");
8097 ggoto();
8098 } else if (tok >= TOK_UIDENT) {
8099 s = label_find(tok);
8100 /* put forward definition if needed */
8101 if (!s) {
8102 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
8103 } else {
8104 if (s->r == LABEL_DECLARED)
8105 s->r = LABEL_FORWARD;
8107 /* label already defined */
8108 if (s->r & LABEL_FORWARD)
8109 s->next = (void *)gjmp((long)s->next);
8110 else
8111 gjmp_addr((long)s->next);
8112 next();
8113 } else {
8114 expect("label identifier");
8116 skip(';');
8117 } else if (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3) {
8118 asm_instr();
8119 } else {
8120 b = is_label();
8121 if (b) {
8122 /* label case */
8123 s = label_find(b);
8124 if (s) {
8125 if (s->r == LABEL_DEFINED)
8126 error("duplicate label '%s'", get_tok_str(s->v, NULL));
8127 gsym((long)s->next);
8128 s->r = LABEL_DEFINED;
8129 } else {
8130 s = label_push(&global_label_stack, b, LABEL_DEFINED);
8132 s->next = (void *)ind;
8133 /* we accept this, but it is a mistake */
8134 block_after_label:
8135 if (tok == '}') {
8136 warning("deprecated use of label at end of compound statement");
8137 } else {
8138 if (is_expr)
8139 vpop();
8140 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
8142 } else {
8143 /* expression case */
8144 if (tok != ';') {
8145 if (is_expr) {
8146 vpop();
8147 gexpr();
8148 } else {
8149 gexpr();
8150 vpop();
8153 skip(';');
8158 /* t is the array or struct type. c is the array or struct
8159 address. cur_index/cur_field is the pointer to the current
8160 value. 'size_only' is true if only size info is needed (only used
8161 in arrays) */
8162 static void decl_designator(CType *type, Section *sec, unsigned long c,
8163 int *cur_index, Sym **cur_field,
8164 int size_only)
8166 Sym *s, *f;
8167 int notfirst, index, index_last, align, l, nb_elems, elem_size;
8168 CType type1;
8170 notfirst = 0;
8171 elem_size = 0;
8172 nb_elems = 1;
8173 if (gnu_ext && (l = is_label()) != 0)
8174 goto struct_field;
8175 while (tok == '[' || tok == '.') {
8176 if (tok == '[') {
8177 if (!(type->t & VT_ARRAY))
8178 expect("array type");
8179 s = type->ref;
8180 next();
8181 index = expr_const();
8182 if (index < 0 || (s->c >= 0 && index >= s->c))
8183 expect("invalid index");
8184 if (tok == TOK_DOTS && gnu_ext) {
8185 next();
8186 index_last = expr_const();
8187 if (index_last < 0 ||
8188 (s->c >= 0 && index_last >= s->c) ||
8189 index_last < index)
8190 expect("invalid index");
8191 } else {
8192 index_last = index;
8194 skip(']');
8195 if (!notfirst)
8196 *cur_index = index_last;
8197 type = pointed_type(type);
8198 elem_size = type_size(type, &align);
8199 c += index * elem_size;
8200 /* NOTE: we only support ranges for last designator */
8201 nb_elems = index_last - index + 1;
8202 if (nb_elems != 1) {
8203 notfirst = 1;
8204 break;
8206 } else {
8207 next();
8208 l = tok;
8209 next();
8210 struct_field:
8211 if ((type->t & VT_BTYPE) != VT_STRUCT)
8212 expect("struct/union type");
8213 s = type->ref;
8214 l |= SYM_FIELD;
8215 f = s->next;
8216 while (f) {
8217 if (f->v == l)
8218 break;
8219 f = f->next;
8221 if (!f)
8222 expect("field");
8223 if (!notfirst)
8224 *cur_field = f;
8225 /* XXX: fix this mess by using explicit storage field */
8226 type1 = f->type;
8227 type1.t |= (type->t & ~VT_TYPE);
8228 type = &type1;
8229 c += f->c;
8231 notfirst = 1;
8233 if (notfirst) {
8234 if (tok == '=') {
8235 next();
8236 } else {
8237 if (!gnu_ext)
8238 expect("=");
8240 } else {
8241 if (type->t & VT_ARRAY) {
8242 index = *cur_index;
8243 type = pointed_type(type);
8244 c += index * type_size(type, &align);
8245 } else {
8246 f = *cur_field;
8247 if (!f)
8248 error("too many field init");
8249 /* XXX: fix this mess by using explicit storage field */
8250 type1 = f->type;
8251 type1.t |= (type->t & ~VT_TYPE);
8252 type = &type1;
8253 c += f->c;
8256 decl_initializer(type, sec, c, 0, size_only);
8258 /* XXX: make it more general */
8259 if (!size_only && nb_elems > 1) {
8260 unsigned long c_end;
8261 uint8_t *src, *dst;
8262 int i;
8264 if (!sec)
8265 error("range init not supported yet for dynamic storage");
8266 c_end = c + nb_elems * elem_size;
8267 if (c_end > sec->data_allocated)
8268 section_realloc(sec, c_end);
8269 src = sec->data + c;
8270 dst = src;
8271 for(i = 1; i < nb_elems; i++) {
8272 dst += elem_size;
8273 memcpy(dst, src, elem_size);
8278 #define EXPR_VAL 0
8279 #define EXPR_CONST 1
8280 #define EXPR_ANY 2
8282 /* store a value or an expression directly in global data or in local array */
8283 static void init_putv(CType *type, Section *sec, unsigned long c,
8284 int v, int expr_type)
8286 int saved_global_expr, bt, bit_pos, bit_size;
8287 void *ptr;
8288 unsigned long long bit_mask;
8289 CType dtype;
8291 switch(expr_type) {
8292 case EXPR_VAL:
8293 vpushi(v);
8294 break;
8295 case EXPR_CONST:
8296 /* compound literals must be allocated globally in this case */
8297 saved_global_expr = global_expr;
8298 global_expr = 1;
8299 expr_const1();
8300 global_expr = saved_global_expr;
8301 /* NOTE: symbols are accepted */
8302 if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST)
8303 error("initializer element is not constant");
8304 break;
8305 case EXPR_ANY:
8306 expr_eq();
8307 break;
8310 dtype = *type;
8311 dtype.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
8313 if (sec) {
8314 /* XXX: not portable */
8315 /* XXX: generate error if incorrect relocation */
8316 gen_assign_cast(&dtype);
8317 bt = type->t & VT_BTYPE;
8318 ptr = sec->data + c;
8319 /* XXX: make code faster ? */
8320 if (!(type->t & VT_BITFIELD)) {
8321 bit_pos = 0;
8322 bit_size = 32;
8323 bit_mask = -1LL;
8324 } else {
8325 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
8326 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
8327 bit_mask = (1LL << bit_size) - 1;
8329 if ((vtop->r & VT_SYM) &&
8330 (bt == VT_BYTE ||
8331 bt == VT_SHORT ||
8332 bt == VT_DOUBLE ||
8333 bt == VT_LDOUBLE ||
8334 bt == VT_LLONG ||
8335 (bt == VT_INT && bit_size != 32)))
8336 error("initializer element is not computable at load time");
8337 switch(bt) {
8338 case VT_BYTE:
8339 *(char *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8340 break;
8341 case VT_SHORT:
8342 *(short *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8343 break;
8344 case VT_DOUBLE:
8345 *(double *)ptr = vtop->c.d;
8346 break;
8347 case VT_LDOUBLE:
8348 *(long double *)ptr = vtop->c.ld;
8349 break;
8350 case VT_LLONG:
8351 *(long long *)ptr |= (vtop->c.ll & bit_mask) << bit_pos;
8352 break;
8353 default:
8354 if (vtop->r & VT_SYM) {
8355 greloc(sec, vtop->sym, c, R_DATA_32);
8357 *(int *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8358 break;
8360 vtop--;
8361 } else {
8362 vset(&dtype, VT_LOCAL, c);
8363 vswap();
8364 vstore();
8365 vpop();
8369 /* put zeros for variable based init */
8370 static void init_putz(CType *t, Section *sec, unsigned long c, int size)
8372 if (sec) {
8373 /* nothing to do because globals are already set to zero */
8374 } else {
8375 vpush_global_sym(&func_old_type, TOK_memset);
8376 vseti(VT_LOCAL, c);
8377 vpushi(0);
8378 vpushi(size);
8379 gfunc_call(3);
8383 /* 't' contains the type and storage info. 'c' is the offset of the
8384 object in section 'sec'. If 'sec' is NULL, it means stack based
8385 allocation. 'first' is true if array '{' must be read (multi
8386 dimension implicit array init handling). 'size_only' is true if
8387 size only evaluation is wanted (only for arrays). */
8388 static void decl_initializer(CType *type, Section *sec, unsigned long c,
8389 int first, int size_only)
8391 int index, array_length, n, no_oblock, nb, parlevel, i;
8392 int size1, align1, expr_type;
8393 Sym *s, *f;
8394 CType *t1;
8396 if (type->t & VT_ARRAY) {
8397 s = type->ref;
8398 n = s->c;
8399 array_length = 0;
8400 t1 = pointed_type(type);
8401 size1 = type_size(t1, &align1);
8403 no_oblock = 1;
8404 if ((first && tok != TOK_LSTR && tok != TOK_STR) ||
8405 tok == '{') {
8406 skip('{');
8407 no_oblock = 0;
8410 /* only parse strings here if correct type (otherwise: handle
8411 them as ((w)char *) expressions */
8412 if ((tok == TOK_LSTR &&
8413 (t1->t & VT_BTYPE) == VT_INT) ||
8414 (tok == TOK_STR &&
8415 (t1->t & VT_BTYPE) == VT_BYTE)) {
8416 while (tok == TOK_STR || tok == TOK_LSTR) {
8417 int cstr_len, ch;
8418 CString *cstr;
8420 cstr = tokc.cstr;
8421 /* compute maximum number of chars wanted */
8422 if (tok == TOK_STR)
8423 cstr_len = cstr->size;
8424 else
8425 cstr_len = cstr->size / sizeof(int);
8426 cstr_len--;
8427 nb = cstr_len;
8428 if (n >= 0 && nb > (n - array_length))
8429 nb = n - array_length;
8430 if (!size_only) {
8431 if (cstr_len > nb)
8432 warning("initializer-string for array is too long");
8433 /* in order to go faster for common case (char
8434 string in global variable, we handle it
8435 specifically */
8436 if (sec && tok == TOK_STR && size1 == 1) {
8437 memcpy(sec->data + c + array_length, cstr->data, nb);
8438 } else {
8439 for(i=0;i<nb;i++) {
8440 if (tok == TOK_STR)
8441 ch = ((unsigned char *)cstr->data)[i];
8442 else
8443 ch = ((int *)cstr->data)[i];
8444 init_putv(t1, sec, c + (array_length + i) * size1,
8445 ch, EXPR_VAL);
8449 array_length += nb;
8450 next();
8452 /* only add trailing zero if enough storage (no
8453 warning in this case since it is standard) */
8454 if (n < 0 || array_length < n) {
8455 if (!size_only) {
8456 init_putv(t1, sec, c + (array_length * size1), 0, EXPR_VAL);
8458 array_length++;
8460 } else {
8461 index = 0;
8462 while (tok != '}') {
8463 decl_designator(type, sec, c, &index, NULL, size_only);
8464 if (n >= 0 && index >= n)
8465 error("index too large");
8466 /* must put zero in holes (note that doing it that way
8467 ensures that it even works with designators) */
8468 if (!size_only && array_length < index) {
8469 init_putz(t1, sec, c + array_length * size1,
8470 (index - array_length) * size1);
8472 index++;
8473 if (index > array_length)
8474 array_length = index;
8475 /* special test for multi dimensional arrays (may not
8476 be strictly correct if designators are used at the
8477 same time) */
8478 if (index >= n && no_oblock)
8479 break;
8480 if (tok == '}')
8481 break;
8482 skip(',');
8485 if (!no_oblock)
8486 skip('}');
8487 /* put zeros at the end */
8488 if (!size_only && n >= 0 && array_length < n) {
8489 init_putz(t1, sec, c + array_length * size1,
8490 (n - array_length) * size1);
8492 /* patch type size if needed */
8493 if (n < 0)
8494 s->c = array_length;
8495 } else if ((type->t & VT_BTYPE) == VT_STRUCT &&
8496 (sec || !first || tok == '{')) {
8497 int par_count;
8499 /* NOTE: the previous test is a specific case for automatic
8500 struct/union init */
8501 /* XXX: union needs only one init */
8503 /* XXX: this test is incorrect for local initializers
8504 beginning with ( without {. It would be much more difficult
8505 to do it correctly (ideally, the expression parser should
8506 be used in all cases) */
8507 par_count = 0;
8508 if (tok == '(') {
8509 AttributeDef ad1;
8510 CType type1;
8511 next();
8512 while (tok == '(') {
8513 par_count++;
8514 next();
8516 if (!parse_btype(&type1, &ad1))
8517 expect("cast");
8518 type_decl(&type1, &ad1, &n, TYPE_ABSTRACT);
8519 #if 0
8520 if (!is_assignable_types(type, &type1))
8521 error("invalid type for cast");
8522 #endif
8523 skip(')');
8525 no_oblock = 1;
8526 if (first || tok == '{') {
8527 skip('{');
8528 no_oblock = 0;
8530 s = type->ref;
8531 f = s->next;
8532 array_length = 0;
8533 index = 0;
8534 n = s->c;
8535 while (tok != '}') {
8536 decl_designator(type, sec, c, NULL, &f, size_only);
8537 index = f->c;
8538 if (!size_only && array_length < index) {
8539 init_putz(type, sec, c + array_length,
8540 index - array_length);
8542 index = index + type_size(&f->type, &align1);
8543 if (index > array_length)
8544 array_length = index;
8545 f = f->next;
8546 if (no_oblock && f == NULL)
8547 break;
8548 if (tok == '}')
8549 break;
8550 skip(',');
8552 /* put zeros at the end */
8553 if (!size_only && array_length < n) {
8554 init_putz(type, sec, c + array_length,
8555 n - array_length);
8557 if (!no_oblock)
8558 skip('}');
8559 while (par_count) {
8560 skip(')');
8561 par_count--;
8563 } else if (tok == '{') {
8564 next();
8565 decl_initializer(type, sec, c, first, size_only);
8566 skip('}');
8567 } else if (size_only) {
8568 /* just skip expression */
8569 parlevel = 0;
8570 while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
8571 tok != -1) {
8572 if (tok == '(')
8573 parlevel++;
8574 else if (tok == ')')
8575 parlevel--;
8576 next();
8578 } else {
8579 /* currently, we always use constant expression for globals
8580 (may change for scripting case) */
8581 expr_type = EXPR_CONST;
8582 if (!sec)
8583 expr_type = EXPR_ANY;
8584 init_putv(type, sec, c, 0, expr_type);
8588 /* parse an initializer for type 't' if 'has_init' is non zero, and
8589 allocate space in local or global data space ('r' is either
8590 VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
8591 variable 'v' of scope 'scope' is declared before initializers are
8592 parsed. If 'v' is zero, then a reference to the new object is put
8593 in the value stack. If 'has_init' is 2, a special parsing is done
8594 to handle string constants. */
8595 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
8596 int has_init, int v, int scope)
8598 int size, align, addr, data_offset;
8599 int level;
8600 ParseState saved_parse_state;
8601 TokenString init_str;
8602 Section *sec;
8604 size = type_size(type, &align);
8605 /* If unknown size, we must evaluate it before
8606 evaluating initializers because
8607 initializers can generate global data too
8608 (e.g. string pointers or ISOC99 compound
8609 literals). It also simplifies local
8610 initializers handling */
8611 tok_str_new(&init_str);
8612 if (size < 0) {
8613 if (!has_init)
8614 error("unknown type size");
8615 /* get all init string */
8616 if (has_init == 2) {
8617 /* only get strings */
8618 while (tok == TOK_STR || tok == TOK_LSTR) {
8619 tok_str_add_tok(&init_str);
8620 next();
8622 } else {
8623 level = 0;
8624 while (level > 0 || (tok != ',' && tok != ';')) {
8625 if (tok < 0)
8626 error("unexpected end of file in initializer");
8627 tok_str_add_tok(&init_str);
8628 if (tok == '{')
8629 level++;
8630 else if (tok == '}') {
8631 if (level == 0)
8632 break;
8633 level--;
8635 next();
8638 tok_str_add(&init_str, -1);
8639 tok_str_add(&init_str, 0);
8641 /* compute size */
8642 save_parse_state(&saved_parse_state);
8644 macro_ptr = init_str.str;
8645 next();
8646 decl_initializer(type, NULL, 0, 1, 1);
8647 /* prepare second initializer parsing */
8648 macro_ptr = init_str.str;
8649 next();
8651 /* if still unknown size, error */
8652 size = type_size(type, &align);
8653 if (size < 0)
8654 error("unknown type size");
8656 /* take into account specified alignment if bigger */
8657 if (ad->aligned) {
8658 if (ad->aligned > align)
8659 align = ad->aligned;
8660 } else if (ad->packed) {
8661 align = 1;
8663 if ((r & VT_VALMASK) == VT_LOCAL) {
8664 sec = NULL;
8665 if (do_bounds_check && (type->t & VT_ARRAY))
8666 loc--;
8667 loc = (loc - size) & -align;
8668 addr = loc;
8669 /* handles bounds */
8670 /* XXX: currently, since we do only one pass, we cannot track
8671 '&' operators, so we add only arrays */
8672 if (do_bounds_check && (type->t & VT_ARRAY)) {
8673 unsigned long *bounds_ptr;
8674 /* add padding between regions */
8675 loc--;
8676 /* then add local bound info */
8677 bounds_ptr = section_ptr_add(lbounds_section, 2 * sizeof(unsigned long));
8678 bounds_ptr[0] = addr;
8679 bounds_ptr[1] = size;
8681 if (v) {
8682 /* local variable */
8683 sym_push(v, type, r, addr);
8684 } else {
8685 /* push local reference */
8686 vset(type, r, addr);
8688 } else {
8689 Sym *sym;
8691 sym = NULL;
8692 if (v && scope == VT_CONST) {
8693 /* see if the symbol was already defined */
8694 sym = sym_find(v);
8695 if (sym) {
8696 if (!is_compatible_types(&sym->type, type))
8697 error("incompatible types for redefinition of '%s'",
8698 get_tok_str(v, NULL));
8699 if (sym->type.t & VT_EXTERN) {
8700 /* if the variable is extern, it was not allocated */
8701 sym->type.t &= ~VT_EXTERN;
8702 /* set array size if it was ommited in extern
8703 declaration */
8704 if ((sym->type.t & VT_ARRAY) &&
8705 sym->type.ref->c < 0 &&
8706 type->ref->c >= 0)
8707 sym->type.ref->c = type->ref->c;
8708 } else {
8709 /* we accept several definitions of the same
8710 global variable. this is tricky, because we
8711 must play with the SHN_COMMON type of the symbol */
8712 /* XXX: should check if the variable was already
8713 initialized. It is incorrect to initialized it
8714 twice */
8715 /* no init data, we won't add more to the symbol */
8716 if (!has_init)
8717 goto no_alloc;
8722 /* allocate symbol in corresponding section */
8723 sec = ad->section;
8724 if (!sec) {
8725 if (has_init)
8726 sec = data_section;
8727 else if (tcc_state->nocommon)
8728 sec = bss_section;
8730 if (sec) {
8731 data_offset = sec->data_offset;
8732 data_offset = (data_offset + align - 1) & -align;
8733 addr = data_offset;
8734 /* very important to increment global pointer at this time
8735 because initializers themselves can create new initializers */
8736 data_offset += size;
8737 /* add padding if bound check */
8738 if (do_bounds_check)
8739 data_offset++;
8740 sec->data_offset = data_offset;
8741 /* allocate section space to put the data */
8742 if (sec->sh_type != SHT_NOBITS &&
8743 data_offset > sec->data_allocated)
8744 section_realloc(sec, data_offset);
8745 /* align section if needed */
8746 if (align > sec->sh_addralign)
8747 sec->sh_addralign = align;
8748 } else {
8749 addr = 0; /* avoid warning */
8752 if (v) {
8753 if (scope == VT_CONST) {
8754 if (!sym)
8755 goto do_def;
8756 } else {
8757 do_def:
8758 sym = sym_push(v, type, r | VT_SYM, 0);
8760 /* update symbol definition */
8761 if (sec) {
8762 put_extern_sym(sym, sec, addr, size);
8763 } else {
8764 Elf32_Sym *esym;
8765 /* put a common area */
8766 put_extern_sym(sym, NULL, align, size);
8767 /* XXX: find a nicer way */
8768 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
8769 esym->st_shndx = SHN_COMMON;
8771 } else {
8772 CValue cval;
8774 /* push global reference */
8775 sym = get_sym_ref(type, sec, addr, size);
8776 cval.ul = 0;
8777 vsetc(type, VT_CONST | VT_SYM, &cval);
8778 vtop->sym = sym;
8781 /* handles bounds now because the symbol must be defined
8782 before for the relocation */
8783 if (do_bounds_check) {
8784 unsigned long *bounds_ptr;
8786 greloc(bounds_section, sym, bounds_section->data_offset, R_DATA_32);
8787 /* then add global bound info */
8788 bounds_ptr = section_ptr_add(bounds_section, 2 * sizeof(long));
8789 bounds_ptr[0] = 0; /* relocated */
8790 bounds_ptr[1] = size;
8793 if (has_init) {
8794 decl_initializer(type, sec, addr, 1, 0);
8795 /* restore parse state if needed */
8796 if (init_str.str) {
8797 tok_str_free(init_str.str);
8798 restore_parse_state(&saved_parse_state);
8801 no_alloc: ;
8804 void put_func_debug(Sym *sym)
8806 char buf[512];
8808 /* stabs info */
8809 /* XXX: we put here a dummy type */
8810 snprintf(buf, sizeof(buf), "%s:%c1",
8811 funcname, sym->type.t & VT_STATIC ? 'f' : 'F');
8812 put_stabs_r(buf, N_FUN, 0, file->line_num, 0,
8813 cur_text_section, sym->c);
8814 last_ind = 0;
8815 last_line_num = 0;
8818 /* parse an old style function declaration list */
8819 /* XXX: check multiple parameter */
8820 static void func_decl_list(Sym *func_sym)
8822 AttributeDef ad;
8823 int v;
8824 Sym *s;
8825 CType btype, type;
8827 /* parse each declaration */
8828 while (tok != '{' && tok != ';' && tok != ',' && tok != TOK_EOF) {
8829 if (!parse_btype(&btype, &ad))
8830 expect("declaration list");
8831 if (((btype.t & VT_BTYPE) == VT_ENUM ||
8832 (btype.t & VT_BTYPE) == VT_STRUCT) &&
8833 tok == ';') {
8834 /* we accept no variable after */
8835 } else {
8836 for(;;) {
8837 type = btype;
8838 type_decl(&type, &ad, &v, TYPE_DIRECT);
8839 /* find parameter in function parameter list */
8840 s = func_sym->next;
8841 while (s != NULL) {
8842 if ((s->v & ~SYM_FIELD) == v)
8843 goto found;
8844 s = s->next;
8846 error("declaration for parameter '%s' but no such parameter",
8847 get_tok_str(v, NULL));
8848 found:
8849 /* check that no storage specifier except 'register' was given */
8850 if (type.t & VT_STORAGE)
8851 error("storage class specified for '%s'", get_tok_str(v, NULL));
8852 convert_parameter_type(&type);
8853 /* we can add the type (NOTE: it could be local to the function) */
8854 s->type = type;
8855 /* accept other parameters */
8856 if (tok == ',')
8857 next();
8858 else
8859 break;
8862 skip(';');
8866 /* parse a function defined by symbol 'sym' and generate its code in
8867 'cur_text_section' */
8868 static void gen_function(Sym *sym)
8870 ind = cur_text_section->data_offset;
8871 /* NOTE: we patch the symbol size later */
8872 put_extern_sym(sym, cur_text_section, ind, 0);
8873 funcname = get_tok_str(sym->v, NULL);
8874 func_ind = ind;
8875 /* put debug symbol */
8876 if (do_debug)
8877 put_func_debug(sym);
8878 /* push a dummy symbol to enable local sym storage */
8879 sym_push2(&local_stack, SYM_FIELD, 0, 0);
8880 gfunc_prolog(&sym->type);
8881 rsym = 0;
8882 block(NULL, NULL, NULL, NULL, 0, 0);
8883 gsym(rsym);
8884 gfunc_epilog();
8885 cur_text_section->data_offset = ind;
8886 label_pop(&global_label_stack, NULL);
8887 sym_pop(&local_stack, NULL); /* reset local stack */
8888 /* end of function */
8889 /* patch symbol size */
8890 ((Elf32_Sym *)symtab_section->data)[sym->c].st_size =
8891 ind - func_ind;
8892 if (do_debug) {
8893 put_stabn(N_FUN, 0, 0, ind - func_ind);
8895 funcname = ""; /* for safety */
8896 func_vt.t = VT_VOID; /* for safety */
8897 ind = 0; /* for safety */
8900 static void gen_inline_functions(void)
8902 Sym *sym;
8903 CType *type;
8904 int *str, inline_generated;
8906 /* iterate while inline function are referenced */
8907 for(;;) {
8908 inline_generated = 0;
8909 for(sym = global_stack; sym != NULL; sym = sym->prev) {
8910 type = &sym->type;
8911 if (((type->t & VT_BTYPE) == VT_FUNC) &&
8912 (type->t & (VT_STATIC | VT_INLINE)) ==
8913 (VT_STATIC | VT_INLINE) &&
8914 sym->c != 0) {
8915 /* the function was used: generate its code and
8916 convert it to a normal function */
8917 str = (int *)sym->r;
8918 sym->r = VT_SYM | VT_CONST;
8919 type->t &= ~VT_INLINE;
8921 macro_ptr = str;
8922 next();
8923 cur_text_section = text_section;
8924 gen_function(sym);
8925 macro_ptr = NULL; /* fail safe */
8927 tok_str_free(str);
8928 inline_generated = 1;
8931 if (!inline_generated)
8932 break;
8935 /* free all remaining inline function tokens */
8936 for(sym = global_stack; sym != NULL; sym = sym->prev) {
8937 type = &sym->type;
8938 if (((type->t & VT_BTYPE) == VT_FUNC) &&
8939 (type->t & (VT_STATIC | VT_INLINE)) ==
8940 (VT_STATIC | VT_INLINE)) {
8941 str = (int *)sym->r;
8942 tok_str_free(str);
8943 sym->r = 0; /* fail safe */
8948 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
8949 static void decl(int l)
8951 int v, has_init, r;
8952 CType type, btype;
8953 Sym *sym;
8954 AttributeDef ad;
8956 while (1) {
8957 if (!parse_btype(&btype, &ad)) {
8958 /* skip redundant ';' */
8959 /* XXX: find more elegant solution */
8960 if (tok == ';') {
8961 next();
8962 continue;
8964 if (l == VT_CONST &&
8965 (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3)) {
8966 /* global asm block */
8967 asm_global_instr();
8968 continue;
8970 /* special test for old K&R protos without explicit int
8971 type. Only accepted when defining global data */
8972 if (l == VT_LOCAL || tok < TOK_DEFINE)
8973 break;
8974 btype.t = VT_INT;
8976 if (((btype.t & VT_BTYPE) == VT_ENUM ||
8977 (btype.t & VT_BTYPE) == VT_STRUCT) &&
8978 tok == ';') {
8979 /* we accept no variable after */
8980 next();
8981 continue;
8983 while (1) { /* iterate thru each declaration */
8984 type = btype;
8985 type_decl(&type, &ad, &v, TYPE_DIRECT);
8986 #if 0
8988 char buf[500];
8989 type_to_str(buf, sizeof(buf), t, get_tok_str(v, NULL));
8990 printf("type = '%s'\n", buf);
8992 #endif
8993 if ((type.t & VT_BTYPE) == VT_FUNC) {
8994 /* if old style function prototype, we accept a
8995 declaration list */
8996 sym = type.ref;
8997 if (sym->c == FUNC_OLD)
8998 func_decl_list(sym);
9001 if (tok == '{') {
9002 if (l == VT_LOCAL)
9003 error("cannot use local functions");
9004 if (!(type.t & VT_FUNC))
9005 expect("function definition");
9007 /* reject abstract declarators in function definition */
9008 sym = type.ref;
9009 while ((sym = sym->next) != NULL)
9010 if (!(sym->v & ~SYM_FIELD))
9011 expect("identifier");
9013 /* XXX: cannot do better now: convert extern line to static inline */
9014 if ((type.t & (VT_EXTERN | VT_INLINE)) == (VT_EXTERN | VT_INLINE))
9015 type.t = (type.t & ~VT_EXTERN) | VT_STATIC;
9017 sym = sym_find(v);
9018 if (sym) {
9019 if ((sym->type.t & VT_BTYPE) != VT_FUNC)
9020 goto func_error1;
9021 /* specific case: if not func_call defined, we put
9022 the one of the prototype */
9023 /* XXX: should have default value */
9024 if (sym->type.ref->r != FUNC_CDECL &&
9025 type.ref->r == FUNC_CDECL)
9026 type.ref->r = sym->type.ref->r;
9027 if (!is_compatible_types(&sym->type, &type)) {
9028 func_error1:
9029 error("incompatible types for redefinition of '%s'",
9030 get_tok_str(v, NULL));
9032 /* if symbol is already defined, then put complete type */
9033 sym->type = type;
9034 } else {
9035 /* put function symbol */
9036 sym = global_identifier_push(v, type.t, 0);
9037 sym->type.ref = type.ref;
9040 /* static inline functions are just recorded as a kind
9041 of macro. Their code will be emitted at the end of
9042 the compilation unit only if they are used */
9043 if ((type.t & (VT_INLINE | VT_STATIC)) ==
9044 (VT_INLINE | VT_STATIC)) {
9045 TokenString func_str;
9046 int block_level;
9048 tok_str_new(&func_str);
9050 block_level = 0;
9051 for(;;) {
9052 int t;
9053 if (tok == TOK_EOF)
9054 error("unexpected end of file");
9055 tok_str_add_tok(&func_str);
9056 t = tok;
9057 next();
9058 if (t == '{') {
9059 block_level++;
9060 } else if (t == '}') {
9061 block_level--;
9062 if (block_level == 0)
9063 break;
9066 tok_str_add(&func_str, -1);
9067 tok_str_add(&func_str, 0);
9068 sym->r = (int)func_str.str;
9069 } else {
9070 /* compute text section */
9071 cur_text_section = ad.section;
9072 if (!cur_text_section)
9073 cur_text_section = text_section;
9074 sym->r = VT_SYM | VT_CONST;
9075 gen_function(sym);
9076 #ifdef TCC_TARGET_PE
9077 if (ad.dllexport) {
9078 ((Elf32_Sym *)symtab_section->data)[sym->c].st_other |= 1;
9080 #endif
9082 break;
9083 } else {
9084 if (btype.t & VT_TYPEDEF) {
9085 /* save typedefed type */
9086 /* XXX: test storage specifiers ? */
9087 sym = sym_push(v, &type, 0, 0);
9088 sym->type.t |= VT_TYPEDEF;
9089 } else if ((type.t & VT_BTYPE) == VT_FUNC) {
9090 /* external function definition */
9091 /* specific case for func_call attribute */
9092 if (ad.func_call)
9093 type.ref->r = ad.func_call;
9094 external_sym(v, &type, 0);
9095 } else {
9096 /* not lvalue if array */
9097 r = 0;
9098 if (!(type.t & VT_ARRAY))
9099 r |= lvalue_type(type.t);
9100 has_init = (tok == '=');
9101 if ((btype.t & VT_EXTERN) ||
9102 ((type.t & VT_ARRAY) && (type.t & VT_STATIC) &&
9103 !has_init && l == VT_CONST && type.ref->c < 0)) {
9104 /* external variable */
9105 /* NOTE: as GCC, uninitialized global static
9106 arrays of null size are considered as
9107 extern */
9108 external_sym(v, &type, r);
9109 } else {
9110 if (type.t & VT_STATIC)
9111 r |= VT_CONST;
9112 else
9113 r |= l;
9114 if (has_init)
9115 next();
9116 decl_initializer_alloc(&type, &ad, r,
9117 has_init, v, l);
9120 if (tok != ',') {
9121 skip(';');
9122 break;
9124 next();
9130 /* better than nothing, but needs extension to handle '-E' option
9131 correctly too */
9132 static void preprocess_init(TCCState *s1)
9134 s1->include_stack_ptr = s1->include_stack;
9135 /* XXX: move that before to avoid having to initialize
9136 file->ifdef_stack_ptr ? */
9137 s1->ifdef_stack_ptr = s1->ifdef_stack;
9138 file->ifdef_stack_ptr = s1->ifdef_stack_ptr;
9140 /* XXX: not ANSI compliant: bound checking says error */
9141 vtop = vstack - 1;
9142 s1->pack_stack[0] = 0;
9143 s1->pack_stack_ptr = s1->pack_stack;
9146 /* compile the C file opened in 'file'. Return non zero if errors. */
9147 static int tcc_compile(TCCState *s1)
9149 Sym *define_start;
9150 char buf[512];
9151 volatile int section_sym;
9153 #ifdef INC_DEBUG
9154 printf("%s: **** new file\n", file->filename);
9155 #endif
9156 preprocess_init(s1);
9158 funcname = "";
9159 anon_sym = SYM_FIRST_ANOM;
9161 /* file info: full path + filename */
9162 section_sym = 0; /* avoid warning */
9163 if (do_debug) {
9164 section_sym = put_elf_sym(symtab_section, 0, 0,
9165 ELF32_ST_INFO(STB_LOCAL, STT_SECTION), 0,
9166 text_section->sh_num, NULL);
9167 getcwd(buf, sizeof(buf));
9168 pstrcat(buf, sizeof(buf), "/");
9169 put_stabs_r(buf, N_SO, 0, 0,
9170 text_section->data_offset, text_section, section_sym);
9171 put_stabs_r(file->filename, N_SO, 0, 0,
9172 text_section->data_offset, text_section, section_sym);
9174 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
9175 symbols can be safely used */
9176 put_elf_sym(symtab_section, 0, 0,
9177 ELF32_ST_INFO(STB_LOCAL, STT_FILE), 0,
9178 SHN_ABS, file->filename);
9180 /* define some often used types */
9181 int_type.t = VT_INT;
9183 char_pointer_type.t = VT_BYTE;
9184 mk_pointer(&char_pointer_type);
9186 func_old_type.t = VT_FUNC;
9187 func_old_type.ref = sym_push(SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD);
9189 #if 0
9190 /* define 'void *alloca(unsigned int)' builtin function */
9192 Sym *s1;
9194 p = anon_sym++;
9195 sym = sym_push(p, mk_pointer(VT_VOID), FUNC_CDECL, FUNC_NEW);
9196 s1 = sym_push(SYM_FIELD, VT_UNSIGNED | VT_INT, 0, 0);
9197 s1->next = NULL;
9198 sym->next = s1;
9199 sym_push(TOK_alloca, VT_FUNC | (p << VT_STRUCT_SHIFT), VT_CONST, 0);
9201 #endif
9203 define_start = define_stack;
9205 if (setjmp(s1->error_jmp_buf) == 0) {
9206 s1->nb_errors = 0;
9207 s1->error_set_jmp_enabled = 1;
9209 ch = file->buf_ptr[0];
9210 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
9211 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM;
9212 next();
9213 decl(VT_CONST);
9214 if (tok != TOK_EOF)
9215 expect("declaration");
9217 /* end of translation unit info */
9218 if (do_debug) {
9219 put_stabs_r(NULL, N_SO, 0, 0,
9220 text_section->data_offset, text_section, section_sym);
9223 s1->error_set_jmp_enabled = 0;
9225 /* reset define stack, but leave -Dsymbols (may be incorrect if
9226 they are undefined) */
9227 free_defines(define_start);
9229 gen_inline_functions();
9231 sym_pop(&global_stack, NULL);
9233 return s1->nb_errors != 0 ? -1 : 0;
9236 #ifdef LIBTCC
9237 int tcc_compile_string(TCCState *s, const char *str)
9239 BufferedFile bf1, *bf = &bf1;
9240 int ret, len;
9241 char *buf;
9243 /* init file structure */
9244 bf->fd = -1;
9245 /* XXX: avoid copying */
9246 len = strlen(str);
9247 buf = tcc_malloc(len + 1);
9248 if (!buf)
9249 return -1;
9250 memcpy(buf, str, len);
9251 buf[len] = CH_EOB;
9252 bf->buf_ptr = buf;
9253 bf->buf_end = buf + len;
9254 pstrcpy(bf->filename, sizeof(bf->filename), "<string>");
9255 bf->line_num = 1;
9256 file = bf;
9258 ret = tcc_compile(s);
9260 tcc_free(buf);
9262 /* currently, no need to close */
9263 return ret;
9265 #endif
9267 /* define a preprocessor symbol. A value can also be provided with the '=' operator */
9268 void tcc_define_symbol(TCCState *s1, const char *sym, const char *value)
9270 BufferedFile bf1, *bf = &bf1;
9272 pstrcpy(bf->buffer, IO_BUF_SIZE, sym);
9273 pstrcat(bf->buffer, IO_BUF_SIZE, " ");
9274 /* default value */
9275 if (!value)
9276 value = "1";
9277 pstrcat(bf->buffer, IO_BUF_SIZE, value);
9279 /* init file structure */
9280 bf->fd = -1;
9281 bf->buf_ptr = bf->buffer;
9282 bf->buf_end = bf->buffer + strlen(bf->buffer);
9283 *bf->buf_end = CH_EOB;
9284 bf->filename[0] = '\0';
9285 bf->line_num = 1;
9286 file = bf;
9288 s1->include_stack_ptr = s1->include_stack;
9290 /* parse with define parser */
9291 ch = file->buf_ptr[0];
9292 next_nomacro();
9293 parse_define();
9294 file = NULL;
9297 /* undefine a preprocessor symbol */
9298 void tcc_undefine_symbol(TCCState *s1, const char *sym)
9300 TokenSym *ts;
9301 Sym *s;
9302 ts = tok_alloc(sym, strlen(sym));
9303 s = define_find(ts->tok);
9304 /* undefine symbol by putting an invalid name */
9305 if (s)
9306 define_undef(s);
9309 #ifdef CONFIG_TCC_ASM
9311 #ifdef TCC_TARGET_I386
9312 #include "i386-asm.c"
9313 #endif
9314 #include "tccasm.c"
9316 #else
9317 static void asm_instr(void)
9319 error("inline asm() not supported");
9321 static void asm_global_instr(void)
9323 error("inline asm() not supported");
9325 #endif
9327 #include "tccelf.c"
9329 #ifdef TCC_TARGET_COFF
9330 #include "tcccoff.c"
9331 #endif
9333 #ifdef TCC_TARGET_PE
9334 #include "tccpe.c"
9335 #endif
9337 /* print the position in the source file of PC value 'pc' by reading
9338 the stabs debug information */
9339 static void rt_printline(unsigned long wanted_pc)
9341 Stab_Sym *sym, *sym_end;
9342 char func_name[128], last_func_name[128];
9343 unsigned long func_addr, last_pc, pc;
9344 const char *incl_files[INCLUDE_STACK_SIZE];
9345 int incl_index, len, last_line_num, i;
9346 const char *str, *p;
9348 fprintf(stderr, "0x%08lx:", wanted_pc);
9350 func_name[0] = '\0';
9351 func_addr = 0;
9352 incl_index = 0;
9353 last_func_name[0] = '\0';
9354 last_pc = 0xffffffff;
9355 last_line_num = 1;
9356 sym = (Stab_Sym *)stab_section->data + 1;
9357 sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset);
9358 while (sym < sym_end) {
9359 switch(sym->n_type) {
9360 /* function start or end */
9361 case N_FUN:
9362 if (sym->n_strx == 0) {
9363 /* we test if between last line and end of function */
9364 pc = sym->n_value + func_addr;
9365 if (wanted_pc >= last_pc && wanted_pc < pc)
9366 goto found;
9367 func_name[0] = '\0';
9368 func_addr = 0;
9369 } else {
9370 str = stabstr_section->data + sym->n_strx;
9371 p = strchr(str, ':');
9372 if (!p) {
9373 pstrcpy(func_name, sizeof(func_name), str);
9374 } else {
9375 len = p - str;
9376 if (len > sizeof(func_name) - 1)
9377 len = sizeof(func_name) - 1;
9378 memcpy(func_name, str, len);
9379 func_name[len] = '\0';
9381 func_addr = sym->n_value;
9383 break;
9384 /* line number info */
9385 case N_SLINE:
9386 pc = sym->n_value + func_addr;
9387 if (wanted_pc >= last_pc && wanted_pc < pc)
9388 goto found;
9389 last_pc = pc;
9390 last_line_num = sym->n_desc;
9391 /* XXX: slow! */
9392 strcpy(last_func_name, func_name);
9393 break;
9394 /* include files */
9395 case N_BINCL:
9396 str = stabstr_section->data + sym->n_strx;
9397 add_incl:
9398 if (incl_index < INCLUDE_STACK_SIZE) {
9399 incl_files[incl_index++] = str;
9401 break;
9402 case N_EINCL:
9403 if (incl_index > 1)
9404 incl_index--;
9405 break;
9406 case N_SO:
9407 if (sym->n_strx == 0) {
9408 incl_index = 0; /* end of translation unit */
9409 } else {
9410 str = stabstr_section->data + sym->n_strx;
9411 /* do not add path */
9412 len = strlen(str);
9413 if (len > 0 && str[len - 1] != '/')
9414 goto add_incl;
9416 break;
9418 sym++;
9421 /* second pass: we try symtab symbols (no line number info) */
9422 incl_index = 0;
9424 Elf32_Sym *sym, *sym_end;
9425 int type;
9427 sym_end = (Elf32_Sym *)(symtab_section->data + symtab_section->data_offset);
9428 for(sym = (Elf32_Sym *)symtab_section->data + 1;
9429 sym < sym_end;
9430 sym++) {
9431 type = ELF32_ST_TYPE(sym->st_info);
9432 if (type == STT_FUNC) {
9433 if (wanted_pc >= sym->st_value &&
9434 wanted_pc < sym->st_value + sym->st_size) {
9435 pstrcpy(last_func_name, sizeof(last_func_name),
9436 strtab_section->data + sym->st_name);
9437 goto found;
9442 /* did not find any info: */
9443 fprintf(stderr, " ???\n");
9444 return;
9445 found:
9446 if (last_func_name[0] != '\0') {
9447 fprintf(stderr, " %s()", last_func_name);
9449 if (incl_index > 0) {
9450 fprintf(stderr, " (%s:%d",
9451 incl_files[incl_index - 1], last_line_num);
9452 for(i = incl_index - 2; i >= 0; i--)
9453 fprintf(stderr, ", included from %s", incl_files[i]);
9454 fprintf(stderr, ")");
9456 fprintf(stderr, "\n");
9459 #if !defined(WIN32) && !defined(CONFIG_TCCBOOT)
9461 #ifdef __i386__
9463 /* fix for glibc 2.1 */
9464 #ifndef REG_EIP
9465 #define REG_EIP EIP
9466 #define REG_EBP EBP
9467 #endif
9469 /* return the PC at frame level 'level'. Return non zero if not found */
9470 static int rt_get_caller_pc(unsigned long *paddr,
9471 ucontext_t *uc, int level)
9473 unsigned long fp;
9474 int i;
9476 if (level == 0) {
9477 #if defined(__FreeBSD__)
9478 *paddr = uc->uc_mcontext.mc_eip;
9479 #elif defined(__dietlibc__)
9480 *paddr = uc->uc_mcontext.eip;
9481 #else
9482 *paddr = uc->uc_mcontext.gregs[REG_EIP];
9483 #endif
9484 return 0;
9485 } else {
9486 #if defined(__FreeBSD__)
9487 fp = uc->uc_mcontext.mc_ebp;
9488 #elif defined(__dietlibc__)
9489 fp = uc->uc_mcontext.ebp;
9490 #else
9491 fp = uc->uc_mcontext.gregs[REG_EBP];
9492 #endif
9493 for(i=1;i<level;i++) {
9494 /* XXX: check address validity with program info */
9495 if (fp <= 0x1000 || fp >= 0xc0000000)
9496 return -1;
9497 fp = ((unsigned long *)fp)[0];
9499 *paddr = ((unsigned long *)fp)[1];
9500 return 0;
9503 #else
9505 #warning add arch specific rt_get_caller_pc()
9507 static int rt_get_caller_pc(unsigned long *paddr,
9508 ucontext_t *uc, int level)
9510 return -1;
9512 #endif
9514 /* emit a run time error at position 'pc' */
9515 void rt_error(ucontext_t *uc, const char *fmt, ...)
9517 va_list ap;
9518 unsigned long pc;
9519 int i;
9521 va_start(ap, fmt);
9522 fprintf(stderr, "Runtime error: ");
9523 vfprintf(stderr, fmt, ap);
9524 fprintf(stderr, "\n");
9525 for(i=0;i<num_callers;i++) {
9526 if (rt_get_caller_pc(&pc, uc, i) < 0)
9527 break;
9528 if (i == 0)
9529 fprintf(stderr, "at ");
9530 else
9531 fprintf(stderr, "by ");
9532 rt_printline(pc);
9534 exit(255);
9535 va_end(ap);
9538 /* signal handler for fatal errors */
9539 static void sig_error(int signum, siginfo_t *siginf, void *puc)
9541 ucontext_t *uc = puc;
9543 switch(signum) {
9544 case SIGFPE:
9545 switch(siginf->si_code) {
9546 case FPE_INTDIV:
9547 case FPE_FLTDIV:
9548 rt_error(uc, "division by zero");
9549 break;
9550 default:
9551 rt_error(uc, "floating point exception");
9552 break;
9554 break;
9555 case SIGBUS:
9556 case SIGSEGV:
9557 if (rt_bound_error_msg && *rt_bound_error_msg)
9558 rt_error(uc, *rt_bound_error_msg);
9559 else
9560 rt_error(uc, "dereferencing invalid pointer");
9561 break;
9562 case SIGILL:
9563 rt_error(uc, "illegal instruction");
9564 break;
9565 case SIGABRT:
9566 rt_error(uc, "abort() called");
9567 break;
9568 default:
9569 rt_error(uc, "caught signal %d", signum);
9570 break;
9572 exit(255);
9574 #endif
9576 /* do all relocations (needed before using tcc_get_symbol()) */
9577 int tcc_relocate(TCCState *s1)
9579 Section *s;
9580 int i;
9582 s1->nb_errors = 0;
9584 #ifdef TCC_TARGET_PE
9585 pe_add_runtime(s1);
9586 #else
9587 tcc_add_runtime(s1);
9588 #endif
9590 relocate_common_syms();
9592 tcc_add_linker_symbols(s1);
9594 build_got_entries(s1);
9596 /* compute relocation address : section are relocated in place. We
9597 also alloc the bss space */
9598 for(i = 1; i < s1->nb_sections; i++) {
9599 s = s1->sections[i];
9600 if (s->sh_flags & SHF_ALLOC) {
9601 if (s->sh_type == SHT_NOBITS)
9602 s->data = tcc_mallocz(s->data_offset);
9603 s->sh_addr = (unsigned long)s->data;
9607 relocate_syms(s1, 1);
9609 if (s1->nb_errors != 0)
9610 return -1;
9612 /* relocate each section */
9613 for(i = 1; i < s1->nb_sections; i++) {
9614 s = s1->sections[i];
9615 if (s->reloc)
9616 relocate_section(s1, s);
9618 return 0;
9621 /* launch the compiled program with the given arguments */
9622 int tcc_run(TCCState *s1, int argc, char **argv)
9624 int (*prog_main)(int, char **);
9626 if (tcc_relocate(s1) < 0)
9627 return -1;
9629 prog_main = tcc_get_symbol_err(s1, "main");
9631 if (do_debug) {
9632 #if defined(WIN32) || defined(CONFIG_TCCBOOT)
9633 error("debug mode currently not available for Windows");
9634 #else
9635 struct sigaction sigact;
9636 /* install TCC signal handlers to print debug info on fatal
9637 runtime errors */
9638 sigact.sa_flags = SA_SIGINFO | SA_RESETHAND;
9639 sigact.sa_sigaction = sig_error;
9640 sigemptyset(&sigact.sa_mask);
9641 sigaction(SIGFPE, &sigact, NULL);
9642 sigaction(SIGILL, &sigact, NULL);
9643 sigaction(SIGSEGV, &sigact, NULL);
9644 sigaction(SIGBUS, &sigact, NULL);
9645 sigaction(SIGABRT, &sigact, NULL);
9646 #endif
9649 #ifdef CONFIG_TCC_BCHECK
9650 if (do_bounds_check) {
9651 void (*bound_init)(void);
9653 /* set error function */
9654 rt_bound_error_msg = (void *)tcc_get_symbol_err(s1,
9655 "__bound_error_msg");
9657 /* XXX: use .init section so that it also work in binary ? */
9658 bound_init = (void *)tcc_get_symbol_err(s1, "__bound_init");
9659 bound_init();
9661 #endif
9662 return (*prog_main)(argc, argv);
9665 TCCState *tcc_new(void)
9667 const char *p, *r;
9668 TCCState *s;
9669 TokenSym *ts;
9670 int i, c;
9672 s = tcc_mallocz(sizeof(TCCState));
9673 if (!s)
9674 return NULL;
9675 tcc_state = s;
9676 s->output_type = TCC_OUTPUT_MEMORY;
9678 /* init isid table */
9679 for(i=0;i<256;i++)
9680 isidnum_table[i] = isid(i) || isnum(i);
9682 /* add all tokens */
9683 table_ident = NULL;
9684 memset(hash_ident, 0, TOK_HASH_SIZE * sizeof(TokenSym *));
9686 tok_ident = TOK_IDENT;
9687 p = tcc_keywords;
9688 while (*p) {
9689 r = p;
9690 for(;;) {
9691 c = *r++;
9692 if (c == '\0')
9693 break;
9695 ts = tok_alloc(p, r - p - 1);
9696 p = r;
9699 /* we add dummy defines for some special macros to speed up tests
9700 and to have working defined() */
9701 define_push(TOK___LINE__, MACRO_OBJ, NULL, NULL);
9702 define_push(TOK___FILE__, MACRO_OBJ, NULL, NULL);
9703 define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL);
9704 define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL);
9706 /* standard defines */
9707 tcc_define_symbol(s, "__STDC__", NULL);
9708 #if defined(TCC_TARGET_I386)
9709 tcc_define_symbol(s, "__i386__", NULL);
9710 #endif
9711 #if defined(TCC_TARGET_ARM)
9712 tcc_define_symbol(s, "__ARM_ARCH_4__", NULL);
9713 tcc_define_symbol(s, "__arm_elf__", NULL);
9714 tcc_define_symbol(s, "__arm_elf", NULL);
9715 tcc_define_symbol(s, "arm_elf", NULL);
9716 tcc_define_symbol(s, "__arm__", NULL);
9717 tcc_define_symbol(s, "__arm", NULL);
9718 tcc_define_symbol(s, "arm", NULL);
9719 tcc_define_symbol(s, "__APCS_32__", NULL);
9720 #endif
9721 #if defined(linux)
9722 tcc_define_symbol(s, "__linux__", NULL);
9723 tcc_define_symbol(s, "linux", NULL);
9724 #endif
9725 /* tiny C specific defines */
9726 tcc_define_symbol(s, "__TINYC__", NULL);
9728 /* tiny C & gcc defines */
9729 tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned int");
9730 tcc_define_symbol(s, "__PTRDIFF_TYPE__", "int");
9731 tcc_define_symbol(s, "__WCHAR_TYPE__", "int");
9733 /* default library paths */
9734 #ifdef TCC_TARGET_PE
9736 char buf[1024];
9737 snprintf(buf, sizeof(buf), "%s/lib", tcc_lib_path);
9738 tcc_add_library_path(s, buf);
9740 #else
9741 tcc_add_library_path(s, "/usr/local/lib");
9742 tcc_add_library_path(s, "/usr/lib");
9743 tcc_add_library_path(s, "/lib");
9744 #endif
9746 /* no section zero */
9747 dynarray_add((void ***)&s->sections, &s->nb_sections, NULL);
9749 /* create standard sections */
9750 text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
9751 data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
9752 bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
9754 /* symbols are always generated for linking stage */
9755 symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0,
9756 ".strtab",
9757 ".hashtab", SHF_PRIVATE);
9758 strtab_section = symtab_section->link;
9760 /* private symbol table for dynamic symbols */
9761 s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE,
9762 ".dynstrtab",
9763 ".dynhashtab", SHF_PRIVATE);
9764 s->alacarte_link = 1;
9766 #ifdef CHAR_IS_UNSIGNED
9767 s->char_is_unsigned = 1;
9768 #endif
9769 #if defined(TCC_TARGET_PE) && 0
9770 /* XXX: currently the PE linker is not ready to support that */
9771 s->leading_underscore = 1;
9772 #endif
9773 return s;
9776 void tcc_delete(TCCState *s1)
9778 int i, n;
9780 /* free -D defines */
9781 free_defines(NULL);
9783 /* free tokens */
9784 n = tok_ident - TOK_IDENT;
9785 for(i = 0; i < n; i++)
9786 tcc_free(table_ident[i]);
9787 tcc_free(table_ident);
9789 /* free all sections */
9791 free_section(symtab_section->hash);
9793 free_section(s1->dynsymtab_section->hash);
9794 free_section(s1->dynsymtab_section->link);
9795 free_section(s1->dynsymtab_section);
9797 for(i = 1; i < s1->nb_sections; i++)
9798 free_section(s1->sections[i]);
9799 tcc_free(s1->sections);
9801 /* free loaded dlls array */
9802 for(i = 0; i < s1->nb_loaded_dlls; i++)
9803 tcc_free(s1->loaded_dlls[i]);
9804 tcc_free(s1->loaded_dlls);
9806 /* library paths */
9807 for(i = 0; i < s1->nb_library_paths; i++)
9808 tcc_free(s1->library_paths[i]);
9809 tcc_free(s1->library_paths);
9811 /* cached includes */
9812 for(i = 0; i < s1->nb_cached_includes; i++)
9813 tcc_free(s1->cached_includes[i]);
9814 tcc_free(s1->cached_includes);
9816 for(i = 0; i < s1->nb_include_paths; i++)
9817 tcc_free(s1->include_paths[i]);
9818 tcc_free(s1->include_paths);
9820 for(i = 0; i < s1->nb_sysinclude_paths; i++)
9821 tcc_free(s1->sysinclude_paths[i]);
9822 tcc_free(s1->sysinclude_paths);
9824 tcc_free(s1);
9827 int tcc_add_include_path(TCCState *s1, const char *pathname)
9829 char *pathname1;
9831 pathname1 = tcc_strdup(pathname);
9832 dynarray_add((void ***)&s1->include_paths, &s1->nb_include_paths, pathname1);
9833 return 0;
9836 int tcc_add_sysinclude_path(TCCState *s1, const char *pathname)
9838 char *pathname1;
9840 pathname1 = tcc_strdup(pathname);
9841 dynarray_add((void ***)&s1->sysinclude_paths, &s1->nb_sysinclude_paths, pathname1);
9842 return 0;
9845 static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
9847 const char *ext, *filename1;
9848 Elf32_Ehdr ehdr;
9849 int fd, ret;
9850 BufferedFile *saved_file;
9852 /* find source file type with extension */
9853 filename1 = strrchr(filename, '/');
9854 if (filename1)
9855 filename1++;
9856 else
9857 filename1 = filename;
9858 ext = strrchr(filename1, '.');
9859 if (ext)
9860 ext++;
9862 /* open the file */
9863 saved_file = file;
9864 file = tcc_open(s1, filename);
9865 if (!file) {
9866 if (flags & AFF_PRINT_ERROR) {
9867 error_noabort("file '%s' not found", filename);
9869 ret = -1;
9870 goto fail1;
9873 if (!ext || !strcmp(ext, "c")) {
9874 /* C file assumed */
9875 ret = tcc_compile(s1);
9876 } else
9877 #ifdef CONFIG_TCC_ASM
9878 if (!strcmp(ext, "S")) {
9879 /* preprocessed assembler */
9880 ret = tcc_assemble(s1, 1);
9881 } else if (!strcmp(ext, "s")) {
9882 /* non preprocessed assembler */
9883 ret = tcc_assemble(s1, 0);
9884 } else
9885 #endif
9886 #ifdef TCC_TARGET_PE
9887 if (!strcmp(ext, "def")) {
9888 ret = pe_load_def_file(s1, fdopen(file->fd, "rb"));
9889 } else
9890 #endif
9892 fd = file->fd;
9893 /* assume executable format: auto guess file type */
9894 ret = read(fd, &ehdr, sizeof(ehdr));
9895 lseek(fd, 0, SEEK_SET);
9896 if (ret <= 0) {
9897 error_noabort("could not read header");
9898 goto fail;
9899 } else if (ret != sizeof(ehdr)) {
9900 goto try_load_script;
9903 if (ehdr.e_ident[0] == ELFMAG0 &&
9904 ehdr.e_ident[1] == ELFMAG1 &&
9905 ehdr.e_ident[2] == ELFMAG2 &&
9906 ehdr.e_ident[3] == ELFMAG3) {
9907 file->line_num = 0; /* do not display line number if error */
9908 if (ehdr.e_type == ET_REL) {
9909 ret = tcc_load_object_file(s1, fd, 0);
9910 } else if (ehdr.e_type == ET_DYN) {
9911 if (s1->output_type == TCC_OUTPUT_MEMORY) {
9912 #ifdef TCC_TARGET_PE
9913 ret = -1;
9914 #else
9915 void *h;
9916 h = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY);
9917 if (h)
9918 ret = 0;
9919 else
9920 ret = -1;
9921 #endif
9922 } else {
9923 ret = tcc_load_dll(s1, fd, filename,
9924 (flags & AFF_REFERENCED_DLL) != 0);
9926 } else {
9927 error_noabort("unrecognized ELF file");
9928 goto fail;
9930 } else if (memcmp((char *)&ehdr, ARMAG, 8) == 0) {
9931 file->line_num = 0; /* do not display line number if error */
9932 ret = tcc_load_archive(s1, fd);
9933 } else
9934 #ifdef TCC_TARGET_COFF
9935 if (*(uint16_t *)(&ehdr) == COFF_C67_MAGIC) {
9936 ret = tcc_load_coff(s1, fd);
9937 } else
9938 #endif
9940 /* as GNU ld, consider it is an ld script if not recognized */
9941 try_load_script:
9942 ret = tcc_load_ldscript(s1);
9943 if (ret < 0) {
9944 error_noabort("unrecognized file type");
9945 goto fail;
9949 the_end:
9950 tcc_close(file);
9951 fail1:
9952 file = saved_file;
9953 return ret;
9954 fail:
9955 ret = -1;
9956 goto the_end;
9959 int tcc_add_file(TCCState *s, const char *filename)
9961 return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR);
9964 int tcc_add_library_path(TCCState *s, const char *pathname)
9966 char *pathname1;
9968 pathname1 = tcc_strdup(pathname);
9969 dynarray_add((void ***)&s->library_paths, &s->nb_library_paths, pathname1);
9970 return 0;
9973 /* find and load a dll. Return non zero if not found */
9974 /* XXX: add '-rpath' option support ? */
9975 static int tcc_add_dll(TCCState *s, const char *filename, int flags)
9977 char buf[1024];
9978 int i;
9980 for(i = 0; i < s->nb_library_paths; i++) {
9981 snprintf(buf, sizeof(buf), "%s/%s",
9982 s->library_paths[i], filename);
9983 if (tcc_add_file_internal(s, buf, flags) == 0)
9984 return 0;
9986 return -1;
9989 /* the library name is the same as the argument of the '-l' option */
9990 int tcc_add_library(TCCState *s, const char *libraryname)
9992 char buf[1024];
9993 int i;
9995 /* first we look for the dynamic library if not static linking */
9996 if (!s->static_link) {
9997 #ifdef TCC_TARGET_PE
9998 snprintf(buf, sizeof(buf), "%s.def", libraryname);
9999 #else
10000 snprintf(buf, sizeof(buf), "lib%s.so", libraryname);
10001 #endif
10002 if (tcc_add_dll(s, buf, 0) == 0)
10003 return 0;
10006 /* then we look for the static library */
10007 for(i = 0; i < s->nb_library_paths; i++) {
10008 snprintf(buf, sizeof(buf), "%s/lib%s.a",
10009 s->library_paths[i], libraryname);
10010 if (tcc_add_file_internal(s, buf, 0) == 0)
10011 return 0;
10013 return -1;
10016 int tcc_add_symbol(TCCState *s, const char *name, unsigned long val)
10018 add_elf_sym(symtab_section, val, 0,
10019 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
10020 SHN_ABS, name);
10021 return 0;
10024 int tcc_set_output_type(TCCState *s, int output_type)
10026 s->output_type = output_type;
10028 if (!s->nostdinc) {
10029 char buf[1024];
10031 /* default include paths */
10032 /* XXX: reverse order needed if -isystem support */
10033 #ifndef TCC_TARGET_PE
10034 tcc_add_sysinclude_path(s, "/usr/local/include");
10035 tcc_add_sysinclude_path(s, "/usr/include");
10036 #endif
10037 snprintf(buf, sizeof(buf), "%s/include", tcc_lib_path);
10038 tcc_add_sysinclude_path(s, buf);
10039 #ifdef TCC_TARGET_PE
10040 snprintf(buf, sizeof(buf), "%s/include/winapi", tcc_lib_path);
10041 tcc_add_sysinclude_path(s, buf);
10042 #endif
10045 /* if bound checking, then add corresponding sections */
10046 #ifdef CONFIG_TCC_BCHECK
10047 if (do_bounds_check) {
10048 /* define symbol */
10049 tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL);
10050 /* create bounds sections */
10051 bounds_section = new_section(s, ".bounds",
10052 SHT_PROGBITS, SHF_ALLOC);
10053 lbounds_section = new_section(s, ".lbounds",
10054 SHT_PROGBITS, SHF_ALLOC);
10056 #endif
10058 if (s->char_is_unsigned) {
10059 tcc_define_symbol(s, "__CHAR_UNSIGNED__", NULL);
10062 /* add debug sections */
10063 if (do_debug) {
10064 /* stab symbols */
10065 stab_section = new_section(s, ".stab", SHT_PROGBITS, 0);
10066 stab_section->sh_entsize = sizeof(Stab_Sym);
10067 stabstr_section = new_section(s, ".stabstr", SHT_STRTAB, 0);
10068 put_elf_str(stabstr_section, "");
10069 stab_section->link = stabstr_section;
10070 /* put first entry */
10071 put_stabs("", 0, 0, 0, 0);
10074 /* add libc crt1/crti objects */
10075 #ifndef TCC_TARGET_PE
10076 if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) &&
10077 !s->nostdlib) {
10078 if (output_type != TCC_OUTPUT_DLL)
10079 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crt1.o");
10080 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crti.o");
10082 #endif
10083 return 0;
10086 #define WD_ALL 0x0001 /* warning is activated when using -Wall */
10087 #define FD_INVERT 0x0002 /* invert value before storing */
10089 typedef struct FlagDef {
10090 uint16_t offset;
10091 uint16_t flags;
10092 const char *name;
10093 } FlagDef;
10095 static const FlagDef warning_defs[] = {
10096 { offsetof(TCCState, warn_unsupported), 0, "unsupported" },
10097 { offsetof(TCCState, warn_write_strings), 0, "write-strings" },
10098 { offsetof(TCCState, warn_error), 0, "error" },
10099 { offsetof(TCCState, warn_implicit_function_declaration), WD_ALL,
10100 "implicit-function-declaration" },
10103 static int set_flag(TCCState *s, const FlagDef *flags, int nb_flags,
10104 const char *name, int value)
10106 int i;
10107 const FlagDef *p;
10108 const char *r;
10110 r = name;
10111 if (r[0] == 'n' && r[1] == 'o' && r[2] == '-') {
10112 r += 3;
10113 value = !value;
10115 for(i = 0, p = flags; i < nb_flags; i++, p++) {
10116 if (!strcmp(r, p->name))
10117 goto found;
10119 return -1;
10120 found:
10121 if (p->flags & FD_INVERT)
10122 value = !value;
10123 *(int *)((uint8_t *)s + p->offset) = value;
10124 return 0;
10128 /* set/reset a warning */
10129 int tcc_set_warning(TCCState *s, const char *warning_name, int value)
10131 int i;
10132 const FlagDef *p;
10134 if (!strcmp(warning_name, "all")) {
10135 for(i = 0, p = warning_defs; i < countof(warning_defs); i++, p++) {
10136 if (p->flags & WD_ALL)
10137 *(int *)((uint8_t *)s + p->offset) = 1;
10139 return 0;
10140 } else {
10141 return set_flag(s, warning_defs, countof(warning_defs),
10142 warning_name, value);
10146 static const FlagDef flag_defs[] = {
10147 { offsetof(TCCState, char_is_unsigned), 0, "unsigned-char" },
10148 { offsetof(TCCState, char_is_unsigned), FD_INVERT, "signed-char" },
10149 { offsetof(TCCState, nocommon), FD_INVERT, "common" },
10150 { offsetof(TCCState, leading_underscore), 0, "leading-underscore" },
10153 /* set/reset a flag */
10154 int tcc_set_flag(TCCState *s, const char *flag_name, int value)
10156 return set_flag(s, flag_defs, countof(flag_defs),
10157 flag_name, value);
10160 #if !defined(LIBTCC)
10162 /* extract the basename of a file */
10163 static const char *tcc_basename(const char *name)
10165 const char *p;
10166 p = strrchr(name, '/');
10167 #ifdef WIN32
10168 if (!p)
10169 p = strrchr(name, '\\');
10170 #endif
10171 if (!p)
10172 p = name;
10173 else
10174 p++;
10175 return p;
10178 static int64_t getclock_us(void)
10180 #ifdef WIN32
10181 struct _timeb tb;
10182 _ftime(&tb);
10183 return (tb.time * 1000LL + tb.millitm) * 1000LL;
10184 #else
10185 struct timeval tv;
10186 gettimeofday(&tv, NULL);
10187 return tv.tv_sec * 1000000LL + tv.tv_usec;
10188 #endif
10191 void help(void)
10193 printf("tcc version " TCC_VERSION " - Tiny C Compiler - Copyright (C) 2001-2005 Fabrice Bellard\n"
10194 "usage: tcc [-v] [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
10195 " [-Wwarn] [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-static]\n"
10196 " [infile1 infile2...] [-run infile args...]\n"
10197 "\n"
10198 "General options:\n"
10199 " -v display current version\n"
10200 " -c compile only - generate an object file\n"
10201 " -o outfile set output filename\n"
10202 " -Bdir set tcc internal library path\n"
10203 " -bench output compilation statistics\n"
10204 " -run run compiled source\n"
10205 " -fflag set or reset (with 'no-' prefix) 'flag' (see man page)\n"
10206 " -Wwarning set or reset (with 'no-' prefix) 'warning' (see man page)\n"
10207 " -w disable all warnings\n"
10208 "Preprocessor options:\n"
10209 " -Idir add include path 'dir'\n"
10210 " -Dsym[=val] define 'sym' with value 'val'\n"
10211 " -Usym undefine 'sym'\n"
10212 "Linker options:\n"
10213 " -Ldir add library path 'dir'\n"
10214 " -llib link with dynamic or static library 'lib'\n"
10215 " -shared generate a shared library\n"
10216 " -static static linking\n"
10217 " -rdynamic export all global symbols to dynamic linker\n"
10218 " -r relocatable output\n"
10219 "Debugger options:\n"
10220 " -g generate runtime debug info\n"
10221 #ifdef CONFIG_TCC_BCHECK
10222 " -b compile with built-in memory and bounds checker (implies -g)\n"
10223 #endif
10224 " -bt N show N callers in stack traces\n"
10228 #define TCC_OPTION_HAS_ARG 0x0001
10229 #define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
10231 typedef struct TCCOption {
10232 const char *name;
10233 uint16_t index;
10234 uint16_t flags;
10235 } TCCOption;
10237 enum {
10238 TCC_OPTION_HELP,
10239 TCC_OPTION_I,
10240 TCC_OPTION_D,
10241 TCC_OPTION_U,
10242 TCC_OPTION_L,
10243 TCC_OPTION_B,
10244 TCC_OPTION_l,
10245 TCC_OPTION_bench,
10246 TCC_OPTION_bt,
10247 TCC_OPTION_b,
10248 TCC_OPTION_g,
10249 TCC_OPTION_c,
10250 TCC_OPTION_static,
10251 TCC_OPTION_shared,
10252 TCC_OPTION_o,
10253 TCC_OPTION_r,
10254 TCC_OPTION_Wl,
10255 TCC_OPTION_W,
10256 TCC_OPTION_O,
10257 TCC_OPTION_m,
10258 TCC_OPTION_f,
10259 TCC_OPTION_nostdinc,
10260 TCC_OPTION_nostdlib,
10261 TCC_OPTION_print_search_dirs,
10262 TCC_OPTION_rdynamic,
10263 TCC_OPTION_run,
10264 TCC_OPTION_v,
10265 TCC_OPTION_w,
10266 TCC_OPTION_pipe,
10269 static const TCCOption tcc_options[] = {
10270 { "h", TCC_OPTION_HELP, 0 },
10271 { "?", TCC_OPTION_HELP, 0 },
10272 { "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG },
10273 { "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG },
10274 { "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG },
10275 { "L", TCC_OPTION_L, TCC_OPTION_HAS_ARG },
10276 { "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG },
10277 { "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10278 { "bench", TCC_OPTION_bench, 0 },
10279 { "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG },
10280 #ifdef CONFIG_TCC_BCHECK
10281 { "b", TCC_OPTION_b, 0 },
10282 #endif
10283 { "g", TCC_OPTION_g, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10284 { "c", TCC_OPTION_c, 0 },
10285 { "static", TCC_OPTION_static, 0 },
10286 { "shared", TCC_OPTION_shared, 0 },
10287 { "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG },
10288 { "run", TCC_OPTION_run, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10289 { "rdynamic", TCC_OPTION_rdynamic, 0 },
10290 { "r", TCC_OPTION_r, 0 },
10291 { "Wl,", TCC_OPTION_Wl, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10292 { "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10293 { "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10294 { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG },
10295 { "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10296 { "nostdinc", TCC_OPTION_nostdinc, 0 },
10297 { "nostdlib", TCC_OPTION_nostdlib, 0 },
10298 { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 },
10299 { "v", TCC_OPTION_v, 0 },
10300 { "w", TCC_OPTION_w, 0 },
10301 { "pipe", TCC_OPTION_pipe, 0},
10302 { NULL },
10305 /* convert 'str' into an array of space separated strings */
10306 static int expand_args(char ***pargv, const char *str)
10308 const char *s1;
10309 char **argv, *arg;
10310 int argc, len;
10312 argc = 0;
10313 argv = NULL;
10314 for(;;) {
10315 while (is_space(*str))
10316 str++;
10317 if (*str == '\0')
10318 break;
10319 s1 = str;
10320 while (*str != '\0' && !is_space(*str))
10321 str++;
10322 len = str - s1;
10323 arg = tcc_malloc(len + 1);
10324 memcpy(arg, s1, len);
10325 arg[len] = '\0';
10326 dynarray_add((void ***)&argv, &argc, arg);
10328 *pargv = argv;
10329 return argc;
10332 static char **files;
10333 static int nb_files, nb_libraries;
10334 static int multiple_files;
10335 static int print_search_dirs;
10336 static int output_type;
10337 static int reloc_output;
10338 static const char *outfile;
10340 int parse_args(TCCState *s, int argc, char **argv)
10342 int optind;
10343 const TCCOption *popt;
10344 const char *optarg, *p1, *r1;
10345 char *r;
10347 optind = 0;
10348 while (1) {
10349 if (optind >= argc) {
10350 if (nb_files == 0 && !print_search_dirs)
10351 goto show_help;
10352 else
10353 break;
10355 r = argv[optind++];
10356 if (r[0] != '-') {
10357 /* add a new file */
10358 dynarray_add((void ***)&files, &nb_files, r);
10359 if (!multiple_files) {
10360 optind--;
10361 /* argv[0] will be this file */
10362 break;
10364 } else {
10365 /* find option in table (match only the first chars */
10366 popt = tcc_options;
10367 for(;;) {
10368 p1 = popt->name;
10369 if (p1 == NULL)
10370 error("invalid option -- '%s'", r);
10371 r1 = r + 1;
10372 for(;;) {
10373 if (*p1 == '\0')
10374 goto option_found;
10375 if (*r1 != *p1)
10376 break;
10377 p1++;
10378 r1++;
10380 popt++;
10382 option_found:
10383 if (popt->flags & TCC_OPTION_HAS_ARG) {
10384 if (*r1 != '\0' || (popt->flags & TCC_OPTION_NOSEP)) {
10385 optarg = r1;
10386 } else {
10387 if (optind >= argc)
10388 error("argument to '%s' is missing", r);
10389 optarg = argv[optind++];
10391 } else {
10392 if (*r1 != '\0')
10393 goto show_help;
10394 optarg = NULL;
10397 switch(popt->index) {
10398 case TCC_OPTION_HELP:
10399 show_help:
10400 help();
10401 exit(1);
10402 case TCC_OPTION_I:
10403 if (tcc_add_include_path(s, optarg) < 0)
10404 error("too many include paths");
10405 break;
10406 case TCC_OPTION_D:
10408 char *sym, *value;
10409 sym = (char *)optarg;
10410 value = strchr(sym, '=');
10411 if (value) {
10412 *value = '\0';
10413 value++;
10415 tcc_define_symbol(s, sym, value);
10417 break;
10418 case TCC_OPTION_U:
10419 tcc_undefine_symbol(s, optarg);
10420 break;
10421 case TCC_OPTION_L:
10422 tcc_add_library_path(s, optarg);
10423 break;
10424 case TCC_OPTION_B:
10425 /* set tcc utilities path (mainly for tcc development) */
10426 tcc_lib_path = optarg;
10427 break;
10428 case TCC_OPTION_l:
10429 dynarray_add((void ***)&files, &nb_files, r);
10430 nb_libraries++;
10431 break;
10432 case TCC_OPTION_bench:
10433 do_bench = 1;
10434 break;
10435 case TCC_OPTION_bt:
10436 num_callers = atoi(optarg);
10437 break;
10438 #ifdef CONFIG_TCC_BCHECK
10439 case TCC_OPTION_b:
10440 do_bounds_check = 1;
10441 do_debug = 1;
10442 break;
10443 #endif
10444 case TCC_OPTION_g:
10445 do_debug = 1;
10446 break;
10447 case TCC_OPTION_c:
10448 multiple_files = 1;
10449 output_type = TCC_OUTPUT_OBJ;
10450 break;
10451 case TCC_OPTION_static:
10452 s->static_link = 1;
10453 break;
10454 case TCC_OPTION_shared:
10455 output_type = TCC_OUTPUT_DLL;
10456 break;
10457 case TCC_OPTION_o:
10458 multiple_files = 1;
10459 outfile = optarg;
10460 break;
10461 case TCC_OPTION_r:
10462 /* generate a .o merging several output files */
10463 reloc_output = 1;
10464 output_type = TCC_OUTPUT_OBJ;
10465 break;
10466 case TCC_OPTION_nostdinc:
10467 s->nostdinc = 1;
10468 break;
10469 case TCC_OPTION_nostdlib:
10470 s->nostdlib = 1;
10471 break;
10472 case TCC_OPTION_print_search_dirs:
10473 print_search_dirs = 1;
10474 break;
10475 case TCC_OPTION_run:
10477 int argc1;
10478 char **argv1;
10479 argc1 = expand_args(&argv1, optarg);
10480 if (argc1 > 0) {
10481 parse_args(s, argc1, argv1);
10483 multiple_files = 0;
10484 output_type = TCC_OUTPUT_MEMORY;
10486 break;
10487 case TCC_OPTION_v:
10488 printf("tcc version %s\n", TCC_VERSION);
10489 exit(0);
10490 case TCC_OPTION_f:
10491 if (tcc_set_flag(s, optarg, 1) < 0 && s->warn_unsupported)
10492 goto unsupported_option;
10493 break;
10494 case TCC_OPTION_W:
10495 if (tcc_set_warning(s, optarg, 1) < 0 &&
10496 s->warn_unsupported)
10497 goto unsupported_option;
10498 break;
10499 case TCC_OPTION_w:
10500 s->warn_none = 1;
10501 break;
10502 case TCC_OPTION_rdynamic:
10503 s->rdynamic = 1;
10504 break;
10505 case TCC_OPTION_Wl:
10507 const char *p;
10508 if (strstart(optarg, "-Ttext,", &p)) {
10509 s->text_addr = strtoul(p, NULL, 16);
10510 s->has_text_addr = 1;
10511 } else if (strstart(optarg, "--oformat,", &p)) {
10512 if (strstart(p, "elf32-", NULL)) {
10513 s->output_format = TCC_OUTPUT_FORMAT_ELF;
10514 } else if (!strcmp(p, "binary")) {
10515 s->output_format = TCC_OUTPUT_FORMAT_BINARY;
10516 } else
10517 #ifdef TCC_TARGET_COFF
10518 if (!strcmp(p, "coff")) {
10519 s->output_format = TCC_OUTPUT_FORMAT_COFF;
10520 } else
10521 #endif
10523 error("target %s not found", p);
10525 } else {
10526 error("unsupported linker option '%s'", optarg);
10529 break;
10530 default:
10531 if (s->warn_unsupported) {
10532 unsupported_option:
10533 warning("unsupported option '%s'", r);
10535 break;
10539 return optind;
10542 int main(int argc, char **argv)
10544 int i;
10545 TCCState *s;
10546 int nb_objfiles, ret, optind;
10547 char objfilename[1024];
10548 int64_t start_time = 0;
10550 #ifdef WIN32
10551 /* on win32, we suppose the lib and includes are at the location
10552 of 'tcc.exe' */
10554 static char path[1024];
10555 char *p, *d;
10557 GetModuleFileNameA(NULL, path, sizeof path);
10558 p = d = strlwr(path);
10559 while (*d)
10561 if (*d == '\\') *d = '/', p = d;
10562 ++d;
10564 *p = '\0';
10565 tcc_lib_path = path;
10567 #endif
10569 s = tcc_new();
10570 output_type = TCC_OUTPUT_EXE;
10571 outfile = NULL;
10572 multiple_files = 1;
10573 files = NULL;
10574 nb_files = 0;
10575 nb_libraries = 0;
10576 reloc_output = 0;
10577 print_search_dirs = 0;
10579 optind = parse_args(s, argc - 1, argv + 1) + 1;
10581 if (print_search_dirs) {
10582 /* enough for Linux kernel */
10583 printf("install: %s/\n", tcc_lib_path);
10584 return 0;
10587 nb_objfiles = nb_files - nb_libraries;
10589 /* if outfile provided without other options, we output an
10590 executable */
10591 if (outfile && output_type == TCC_OUTPUT_MEMORY)
10592 output_type = TCC_OUTPUT_EXE;
10594 /* check -c consistency : only single file handled. XXX: checks file type */
10595 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
10596 /* accepts only a single input file */
10597 if (nb_objfiles != 1)
10598 error("cannot specify multiple files with -c");
10599 if (nb_libraries != 0)
10600 error("cannot specify libraries with -c");
10603 if (output_type != TCC_OUTPUT_MEMORY) {
10604 if (!outfile) {
10605 /* compute default outfile name */
10606 pstrcpy(objfilename, sizeof(objfilename) - 1,
10607 /* strip path */
10608 tcc_basename(files[0]));
10609 #ifdef TCC_TARGET_PE
10610 pe_guess_outfile(objfilename, output_type);
10611 #else
10612 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
10613 char *ext = strrchr(objfilename, '.');
10614 if (!ext)
10615 goto default_outfile;
10616 /* add .o extension */
10617 strcpy(ext + 1, "o");
10618 } else {
10619 default_outfile:
10620 pstrcpy(objfilename, sizeof(objfilename), "a.out");
10622 #endif
10623 outfile = objfilename;
10627 if (do_bench) {
10628 start_time = getclock_us();
10631 tcc_set_output_type(s, output_type);
10633 /* compile or add each files or library */
10634 for(i = 0;i < nb_files; i++) {
10635 const char *filename;
10637 filename = files[i];
10638 if (filename[0] == '-') {
10639 if (tcc_add_library(s, filename + 2) < 0)
10640 error("cannot find %s", filename);
10641 } else {
10642 if (tcc_add_file(s, filename) < 0) {
10643 ret = 1;
10644 goto the_end;
10649 /* free all files */
10650 tcc_free(files);
10652 if (do_bench) {
10653 double total_time;
10654 total_time = (double)(getclock_us() - start_time) / 1000000.0;
10655 if (total_time < 0.001)
10656 total_time = 0.001;
10657 if (total_bytes < 1)
10658 total_bytes = 1;
10659 printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
10660 tok_ident - TOK_IDENT, total_lines, total_bytes,
10661 total_time, (int)(total_lines / total_time),
10662 total_bytes / total_time / 1000000.0);
10665 if (s->output_type == TCC_OUTPUT_MEMORY) {
10666 ret = tcc_run(s, argc - optind, argv + optind);
10667 } else
10668 #ifdef TCC_TARGET_PE
10669 if (s->output_type != TCC_OUTPUT_OBJ) {
10670 ret = tcc_output_pe(s, outfile);
10671 } else
10672 #endif
10674 tcc_output_file(s, outfile);
10675 ret = 0;
10677 the_end:
10678 /* XXX: cannot do it with bound checking because of the malloc hooks */
10679 if (!do_bounds_check)
10680 tcc_delete(s);
10682 #ifdef MEM_DEBUG
10683 if (do_bench) {
10684 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size, mem_max_size);
10686 #endif
10687 return ret;
10690 #endif