added support for win32 wchar_t (Filip Navara)
[tinycc.git] / tcc.c
blob70692fc34017a5ed76b2307991c3d280e948dcb5
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 #include <windows.h>
44 #endif
45 #ifndef WIN32
46 #include <sys/time.h>
47 #include <sys/ucontext.h>
48 #include <sys/mman.h>
49 #endif
51 #endif /* !CONFIG_TCCBOOT */
53 #ifndef PAGESIZE
54 #define PAGESIZE 4096
55 #endif
57 #include "elf.h"
58 #include "stab.h"
60 #ifndef O_BINARY
61 #define O_BINARY 0
62 #endif
64 #include "libtcc.h"
66 /* parser debug */
67 //#define PARSE_DEBUG
68 /* preprocessor debug */
69 //#define PP_DEBUG
70 /* include file debug */
71 //#define INC_DEBUG
73 //#define MEM_DEBUG
75 /* assembler debug */
76 //#define ASM_DEBUG
78 /* target selection */
79 //#define TCC_TARGET_I386 /* i386 code generator */
80 //#define TCC_TARGET_ARM /* ARMv4 code generator */
81 //#define TCC_TARGET_C67 /* TMS320C67xx code generator */
83 /* default target is I386 */
84 #if !defined(TCC_TARGET_I386) && !defined(TCC_TARGET_ARM) && \
85 !defined(TCC_TARGET_C67)
86 #define TCC_TARGET_I386
87 #endif
89 #if !defined(WIN32) && !defined(TCC_UCLIBC) && !defined(TCC_TARGET_ARM) && \
90 !defined(TCC_TARGET_C67)
91 #define CONFIG_TCC_BCHECK /* enable bound checking code */
92 #endif
94 #if defined(WIN32) && !defined(TCC_TARGET_PE)
95 #define CONFIG_TCC_STATIC
96 #endif
98 /* define it to include assembler support */
99 #if !defined(TCC_TARGET_ARM) && !defined(TCC_TARGET_C67)
100 #define CONFIG_TCC_ASM
101 #endif
103 /* object format selection */
104 #if defined(TCC_TARGET_C67)
105 #define TCC_TARGET_COFF
106 #endif
108 #define FALSE 0
109 #define false 0
110 #define TRUE 1
111 #define true 1
112 typedef int BOOL;
114 /* path to find crt1.o, crti.o and crtn.o. Only needed when generating
115 executables or dlls */
116 #define CONFIG_TCC_CRT_PREFIX "/usr/lib"
118 #define INCLUDE_STACK_SIZE 32
119 #define IFDEF_STACK_SIZE 64
120 #define VSTACK_SIZE 256
121 #define STRING_MAX_SIZE 1024
122 #define PACK_STACK_SIZE 8
124 #define TOK_HASH_SIZE 8192 /* must be a power of two */
125 #define TOK_ALLOC_INCR 512 /* must be a power of two */
126 #define TOK_MAX_SIZE 4 /* token max size in int unit when stored in string */
128 /* token symbol management */
129 typedef struct TokenSym {
130 struct TokenSym *hash_next;
131 struct Sym *sym_define; /* direct pointer to define */
132 struct Sym *sym_label; /* direct pointer to label */
133 struct Sym *sym_struct; /* direct pointer to structure */
134 struct Sym *sym_identifier; /* direct pointer to identifier */
135 int tok; /* token number */
136 int len;
137 char str[1];
138 } TokenSym;
140 #ifdef TCC_TARGET_PE
141 typedef unsigned short nwchar_t;
142 #else
143 typedef int nwchar_t;
144 #endif
146 typedef struct CString {
147 int size; /* size in bytes */
148 void *data; /* either 'char *' or 'nwchar_t *' */
149 int size_allocated;
150 void *data_allocated; /* if non NULL, data has been malloced */
151 } CString;
153 /* type definition */
154 typedef struct CType {
155 int t;
156 struct Sym *ref;
157 } CType;
159 /* constant value */
160 typedef union CValue {
161 long double ld;
162 double d;
163 float f;
164 int i;
165 unsigned int ui;
166 unsigned int ul; /* address (should be unsigned long on 64 bit cpu) */
167 long long ll;
168 unsigned long long ull;
169 struct CString *cstr;
170 void *ptr;
171 int tab[1];
172 } CValue;
174 /* value on stack */
175 typedef struct SValue {
176 CType type; /* type */
177 unsigned short r; /* register + flags */
178 unsigned short r2; /* second register, used for 'long long'
179 type. If not used, set to VT_CONST */
180 CValue c; /* constant, if VT_CONST */
181 struct Sym *sym; /* symbol, if (VT_SYM | VT_CONST) */
182 } SValue;
184 /* symbol management */
185 typedef struct Sym {
186 int v; /* symbol token */
187 int r; /* associated register */
188 int c; /* associated number */
189 CType type; /* associated type */
190 struct Sym *next; /* next related symbol */
191 struct Sym *prev; /* prev symbol in stack */
192 struct Sym *prev_tok; /* previous symbol for this token */
193 } Sym;
195 /* section definition */
196 /* XXX: use directly ELF structure for parameters ? */
197 /* special flag to indicate that the section should not be linked to
198 the other ones */
199 #define SHF_PRIVATE 0x80000000
201 typedef struct Section {
202 unsigned long data_offset; /* current data offset */
203 unsigned char *data; /* section data */
204 unsigned long data_allocated; /* used for realloc() handling */
205 int sh_name; /* elf section name (only used during output) */
206 int sh_num; /* elf section number */
207 int sh_type; /* elf section type */
208 int sh_flags; /* elf section flags */
209 int sh_info; /* elf section info */
210 int sh_addralign; /* elf section alignment */
211 int sh_entsize; /* elf entry size */
212 unsigned long sh_size; /* section size (only used during output) */
213 unsigned long sh_addr; /* address at which the section is relocated */
214 unsigned long sh_offset; /* file offset */
215 int nb_hashed_syms; /* used to resize the hash table */
216 struct Section *link; /* link to another section */
217 struct Section *reloc; /* corresponding section for relocation, if any */
218 struct Section *hash; /* hash table for symbols */
219 struct Section *next;
220 char name[1]; /* section name */
221 } Section;
223 typedef struct DLLReference {
224 int level;
225 char name[1];
226 } DLLReference;
228 /* GNUC attribute definition */
229 typedef struct AttributeDef {
230 int aligned;
231 int packed;
232 Section *section;
233 unsigned char func_call; /* FUNC_CDECL, FUNC_STDCALL, FUNC_FASTCALLx */
234 unsigned char dllexport;
235 } AttributeDef;
237 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
238 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
239 #define SYM_FIRST_ANOM 0x10000000 /* first anonymous sym */
241 /* stored in 'Sym.c' field */
242 #define FUNC_NEW 1 /* ansi function prototype */
243 #define FUNC_OLD 2 /* old function prototype */
244 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
246 /* stored in 'Sym.r' field */
247 #define FUNC_CDECL 0 /* standard c call */
248 #define FUNC_STDCALL 1 /* pascal c call */
249 #define FUNC_FASTCALL1 2 /* first param in %eax */
250 #define FUNC_FASTCALL2 3 /* first parameters in %eax, %edx */
251 #define FUNC_FASTCALL3 4 /* first parameter in %eax, %edx, %ecx */
253 /* field 'Sym.t' for macros */
254 #define MACRO_OBJ 0 /* object like macro */
255 #define MACRO_FUNC 1 /* function like macro */
257 /* field 'Sym.r' for C labels */
258 #define LABEL_DEFINED 0 /* label is defined */
259 #define LABEL_FORWARD 1 /* label is forward defined */
260 #define LABEL_DECLARED 2 /* label is declared but never used */
262 /* type_decl() types */
263 #define TYPE_ABSTRACT 1 /* type without variable */
264 #define TYPE_DIRECT 2 /* type with variable */
266 #define IO_BUF_SIZE 8192
268 typedef struct BufferedFile {
269 uint8_t *buf_ptr;
270 uint8_t *buf_end;
271 int fd;
272 int line_num; /* current line number - here to simplify code */
273 int ifndef_macro; /* #ifndef macro / #endif search */
274 int ifndef_macro_saved; /* saved ifndef_macro */
275 int *ifdef_stack_ptr; /* ifdef_stack value at the start of the file */
276 char inc_type; /* type of include */
277 char inc_filename[512]; /* filename specified by the user */
278 char filename[1024]; /* current filename - here to simplify code */
279 unsigned char buffer[IO_BUF_SIZE + 1]; /* extra size for CH_EOB char */
280 } BufferedFile;
282 #define CH_EOB '\\' /* end of buffer or '\0' char in file */
283 #define CH_EOF (-1) /* end of file */
285 /* parsing state (used to save parser state to reparse part of the
286 source several times) */
287 typedef struct ParseState {
288 int *macro_ptr;
289 int line_num;
290 int tok;
291 CValue tokc;
292 } ParseState;
294 /* used to record tokens */
295 typedef struct TokenString {
296 int *str;
297 int len;
298 int allocated_len;
299 int last_line_num;
300 } TokenString;
302 /* include file cache, used to find files faster and also to eliminate
303 inclusion if the include file is protected by #ifndef ... #endif */
304 typedef struct CachedInclude {
305 int ifndef_macro;
306 int hash_next; /* -1 if none */
307 char type; /* '"' or '>' to give include type */
308 char filename[1]; /* path specified in #include */
309 } CachedInclude;
311 #define CACHED_INCLUDES_HASH_SIZE 512
313 /* parser */
314 static struct BufferedFile *file;
315 static int ch, tok;
316 static CValue tokc;
317 static CString tokcstr; /* current parsed string, if any */
318 /* additional informations about token */
319 static int tok_flags;
320 #define TOK_FLAG_BOL 0x0001 /* beginning of line before */
321 #define TOK_FLAG_BOF 0x0002 /* beginning of file before */
322 #define TOK_FLAG_ENDIF 0x0004 /* a endif was found matching starting #ifdef */
324 static int *macro_ptr, *macro_ptr_allocated;
325 static int *unget_saved_macro_ptr;
326 static int unget_saved_buffer[TOK_MAX_SIZE + 1];
327 static int unget_buffer_enabled;
328 static int parse_flags;
329 #define PARSE_FLAG_PREPROCESS 0x0001 /* activate preprocessing */
330 #define PARSE_FLAG_TOK_NUM 0x0002 /* return numbers instead of TOK_PPNUM */
331 #define PARSE_FLAG_LINEFEED 0x0004 /* line feed is returned as a
332 token. line feed is also
333 returned at eof */
334 #define PARSE_FLAG_ASM_COMMENTS 0x0008 /* '#' can be used for line comment */
336 static Section *text_section, *data_section, *bss_section; /* predefined sections */
337 static Section *cur_text_section; /* current section where function code is
338 generated */
339 #ifdef CONFIG_TCC_ASM
340 static Section *last_text_section; /* to handle .previous asm directive */
341 #endif
342 /* bound check related sections */
343 static Section *bounds_section; /* contains global data bound description */
344 static Section *lbounds_section; /* contains local data bound description */
345 /* symbol sections */
346 static Section *symtab_section, *strtab_section;
348 /* debug sections */
349 static Section *stab_section, *stabstr_section;
351 /* loc : local variable index
352 ind : output code index
353 rsym: return symbol
354 anon_sym: anonymous symbol index
356 static int rsym, anon_sym, ind, loc;
357 /* expression generation modifiers */
358 static int const_wanted; /* true if constant wanted */
359 static int nocode_wanted; /* true if no code generation wanted for an expression */
360 static int global_expr; /* true if compound literals must be allocated
361 globally (used during initializers parsing */
362 static CType func_vt; /* current function return type (used by return
363 instruction) */
364 static int func_vc;
365 static int last_line_num, last_ind, func_ind; /* debug last line number and pc */
366 static int tok_ident;
367 static TokenSym **table_ident;
368 static TokenSym *hash_ident[TOK_HASH_SIZE];
369 static char token_buf[STRING_MAX_SIZE + 1];
370 static char *funcname;
371 static Sym *global_stack, *local_stack;
372 static Sym *define_stack;
373 static Sym *global_label_stack, *local_label_stack;
374 /* symbol allocator */
375 #define SYM_POOL_NB (8192 / sizeof(Sym))
376 static Sym *sym_free_first;
378 static SValue vstack[VSTACK_SIZE], *vtop;
379 /* some predefined types */
380 static CType char_pointer_type, func_old_type, int_type;
381 /* true if isid(c) || isnum(c) */
382 static unsigned char isidnum_table[256];
384 /* compile with debug symbol (and use them if error during execution) */
385 static int do_debug = 0;
387 /* compile with built-in memory and bounds checker */
388 static int do_bounds_check = 0;
390 /* display benchmark infos */
391 #if !defined(LIBTCC)
392 static int do_bench = 0;
393 #endif
394 static int total_lines;
395 static int total_bytes;
397 /* use GNU C extensions */
398 static int gnu_ext = 1;
400 /* use Tiny C extensions */
401 static int tcc_ext = 1;
403 /* max number of callers shown if error */
404 static int num_callers = 6;
405 static const char **rt_bound_error_msg;
407 /* XXX: get rid of this ASAP */
408 static struct TCCState *tcc_state;
410 /* give the path of the tcc libraries */
411 static const char *tcc_lib_path = CONFIG_TCCDIR;
413 struct TCCState {
414 int output_type;
416 BufferedFile **include_stack_ptr;
417 int *ifdef_stack_ptr;
419 /* include file handling */
420 char **include_paths;
421 int nb_include_paths;
422 char **sysinclude_paths;
423 int nb_sysinclude_paths;
424 CachedInclude **cached_includes;
425 int nb_cached_includes;
427 char **library_paths;
428 int nb_library_paths;
430 /* array of all loaded dlls (including those referenced by loaded
431 dlls) */
432 DLLReference **loaded_dlls;
433 int nb_loaded_dlls;
435 /* sections */
436 Section **sections;
437 int nb_sections; /* number of sections, including first dummy section */
439 /* got handling */
440 Section *got;
441 Section *plt;
442 unsigned long *got_offsets;
443 int nb_got_offsets;
444 /* give the correspondance from symtab indexes to dynsym indexes */
445 int *symtab_to_dynsym;
447 /* temporary dynamic symbol sections (for dll loading) */
448 Section *dynsymtab_section;
449 /* exported dynamic symbol section */
450 Section *dynsym;
452 int nostdinc; /* if true, no standard headers are added */
453 int nostdlib; /* if true, no standard libraries are added */
455 int nocommon; /* if true, do not use common symbols for .bss data */
457 /* if true, static linking is performed */
458 int static_link;
460 /* if true, all symbols are exported */
461 int rdynamic;
463 /* if true, only link in referenced objects from archive */
464 int alacarte_link;
466 /* address of text section */
467 unsigned long text_addr;
468 int has_text_addr;
470 /* output format, see TCC_OUTPUT_FORMAT_xxx */
471 int output_format;
473 /* C language options */
474 int char_is_unsigned;
475 int leading_underscore;
477 /* warning switches */
478 int warn_write_strings;
479 int warn_unsupported;
480 int warn_error;
481 int warn_none;
482 int warn_implicit_function_declaration;
484 /* error handling */
485 void *error_opaque;
486 void (*error_func)(void *opaque, const char *msg);
487 int error_set_jmp_enabled;
488 jmp_buf error_jmp_buf;
489 int nb_errors;
491 /* tiny assembler state */
492 Sym *asm_labels;
494 /* see include_stack_ptr */
495 BufferedFile *include_stack[INCLUDE_STACK_SIZE];
497 /* see ifdef_stack_ptr */
498 int ifdef_stack[IFDEF_STACK_SIZE];
500 /* see cached_includes */
501 int cached_includes_hash[CACHED_INCLUDES_HASH_SIZE];
503 /* pack stack */
504 int pack_stack[PACK_STACK_SIZE];
505 int *pack_stack_ptr;
508 /* The current value can be: */
509 #define VT_VALMASK 0x00ff
510 #define VT_CONST 0x00f0 /* constant in vc
511 (must be first non register value) */
512 #define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */
513 #define VT_LOCAL 0x00f2 /* offset on stack */
514 #define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */
515 #define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */
516 #define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */
517 #define VT_LVAL 0x0100 /* var is an lvalue */
518 #define VT_SYM 0x0200 /* a symbol value is added */
519 #define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for
520 char/short stored in integer registers) */
521 #define VT_MUSTBOUND 0x0800 /* bound checking must be done before
522 dereferencing value */
523 #define VT_BOUNDED 0x8000 /* value is bounded. The address of the
524 bounding function call point is in vc */
525 #define VT_LVAL_BYTE 0x1000 /* lvalue is a byte */
526 #define VT_LVAL_SHORT 0x2000 /* lvalue is a short */
527 #define VT_LVAL_UNSIGNED 0x4000 /* lvalue is unsigned */
528 #define VT_LVAL_TYPE (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)
530 /* types */
531 #define VT_INT 0 /* integer type */
532 #define VT_BYTE 1 /* signed byte type */
533 #define VT_SHORT 2 /* short type */
534 #define VT_VOID 3 /* void type */
535 #define VT_PTR 4 /* pointer */
536 #define VT_ENUM 5 /* enum definition */
537 #define VT_FUNC 6 /* function type */
538 #define VT_STRUCT 7 /* struct/union definition */
539 #define VT_FLOAT 8 /* IEEE float */
540 #define VT_DOUBLE 9 /* IEEE double */
541 #define VT_LDOUBLE 10 /* IEEE long double */
542 #define VT_BOOL 11 /* ISOC99 boolean type */
543 #define VT_LLONG 12 /* 64 bit integer */
544 #define VT_LONG 13 /* long integer (NEVER USED as type, only
545 during parsing) */
546 #define VT_BTYPE 0x000f /* mask for basic type */
547 #define VT_UNSIGNED 0x0010 /* unsigned type */
548 #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
549 #define VT_BITFIELD 0x0040 /* bitfield modifier */
550 #define VT_CONSTANT 0x0800 /* const modifier */
551 #define VT_VOLATILE 0x1000 /* volatile modifier */
552 #define VT_SIGNED 0x2000 /* signed type */
554 /* storage */
555 #define VT_EXTERN 0x00000080 /* extern definition */
556 #define VT_STATIC 0x00000100 /* static variable */
557 #define VT_TYPEDEF 0x00000200 /* typedef definition */
558 #define VT_INLINE 0x00000400 /* inline definition */
560 #define VT_STRUCT_SHIFT 16 /* shift for bitfield shift values */
562 /* type mask (except storage) */
563 #define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE)
564 #define VT_TYPE (~(VT_STORAGE))
566 /* token values */
568 /* warning: the following compare tokens depend on i386 asm code */
569 #define TOK_ULT 0x92
570 #define TOK_UGE 0x93
571 #define TOK_EQ 0x94
572 #define TOK_NE 0x95
573 #define TOK_ULE 0x96
574 #define TOK_UGT 0x97
575 #define TOK_LT 0x9c
576 #define TOK_GE 0x9d
577 #define TOK_LE 0x9e
578 #define TOK_GT 0x9f
580 #define TOK_LAND 0xa0
581 #define TOK_LOR 0xa1
583 #define TOK_DEC 0xa2
584 #define TOK_MID 0xa3 /* inc/dec, to void constant */
585 #define TOK_INC 0xa4
586 #define TOK_UDIV 0xb0 /* unsigned division */
587 #define TOK_UMOD 0xb1 /* unsigned modulo */
588 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
589 #define TOK_CINT 0xb3 /* number in tokc */
590 #define TOK_CCHAR 0xb4 /* char constant in tokc */
591 #define TOK_STR 0xb5 /* pointer to string in tokc */
592 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
593 #define TOK_LCHAR 0xb7
594 #define TOK_LSTR 0xb8
595 #define TOK_CFLOAT 0xb9 /* float constant */
596 #define TOK_LINENUM 0xba /* line number info */
597 #define TOK_CDOUBLE 0xc0 /* double constant */
598 #define TOK_CLDOUBLE 0xc1 /* long double constant */
599 #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
600 #define TOK_ADDC1 0xc3 /* add with carry generation */
601 #define TOK_ADDC2 0xc4 /* add with carry use */
602 #define TOK_SUBC1 0xc5 /* add with carry generation */
603 #define TOK_SUBC2 0xc6 /* add with carry use */
604 #define TOK_CUINT 0xc8 /* unsigned int constant */
605 #define TOK_CLLONG 0xc9 /* long long constant */
606 #define TOK_CULLONG 0xca /* unsigned long long constant */
607 #define TOK_ARROW 0xcb
608 #define TOK_DOTS 0xcc /* three dots */
609 #define TOK_SHR 0xcd /* unsigned shift right */
610 #define TOK_PPNUM 0xce /* preprocessor number */
612 #define TOK_SHL 0x01 /* shift left */
613 #define TOK_SAR 0x02 /* signed shift right */
615 /* assignement operators : normal operator or 0x80 */
616 #define TOK_A_MOD 0xa5
617 #define TOK_A_AND 0xa6
618 #define TOK_A_MUL 0xaa
619 #define TOK_A_ADD 0xab
620 #define TOK_A_SUB 0xad
621 #define TOK_A_DIV 0xaf
622 #define TOK_A_XOR 0xde
623 #define TOK_A_OR 0xfc
624 #define TOK_A_SHL 0x81
625 #define TOK_A_SAR 0x82
627 #ifndef offsetof
628 #define offsetof(type, field) ((size_t) &((type *)0)->field)
629 #endif
631 #ifndef countof
632 #define countof(tab) (sizeof(tab) / sizeof((tab)[0]))
633 #endif
635 /* WARNING: the content of this string encodes token numbers */
636 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";
638 #define TOK_EOF (-1) /* end of file */
639 #define TOK_LINEFEED 10 /* line feed */
641 /* all identificators and strings have token above that */
642 #define TOK_IDENT 256
644 /* only used for i386 asm opcodes definitions */
645 #define DEF_ASM(x) DEF(TOK_ASM_ ## x, #x)
647 #define DEF_BWL(x) \
648 DEF(TOK_ASM_ ## x ## b, #x "b") \
649 DEF(TOK_ASM_ ## x ## w, #x "w") \
650 DEF(TOK_ASM_ ## x ## l, #x "l") \
651 DEF(TOK_ASM_ ## x, #x)
653 #define DEF_WL(x) \
654 DEF(TOK_ASM_ ## x ## w, #x "w") \
655 DEF(TOK_ASM_ ## x ## l, #x "l") \
656 DEF(TOK_ASM_ ## x, #x)
658 #define DEF_FP1(x) \
659 DEF(TOK_ASM_ ## f ## x ## s, "f" #x "s") \
660 DEF(TOK_ASM_ ## fi ## x ## l, "fi" #x "l") \
661 DEF(TOK_ASM_ ## f ## x ## l, "f" #x "l") \
662 DEF(TOK_ASM_ ## fi ## x ## s, "fi" #x "s")
664 #define DEF_FP(x) \
665 DEF(TOK_ASM_ ## f ## x, "f" #x ) \
666 DEF(TOK_ASM_ ## f ## x ## p, "f" #x "p") \
667 DEF_FP1(x)
669 #define DEF_ASMTEST(x) \
670 DEF_ASM(x ## o) \
671 DEF_ASM(x ## no) \
672 DEF_ASM(x ## b) \
673 DEF_ASM(x ## c) \
674 DEF_ASM(x ## nae) \
675 DEF_ASM(x ## nb) \
676 DEF_ASM(x ## nc) \
677 DEF_ASM(x ## ae) \
678 DEF_ASM(x ## e) \
679 DEF_ASM(x ## z) \
680 DEF_ASM(x ## ne) \
681 DEF_ASM(x ## nz) \
682 DEF_ASM(x ## be) \
683 DEF_ASM(x ## na) \
684 DEF_ASM(x ## nbe) \
685 DEF_ASM(x ## a) \
686 DEF_ASM(x ## s) \
687 DEF_ASM(x ## ns) \
688 DEF_ASM(x ## p) \
689 DEF_ASM(x ## pe) \
690 DEF_ASM(x ## np) \
691 DEF_ASM(x ## po) \
692 DEF_ASM(x ## l) \
693 DEF_ASM(x ## nge) \
694 DEF_ASM(x ## nl) \
695 DEF_ASM(x ## ge) \
696 DEF_ASM(x ## le) \
697 DEF_ASM(x ## ng) \
698 DEF_ASM(x ## nle) \
699 DEF_ASM(x ## g)
701 #define TOK_ASM_int TOK_INT
703 enum tcc_token {
704 TOK_LAST = TOK_IDENT - 1,
705 #define DEF(id, str) id,
706 #include "tcctok.h"
707 #undef DEF
710 static const char tcc_keywords[] =
711 #define DEF(id, str) str "\0"
712 #include "tcctok.h"
713 #undef DEF
716 #define TOK_UIDENT TOK_DEFINE
718 #ifdef WIN32
719 int __stdcall GetModuleFileNameA(void *, char *, int);
720 void *__stdcall GetProcAddress(void *, const char *);
721 void *__stdcall GetModuleHandleA(const char *);
722 void *__stdcall LoadLibraryA(const char *);
723 int __stdcall FreeConsole(void);
725 #define snprintf _snprintf
726 #define vsnprintf _vsnprintf
727 #ifndef __GNUC__
728 #define strtold (long double)strtod
729 #define strtof (float)strtod
730 #define strtoll (long long)strtol
731 #endif
732 #elif defined(TCC_UCLIBC) || defined(__FreeBSD__)
733 /* currently incorrect */
734 long double strtold(const char *nptr, char **endptr)
736 return (long double)strtod(nptr, endptr);
738 float strtof(const char *nptr, char **endptr)
740 return (float)strtod(nptr, endptr);
742 #else
743 /* XXX: need to define this to use them in non ISOC99 context */
744 extern float strtof (const char *__nptr, char **__endptr);
745 extern long double strtold (const char *__nptr, char **__endptr);
746 #endif
748 static char *pstrcpy(char *buf, int buf_size, const char *s);
749 static char *pstrcat(char *buf, int buf_size, const char *s);
750 static const char *tcc_basename(const char *name);
752 static void next(void);
753 static void next_nomacro(void);
754 static void parse_expr_type(CType *type);
755 static void expr_type(CType *type);
756 static void unary_type(CType *type);
757 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
758 int case_reg, int is_expr);
759 static int expr_const(void);
760 static void expr_eq(void);
761 static void gexpr(void);
762 static void gen_inline_functions(void);
763 static void decl(int l);
764 static void decl_initializer(CType *type, Section *sec, unsigned long c,
765 int first, int size_only);
766 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
767 int has_init, int v, int scope);
768 int gv(int rc);
769 void gv2(int rc1, int rc2);
770 void move_reg(int r, int s);
771 void save_regs(int n);
772 void save_reg(int r);
773 void vpop(void);
774 void vswap(void);
775 void vdup(void);
776 int get_reg(int rc);
777 int get_reg_ex(int rc,int rc2);
779 struct macro_level {
780 struct macro_level *prev;
781 int *p;
784 static void macro_subst(TokenString *tok_str, Sym **nested_list,
785 const int *macro_str, struct macro_level **can_read_stream);
786 void gen_op(int op);
787 void force_charshort_cast(int t);
788 static void gen_cast(CType *type);
789 void vstore(void);
790 static Sym *sym_find(int v);
791 static Sym *sym_push(int v, CType *type, int r, int c);
793 /* type handling */
794 static int type_size(CType *type, int *a);
795 static inline CType *pointed_type(CType *type);
796 static int pointed_size(CType *type);
797 static int lvalue_type(int t);
798 static int parse_btype(CType *type, AttributeDef *ad);
799 static void type_decl(CType *type, AttributeDef *ad, int *v, int td);
800 static int is_compatible_types(CType *type1, CType *type2);
802 int ieee_finite(double d);
803 void error(const char *fmt, ...);
804 void vpushi(int v);
805 void vrott(int n);
806 void vnrott(int n);
807 void lexpand_nr(void);
808 static void vpush_global_sym(CType *type, int v);
809 void vset(CType *type, int r, int v);
810 void type_to_str(char *buf, int buf_size,
811 CType *type, const char *varstr);
812 char *get_tok_str(int v, CValue *cv);
813 static Sym *get_sym_ref(CType *type, Section *sec,
814 unsigned long offset, unsigned long size);
815 static Sym *external_global_sym(int v, CType *type, int r);
817 /* section generation */
818 static void section_realloc(Section *sec, unsigned long new_size);
819 static void *section_ptr_add(Section *sec, unsigned long size);
820 static void put_extern_sym(Sym *sym, Section *section,
821 unsigned long value, unsigned long size);
822 static void greloc(Section *s, Sym *sym, unsigned long addr, int type);
823 static int put_elf_str(Section *s, const char *sym);
824 static int put_elf_sym(Section *s,
825 unsigned long value, unsigned long size,
826 int info, int other, int shndx, const char *name);
827 static int add_elf_sym(Section *s, unsigned long value, unsigned long size,
828 int info, int other, int sh_num, const char *name);
829 static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
830 int type, int symbol);
831 static void put_stabs(const char *str, int type, int other, int desc,
832 unsigned long value);
833 static void put_stabs_r(const char *str, int type, int other, int desc,
834 unsigned long value, Section *sec, int sym_index);
835 static void put_stabn(int type, int other, int desc, int value);
836 static void put_stabd(int type, int other, int desc);
837 static int tcc_add_dll(TCCState *s, const char *filename, int flags);
839 #define AFF_PRINT_ERROR 0x0001 /* print error if file not found */
840 #define AFF_REFERENCED_DLL 0x0002 /* load a referenced dll from another dll */
841 static int tcc_add_file_internal(TCCState *s, const char *filename, int flags);
843 /* tcccoff.c */
844 int tcc_output_coff(TCCState *s1, FILE *f);
846 /* tccpe.c */
847 void *resolve_sym(TCCState *s1, const char *sym, int type);
848 int pe_load_def_file(struct TCCState *s1, FILE *fp);
849 void pe_setup_paths(struct TCCState *s1, int *p_output_type, const char **p_outfile, char *first_file);
850 unsigned long pe_add_runtime(struct TCCState *s1);
851 int tcc_output_pe(struct TCCState *s1, const char *filename);
853 /* tccasm.c */
855 #ifdef CONFIG_TCC_ASM
857 typedef struct ExprValue {
858 uint32_t v;
859 Sym *sym;
860 } ExprValue;
862 #define MAX_ASM_OPERANDS 30
864 typedef struct ASMOperand {
865 int id; /* GCC 3 optionnal identifier (0 if number only supported */
866 char *constraint;
867 char asm_str[16]; /* computed asm string for operand */
868 SValue *vt; /* C value of the expression */
869 int ref_index; /* if >= 0, gives reference to a output constraint */
870 int input_index; /* if >= 0, gives reference to an input constraint */
871 int priority; /* priority, used to assign registers */
872 int reg; /* if >= 0, register number used for this operand */
873 int is_llong; /* true if double register value */
874 int is_memory; /* true if memory operand */
875 int is_rw; /* for '+' modifier */
876 } ASMOperand;
878 static void asm_expr(TCCState *s1, ExprValue *pe);
879 static int asm_int_expr(TCCState *s1);
880 static int find_constraint(ASMOperand *operands, int nb_operands,
881 const char *name, const char **pp);
883 static int tcc_assemble(TCCState *s1, int do_preprocess);
885 #endif
887 static void asm_instr(void);
888 static void asm_global_instr(void);
890 /* true if float/double/long double type */
891 static inline int is_float(int t)
893 int bt;
894 bt = t & VT_BTYPE;
895 return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT;
898 #ifdef TCC_TARGET_I386
899 #include "i386-gen.c"
900 #endif
902 #ifdef TCC_TARGET_ARM
903 #include "arm-gen.c"
904 #endif
906 #ifdef TCC_TARGET_C67
907 #include "c67-gen.c"
908 #endif
910 #ifdef CONFIG_TCC_STATIC
912 #define RTLD_LAZY 0x001
913 #define RTLD_NOW 0x002
914 #define RTLD_GLOBAL 0x100
915 #define RTLD_DEFAULT NULL
917 /* dummy function for profiling */
918 void *dlopen(const char *filename, int flag)
920 return NULL;
923 const char *dlerror(void)
925 return "error";
928 typedef struct TCCSyms {
929 char *str;
930 void *ptr;
931 } TCCSyms;
933 #define TCCSYM(a) { #a, &a, },
935 /* add the symbol you want here if no dynamic linking is done */
936 static TCCSyms tcc_syms[] = {
937 #if !defined(CONFIG_TCCBOOT)
938 TCCSYM(printf)
939 TCCSYM(fprintf)
940 TCCSYM(fopen)
941 TCCSYM(fclose)
942 #endif
943 { NULL, NULL },
946 void *resolve_sym(TCCState *s1, const char *symbol, int type)
948 TCCSyms *p;
949 p = tcc_syms;
950 while (p->str != NULL) {
951 if (!strcmp(p->str, symbol))
952 return p->ptr;
953 p++;
955 return NULL;
958 #elif !defined(WIN32)
960 #include <dlfcn.h>
962 void *resolve_sym(TCCState *s1, const char *sym, int type)
964 return dlsym(RTLD_DEFAULT, sym);
967 #endif
969 /********************************************************/
971 /* we use our own 'finite' function to avoid potential problems with
972 non standard math libs */
973 /* XXX: endianness dependent */
974 int ieee_finite(double d)
976 int *p = (int *)&d;
977 return ((unsigned)((p[1] | 0x800fffff) + 1)) >> 31;
980 /* copy a string and truncate it. */
981 static char *pstrcpy(char *buf, int buf_size, const char *s)
983 char *q, *q_end;
984 int c;
986 if (buf_size > 0) {
987 q = buf;
988 q_end = buf + buf_size - 1;
989 while (q < q_end) {
990 c = *s++;
991 if (c == '\0')
992 break;
993 *q++ = c;
995 *q = '\0';
997 return buf;
1000 /* strcat and truncate. */
1001 static char *pstrcat(char *buf, int buf_size, const char *s)
1003 int len;
1004 len = strlen(buf);
1005 if (len < buf_size)
1006 pstrcpy(buf + len, buf_size - len, s);
1007 return buf;
1010 static int strstart(const char *str, const char *val, const char **ptr)
1012 const char *p, *q;
1013 p = str;
1014 q = val;
1015 while (*q != '\0') {
1016 if (*p != *q)
1017 return 0;
1018 p++;
1019 q++;
1021 if (ptr)
1022 *ptr = p;
1023 return 1;
1026 /* memory management */
1027 #ifdef MEM_DEBUG
1028 int mem_cur_size;
1029 int mem_max_size;
1030 #endif
1032 static inline void tcc_free(void *ptr)
1034 #ifdef MEM_DEBUG
1035 mem_cur_size -= malloc_usable_size(ptr);
1036 #endif
1037 free(ptr);
1040 static void *tcc_malloc(unsigned long size)
1042 void *ptr;
1043 ptr = malloc(size);
1044 if (!ptr && size)
1045 error("memory full");
1046 #ifdef MEM_DEBUG
1047 mem_cur_size += malloc_usable_size(ptr);
1048 if (mem_cur_size > mem_max_size)
1049 mem_max_size = mem_cur_size;
1050 #endif
1051 return ptr;
1054 static void *tcc_mallocz(unsigned long size)
1056 void *ptr;
1057 ptr = tcc_malloc(size);
1058 memset(ptr, 0, size);
1059 return ptr;
1062 static inline void *tcc_realloc(void *ptr, unsigned long size)
1064 void *ptr1;
1065 #ifdef MEM_DEBUG
1066 mem_cur_size -= malloc_usable_size(ptr);
1067 #endif
1068 ptr1 = realloc(ptr, size);
1069 #ifdef MEM_DEBUG
1070 /* NOTE: count not correct if alloc error, but not critical */
1071 mem_cur_size += malloc_usable_size(ptr1);
1072 if (mem_cur_size > mem_max_size)
1073 mem_max_size = mem_cur_size;
1074 #endif
1075 return ptr1;
1078 static char *tcc_strdup(const char *str)
1080 char *ptr;
1081 ptr = tcc_malloc(strlen(str) + 1);
1082 strcpy(ptr, str);
1083 return ptr;
1086 #define free(p) use_tcc_free(p)
1087 #define malloc(s) use_tcc_malloc(s)
1088 #define realloc(p, s) use_tcc_realloc(p, s)
1090 static void dynarray_add(void ***ptab, int *nb_ptr, void *data)
1092 int nb, nb_alloc;
1093 void **pp;
1095 nb = *nb_ptr;
1096 pp = *ptab;
1097 /* every power of two we double array size */
1098 if ((nb & (nb - 1)) == 0) {
1099 if (!nb)
1100 nb_alloc = 1;
1101 else
1102 nb_alloc = nb * 2;
1103 pp = tcc_realloc(pp, nb_alloc * sizeof(void *));
1104 if (!pp)
1105 error("memory full");
1106 *ptab = pp;
1108 pp[nb++] = data;
1109 *nb_ptr = nb;
1112 /* symbol allocator */
1113 static Sym *__sym_malloc(void)
1115 Sym *sym_pool, *sym, *last_sym;
1116 int i;
1118 sym_pool = tcc_malloc(SYM_POOL_NB * sizeof(Sym));
1120 last_sym = sym_free_first;
1121 sym = sym_pool;
1122 for(i = 0; i < SYM_POOL_NB; i++) {
1123 sym->next = last_sym;
1124 last_sym = sym;
1125 sym++;
1127 sym_free_first = last_sym;
1128 return last_sym;
1131 static inline Sym *sym_malloc(void)
1133 Sym *sym;
1134 sym = sym_free_first;
1135 if (!sym)
1136 sym = __sym_malloc();
1137 sym_free_first = sym->next;
1138 return sym;
1141 static inline void sym_free(Sym *sym)
1143 sym->next = sym_free_first;
1144 sym_free_first = sym;
1147 Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags)
1149 Section *sec;
1151 sec = tcc_mallocz(sizeof(Section) + strlen(name));
1152 strcpy(sec->name, name);
1153 sec->sh_type = sh_type;
1154 sec->sh_flags = sh_flags;
1155 switch(sh_type) {
1156 case SHT_HASH:
1157 case SHT_REL:
1158 case SHT_DYNSYM:
1159 case SHT_SYMTAB:
1160 case SHT_DYNAMIC:
1161 sec->sh_addralign = 4;
1162 break;
1163 case SHT_STRTAB:
1164 sec->sh_addralign = 1;
1165 break;
1166 default:
1167 sec->sh_addralign = 32; /* default conservative alignment */
1168 break;
1171 /* only add section if not private */
1172 if (!(sh_flags & SHF_PRIVATE)) {
1173 sec->sh_num = s1->nb_sections;
1174 dynarray_add((void ***)&s1->sections, &s1->nb_sections, sec);
1176 return sec;
1179 static void free_section(Section *s)
1181 tcc_free(s->data);
1182 tcc_free(s);
1185 /* realloc section and set its content to zero */
1186 static void section_realloc(Section *sec, unsigned long new_size)
1188 unsigned long size;
1189 unsigned char *data;
1191 size = sec->data_allocated;
1192 if (size == 0)
1193 size = 1;
1194 while (size < new_size)
1195 size = size * 2;
1196 data = tcc_realloc(sec->data, size);
1197 if (!data)
1198 error("memory full");
1199 memset(data + sec->data_allocated, 0, size - sec->data_allocated);
1200 sec->data = data;
1201 sec->data_allocated = size;
1204 /* reserve at least 'size' bytes in section 'sec' from
1205 sec->data_offset. */
1206 static void *section_ptr_add(Section *sec, unsigned long size)
1208 unsigned long offset, offset1;
1210 offset = sec->data_offset;
1211 offset1 = offset + size;
1212 if (offset1 > sec->data_allocated)
1213 section_realloc(sec, offset1);
1214 sec->data_offset = offset1;
1215 return sec->data + offset;
1218 /* return a reference to a section, and create it if it does not
1219 exists */
1220 Section *find_section(TCCState *s1, const char *name)
1222 Section *sec;
1223 int i;
1224 for(i = 1; i < s1->nb_sections; i++) {
1225 sec = s1->sections[i];
1226 if (!strcmp(name, sec->name))
1227 return sec;
1229 /* sections are created as PROGBITS */
1230 return new_section(s1, name, SHT_PROGBITS, SHF_ALLOC);
1233 #define SECTION_ABS ((void *)1)
1235 /* update sym->c so that it points to an external symbol in section
1236 'section' with value 'value' */
1237 static void put_extern_sym2(Sym *sym, Section *section,
1238 unsigned long value, unsigned long size,
1239 int can_add_underscore)
1241 int sym_type, sym_bind, sh_num, info;
1242 Elf32_Sym *esym;
1243 const char *name;
1244 char buf1[256];
1246 if (section == NULL)
1247 sh_num = SHN_UNDEF;
1248 else if (section == SECTION_ABS)
1249 sh_num = SHN_ABS;
1250 else
1251 sh_num = section->sh_num;
1252 if (!sym->c) {
1253 if ((sym->type.t & VT_BTYPE) == VT_FUNC)
1254 sym_type = STT_FUNC;
1255 else
1256 sym_type = STT_OBJECT;
1257 if (sym->type.t & VT_STATIC)
1258 sym_bind = STB_LOCAL;
1259 else
1260 sym_bind = STB_GLOBAL;
1262 name = get_tok_str(sym->v, NULL);
1263 #ifdef CONFIG_TCC_BCHECK
1264 if (do_bounds_check) {
1265 char buf[32];
1267 /* XXX: avoid doing that for statics ? */
1268 /* if bound checking is activated, we change some function
1269 names by adding the "__bound" prefix */
1270 switch(sym->v) {
1271 #if 0
1272 /* XXX: we rely only on malloc hooks */
1273 case TOK_malloc:
1274 case TOK_free:
1275 case TOK_realloc:
1276 case TOK_memalign:
1277 case TOK_calloc:
1278 #endif
1279 case TOK_memcpy:
1280 case TOK_memmove:
1281 case TOK_memset:
1282 case TOK_strlen:
1283 case TOK_strcpy:
1284 strcpy(buf, "__bound_");
1285 strcat(buf, name);
1286 name = buf;
1287 break;
1290 #endif
1291 if (tcc_state->leading_underscore && can_add_underscore) {
1292 buf1[0] = '_';
1293 pstrcpy(buf1 + 1, sizeof(buf1) - 1, name);
1294 name = buf1;
1296 info = ELF32_ST_INFO(sym_bind, sym_type);
1297 sym->c = add_elf_sym(symtab_section, value, size, info, 0, sh_num, name);
1298 } else {
1299 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
1300 esym->st_value = value;
1301 esym->st_size = size;
1302 esym->st_shndx = sh_num;
1306 static void put_extern_sym(Sym *sym, Section *section,
1307 unsigned long value, unsigned long size)
1309 put_extern_sym2(sym, section, value, size, 1);
1312 /* add a new relocation entry to symbol 'sym' in section 's' */
1313 static void greloc(Section *s, Sym *sym, unsigned long offset, int type)
1315 if (!sym->c)
1316 put_extern_sym(sym, NULL, 0, 0);
1317 /* now we can add ELF relocation info */
1318 put_elf_reloc(symtab_section, s, offset, type, sym->c);
1321 static inline int isid(int c)
1323 return (c >= 'a' && c <= 'z') ||
1324 (c >= 'A' && c <= 'Z') ||
1325 c == '_';
1328 static inline int isnum(int c)
1330 return c >= '0' && c <= '9';
1333 static inline int isoct(int c)
1335 return c >= '0' && c <= '7';
1338 static inline int toup(int c)
1340 if (c >= 'a' && c <= 'z')
1341 return c - 'a' + 'A';
1342 else
1343 return c;
1346 static void strcat_vprintf(char *buf, int buf_size, const char *fmt, va_list ap)
1348 int len;
1349 len = strlen(buf);
1350 vsnprintf(buf + len, buf_size - len, fmt, ap);
1353 static void strcat_printf(char *buf, int buf_size, const char *fmt, ...)
1355 va_list ap;
1356 va_start(ap, fmt);
1357 strcat_vprintf(buf, buf_size, fmt, ap);
1358 va_end(ap);
1361 void error1(TCCState *s1, int is_warning, const char *fmt, va_list ap)
1363 char buf[2048];
1364 BufferedFile **f;
1366 buf[0] = '\0';
1367 if (file) {
1368 for(f = s1->include_stack; f < s1->include_stack_ptr; f++)
1369 strcat_printf(buf, sizeof(buf), "In file included from %s:%d:\n",
1370 (*f)->filename, (*f)->line_num);
1371 if (file->line_num > 0) {
1372 strcat_printf(buf, sizeof(buf),
1373 "%s:%d: ", file->filename, file->line_num);
1374 } else {
1375 strcat_printf(buf, sizeof(buf),
1376 "%s: ", file->filename);
1378 } else {
1379 strcat_printf(buf, sizeof(buf),
1380 "tcc: ");
1382 if (is_warning)
1383 strcat_printf(buf, sizeof(buf), "warning: ");
1384 strcat_vprintf(buf, sizeof(buf), fmt, ap);
1386 if (!s1->error_func) {
1387 /* default case: stderr */
1388 fprintf(stderr, "%s\n", buf);
1389 } else {
1390 s1->error_func(s1->error_opaque, buf);
1392 if (!is_warning || s1->warn_error)
1393 s1->nb_errors++;
1396 #ifdef LIBTCC
1397 void tcc_set_error_func(TCCState *s, void *error_opaque,
1398 void (*error_func)(void *opaque, const char *msg))
1400 s->error_opaque = error_opaque;
1401 s->error_func = error_func;
1403 #endif
1405 /* error without aborting current compilation */
1406 void error_noabort(const char *fmt, ...)
1408 TCCState *s1 = tcc_state;
1409 va_list ap;
1411 va_start(ap, fmt);
1412 error1(s1, 0, fmt, ap);
1413 va_end(ap);
1416 void error(const char *fmt, ...)
1418 TCCState *s1 = tcc_state;
1419 va_list ap;
1421 va_start(ap, fmt);
1422 error1(s1, 0, fmt, ap);
1423 va_end(ap);
1424 /* better than nothing: in some cases, we accept to handle errors */
1425 if (s1->error_set_jmp_enabled) {
1426 longjmp(s1->error_jmp_buf, 1);
1427 } else {
1428 /* XXX: eliminate this someday */
1429 exit(1);
1433 void expect(const char *msg)
1435 error("%s expected", msg);
1438 void warning(const char *fmt, ...)
1440 TCCState *s1 = tcc_state;
1441 va_list ap;
1443 if (s1->warn_none)
1444 return;
1446 va_start(ap, fmt);
1447 error1(s1, 1, fmt, ap);
1448 va_end(ap);
1451 void skip(int c)
1453 if (tok != c)
1454 error("'%c' expected", c);
1455 next();
1458 static void test_lvalue(void)
1460 if (!(vtop->r & VT_LVAL))
1461 expect("lvalue");
1464 /* allocate a new token */
1465 static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len)
1467 TokenSym *ts, **ptable;
1468 int i;
1470 if (tok_ident >= SYM_FIRST_ANOM)
1471 error("memory full");
1473 /* expand token table if needed */
1474 i = tok_ident - TOK_IDENT;
1475 if ((i % TOK_ALLOC_INCR) == 0) {
1476 ptable = tcc_realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *));
1477 if (!ptable)
1478 error("memory full");
1479 table_ident = ptable;
1482 ts = tcc_malloc(sizeof(TokenSym) + len);
1483 table_ident[i] = ts;
1484 ts->tok = tok_ident++;
1485 ts->sym_define = NULL;
1486 ts->sym_label = NULL;
1487 ts->sym_struct = NULL;
1488 ts->sym_identifier = NULL;
1489 ts->len = len;
1490 ts->hash_next = NULL;
1491 memcpy(ts->str, str, len);
1492 ts->str[len] = '\0';
1493 *pts = ts;
1494 return ts;
1497 #define TOK_HASH_INIT 1
1498 #define TOK_HASH_FUNC(h, c) ((h) * 263 + (c))
1500 /* find a token and add it if not found */
1501 static TokenSym *tok_alloc(const char *str, int len)
1503 TokenSym *ts, **pts;
1504 int i;
1505 unsigned int h;
1507 h = TOK_HASH_INIT;
1508 for(i=0;i<len;i++)
1509 h = TOK_HASH_FUNC(h, ((unsigned char *)str)[i]);
1510 h &= (TOK_HASH_SIZE - 1);
1512 pts = &hash_ident[h];
1513 for(;;) {
1514 ts = *pts;
1515 if (!ts)
1516 break;
1517 if (ts->len == len && !memcmp(ts->str, str, len))
1518 return ts;
1519 pts = &(ts->hash_next);
1521 return tok_alloc_new(pts, str, len);
1524 /* CString handling */
1526 static void cstr_realloc(CString *cstr, int new_size)
1528 int size;
1529 void *data;
1531 size = cstr->size_allocated;
1532 if (size == 0)
1533 size = 8; /* no need to allocate a too small first string */
1534 while (size < new_size)
1535 size = size * 2;
1536 data = tcc_realloc(cstr->data_allocated, size);
1537 if (!data)
1538 error("memory full");
1539 cstr->data_allocated = data;
1540 cstr->size_allocated = size;
1541 cstr->data = data;
1544 /* add a byte */
1545 static inline void cstr_ccat(CString *cstr, int ch)
1547 int size;
1548 size = cstr->size + 1;
1549 if (size > cstr->size_allocated)
1550 cstr_realloc(cstr, size);
1551 ((unsigned char *)cstr->data)[size - 1] = ch;
1552 cstr->size = size;
1555 static void cstr_cat(CString *cstr, const char *str)
1557 int c;
1558 for(;;) {
1559 c = *str;
1560 if (c == '\0')
1561 break;
1562 cstr_ccat(cstr, c);
1563 str++;
1567 /* add a wide char */
1568 static void cstr_wccat(CString *cstr, int ch)
1570 int size;
1571 size = cstr->size + sizeof(nwchar_t);
1572 if (size > cstr->size_allocated)
1573 cstr_realloc(cstr, size);
1574 *(nwchar_t *)(((unsigned char *)cstr->data) + size - sizeof(nwchar_t)) = ch;
1575 cstr->size = size;
1578 static void cstr_new(CString *cstr)
1580 memset(cstr, 0, sizeof(CString));
1583 /* free string and reset it to NULL */
1584 static void cstr_free(CString *cstr)
1586 tcc_free(cstr->data_allocated);
1587 cstr_new(cstr);
1590 #define cstr_reset(cstr) cstr_free(cstr)
1592 /* XXX: unicode ? */
1593 static void add_char(CString *cstr, int c)
1595 if (c == '\'' || c == '\"' || c == '\\') {
1596 /* XXX: could be more precise if char or string */
1597 cstr_ccat(cstr, '\\');
1599 if (c >= 32 && c <= 126) {
1600 cstr_ccat(cstr, c);
1601 } else {
1602 cstr_ccat(cstr, '\\');
1603 if (c == '\n') {
1604 cstr_ccat(cstr, 'n');
1605 } else {
1606 cstr_ccat(cstr, '0' + ((c >> 6) & 7));
1607 cstr_ccat(cstr, '0' + ((c >> 3) & 7));
1608 cstr_ccat(cstr, '0' + (c & 7));
1613 /* XXX: buffer overflow */
1614 /* XXX: float tokens */
1615 char *get_tok_str(int v, CValue *cv)
1617 static char buf[STRING_MAX_SIZE + 1];
1618 static CString cstr_buf;
1619 CString *cstr;
1620 unsigned char *q;
1621 char *p;
1622 int i, len;
1624 /* NOTE: to go faster, we give a fixed buffer for small strings */
1625 cstr_reset(&cstr_buf);
1626 cstr_buf.data = buf;
1627 cstr_buf.size_allocated = sizeof(buf);
1628 p = buf;
1630 switch(v) {
1631 case TOK_CINT:
1632 case TOK_CUINT:
1633 /* XXX: not quite exact, but only useful for testing */
1634 sprintf(p, "%u", cv->ui);
1635 break;
1636 case TOK_CLLONG:
1637 case TOK_CULLONG:
1638 /* XXX: not quite exact, but only useful for testing */
1639 sprintf(p, "%Lu", cv->ull);
1640 break;
1641 case TOK_CCHAR:
1642 case TOK_LCHAR:
1643 cstr_ccat(&cstr_buf, '\'');
1644 add_char(&cstr_buf, cv->i);
1645 cstr_ccat(&cstr_buf, '\'');
1646 cstr_ccat(&cstr_buf, '\0');
1647 break;
1648 case TOK_PPNUM:
1649 cstr = cv->cstr;
1650 len = cstr->size - 1;
1651 for(i=0;i<len;i++)
1652 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1653 cstr_ccat(&cstr_buf, '\0');
1654 break;
1655 case TOK_STR:
1656 case TOK_LSTR:
1657 cstr = cv->cstr;
1658 cstr_ccat(&cstr_buf, '\"');
1659 if (v == TOK_STR) {
1660 len = cstr->size - 1;
1661 for(i=0;i<len;i++)
1662 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1663 } else {
1664 len = (cstr->size / sizeof(nwchar_t)) - 1;
1665 for(i=0;i<len;i++)
1666 add_char(&cstr_buf, ((nwchar_t *)cstr->data)[i]);
1668 cstr_ccat(&cstr_buf, '\"');
1669 cstr_ccat(&cstr_buf, '\0');
1670 break;
1671 case TOK_LT:
1672 v = '<';
1673 goto addv;
1674 case TOK_GT:
1675 v = '>';
1676 goto addv;
1677 case TOK_A_SHL:
1678 return strcpy(p, "<<=");
1679 case TOK_A_SAR:
1680 return strcpy(p, ">>=");
1681 default:
1682 if (v < TOK_IDENT) {
1683 /* search in two bytes table */
1684 q = tok_two_chars;
1685 while (*q) {
1686 if (q[2] == v) {
1687 *p++ = q[0];
1688 *p++ = q[1];
1689 *p = '\0';
1690 return buf;
1692 q += 3;
1694 addv:
1695 *p++ = v;
1696 *p = '\0';
1697 } else if (v < tok_ident) {
1698 return table_ident[v - TOK_IDENT]->str;
1699 } else if (v >= SYM_FIRST_ANOM) {
1700 /* special name for anonymous symbol */
1701 sprintf(p, "L.%u", v - SYM_FIRST_ANOM);
1702 } else {
1703 /* should never happen */
1704 return NULL;
1706 break;
1708 return cstr_buf.data;
1711 /* push, without hashing */
1712 static Sym *sym_push2(Sym **ps, int v, int t, int c)
1714 Sym *s;
1715 s = sym_malloc();
1716 s->v = v;
1717 s->type.t = t;
1718 s->c = c;
1719 s->next = NULL;
1720 /* add in stack */
1721 s->prev = *ps;
1722 *ps = s;
1723 return s;
1726 /* find a symbol and return its associated structure. 's' is the top
1727 of the symbol stack */
1728 static Sym *sym_find2(Sym *s, int v)
1730 while (s) {
1731 if (s->v == v)
1732 return s;
1733 s = s->prev;
1735 return NULL;
1738 /* structure lookup */
1739 static inline Sym *struct_find(int v)
1741 v -= TOK_IDENT;
1742 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1743 return NULL;
1744 return table_ident[v]->sym_struct;
1747 /* find an identifier */
1748 static inline Sym *sym_find(int v)
1750 v -= TOK_IDENT;
1751 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1752 return NULL;
1753 return table_ident[v]->sym_identifier;
1756 /* push a given symbol on the symbol stack */
1757 static Sym *sym_push(int v, CType *type, int r, int c)
1759 Sym *s, **ps;
1760 TokenSym *ts;
1762 if (local_stack)
1763 ps = &local_stack;
1764 else
1765 ps = &global_stack;
1766 s = sym_push2(ps, v, type->t, c);
1767 s->type.ref = type->ref;
1768 s->r = r;
1769 /* don't record fields or anonymous symbols */
1770 /* XXX: simplify */
1771 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1772 /* record symbol in token array */
1773 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1774 if (v & SYM_STRUCT)
1775 ps = &ts->sym_struct;
1776 else
1777 ps = &ts->sym_identifier;
1778 s->prev_tok = *ps;
1779 *ps = s;
1781 return s;
1784 /* push a global identifier */
1785 static Sym *global_identifier_push(int v, int t, int c)
1787 Sym *s, **ps;
1788 s = sym_push2(&global_stack, v, t, c);
1789 /* don't record anonymous symbol */
1790 if (v < SYM_FIRST_ANOM) {
1791 ps = &table_ident[v - TOK_IDENT]->sym_identifier;
1792 /* modify the top most local identifier, so that
1793 sym_identifier will point to 's' when popped */
1794 while (*ps != NULL)
1795 ps = &(*ps)->prev_tok;
1796 s->prev_tok = NULL;
1797 *ps = s;
1799 return s;
1802 /* pop symbols until top reaches 'b' */
1803 static void sym_pop(Sym **ptop, Sym *b)
1805 Sym *s, *ss, **ps;
1806 TokenSym *ts;
1807 int v;
1809 s = *ptop;
1810 while(s != b) {
1811 ss = s->prev;
1812 v = s->v;
1813 /* remove symbol in token array */
1814 /* XXX: simplify */
1815 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1816 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1817 if (v & SYM_STRUCT)
1818 ps = &ts->sym_struct;
1819 else
1820 ps = &ts->sym_identifier;
1821 *ps = s->prev_tok;
1823 sym_free(s);
1824 s = ss;
1826 *ptop = b;
1829 /* I/O layer */
1831 BufferedFile *tcc_open(TCCState *s1, const char *filename)
1833 int fd;
1834 BufferedFile *bf;
1836 fd = open(filename, O_RDONLY | O_BINARY);
1837 if (fd < 0)
1838 return NULL;
1839 bf = tcc_malloc(sizeof(BufferedFile));
1840 if (!bf) {
1841 close(fd);
1842 return NULL;
1844 bf->fd = fd;
1845 bf->buf_ptr = bf->buffer;
1846 bf->buf_end = bf->buffer;
1847 bf->buffer[0] = CH_EOB; /* put eob symbol */
1848 pstrcpy(bf->filename, sizeof(bf->filename), filename);
1849 bf->line_num = 1;
1850 bf->ifndef_macro = 0;
1851 bf->ifdef_stack_ptr = s1->ifdef_stack_ptr;
1852 // printf("opening '%s'\n", filename);
1853 return bf;
1856 void tcc_close(BufferedFile *bf)
1858 total_lines += bf->line_num;
1859 close(bf->fd);
1860 tcc_free(bf);
1863 /* fill input buffer and peek next char */
1864 static int tcc_peekc_slow(BufferedFile *bf)
1866 int len;
1867 /* only tries to read if really end of buffer */
1868 if (bf->buf_ptr >= bf->buf_end) {
1869 if (bf->fd != -1) {
1870 #if defined(PARSE_DEBUG)
1871 len = 8;
1872 #else
1873 len = IO_BUF_SIZE;
1874 #endif
1875 len = read(bf->fd, bf->buffer, len);
1876 if (len < 0)
1877 len = 0;
1878 } else {
1879 len = 0;
1881 total_bytes += len;
1882 bf->buf_ptr = bf->buffer;
1883 bf->buf_end = bf->buffer + len;
1884 *bf->buf_end = CH_EOB;
1886 if (bf->buf_ptr < bf->buf_end) {
1887 return bf->buf_ptr[0];
1888 } else {
1889 bf->buf_ptr = bf->buf_end;
1890 return CH_EOF;
1894 /* return the current character, handling end of block if necessary
1895 (but not stray) */
1896 static int handle_eob(void)
1898 return tcc_peekc_slow(file);
1901 /* read next char from current input file and handle end of input buffer */
1902 static inline void inp(void)
1904 ch = *(++(file->buf_ptr));
1905 /* end of buffer/file handling */
1906 if (ch == CH_EOB)
1907 ch = handle_eob();
1910 /* handle '\[\r]\n' */
1911 static void handle_stray(void)
1913 while (ch == '\\') {
1914 inp();
1915 if (ch == '\n') {
1916 file->line_num++;
1917 inp();
1918 } else if (ch == '\r') {
1919 inp();
1920 if (ch != '\n')
1921 goto fail;
1922 file->line_num++;
1923 inp();
1924 } else {
1925 fail:
1926 error("stray '\\' in program");
1931 /* skip the stray and handle the \\n case. Output an error if
1932 incorrect char after the stray */
1933 static int handle_stray1(uint8_t *p)
1935 int c;
1937 if (p >= file->buf_end) {
1938 file->buf_ptr = p;
1939 c = handle_eob();
1940 p = file->buf_ptr;
1941 if (c == '\\')
1942 goto parse_stray;
1943 } else {
1944 parse_stray:
1945 file->buf_ptr = p;
1946 ch = *p;
1947 handle_stray();
1948 p = file->buf_ptr;
1949 c = *p;
1951 return c;
1954 /* handle just the EOB case, but not stray */
1955 #define PEEKC_EOB(c, p)\
1957 p++;\
1958 c = *p;\
1959 if (c == '\\') {\
1960 file->buf_ptr = p;\
1961 c = handle_eob();\
1962 p = file->buf_ptr;\
1966 /* handle the complicated stray case */
1967 #define PEEKC(c, p)\
1969 p++;\
1970 c = *p;\
1971 if (c == '\\') {\
1972 c = handle_stray1(p);\
1973 p = file->buf_ptr;\
1977 /* input with '\[\r]\n' handling. Note that this function cannot
1978 handle other characters after '\', so you cannot call it inside
1979 strings or comments */
1980 static void minp(void)
1982 inp();
1983 if (ch == '\\')
1984 handle_stray();
1988 /* single line C++ comments */
1989 static uint8_t *parse_line_comment(uint8_t *p)
1991 int c;
1993 p++;
1994 for(;;) {
1995 c = *p;
1996 redo:
1997 if (c == '\n' || c == CH_EOF) {
1998 break;
1999 } else if (c == '\\') {
2000 file->buf_ptr = p;
2001 c = handle_eob();
2002 p = file->buf_ptr;
2003 if (c == '\\') {
2004 PEEKC_EOB(c, p);
2005 if (c == '\n') {
2006 file->line_num++;
2007 PEEKC_EOB(c, p);
2008 } else if (c == '\r') {
2009 PEEKC_EOB(c, p);
2010 if (c == '\n') {
2011 file->line_num++;
2012 PEEKC_EOB(c, p);
2015 } else {
2016 goto redo;
2018 } else {
2019 p++;
2022 return p;
2025 /* C comments */
2026 static uint8_t *parse_comment(uint8_t *p)
2028 int c;
2030 p++;
2031 for(;;) {
2032 /* fast skip loop */
2033 for(;;) {
2034 c = *p;
2035 if (c == '\n' || c == '*' || c == '\\')
2036 break;
2037 p++;
2038 c = *p;
2039 if (c == '\n' || c == '*' || c == '\\')
2040 break;
2041 p++;
2043 /* now we can handle all the cases */
2044 if (c == '\n') {
2045 file->line_num++;
2046 p++;
2047 } else if (c == '*') {
2048 p++;
2049 for(;;) {
2050 c = *p;
2051 if (c == '*') {
2052 p++;
2053 } else if (c == '/') {
2054 goto end_of_comment;
2055 } else if (c == '\\') {
2056 file->buf_ptr = p;
2057 c = handle_eob();
2058 p = file->buf_ptr;
2059 if (c == '\\') {
2060 /* skip '\[\r]\n', otherwise just skip the stray */
2061 while (c == '\\') {
2062 PEEKC_EOB(c, p);
2063 if (c == '\n') {
2064 file->line_num++;
2065 PEEKC_EOB(c, p);
2066 } else if (c == '\r') {
2067 PEEKC_EOB(c, p);
2068 if (c == '\n') {
2069 file->line_num++;
2070 PEEKC_EOB(c, p);
2072 } else {
2073 goto after_star;
2077 } else {
2078 break;
2081 after_star: ;
2082 } else {
2083 /* stray, eob or eof */
2084 file->buf_ptr = p;
2085 c = handle_eob();
2086 p = file->buf_ptr;
2087 if (c == CH_EOF) {
2088 error("unexpected end of file in comment");
2089 } else if (c == '\\') {
2090 p++;
2094 end_of_comment:
2095 p++;
2096 return p;
2099 #define cinp minp
2101 /* space exlcuding newline */
2102 static inline int is_space(int ch)
2104 return ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f' || ch == '\r';
2107 static inline void skip_spaces(void)
2109 while (is_space(ch))
2110 cinp();
2113 /* parse a string without interpreting escapes */
2114 static uint8_t *parse_pp_string(uint8_t *p,
2115 int sep, CString *str)
2117 int c;
2118 p++;
2119 for(;;) {
2120 c = *p;
2121 if (c == sep) {
2122 break;
2123 } else if (c == '\\') {
2124 file->buf_ptr = p;
2125 c = handle_eob();
2126 p = file->buf_ptr;
2127 if (c == CH_EOF) {
2128 unterminated_string:
2129 /* XXX: indicate line number of start of string */
2130 error("missing terminating %c character", sep);
2131 } else if (c == '\\') {
2132 /* escape : just skip \[\r]\n */
2133 PEEKC_EOB(c, p);
2134 if (c == '\n') {
2135 file->line_num++;
2136 p++;
2137 } else if (c == '\r') {
2138 PEEKC_EOB(c, p);
2139 if (c != '\n')
2140 expect("'\n' after '\r'");
2141 file->line_num++;
2142 p++;
2143 } else if (c == CH_EOF) {
2144 goto unterminated_string;
2145 } else {
2146 if (str) {
2147 cstr_ccat(str, '\\');
2148 cstr_ccat(str, c);
2150 p++;
2153 } else if (c == '\n') {
2154 file->line_num++;
2155 goto add_char;
2156 } else if (c == '\r') {
2157 PEEKC_EOB(c, p);
2158 if (c != '\n') {
2159 if (str)
2160 cstr_ccat(str, '\r');
2161 } else {
2162 file->line_num++;
2163 goto add_char;
2165 } else {
2166 add_char:
2167 if (str)
2168 cstr_ccat(str, c);
2169 p++;
2172 p++;
2173 return p;
2176 /* skip block of text until #else, #elif or #endif. skip also pairs of
2177 #if/#endif */
2178 void preprocess_skip(void)
2180 int a, start_of_line, c;
2181 uint8_t *p;
2183 p = file->buf_ptr;
2184 start_of_line = 1;
2185 a = 0;
2186 for(;;) {
2187 redo_no_start:
2188 c = *p;
2189 switch(c) {
2190 case ' ':
2191 case '\t':
2192 case '\f':
2193 case '\v':
2194 case '\r':
2195 p++;
2196 goto redo_no_start;
2197 case '\n':
2198 start_of_line = 1;
2199 file->line_num++;
2200 p++;
2201 goto redo_no_start;
2202 case '\\':
2203 file->buf_ptr = p;
2204 c = handle_eob();
2205 if (c == CH_EOF) {
2206 expect("#endif");
2207 } else if (c == '\\') {
2208 /* XXX: incorrect: should not give an error */
2209 ch = file->buf_ptr[0];
2210 handle_stray();
2212 p = file->buf_ptr;
2213 goto redo_no_start;
2214 /* skip strings */
2215 case '\"':
2216 case '\'':
2217 p = parse_pp_string(p, c, NULL);
2218 break;
2219 /* skip comments */
2220 case '/':
2221 file->buf_ptr = p;
2222 ch = *p;
2223 minp();
2224 p = file->buf_ptr;
2225 if (ch == '*') {
2226 p = parse_comment(p);
2227 } else if (ch == '/') {
2228 p = parse_line_comment(p);
2230 break;
2232 case '#':
2233 p++;
2234 if (start_of_line) {
2235 file->buf_ptr = p;
2236 next_nomacro();
2237 p = file->buf_ptr;
2238 if (a == 0 &&
2239 (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
2240 goto the_end;
2241 if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
2242 a++;
2243 else if (tok == TOK_ENDIF)
2244 a--;
2246 break;
2247 default:
2248 p++;
2249 break;
2251 start_of_line = 0;
2253 the_end: ;
2254 file->buf_ptr = p;
2257 /* ParseState handling */
2259 /* XXX: currently, no include file info is stored. Thus, we cannot display
2260 accurate messages if the function or data definition spans multiple
2261 files */
2263 /* save current parse state in 's' */
2264 void save_parse_state(ParseState *s)
2266 s->line_num = file->line_num;
2267 s->macro_ptr = macro_ptr;
2268 s->tok = tok;
2269 s->tokc = tokc;
2272 /* restore parse state from 's' */
2273 void restore_parse_state(ParseState *s)
2275 file->line_num = s->line_num;
2276 macro_ptr = s->macro_ptr;
2277 tok = s->tok;
2278 tokc = s->tokc;
2281 /* return the number of additional 'ints' necessary to store the
2282 token */
2283 static inline int tok_ext_size(int t)
2285 switch(t) {
2286 /* 4 bytes */
2287 case TOK_CINT:
2288 case TOK_CUINT:
2289 case TOK_CCHAR:
2290 case TOK_LCHAR:
2291 case TOK_CFLOAT:
2292 case TOK_LINENUM:
2293 return 1;
2294 case TOK_STR:
2295 case TOK_LSTR:
2296 case TOK_PPNUM:
2297 error("unsupported token");
2298 return 1;
2299 case TOK_CDOUBLE:
2300 case TOK_CLLONG:
2301 case TOK_CULLONG:
2302 return 2;
2303 case TOK_CLDOUBLE:
2304 return LDOUBLE_SIZE / 4;
2305 default:
2306 return 0;
2310 /* token string handling */
2312 static inline void tok_str_new(TokenString *s)
2314 s->str = NULL;
2315 s->len = 0;
2316 s->allocated_len = 0;
2317 s->last_line_num = -1;
2320 static void tok_str_free(int *str)
2322 tcc_free(str);
2325 static int *tok_str_realloc(TokenString *s)
2327 int *str, len;
2329 if (s->allocated_len == 0) {
2330 len = 8;
2331 } else {
2332 len = s->allocated_len * 2;
2334 str = tcc_realloc(s->str, len * sizeof(int));
2335 if (!str)
2336 error("memory full");
2337 s->allocated_len = len;
2338 s->str = str;
2339 return str;
2342 static void tok_str_add(TokenString *s, int t)
2344 int len, *str;
2346 len = s->len;
2347 str = s->str;
2348 if (len >= s->allocated_len)
2349 str = tok_str_realloc(s);
2350 str[len++] = t;
2351 s->len = len;
2354 static void tok_str_add2(TokenString *s, int t, CValue *cv)
2356 int len, *str;
2358 len = s->len;
2359 str = s->str;
2361 /* allocate space for worst case */
2362 if (len + TOK_MAX_SIZE > s->allocated_len)
2363 str = tok_str_realloc(s);
2364 str[len++] = t;
2365 switch(t) {
2366 case TOK_CINT:
2367 case TOK_CUINT:
2368 case TOK_CCHAR:
2369 case TOK_LCHAR:
2370 case TOK_CFLOAT:
2371 case TOK_LINENUM:
2372 str[len++] = cv->tab[0];
2373 break;
2374 case TOK_PPNUM:
2375 case TOK_STR:
2376 case TOK_LSTR:
2378 int nb_words;
2379 CString *cstr;
2381 nb_words = (sizeof(CString) + cv->cstr->size + 3) >> 2;
2382 while ((len + nb_words) > s->allocated_len)
2383 str = tok_str_realloc(s);
2384 cstr = (CString *)(str + len);
2385 cstr->data = NULL;
2386 cstr->size = cv->cstr->size;
2387 cstr->data_allocated = NULL;
2388 cstr->size_allocated = cstr->size;
2389 memcpy((char *)cstr + sizeof(CString),
2390 cv->cstr->data, cstr->size);
2391 len += nb_words;
2393 break;
2394 case TOK_CDOUBLE:
2395 case TOK_CLLONG:
2396 case TOK_CULLONG:
2397 #if LDOUBLE_SIZE == 8
2398 case TOK_CLDOUBLE:
2399 #endif
2400 str[len++] = cv->tab[0];
2401 str[len++] = cv->tab[1];
2402 break;
2403 #if LDOUBLE_SIZE == 12
2404 case TOK_CLDOUBLE:
2405 str[len++] = cv->tab[0];
2406 str[len++] = cv->tab[1];
2407 str[len++] = cv->tab[2];
2408 #elif LDOUBLE_SIZE != 8
2409 #error add long double size support
2410 #endif
2411 break;
2412 default:
2413 break;
2415 s->len = len;
2418 /* add the current parse token in token string 's' */
2419 static void tok_str_add_tok(TokenString *s)
2421 CValue cval;
2423 /* save line number info */
2424 if (file->line_num != s->last_line_num) {
2425 s->last_line_num = file->line_num;
2426 cval.i = s->last_line_num;
2427 tok_str_add2(s, TOK_LINENUM, &cval);
2429 tok_str_add2(s, tok, &tokc);
2432 #if LDOUBLE_SIZE == 12
2433 #define LDOUBLE_GET(p, cv) \
2434 cv.tab[0] = p[0]; \
2435 cv.tab[1] = p[1]; \
2436 cv.tab[2] = p[2];
2437 #elif LDOUBLE_SIZE == 8
2438 #define LDOUBLE_GET(p, cv) \
2439 cv.tab[0] = p[0]; \
2440 cv.tab[1] = p[1];
2441 #else
2442 #error add long double size support
2443 #endif
2446 /* get a token from an integer array and increment pointer
2447 accordingly. we code it as a macro to avoid pointer aliasing. */
2448 #define TOK_GET(t, p, cv) \
2450 t = *p++; \
2451 switch(t) { \
2452 case TOK_CINT: \
2453 case TOK_CUINT: \
2454 case TOK_CCHAR: \
2455 case TOK_LCHAR: \
2456 case TOK_CFLOAT: \
2457 case TOK_LINENUM: \
2458 cv.tab[0] = *p++; \
2459 break; \
2460 case TOK_STR: \
2461 case TOK_LSTR: \
2462 case TOK_PPNUM: \
2463 cv.cstr = (CString *)p; \
2464 cv.cstr->data = (char *)p + sizeof(CString);\
2465 p += (sizeof(CString) + cv.cstr->size + 3) >> 2;\
2466 break; \
2467 case TOK_CDOUBLE: \
2468 case TOK_CLLONG: \
2469 case TOK_CULLONG: \
2470 cv.tab[0] = p[0]; \
2471 cv.tab[1] = p[1]; \
2472 p += 2; \
2473 break; \
2474 case TOK_CLDOUBLE: \
2475 LDOUBLE_GET(p, cv); \
2476 p += LDOUBLE_SIZE / 4; \
2477 break; \
2478 default: \
2479 break; \
2483 /* defines handling */
2484 static inline void define_push(int v, int macro_type, int *str, Sym *first_arg)
2486 Sym *s;
2488 s = sym_push2(&define_stack, v, macro_type, (int)str);
2489 s->next = first_arg;
2490 table_ident[v - TOK_IDENT]->sym_define = s;
2493 /* undefined a define symbol. Its name is just set to zero */
2494 static void define_undef(Sym *s)
2496 int v;
2497 v = s->v;
2498 if (v >= TOK_IDENT && v < tok_ident)
2499 table_ident[v - TOK_IDENT]->sym_define = NULL;
2500 s->v = 0;
2503 static inline Sym *define_find(int v)
2505 v -= TOK_IDENT;
2506 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2507 return NULL;
2508 return table_ident[v]->sym_define;
2511 /* free define stack until top reaches 'b' */
2512 static void free_defines(Sym *b)
2514 Sym *top, *top1;
2515 int v;
2517 top = define_stack;
2518 while (top != b) {
2519 top1 = top->prev;
2520 /* do not free args or predefined defines */
2521 if (top->c)
2522 tok_str_free((int *)top->c);
2523 v = top->v;
2524 if (v >= TOK_IDENT && v < tok_ident)
2525 table_ident[v - TOK_IDENT]->sym_define = NULL;
2526 sym_free(top);
2527 top = top1;
2529 define_stack = b;
2532 /* label lookup */
2533 static Sym *label_find(int v)
2535 v -= TOK_IDENT;
2536 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2537 return NULL;
2538 return table_ident[v]->sym_label;
2541 static Sym *label_push(Sym **ptop, int v, int flags)
2543 Sym *s, **ps;
2544 s = sym_push2(ptop, v, 0, 0);
2545 s->r = flags;
2546 ps = &table_ident[v - TOK_IDENT]->sym_label;
2547 if (ptop == &global_label_stack) {
2548 /* modify the top most local identifier, so that
2549 sym_identifier will point to 's' when popped */
2550 while (*ps != NULL)
2551 ps = &(*ps)->prev_tok;
2553 s->prev_tok = *ps;
2554 *ps = s;
2555 return s;
2558 /* pop labels until element last is reached. Look if any labels are
2559 undefined. Define symbols if '&&label' was used. */
2560 static void label_pop(Sym **ptop, Sym *slast)
2562 Sym *s, *s1;
2563 for(s = *ptop; s != slast; s = s1) {
2564 s1 = s->prev;
2565 if (s->r == LABEL_DECLARED) {
2566 warning("label '%s' declared but not used", get_tok_str(s->v, NULL));
2567 } else if (s->r == LABEL_FORWARD) {
2568 error("label '%s' used but not defined",
2569 get_tok_str(s->v, NULL));
2570 } else {
2571 if (s->c) {
2572 /* define corresponding symbol. A size of
2573 1 is put. */
2574 put_extern_sym(s, cur_text_section, (long)s->next, 1);
2577 /* remove label */
2578 table_ident[s->v - TOK_IDENT]->sym_label = s->prev_tok;
2579 sym_free(s);
2581 *ptop = slast;
2584 /* eval an expression for #if/#elif */
2585 static int expr_preprocess(void)
2587 int c, t;
2588 TokenString str;
2590 tok_str_new(&str);
2591 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2592 next(); /* do macro subst */
2593 if (tok == TOK_DEFINED) {
2594 next_nomacro();
2595 t = tok;
2596 if (t == '(')
2597 next_nomacro();
2598 c = define_find(tok) != 0;
2599 if (t == '(')
2600 next_nomacro();
2601 tok = TOK_CINT;
2602 tokc.i = c;
2603 } else if (tok >= TOK_IDENT) {
2604 /* if undefined macro */
2605 tok = TOK_CINT;
2606 tokc.i = 0;
2608 tok_str_add_tok(&str);
2610 tok_str_add(&str, -1); /* simulate end of file */
2611 tok_str_add(&str, 0);
2612 /* now evaluate C constant expression */
2613 macro_ptr = str.str;
2614 next();
2615 c = expr_const();
2616 macro_ptr = NULL;
2617 tok_str_free(str.str);
2618 return c != 0;
2621 #if defined(PARSE_DEBUG) || defined(PP_DEBUG)
2622 static void tok_print(int *str)
2624 int t;
2625 CValue cval;
2627 while (1) {
2628 TOK_GET(t, str, cval);
2629 if (!t)
2630 break;
2631 printf(" %s", get_tok_str(t, &cval));
2633 printf("\n");
2635 #endif
2637 /* parse after #define */
2638 static void parse_define(void)
2640 Sym *s, *first, **ps;
2641 int v, t, varg, is_vaargs, c;
2642 TokenString str;
2644 v = tok;
2645 if (v < TOK_IDENT)
2646 error("invalid macro name '%s'", get_tok_str(tok, &tokc));
2647 /* XXX: should check if same macro (ANSI) */
2648 first = NULL;
2649 t = MACRO_OBJ;
2650 /* '(' must be just after macro definition for MACRO_FUNC */
2651 c = file->buf_ptr[0];
2652 if (c == '\\')
2653 c = handle_stray1(file->buf_ptr);
2654 if (c == '(') {
2655 next_nomacro();
2656 next_nomacro();
2657 ps = &first;
2658 while (tok != ')') {
2659 varg = tok;
2660 next_nomacro();
2661 is_vaargs = 0;
2662 if (varg == TOK_DOTS) {
2663 varg = TOK___VA_ARGS__;
2664 is_vaargs = 1;
2665 } else if (tok == TOK_DOTS && gnu_ext) {
2666 is_vaargs = 1;
2667 next_nomacro();
2669 if (varg < TOK_IDENT)
2670 error("badly punctuated parameter list");
2671 s = sym_push2(&define_stack, varg | SYM_FIELD, is_vaargs, 0);
2672 *ps = s;
2673 ps = &s->next;
2674 if (tok != ',')
2675 break;
2676 next_nomacro();
2678 t = MACRO_FUNC;
2680 tok_str_new(&str);
2681 next_nomacro();
2682 /* EOF testing necessary for '-D' handling */
2683 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2684 tok_str_add2(&str, tok, &tokc);
2685 next_nomacro();
2687 tok_str_add(&str, 0);
2688 #ifdef PP_DEBUG
2689 printf("define %s %d: ", get_tok_str(v, NULL), t);
2690 tok_print(str.str);
2691 #endif
2692 define_push(v, t, str.str, first);
2695 static inline int hash_cached_include(int type, const char *filename)
2697 const unsigned char *s;
2698 unsigned int h;
2700 h = TOK_HASH_INIT;
2701 h = TOK_HASH_FUNC(h, type);
2702 s = filename;
2703 while (*s) {
2704 h = TOK_HASH_FUNC(h, *s);
2705 s++;
2707 h &= (CACHED_INCLUDES_HASH_SIZE - 1);
2708 return h;
2711 /* XXX: use a token or a hash table to accelerate matching ? */
2712 static CachedInclude *search_cached_include(TCCState *s1,
2713 int type, const char *filename)
2715 CachedInclude *e;
2716 int i, h;
2717 h = hash_cached_include(type, filename);
2718 i = s1->cached_includes_hash[h];
2719 for(;;) {
2720 if (i == 0)
2721 break;
2722 e = s1->cached_includes[i - 1];
2723 if (e->type == type && !strcmp(e->filename, filename))
2724 return e;
2725 i = e->hash_next;
2727 return NULL;
2730 static inline void add_cached_include(TCCState *s1, int type,
2731 const char *filename, int ifndef_macro)
2733 CachedInclude *e;
2734 int h;
2736 if (search_cached_include(s1, type, filename))
2737 return;
2738 #ifdef INC_DEBUG
2739 printf("adding cached '%s' %s\n", filename, get_tok_str(ifndef_macro, NULL));
2740 #endif
2741 e = tcc_malloc(sizeof(CachedInclude) + strlen(filename));
2742 if (!e)
2743 return;
2744 e->type = type;
2745 strcpy(e->filename, filename);
2746 e->ifndef_macro = ifndef_macro;
2747 dynarray_add((void ***)&s1->cached_includes, &s1->nb_cached_includes, e);
2748 /* add in hash table */
2749 h = hash_cached_include(type, filename);
2750 e->hash_next = s1->cached_includes_hash[h];
2751 s1->cached_includes_hash[h] = s1->nb_cached_includes;
2754 static void pragma_parse(TCCState *s1)
2756 int val;
2758 next();
2759 if (tok == TOK_pack) {
2761 This may be:
2762 #pragma pack(1) // set
2763 #pragma pack() // reset to default
2764 #pragma pack(push,1) // push & set
2765 #pragma pack(pop) // restore previous
2767 next();
2768 skip('(');
2769 if (tok == TOK_ASM_pop) {
2770 next();
2771 if (s1->pack_stack_ptr <= s1->pack_stack) {
2772 stk_error:
2773 error("out of pack stack");
2775 s1->pack_stack_ptr--;
2776 } else {
2777 val = 0;
2778 if (tok != ')') {
2779 if (tok == TOK_ASM_push) {
2780 next();
2781 if (s1->pack_stack_ptr >= s1->pack_stack + PACK_STACK_SIZE - 1)
2782 goto stk_error;
2783 s1->pack_stack_ptr++;
2784 skip(',');
2786 if (tok != TOK_CINT) {
2787 pack_error:
2788 error("invalid pack pragma");
2790 val = tokc.i;
2791 if (val < 1 || val > 16 || (val & (val - 1)) != 0)
2792 goto pack_error;
2793 next();
2795 *s1->pack_stack_ptr = val;
2796 skip(')');
2801 /* is_bof is true if first non space token at beginning of file */
2802 static void preprocess(int is_bof)
2804 TCCState *s1 = tcc_state;
2805 int size, i, c, n, saved_parse_flags;
2806 char buf[1024], *q, *p;
2807 char buf1[1024];
2808 BufferedFile *f;
2809 Sym *s;
2810 CachedInclude *e;
2812 saved_parse_flags = parse_flags;
2813 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM |
2814 PARSE_FLAG_LINEFEED;
2815 next_nomacro();
2816 redo:
2817 switch(tok) {
2818 case TOK_DEFINE:
2819 next_nomacro();
2820 parse_define();
2821 break;
2822 case TOK_UNDEF:
2823 next_nomacro();
2824 s = define_find(tok);
2825 /* undefine symbol by putting an invalid name */
2826 if (s)
2827 define_undef(s);
2828 break;
2829 case TOK_INCLUDE:
2830 case TOK_INCLUDE_NEXT:
2831 ch = file->buf_ptr[0];
2832 /* XXX: incorrect if comments : use next_nomacro with a special mode */
2833 skip_spaces();
2834 if (ch == '<') {
2835 c = '>';
2836 goto read_name;
2837 } else if (ch == '\"') {
2838 c = ch;
2839 read_name:
2840 /* XXX: better stray handling */
2841 minp();
2842 q = buf;
2843 while (ch != c && ch != '\n' && ch != CH_EOF) {
2844 if ((q - buf) < sizeof(buf) - 1)
2845 *q++ = ch;
2846 minp();
2848 *q = '\0';
2849 minp();
2850 #if 0
2851 /* eat all spaces and comments after include */
2852 /* XXX: slightly incorrect */
2853 while (ch1 != '\n' && ch1 != CH_EOF)
2854 inp();
2855 #endif
2856 } else {
2857 /* computed #include : either we have only strings or
2858 we have anything enclosed in '<>' */
2859 next();
2860 buf[0] = '\0';
2861 if (tok == TOK_STR) {
2862 while (tok != TOK_LINEFEED) {
2863 if (tok != TOK_STR) {
2864 include_syntax:
2865 error("'#include' expects \"FILENAME\" or <FILENAME>");
2867 pstrcat(buf, sizeof(buf), (char *)tokc.cstr->data);
2868 next();
2870 c = '\"';
2871 } else {
2872 int len;
2873 while (tok != TOK_LINEFEED) {
2874 pstrcat(buf, sizeof(buf), get_tok_str(tok, &tokc));
2875 next();
2877 len = strlen(buf);
2878 /* check syntax and remove '<>' */
2879 if (len < 2 || buf[0] != '<' || buf[len - 1] != '>')
2880 goto include_syntax;
2881 memmove(buf, buf + 1, len - 2);
2882 buf[len - 2] = '\0';
2883 c = '>';
2887 e = search_cached_include(s1, c, buf);
2888 if (e && define_find(e->ifndef_macro)) {
2889 /* no need to parse the include because the 'ifndef macro'
2890 is defined */
2891 #ifdef INC_DEBUG
2892 printf("%s: skipping %s\n", file->filename, buf);
2893 #endif
2894 } else {
2895 if (c == '\"') {
2896 /* first search in current dir if "header.h" */
2897 size = 0;
2898 p = strrchr(file->filename, '/');
2899 if (p)
2900 size = p + 1 - file->filename;
2901 if (size > sizeof(buf1) - 1)
2902 size = sizeof(buf1) - 1;
2903 memcpy(buf1, file->filename, size);
2904 buf1[size] = '\0';
2905 pstrcat(buf1, sizeof(buf1), buf);
2906 f = tcc_open(s1, buf1);
2907 if (f) {
2908 if (tok == TOK_INCLUDE_NEXT)
2909 tok = TOK_INCLUDE;
2910 else
2911 goto found;
2914 if (s1->include_stack_ptr >= s1->include_stack + INCLUDE_STACK_SIZE)
2915 error("#include recursion too deep");
2916 /* now search in all the include paths */
2917 n = s1->nb_include_paths + s1->nb_sysinclude_paths;
2918 for(i = 0; i < n; i++) {
2919 const char *path;
2920 if (i < s1->nb_include_paths)
2921 path = s1->include_paths[i];
2922 else
2923 path = s1->sysinclude_paths[i - s1->nb_include_paths];
2924 pstrcpy(buf1, sizeof(buf1), path);
2925 pstrcat(buf1, sizeof(buf1), "/");
2926 pstrcat(buf1, sizeof(buf1), buf);
2927 f = tcc_open(s1, buf1);
2928 if (f) {
2929 if (tok == TOK_INCLUDE_NEXT)
2930 tok = TOK_INCLUDE;
2931 else
2932 goto found;
2935 error("include file '%s' not found", buf);
2936 f = NULL;
2937 found:
2938 #ifdef INC_DEBUG
2939 printf("%s: including %s\n", file->filename, buf1);
2940 #endif
2941 f->inc_type = c;
2942 pstrcpy(f->inc_filename, sizeof(f->inc_filename), buf);
2943 /* push current file in stack */
2944 /* XXX: fix current line init */
2945 *s1->include_stack_ptr++ = file;
2946 file = f;
2947 /* add include file debug info */
2948 if (do_debug) {
2949 put_stabs(file->filename, N_BINCL, 0, 0, 0);
2951 tok_flags |= TOK_FLAG_BOF | TOK_FLAG_BOL;
2952 ch = file->buf_ptr[0];
2953 goto the_end;
2955 break;
2956 case TOK_IFNDEF:
2957 c = 1;
2958 goto do_ifdef;
2959 case TOK_IF:
2960 c = expr_preprocess();
2961 goto do_if;
2962 case TOK_IFDEF:
2963 c = 0;
2964 do_ifdef:
2965 next_nomacro();
2966 if (tok < TOK_IDENT)
2967 error("invalid argument for '#if%sdef'", c ? "n" : "");
2968 if (is_bof) {
2969 if (c) {
2970 #ifdef INC_DEBUG
2971 printf("#ifndef %s\n", get_tok_str(tok, NULL));
2972 #endif
2973 file->ifndef_macro = tok;
2976 c = (define_find(tok) != 0) ^ c;
2977 do_if:
2978 if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE)
2979 error("memory full");
2980 *s1->ifdef_stack_ptr++ = c;
2981 goto test_skip;
2982 case TOK_ELSE:
2983 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
2984 error("#else without matching #if");
2985 if (s1->ifdef_stack_ptr[-1] & 2)
2986 error("#else after #else");
2987 c = (s1->ifdef_stack_ptr[-1] ^= 3);
2988 goto test_skip;
2989 case TOK_ELIF:
2990 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
2991 error("#elif without matching #if");
2992 c = s1->ifdef_stack_ptr[-1];
2993 if (c > 1)
2994 error("#elif after #else");
2995 /* last #if/#elif expression was true: we skip */
2996 if (c == 1)
2997 goto skip;
2998 c = expr_preprocess();
2999 s1->ifdef_stack_ptr[-1] = c;
3000 test_skip:
3001 if (!(c & 1)) {
3002 skip:
3003 preprocess_skip();
3004 is_bof = 0;
3005 goto redo;
3007 break;
3008 case TOK_ENDIF:
3009 if (s1->ifdef_stack_ptr <= file->ifdef_stack_ptr)
3010 error("#endif without matching #if");
3011 s1->ifdef_stack_ptr--;
3012 /* '#ifndef macro' was at the start of file. Now we check if
3013 an '#endif' is exactly at the end of file */
3014 if (file->ifndef_macro &&
3015 s1->ifdef_stack_ptr == file->ifdef_stack_ptr) {
3016 file->ifndef_macro_saved = file->ifndef_macro;
3017 /* need to set to zero to avoid false matches if another
3018 #ifndef at middle of file */
3019 file->ifndef_macro = 0;
3020 while (tok != TOK_LINEFEED)
3021 next_nomacro();
3022 tok_flags |= TOK_FLAG_ENDIF;
3023 goto the_end;
3025 break;
3026 case TOK_LINE:
3027 next();
3028 if (tok != TOK_CINT)
3029 error("#line");
3030 file->line_num = tokc.i - 1; /* the line number will be incremented after */
3031 next();
3032 if (tok != TOK_LINEFEED) {
3033 if (tok != TOK_STR)
3034 error("#line");
3035 pstrcpy(file->filename, sizeof(file->filename),
3036 (char *)tokc.cstr->data);
3038 break;
3039 case TOK_ERROR:
3040 case TOK_WARNING:
3041 c = tok;
3042 ch = file->buf_ptr[0];
3043 skip_spaces();
3044 q = buf;
3045 while (ch != '\n' && ch != CH_EOF) {
3046 if ((q - buf) < sizeof(buf) - 1)
3047 *q++ = ch;
3048 minp();
3050 *q = '\0';
3051 if (c == TOK_ERROR)
3052 error("#error %s", buf);
3053 else
3054 warning("#warning %s", buf);
3055 break;
3056 case TOK_PRAGMA:
3057 pragma_parse(s1);
3058 break;
3059 default:
3060 if (tok == TOK_LINEFEED || tok == '!' || tok == TOK_CINT) {
3061 /* '!' is ignored to allow C scripts. numbers are ignored
3062 to emulate cpp behaviour */
3063 } else {
3064 if (!(saved_parse_flags & PARSE_FLAG_ASM_COMMENTS))
3065 error("invalid preprocessing directive #%s", get_tok_str(tok, &tokc));
3067 break;
3069 /* ignore other preprocess commands or #! for C scripts */
3070 while (tok != TOK_LINEFEED)
3071 next_nomacro();
3072 the_end:
3073 parse_flags = saved_parse_flags;
3076 /* evaluate escape codes in a string. */
3077 static void parse_escape_string(CString *outstr, const uint8_t *buf, int is_long)
3079 int c, n;
3080 const uint8_t *p;
3082 p = buf;
3083 for(;;) {
3084 c = *p;
3085 if (c == '\0')
3086 break;
3087 if (c == '\\') {
3088 p++;
3089 /* escape */
3090 c = *p;
3091 switch(c) {
3092 case '0': case '1': case '2': case '3':
3093 case '4': case '5': case '6': case '7':
3094 /* at most three octal digits */
3095 n = c - '0';
3096 p++;
3097 c = *p;
3098 if (isoct(c)) {
3099 n = n * 8 + c - '0';
3100 p++;
3101 c = *p;
3102 if (isoct(c)) {
3103 n = n * 8 + c - '0';
3104 p++;
3107 c = n;
3108 goto add_char_nonext;
3109 case 'x':
3110 p++;
3111 n = 0;
3112 for(;;) {
3113 c = *p;
3114 if (c >= 'a' && c <= 'f')
3115 c = c - 'a' + 10;
3116 else if (c >= 'A' && c <= 'F')
3117 c = c - 'A' + 10;
3118 else if (isnum(c))
3119 c = c - '0';
3120 else
3121 break;
3122 n = n * 16 + c;
3123 p++;
3125 c = n;
3126 goto add_char_nonext;
3127 case 'a':
3128 c = '\a';
3129 break;
3130 case 'b':
3131 c = '\b';
3132 break;
3133 case 'f':
3134 c = '\f';
3135 break;
3136 case 'n':
3137 c = '\n';
3138 break;
3139 case 'r':
3140 c = '\r';
3141 break;
3142 case 't':
3143 c = '\t';
3144 break;
3145 case 'v':
3146 c = '\v';
3147 break;
3148 case 'e':
3149 if (!gnu_ext)
3150 goto invalid_escape;
3151 c = 27;
3152 break;
3153 case '\'':
3154 case '\"':
3155 case '\\':
3156 case '?':
3157 break;
3158 default:
3159 invalid_escape:
3160 if (c >= '!' && c <= '~')
3161 warning("unknown escape sequence: \'\\%c\'", c);
3162 else
3163 warning("unknown escape sequence: \'\\x%x\'", c);
3164 break;
3167 p++;
3168 add_char_nonext:
3169 if (!is_long)
3170 cstr_ccat(outstr, c);
3171 else
3172 cstr_wccat(outstr, c);
3174 /* add a trailing '\0' */
3175 if (!is_long)
3176 cstr_ccat(outstr, '\0');
3177 else
3178 cstr_wccat(outstr, '\0');
3181 /* we use 64 bit numbers */
3182 #define BN_SIZE 2
3184 /* bn = (bn << shift) | or_val */
3185 void bn_lshift(unsigned int *bn, int shift, int or_val)
3187 int i;
3188 unsigned int v;
3189 for(i=0;i<BN_SIZE;i++) {
3190 v = bn[i];
3191 bn[i] = (v << shift) | or_val;
3192 or_val = v >> (32 - shift);
3196 void bn_zero(unsigned int *bn)
3198 int i;
3199 for(i=0;i<BN_SIZE;i++) {
3200 bn[i] = 0;
3204 /* parse number in null terminated string 'p' and return it in the
3205 current token */
3206 void parse_number(const char *p)
3208 int b, t, shift, frac_bits, s, exp_val, ch;
3209 char *q;
3210 unsigned int bn[BN_SIZE];
3211 double d;
3213 /* number */
3214 q = token_buf;
3215 ch = *p++;
3216 t = ch;
3217 ch = *p++;
3218 *q++ = t;
3219 b = 10;
3220 if (t == '.') {
3221 goto float_frac_parse;
3222 } else if (t == '0') {
3223 if (ch == 'x' || ch == 'X') {
3224 q--;
3225 ch = *p++;
3226 b = 16;
3227 } else if (tcc_ext && (ch == 'b' || ch == 'B')) {
3228 q--;
3229 ch = *p++;
3230 b = 2;
3233 /* parse all digits. cannot check octal numbers at this stage
3234 because of floating point constants */
3235 while (1) {
3236 if (ch >= 'a' && ch <= 'f')
3237 t = ch - 'a' + 10;
3238 else if (ch >= 'A' && ch <= 'F')
3239 t = ch - 'A' + 10;
3240 else if (isnum(ch))
3241 t = ch - '0';
3242 else
3243 break;
3244 if (t >= b)
3245 break;
3246 if (q >= token_buf + STRING_MAX_SIZE) {
3247 num_too_long:
3248 error("number too long");
3250 *q++ = ch;
3251 ch = *p++;
3253 if (ch == '.' ||
3254 ((ch == 'e' || ch == 'E') && b == 10) ||
3255 ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
3256 if (b != 10) {
3257 /* NOTE: strtox should support that for hexa numbers, but
3258 non ISOC99 libcs do not support it, so we prefer to do
3259 it by hand */
3260 /* hexadecimal or binary floats */
3261 /* XXX: handle overflows */
3262 *q = '\0';
3263 if (b == 16)
3264 shift = 4;
3265 else
3266 shift = 2;
3267 bn_zero(bn);
3268 q = token_buf;
3269 while (1) {
3270 t = *q++;
3271 if (t == '\0') {
3272 break;
3273 } else if (t >= 'a') {
3274 t = t - 'a' + 10;
3275 } else if (t >= 'A') {
3276 t = t - 'A' + 10;
3277 } else {
3278 t = t - '0';
3280 bn_lshift(bn, shift, t);
3282 frac_bits = 0;
3283 if (ch == '.') {
3284 ch = *p++;
3285 while (1) {
3286 t = ch;
3287 if (t >= 'a' && t <= 'f') {
3288 t = t - 'a' + 10;
3289 } else if (t >= 'A' && t <= 'F') {
3290 t = t - 'A' + 10;
3291 } else if (t >= '0' && t <= '9') {
3292 t = t - '0';
3293 } else {
3294 break;
3296 if (t >= b)
3297 error("invalid digit");
3298 bn_lshift(bn, shift, t);
3299 frac_bits += shift;
3300 ch = *p++;
3303 if (ch != 'p' && ch != 'P')
3304 expect("exponent");
3305 ch = *p++;
3306 s = 1;
3307 exp_val = 0;
3308 if (ch == '+') {
3309 ch = *p++;
3310 } else if (ch == '-') {
3311 s = -1;
3312 ch = *p++;
3314 if (ch < '0' || ch > '9')
3315 expect("exponent digits");
3316 while (ch >= '0' && ch <= '9') {
3317 exp_val = exp_val * 10 + ch - '0';
3318 ch = *p++;
3320 exp_val = exp_val * s;
3322 /* now we can generate the number */
3323 /* XXX: should patch directly float number */
3324 d = (double)bn[1] * 4294967296.0 + (double)bn[0];
3325 d = ldexp(d, exp_val - frac_bits);
3326 t = toup(ch);
3327 if (t == 'F') {
3328 ch = *p++;
3329 tok = TOK_CFLOAT;
3330 /* float : should handle overflow */
3331 tokc.f = (float)d;
3332 } else if (t == 'L') {
3333 ch = *p++;
3334 tok = TOK_CLDOUBLE;
3335 /* XXX: not large enough */
3336 tokc.ld = (long double)d;
3337 } else {
3338 tok = TOK_CDOUBLE;
3339 tokc.d = d;
3341 } else {
3342 /* decimal floats */
3343 if (ch == '.') {
3344 if (q >= token_buf + STRING_MAX_SIZE)
3345 goto num_too_long;
3346 *q++ = ch;
3347 ch = *p++;
3348 float_frac_parse:
3349 while (ch >= '0' && ch <= '9') {
3350 if (q >= token_buf + STRING_MAX_SIZE)
3351 goto num_too_long;
3352 *q++ = ch;
3353 ch = *p++;
3356 if (ch == 'e' || ch == 'E') {
3357 if (q >= token_buf + STRING_MAX_SIZE)
3358 goto num_too_long;
3359 *q++ = ch;
3360 ch = *p++;
3361 if (ch == '-' || ch == '+') {
3362 if (q >= token_buf + STRING_MAX_SIZE)
3363 goto num_too_long;
3364 *q++ = ch;
3365 ch = *p++;
3367 if (ch < '0' || ch > '9')
3368 expect("exponent digits");
3369 while (ch >= '0' && ch <= '9') {
3370 if (q >= token_buf + STRING_MAX_SIZE)
3371 goto num_too_long;
3372 *q++ = ch;
3373 ch = *p++;
3376 *q = '\0';
3377 t = toup(ch);
3378 errno = 0;
3379 if (t == 'F') {
3380 ch = *p++;
3381 tok = TOK_CFLOAT;
3382 tokc.f = strtof(token_buf, NULL);
3383 } else if (t == 'L') {
3384 ch = *p++;
3385 tok = TOK_CLDOUBLE;
3386 tokc.ld = strtold(token_buf, NULL);
3387 } else {
3388 tok = TOK_CDOUBLE;
3389 tokc.d = strtod(token_buf, NULL);
3392 } else {
3393 unsigned long long n, n1;
3394 int lcount, ucount;
3396 /* integer number */
3397 *q = '\0';
3398 q = token_buf;
3399 if (b == 10 && *q == '0') {
3400 b = 8;
3401 q++;
3403 n = 0;
3404 while(1) {
3405 t = *q++;
3406 /* no need for checks except for base 10 / 8 errors */
3407 if (t == '\0') {
3408 break;
3409 } else if (t >= 'a') {
3410 t = t - 'a' + 10;
3411 } else if (t >= 'A') {
3412 t = t - 'A' + 10;
3413 } else {
3414 t = t - '0';
3415 if (t >= b)
3416 error("invalid digit");
3418 n1 = n;
3419 n = n * b + t;
3420 /* detect overflow */
3421 /* XXX: this test is not reliable */
3422 if (n < n1)
3423 error("integer constant overflow");
3426 /* XXX: not exactly ANSI compliant */
3427 if ((n & 0xffffffff00000000LL) != 0) {
3428 if ((n >> 63) != 0)
3429 tok = TOK_CULLONG;
3430 else
3431 tok = TOK_CLLONG;
3432 } else if (n > 0x7fffffff) {
3433 tok = TOK_CUINT;
3434 } else {
3435 tok = TOK_CINT;
3437 lcount = 0;
3438 ucount = 0;
3439 for(;;) {
3440 t = toup(ch);
3441 if (t == 'L') {
3442 if (lcount >= 2)
3443 error("three 'l's in integer constant");
3444 lcount++;
3445 if (lcount == 2) {
3446 if (tok == TOK_CINT)
3447 tok = TOK_CLLONG;
3448 else if (tok == TOK_CUINT)
3449 tok = TOK_CULLONG;
3451 ch = *p++;
3452 } else if (t == 'U') {
3453 if (ucount >= 1)
3454 error("two 'u's in integer constant");
3455 ucount++;
3456 if (tok == TOK_CINT)
3457 tok = TOK_CUINT;
3458 else if (tok == TOK_CLLONG)
3459 tok = TOK_CULLONG;
3460 ch = *p++;
3461 } else {
3462 break;
3465 if (tok == TOK_CINT || tok == TOK_CUINT)
3466 tokc.ui = n;
3467 else
3468 tokc.ull = n;
3473 #define PARSE2(c1, tok1, c2, tok2) \
3474 case c1: \
3475 PEEKC(c, p); \
3476 if (c == c2) { \
3477 p++; \
3478 tok = tok2; \
3479 } else { \
3480 tok = tok1; \
3482 break;
3484 /* return next token without macro substitution */
3485 static inline void next_nomacro1(void)
3487 int t, c, is_long;
3488 TokenSym *ts;
3489 uint8_t *p, *p1;
3490 unsigned int h;
3492 p = file->buf_ptr;
3493 redo_no_start:
3494 c = *p;
3495 switch(c) {
3496 case ' ':
3497 case '\t':
3498 case '\f':
3499 case '\v':
3500 case '\r':
3501 p++;
3502 goto redo_no_start;
3504 case '\\':
3505 /* first look if it is in fact an end of buffer */
3506 if (p >= file->buf_end) {
3507 file->buf_ptr = p;
3508 handle_eob();
3509 p = file->buf_ptr;
3510 if (p >= file->buf_end)
3511 goto parse_eof;
3512 else
3513 goto redo_no_start;
3514 } else {
3515 file->buf_ptr = p;
3516 ch = *p;
3517 handle_stray();
3518 p = file->buf_ptr;
3519 goto redo_no_start;
3521 parse_eof:
3523 TCCState *s1 = tcc_state;
3524 if (parse_flags & PARSE_FLAG_LINEFEED) {
3525 tok = TOK_LINEFEED;
3526 } else if (s1->include_stack_ptr == s1->include_stack ||
3527 !(parse_flags & PARSE_FLAG_PREPROCESS)) {
3528 /* no include left : end of file. */
3529 tok = TOK_EOF;
3530 } else {
3531 /* pop include file */
3533 /* test if previous '#endif' was after a #ifdef at
3534 start of file */
3535 if (tok_flags & TOK_FLAG_ENDIF) {
3536 #ifdef INC_DEBUG
3537 printf("#endif %s\n", get_tok_str(file->ifndef_macro_saved, NULL));
3538 #endif
3539 add_cached_include(s1, file->inc_type, file->inc_filename,
3540 file->ifndef_macro_saved);
3543 /* add end of include file debug info */
3544 if (do_debug) {
3545 put_stabd(N_EINCL, 0, 0);
3547 /* pop include stack */
3548 tcc_close(file);
3549 s1->include_stack_ptr--;
3550 file = *s1->include_stack_ptr;
3551 p = file->buf_ptr;
3552 goto redo_no_start;
3555 break;
3557 case '\n':
3558 if (parse_flags & PARSE_FLAG_LINEFEED) {
3559 tok = TOK_LINEFEED;
3560 } else {
3561 file->line_num++;
3562 tok_flags |= TOK_FLAG_BOL;
3563 p++;
3564 goto redo_no_start;
3566 break;
3568 case '#':
3569 /* XXX: simplify */
3570 PEEKC(c, p);
3571 if ((tok_flags & TOK_FLAG_BOL) &&
3572 (parse_flags & PARSE_FLAG_PREPROCESS)) {
3573 file->buf_ptr = p;
3574 preprocess(tok_flags & TOK_FLAG_BOF);
3575 p = file->buf_ptr;
3576 goto redo_no_start;
3577 } else {
3578 if (c == '#') {
3579 p++;
3580 tok = TOK_TWOSHARPS;
3581 } else {
3582 if (parse_flags & PARSE_FLAG_ASM_COMMENTS) {
3583 p = parse_line_comment(p - 1);
3584 goto redo_no_start;
3585 } else {
3586 tok = '#';
3590 break;
3592 case 'a': case 'b': case 'c': case 'd':
3593 case 'e': case 'f': case 'g': case 'h':
3594 case 'i': case 'j': case 'k': case 'l':
3595 case 'm': case 'n': case 'o': case 'p':
3596 case 'q': case 'r': case 's': case 't':
3597 case 'u': case 'v': case 'w': case 'x':
3598 case 'y': case 'z':
3599 case 'A': case 'B': case 'C': case 'D':
3600 case 'E': case 'F': case 'G': case 'H':
3601 case 'I': case 'J': case 'K':
3602 case 'M': case 'N': case 'O': case 'P':
3603 case 'Q': case 'R': case 'S': case 'T':
3604 case 'U': case 'V': case 'W': case 'X':
3605 case 'Y': case 'Z':
3606 case '_':
3607 parse_ident_fast:
3608 p1 = p;
3609 h = TOK_HASH_INIT;
3610 h = TOK_HASH_FUNC(h, c);
3611 p++;
3612 for(;;) {
3613 c = *p;
3614 if (!isidnum_table[c])
3615 break;
3616 h = TOK_HASH_FUNC(h, c);
3617 p++;
3619 if (c != '\\') {
3620 TokenSym **pts;
3621 int len;
3623 /* fast case : no stray found, so we have the full token
3624 and we have already hashed it */
3625 len = p - p1;
3626 h &= (TOK_HASH_SIZE - 1);
3627 pts = &hash_ident[h];
3628 for(;;) {
3629 ts = *pts;
3630 if (!ts)
3631 break;
3632 if (ts->len == len && !memcmp(ts->str, p1, len))
3633 goto token_found;
3634 pts = &(ts->hash_next);
3636 ts = tok_alloc_new(pts, p1, len);
3637 token_found: ;
3638 } else {
3639 /* slower case */
3640 cstr_reset(&tokcstr);
3642 while (p1 < p) {
3643 cstr_ccat(&tokcstr, *p1);
3644 p1++;
3646 p--;
3647 PEEKC(c, p);
3648 parse_ident_slow:
3649 while (isidnum_table[c]) {
3650 cstr_ccat(&tokcstr, c);
3651 PEEKC(c, p);
3653 ts = tok_alloc(tokcstr.data, tokcstr.size);
3655 tok = ts->tok;
3656 break;
3657 case 'L':
3658 t = p[1];
3659 if (t != '\\' && t != '\'' && t != '\"') {
3660 /* fast case */
3661 goto parse_ident_fast;
3662 } else {
3663 PEEKC(c, p);
3664 if (c == '\'' || c == '\"') {
3665 is_long = 1;
3666 goto str_const;
3667 } else {
3668 cstr_reset(&tokcstr);
3669 cstr_ccat(&tokcstr, 'L');
3670 goto parse_ident_slow;
3673 break;
3674 case '0': case '1': case '2': case '3':
3675 case '4': case '5': case '6': case '7':
3676 case '8': case '9':
3678 cstr_reset(&tokcstr);
3679 /* after the first digit, accept digits, alpha, '.' or sign if
3680 prefixed by 'eEpP' */
3681 parse_num:
3682 for(;;) {
3683 t = c;
3684 cstr_ccat(&tokcstr, c);
3685 PEEKC(c, p);
3686 if (!(isnum(c) || isid(c) || c == '.' ||
3687 ((c == '+' || c == '-') &&
3688 (t == 'e' || t == 'E' || t == 'p' || t == 'P'))))
3689 break;
3691 /* We add a trailing '\0' to ease parsing */
3692 cstr_ccat(&tokcstr, '\0');
3693 tokc.cstr = &tokcstr;
3694 tok = TOK_PPNUM;
3695 break;
3696 case '.':
3697 /* special dot handling because it can also start a number */
3698 PEEKC(c, p);
3699 if (isnum(c)) {
3700 cstr_reset(&tokcstr);
3701 cstr_ccat(&tokcstr, '.');
3702 goto parse_num;
3703 } else if (c == '.') {
3704 PEEKC(c, p);
3705 if (c != '.')
3706 expect("'.'");
3707 PEEKC(c, p);
3708 tok = TOK_DOTS;
3709 } else {
3710 tok = '.';
3712 break;
3713 case '\'':
3714 case '\"':
3715 is_long = 0;
3716 str_const:
3718 CString str;
3719 int sep;
3721 sep = c;
3723 /* parse the string */
3724 cstr_new(&str);
3725 p = parse_pp_string(p, sep, &str);
3726 cstr_ccat(&str, '\0');
3728 /* eval the escape (should be done as TOK_PPNUM) */
3729 cstr_reset(&tokcstr);
3730 parse_escape_string(&tokcstr, str.data, is_long);
3731 cstr_free(&str);
3733 if (sep == '\'') {
3734 int char_size;
3735 /* XXX: make it portable */
3736 if (!is_long)
3737 char_size = 1;
3738 else
3739 char_size = sizeof(nwchar_t);
3740 if (tokcstr.size <= char_size)
3741 error("empty character constant");
3742 if (tokcstr.size > 2 * char_size)
3743 warning("multi-character character constant");
3744 if (!is_long) {
3745 tokc.i = *(int8_t *)tokcstr.data;
3746 tok = TOK_CCHAR;
3747 } else {
3748 tokc.i = *(nwchar_t *)tokcstr.data;
3749 tok = TOK_LCHAR;
3751 } else {
3752 tokc.cstr = &tokcstr;
3753 if (!is_long)
3754 tok = TOK_STR;
3755 else
3756 tok = TOK_LSTR;
3759 break;
3761 case '<':
3762 PEEKC(c, p);
3763 if (c == '=') {
3764 p++;
3765 tok = TOK_LE;
3766 } else if (c == '<') {
3767 PEEKC(c, p);
3768 if (c == '=') {
3769 p++;
3770 tok = TOK_A_SHL;
3771 } else {
3772 tok = TOK_SHL;
3774 } else {
3775 tok = TOK_LT;
3777 break;
3779 case '>':
3780 PEEKC(c, p);
3781 if (c == '=') {
3782 p++;
3783 tok = TOK_GE;
3784 } else if (c == '>') {
3785 PEEKC(c, p);
3786 if (c == '=') {
3787 p++;
3788 tok = TOK_A_SAR;
3789 } else {
3790 tok = TOK_SAR;
3792 } else {
3793 tok = TOK_GT;
3795 break;
3797 case '&':
3798 PEEKC(c, p);
3799 if (c == '&') {
3800 p++;
3801 tok = TOK_LAND;
3802 } else if (c == '=') {
3803 p++;
3804 tok = TOK_A_AND;
3805 } else {
3806 tok = '&';
3808 break;
3810 case '|':
3811 PEEKC(c, p);
3812 if (c == '|') {
3813 p++;
3814 tok = TOK_LOR;
3815 } else if (c == '=') {
3816 p++;
3817 tok = TOK_A_OR;
3818 } else {
3819 tok = '|';
3821 break;
3823 case '+':
3824 PEEKC(c, p);
3825 if (c == '+') {
3826 p++;
3827 tok = TOK_INC;
3828 } else if (c == '=') {
3829 p++;
3830 tok = TOK_A_ADD;
3831 } else {
3832 tok = '+';
3834 break;
3836 case '-':
3837 PEEKC(c, p);
3838 if (c == '-') {
3839 p++;
3840 tok = TOK_DEC;
3841 } else if (c == '=') {
3842 p++;
3843 tok = TOK_A_SUB;
3844 } else if (c == '>') {
3845 p++;
3846 tok = TOK_ARROW;
3847 } else {
3848 tok = '-';
3850 break;
3852 PARSE2('!', '!', '=', TOK_NE)
3853 PARSE2('=', '=', '=', TOK_EQ)
3854 PARSE2('*', '*', '=', TOK_A_MUL)
3855 PARSE2('%', '%', '=', TOK_A_MOD)
3856 PARSE2('^', '^', '=', TOK_A_XOR)
3858 /* comments or operator */
3859 case '/':
3860 PEEKC(c, p);
3861 if (c == '*') {
3862 p = parse_comment(p);
3863 goto redo_no_start;
3864 } else if (c == '/') {
3865 p = parse_line_comment(p);
3866 goto redo_no_start;
3867 } else if (c == '=') {
3868 p++;
3869 tok = TOK_A_DIV;
3870 } else {
3871 tok = '/';
3873 break;
3875 /* simple tokens */
3876 case '(':
3877 case ')':
3878 case '[':
3879 case ']':
3880 case '{':
3881 case '}':
3882 case ',':
3883 case ';':
3884 case ':':
3885 case '?':
3886 case '~':
3887 case '$': /* only used in assembler */
3888 case '@': /* dito */
3889 tok = c;
3890 p++;
3891 break;
3892 default:
3893 error("unrecognized character \\x%02x", c);
3894 break;
3896 file->buf_ptr = p;
3897 tok_flags = 0;
3898 #if defined(PARSE_DEBUG)
3899 printf("token = %s\n", get_tok_str(tok, &tokc));
3900 #endif
3903 /* return next token without macro substitution. Can read input from
3904 macro_ptr buffer */
3905 static void next_nomacro(void)
3907 if (macro_ptr) {
3908 redo:
3909 tok = *macro_ptr;
3910 if (tok) {
3911 TOK_GET(tok, macro_ptr, tokc);
3912 if (tok == TOK_LINENUM) {
3913 file->line_num = tokc.i;
3914 goto redo;
3917 } else {
3918 next_nomacro1();
3922 /* substitute args in macro_str and return allocated string */
3923 static int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
3925 int *st, last_tok, t, notfirst;
3926 Sym *s;
3927 CValue cval;
3928 TokenString str;
3929 CString cstr;
3931 tok_str_new(&str);
3932 last_tok = 0;
3933 while(1) {
3934 TOK_GET(t, macro_str, cval);
3935 if (!t)
3936 break;
3937 if (t == '#') {
3938 /* stringize */
3939 TOK_GET(t, macro_str, cval);
3940 if (!t)
3941 break;
3942 s = sym_find2(args, t);
3943 if (s) {
3944 cstr_new(&cstr);
3945 st = (int *)s->c;
3946 notfirst = 0;
3947 while (*st) {
3948 if (notfirst)
3949 cstr_ccat(&cstr, ' ');
3950 TOK_GET(t, st, cval);
3951 cstr_cat(&cstr, get_tok_str(t, &cval));
3952 notfirst = 1;
3954 cstr_ccat(&cstr, '\0');
3955 #ifdef PP_DEBUG
3956 printf("stringize: %s\n", (char *)cstr.data);
3957 #endif
3958 /* add string */
3959 cval.cstr = &cstr;
3960 tok_str_add2(&str, TOK_STR, &cval);
3961 cstr_free(&cstr);
3962 } else {
3963 tok_str_add2(&str, t, &cval);
3965 } else if (t >= TOK_IDENT) {
3966 s = sym_find2(args, t);
3967 if (s) {
3968 st = (int *)s->c;
3969 /* if '##' is present before or after, no arg substitution */
3970 if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) {
3971 /* special case for var arg macros : ## eats the
3972 ',' if empty VA_ARGS variable. */
3973 /* XXX: test of the ',' is not 100%
3974 reliable. should fix it to avoid security
3975 problems */
3976 if (gnu_ext && s->type.t &&
3977 last_tok == TOK_TWOSHARPS &&
3978 str.len >= 2 && str.str[str.len - 2] == ',') {
3979 if (*st == 0) {
3980 /* suppress ',' '##' */
3981 str.len -= 2;
3982 } else {
3983 /* suppress '##' and add variable */
3984 str.len--;
3985 goto add_var;
3987 } else {
3988 int t1;
3989 add_var:
3990 for(;;) {
3991 TOK_GET(t1, st, cval);
3992 if (!t1)
3993 break;
3994 tok_str_add2(&str, t1, &cval);
3997 } else {
3998 /* NOTE: the stream cannot be read when macro
3999 substituing an argument */
4000 macro_subst(&str, nested_list, st, NULL);
4002 } else {
4003 tok_str_add(&str, t);
4005 } else {
4006 tok_str_add2(&str, t, &cval);
4008 last_tok = t;
4010 tok_str_add(&str, 0);
4011 return str.str;
4014 static char const ab_month_name[12][4] =
4016 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
4017 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
4020 /* do macro substitution of current token with macro 's' and add
4021 result to (tok_str,tok_len). 'nested_list' is the list of all
4022 macros we got inside to avoid recursing. Return non zero if no
4023 substitution needs to be done */
4024 static int macro_subst_tok(TokenString *tok_str,
4025 Sym **nested_list, Sym *s, struct macro_level **can_read_stream)
4027 Sym *args, *sa, *sa1;
4028 int mstr_allocated, parlevel, *mstr, t, t1;
4029 TokenString str;
4030 char *cstrval;
4031 CValue cval;
4032 CString cstr;
4033 char buf[32];
4035 /* if symbol is a macro, prepare substitution */
4036 /* special macros */
4037 if (tok == TOK___LINE__) {
4038 snprintf(buf, sizeof(buf), "%d", file->line_num);
4039 cstrval = buf;
4040 t1 = TOK_PPNUM;
4041 goto add_cstr1;
4042 } else if (tok == TOK___FILE__) {
4043 cstrval = file->filename;
4044 goto add_cstr;
4045 } else if (tok == TOK___DATE__ || tok == TOK___TIME__) {
4046 time_t ti;
4047 struct tm *tm;
4049 time(&ti);
4050 tm = localtime(&ti);
4051 if (tok == TOK___DATE__) {
4052 snprintf(buf, sizeof(buf), "%s %2d %d",
4053 ab_month_name[tm->tm_mon], tm->tm_mday, tm->tm_year + 1900);
4054 } else {
4055 snprintf(buf, sizeof(buf), "%02d:%02d:%02d",
4056 tm->tm_hour, tm->tm_min, tm->tm_sec);
4058 cstrval = buf;
4059 add_cstr:
4060 t1 = TOK_STR;
4061 add_cstr1:
4062 cstr_new(&cstr);
4063 cstr_cat(&cstr, cstrval);
4064 cstr_ccat(&cstr, '\0');
4065 cval.cstr = &cstr;
4066 tok_str_add2(tok_str, t1, &cval);
4067 cstr_free(&cstr);
4068 } else {
4069 mstr = (int *)s->c;
4070 mstr_allocated = 0;
4071 if (s->type.t == MACRO_FUNC) {
4072 /* NOTE: we do not use next_nomacro to avoid eating the
4073 next token. XXX: find better solution */
4074 redo:
4075 if (macro_ptr) {
4076 t = *macro_ptr;
4077 if (t == 0 && can_read_stream) {
4078 /* end of macro stream: we must look at the token
4079 after in the file */
4080 struct macro_level *ml = *can_read_stream;
4081 macro_ptr = NULL;
4082 if (ml)
4084 macro_ptr = ml->p;
4085 ml->p = NULL;
4086 *can_read_stream = ml -> prev;
4088 goto redo;
4090 } else {
4091 /* XXX: incorrect with comments */
4092 ch = file->buf_ptr[0];
4093 while (is_space(ch) || ch == '\n')
4094 cinp();
4095 t = ch;
4097 if (t != '(') /* no macro subst */
4098 return -1;
4100 /* argument macro */
4101 next_nomacro();
4102 next_nomacro();
4103 args = NULL;
4104 sa = s->next;
4105 /* NOTE: empty args are allowed, except if no args */
4106 for(;;) {
4107 /* handle '()' case */
4108 if (!args && !sa && tok == ')')
4109 break;
4110 if (!sa)
4111 error("macro '%s' used with too many args",
4112 get_tok_str(s->v, 0));
4113 tok_str_new(&str);
4114 parlevel = 0;
4115 /* NOTE: non zero sa->t indicates VA_ARGS */
4116 while ((parlevel > 0 ||
4117 (tok != ')' &&
4118 (tok != ',' || sa->type.t))) &&
4119 tok != -1) {
4120 if (tok == '(')
4121 parlevel++;
4122 else if (tok == ')')
4123 parlevel--;
4124 tok_str_add2(&str, tok, &tokc);
4125 next_nomacro();
4127 tok_str_add(&str, 0);
4128 sym_push2(&args, sa->v & ~SYM_FIELD, sa->type.t, (int)str.str);
4129 sa = sa->next;
4130 if (tok == ')') {
4131 /* special case for gcc var args: add an empty
4132 var arg argument if it is omitted */
4133 if (sa && sa->type.t && gnu_ext)
4134 continue;
4135 else
4136 break;
4138 if (tok != ',')
4139 expect(",");
4140 next_nomacro();
4142 if (sa) {
4143 error("macro '%s' used with too few args",
4144 get_tok_str(s->v, 0));
4147 /* now subst each arg */
4148 mstr = macro_arg_subst(nested_list, mstr, args);
4149 /* free memory */
4150 sa = args;
4151 while (sa) {
4152 sa1 = sa->prev;
4153 tok_str_free((int *)sa->c);
4154 sym_free(sa);
4155 sa = sa1;
4157 mstr_allocated = 1;
4159 sym_push2(nested_list, s->v, 0, 0);
4160 macro_subst(tok_str, nested_list, mstr, can_read_stream);
4161 /* pop nested defined symbol */
4162 sa1 = *nested_list;
4163 *nested_list = sa1->prev;
4164 sym_free(sa1);
4165 if (mstr_allocated)
4166 tok_str_free(mstr);
4168 return 0;
4171 /* handle the '##' operator. Return NULL if no '##' seen. Otherwise
4172 return the resulting string (which must be freed). */
4173 static inline int *macro_twosharps(const int *macro_str)
4175 TokenSym *ts;
4176 const int *macro_ptr1, *start_macro_ptr, *ptr, *saved_macro_ptr;
4177 int t;
4178 const char *p1, *p2;
4179 CValue cval;
4180 TokenString macro_str1;
4181 CString cstr;
4183 start_macro_ptr = macro_str;
4184 /* we search the first '##' */
4185 for(;;) {
4186 macro_ptr1 = macro_str;
4187 TOK_GET(t, macro_str, cval);
4188 /* nothing more to do if end of string */
4189 if (t == 0)
4190 return NULL;
4191 if (*macro_str == TOK_TWOSHARPS)
4192 break;
4195 /* we saw '##', so we need more processing to handle it */
4196 cstr_new(&cstr);
4197 tok_str_new(&macro_str1);
4198 tok = t;
4199 tokc = cval;
4201 /* add all tokens seen so far */
4202 for(ptr = start_macro_ptr; ptr < macro_ptr1;) {
4203 TOK_GET(t, ptr, cval);
4204 tok_str_add2(&macro_str1, t, &cval);
4206 saved_macro_ptr = macro_ptr;
4207 /* XXX: get rid of the use of macro_ptr here */
4208 macro_ptr = (int *)macro_str;
4209 for(;;) {
4210 while (*macro_ptr == TOK_TWOSHARPS) {
4211 macro_ptr++;
4212 macro_ptr1 = macro_ptr;
4213 t = *macro_ptr;
4214 if (t) {
4215 TOK_GET(t, macro_ptr, cval);
4216 /* We concatenate the two tokens if we have an
4217 identifier or a preprocessing number */
4218 cstr_reset(&cstr);
4219 p1 = get_tok_str(tok, &tokc);
4220 cstr_cat(&cstr, p1);
4221 p2 = get_tok_str(t, &cval);
4222 cstr_cat(&cstr, p2);
4223 cstr_ccat(&cstr, '\0');
4225 if ((tok >= TOK_IDENT || tok == TOK_PPNUM) &&
4226 (t >= TOK_IDENT || t == TOK_PPNUM)) {
4227 if (tok == TOK_PPNUM) {
4228 /* if number, then create a number token */
4229 /* NOTE: no need to allocate because
4230 tok_str_add2() does it */
4231 tokc.cstr = &cstr;
4232 } else {
4233 /* if identifier, we must do a test to
4234 validate we have a correct identifier */
4235 if (t == TOK_PPNUM) {
4236 const char *p;
4237 int c;
4239 p = p2;
4240 for(;;) {
4241 c = *p;
4242 if (c == '\0')
4243 break;
4244 p++;
4245 if (!isnum(c) && !isid(c))
4246 goto error_pasting;
4249 ts = tok_alloc(cstr.data, strlen(cstr.data));
4250 tok = ts->tok; /* modify current token */
4252 } else {
4253 const char *str = cstr.data;
4254 const unsigned char *q;
4256 /* we look for a valid token */
4257 /* XXX: do more extensive checks */
4258 if (!strcmp(str, ">>=")) {
4259 tok = TOK_A_SAR;
4260 } else if (!strcmp(str, "<<=")) {
4261 tok = TOK_A_SHL;
4262 } else if (strlen(str) == 2) {
4263 /* search in two bytes table */
4264 q = tok_two_chars;
4265 for(;;) {
4266 if (!*q)
4267 goto error_pasting;
4268 if (q[0] == str[0] && q[1] == str[1])
4269 break;
4270 q += 3;
4272 tok = q[2];
4273 } else {
4274 error_pasting:
4275 /* NOTE: because get_tok_str use a static buffer,
4276 we must save it */
4277 cstr_reset(&cstr);
4278 p1 = get_tok_str(tok, &tokc);
4279 cstr_cat(&cstr, p1);
4280 cstr_ccat(&cstr, '\0');
4281 p2 = get_tok_str(t, &cval);
4282 warning("pasting \"%s\" and \"%s\" does not give a valid preprocessing token", cstr.data, p2);
4283 /* cannot merge tokens: just add them separately */
4284 tok_str_add2(&macro_str1, tok, &tokc);
4285 /* XXX: free associated memory ? */
4286 tok = t;
4287 tokc = cval;
4292 tok_str_add2(&macro_str1, tok, &tokc);
4293 next_nomacro();
4294 if (tok == 0)
4295 break;
4297 macro_ptr = (int *)saved_macro_ptr;
4298 cstr_free(&cstr);
4299 tok_str_add(&macro_str1, 0);
4300 return macro_str1.str;
4304 /* do macro substitution of macro_str and add result to
4305 (tok_str,tok_len). 'nested_list' is the list of all macros we got
4306 inside to avoid recursing. */
4307 static void macro_subst(TokenString *tok_str, Sym **nested_list,
4308 const int *macro_str, struct macro_level ** can_read_stream)
4310 Sym *s;
4311 int *macro_str1;
4312 const int *ptr;
4313 int t, ret;
4314 CValue cval;
4315 struct macro_level ml;
4317 /* first scan for '##' operator handling */
4318 ptr = macro_str;
4319 macro_str1 = macro_twosharps(ptr);
4320 if (macro_str1)
4321 ptr = macro_str1;
4322 while (1) {
4323 /* NOTE: ptr == NULL can only happen if tokens are read from
4324 file stream due to a macro function call */
4325 if (ptr == NULL)
4326 break;
4327 TOK_GET(t, ptr, cval);
4328 if (t == 0)
4329 break;
4330 s = define_find(t);
4331 if (s != NULL) {
4332 /* if nested substitution, do nothing */
4333 if (sym_find2(*nested_list, t))
4334 goto no_subst;
4335 ml.p = macro_ptr;
4336 if (can_read_stream)
4337 ml.prev = *can_read_stream, *can_read_stream = &ml;
4338 macro_ptr = (int *)ptr;
4339 tok = t;
4340 ret = macro_subst_tok(tok_str, nested_list, s, can_read_stream);
4341 ptr = (int *)macro_ptr;
4342 macro_ptr = ml.p;
4343 if (can_read_stream && *can_read_stream == &ml)
4344 *can_read_stream = ml.prev;
4345 if (ret != 0)
4346 goto no_subst;
4347 } else {
4348 no_subst:
4349 tok_str_add2(tok_str, t, &cval);
4352 if (macro_str1)
4353 tok_str_free(macro_str1);
4356 /* return next token with macro substitution */
4357 static void next(void)
4359 Sym *nested_list, *s;
4360 TokenString str;
4361 struct macro_level *ml;
4363 redo:
4364 next_nomacro();
4365 if (!macro_ptr) {
4366 /* if not reading from macro substituted string, then try
4367 to substitute macros */
4368 if (tok >= TOK_IDENT &&
4369 (parse_flags & PARSE_FLAG_PREPROCESS)) {
4370 s = define_find(tok);
4371 if (s) {
4372 /* we have a macro: we try to substitute */
4373 tok_str_new(&str);
4374 nested_list = NULL;
4375 ml = NULL;
4376 if (macro_subst_tok(&str, &nested_list, s, &ml) == 0) {
4377 /* substitution done, NOTE: maybe empty */
4378 tok_str_add(&str, 0);
4379 macro_ptr = str.str;
4380 macro_ptr_allocated = str.str;
4381 goto redo;
4385 } else {
4386 if (tok == 0) {
4387 /* end of macro or end of unget buffer */
4388 if (unget_buffer_enabled) {
4389 macro_ptr = unget_saved_macro_ptr;
4390 unget_buffer_enabled = 0;
4391 } else {
4392 /* end of macro string: free it */
4393 tok_str_free(macro_ptr_allocated);
4394 macro_ptr = NULL;
4396 goto redo;
4400 /* convert preprocessor tokens into C tokens */
4401 if (tok == TOK_PPNUM &&
4402 (parse_flags & PARSE_FLAG_TOK_NUM)) {
4403 parse_number((char *)tokc.cstr->data);
4407 /* push back current token and set current token to 'last_tok'. Only
4408 identifier case handled for labels. */
4409 static inline void unget_tok(int last_tok)
4411 int i, n;
4412 int *q;
4413 unget_saved_macro_ptr = macro_ptr;
4414 unget_buffer_enabled = 1;
4415 q = unget_saved_buffer;
4416 macro_ptr = q;
4417 *q++ = tok;
4418 n = tok_ext_size(tok) - 1;
4419 for(i=0;i<n;i++)
4420 *q++ = tokc.tab[i];
4421 *q = 0; /* end of token string */
4422 tok = last_tok;
4426 void swap(int *p, int *q)
4428 int t;
4429 t = *p;
4430 *p = *q;
4431 *q = t;
4434 void vsetc(CType *type, int r, CValue *vc)
4436 int v;
4438 if (vtop >= vstack + (VSTACK_SIZE - 1))
4439 error("memory full");
4440 /* cannot let cpu flags if other instruction are generated. Also
4441 avoid leaving VT_JMP anywhere except on the top of the stack
4442 because it would complicate the code generator. */
4443 if (vtop >= vstack) {
4444 v = vtop->r & VT_VALMASK;
4445 if (v == VT_CMP || (v & ~1) == VT_JMP)
4446 gv(RC_INT);
4448 vtop++;
4449 vtop->type = *type;
4450 vtop->r = r;
4451 vtop->r2 = VT_CONST;
4452 vtop->c = *vc;
4455 /* push integer constant */
4456 void vpushi(int v)
4458 CValue cval;
4459 cval.i = v;
4460 vsetc(&int_type, VT_CONST, &cval);
4463 /* Return a static symbol pointing to a section */
4464 static Sym *get_sym_ref(CType *type, Section *sec,
4465 unsigned long offset, unsigned long size)
4467 int v;
4468 Sym *sym;
4470 v = anon_sym++;
4471 sym = global_identifier_push(v, type->t | VT_STATIC, 0);
4472 sym->type.ref = type->ref;
4473 sym->r = VT_CONST | VT_SYM;
4474 put_extern_sym(sym, sec, offset, size);
4475 return sym;
4478 /* push a reference to a section offset by adding a dummy symbol */
4479 static void vpush_ref(CType *type, Section *sec, unsigned long offset, unsigned long size)
4481 CValue cval;
4483 cval.ul = 0;
4484 vsetc(type, VT_CONST | VT_SYM, &cval);
4485 vtop->sym = get_sym_ref(type, sec, offset, size);
4488 /* define a new external reference to a symbol 'v' of type 'u' */
4489 static Sym *external_global_sym(int v, CType *type, int r)
4491 Sym *s;
4493 s = sym_find(v);
4494 if (!s) {
4495 /* push forward reference */
4496 s = global_identifier_push(v, type->t | VT_EXTERN, 0);
4497 s->type.ref = type->ref;
4498 s->r = r | VT_CONST | VT_SYM;
4500 return s;
4503 /* define a new external reference to a symbol 'v' of type 'u' */
4504 static Sym *external_sym(int v, CType *type, int r)
4506 Sym *s;
4508 s = sym_find(v);
4509 if (!s) {
4510 /* push forward reference */
4511 s = sym_push(v, type, r | VT_CONST | VT_SYM, 0);
4512 s->type.t |= VT_EXTERN;
4513 } else {
4514 if (!is_compatible_types(&s->type, type))
4515 error("incompatible types for redefinition of '%s'",
4516 get_tok_str(v, NULL));
4518 return s;
4521 /* push a reference to global symbol v */
4522 static void vpush_global_sym(CType *type, int v)
4524 Sym *sym;
4525 CValue cval;
4527 sym = external_global_sym(v, type, 0);
4528 cval.ul = 0;
4529 vsetc(type, VT_CONST | VT_SYM, &cval);
4530 vtop->sym = sym;
4533 void vset(CType *type, int r, int v)
4535 CValue cval;
4537 cval.i = v;
4538 vsetc(type, r, &cval);
4541 void vseti(int r, int v)
4543 CType type;
4544 type.t = VT_INT;
4545 vset(&type, r, v);
4548 void vswap(void)
4550 SValue tmp;
4552 tmp = vtop[0];
4553 vtop[0] = vtop[-1];
4554 vtop[-1] = tmp;
4557 void vpushv(SValue *v)
4559 if (vtop >= vstack + (VSTACK_SIZE - 1))
4560 error("memory full");
4561 vtop++;
4562 *vtop = *v;
4565 void vdup(void)
4567 vpushv(vtop);
4570 /* save r to the memory stack, and mark it as being free */
4571 void save_reg(int r)
4573 int l, saved, size, align;
4574 SValue *p, sv;
4575 CType *type;
4577 /* modify all stack values */
4578 saved = 0;
4579 l = 0;
4580 for(p=vstack;p<=vtop;p++) {
4581 if ((p->r & VT_VALMASK) == r ||
4582 (p->r2 & VT_VALMASK) == r) {
4583 /* must save value on stack if not already done */
4584 if (!saved) {
4585 /* NOTE: must reload 'r' because r might be equal to r2 */
4586 r = p->r & VT_VALMASK;
4587 /* store register in the stack */
4588 type = &p->type;
4589 if ((p->r & VT_LVAL) ||
4590 (!is_float(type->t) && (type->t & VT_BTYPE) != VT_LLONG))
4591 type = &int_type;
4592 size = type_size(type, &align);
4593 loc = (loc - size) & -align;
4594 sv.type.t = type->t;
4595 sv.r = VT_LOCAL | VT_LVAL;
4596 sv.c.ul = loc;
4597 store(r, &sv);
4598 #ifdef TCC_TARGET_I386
4599 /* x86 specific: need to pop fp register ST0 if saved */
4600 if (r == TREG_ST0) {
4601 o(0xd9dd); /* fstp %st(1) */
4603 #endif
4604 /* special long long case */
4605 if ((type->t & VT_BTYPE) == VT_LLONG) {
4606 sv.c.ul += 4;
4607 store(p->r2, &sv);
4609 l = loc;
4610 saved = 1;
4612 /* mark that stack entry as being saved on the stack */
4613 if (p->r & VT_LVAL) {
4614 /* also clear the bounded flag because the
4615 relocation address of the function was stored in
4616 p->c.ul */
4617 p->r = (p->r & ~(VT_VALMASK | VT_BOUNDED)) | VT_LLOCAL;
4618 } else {
4619 p->r = lvalue_type(p->type.t) | VT_LOCAL;
4621 p->r2 = VT_CONST;
4622 p->c.ul = l;
4627 /* find a register of class 'rc2' with at most one reference on stack.
4628 * If none, call get_reg(rc) */
4629 int get_reg_ex(int rc, int rc2)
4631 int r;
4632 SValue *p;
4634 for(r=0;r<NB_REGS;r++) {
4635 if (reg_classes[r] & rc2) {
4636 int n;
4637 n=0;
4638 for(p = vstack; p <= vtop; p++) {
4639 if ((p->r & VT_VALMASK) == r ||
4640 (p->r2 & VT_VALMASK) == r)
4641 n++;
4643 if (n <= 1)
4644 return r;
4647 return get_reg(rc);
4650 /* find a free register of class 'rc'. If none, save one register */
4651 int get_reg(int rc)
4653 int r;
4654 SValue *p;
4656 /* find a free register */
4657 for(r=0;r<NB_REGS;r++) {
4658 if (reg_classes[r] & rc) {
4659 for(p=vstack;p<=vtop;p++) {
4660 if ((p->r & VT_VALMASK) == r ||
4661 (p->r2 & VT_VALMASK) == r)
4662 goto notfound;
4664 return r;
4666 notfound: ;
4669 /* no register left : free the first one on the stack (VERY
4670 IMPORTANT to start from the bottom to ensure that we don't
4671 spill registers used in gen_opi()) */
4672 for(p=vstack;p<=vtop;p++) {
4673 r = p->r & VT_VALMASK;
4674 if (r < VT_CONST && (reg_classes[r] & rc))
4675 goto save_found;
4676 /* also look at second register (if long long) */
4677 r = p->r2 & VT_VALMASK;
4678 if (r < VT_CONST && (reg_classes[r] & rc)) {
4679 save_found:
4680 save_reg(r);
4681 return r;
4684 /* Should never comes here */
4685 return -1;
4688 /* save registers up to (vtop - n) stack entry */
4689 void save_regs(int n)
4691 int r;
4692 SValue *p, *p1;
4693 p1 = vtop - n;
4694 for(p = vstack;p <= p1; p++) {
4695 r = p->r & VT_VALMASK;
4696 if (r < VT_CONST) {
4697 save_reg(r);
4702 /* move register 's' to 'r', and flush previous value of r to memory
4703 if needed */
4704 void move_reg(int r, int s)
4706 SValue sv;
4708 if (r != s) {
4709 save_reg(r);
4710 sv.type.t = VT_INT;
4711 sv.r = s;
4712 sv.c.ul = 0;
4713 load(r, &sv);
4717 /* get address of vtop (vtop MUST BE an lvalue) */
4718 void gaddrof(void)
4720 vtop->r &= ~VT_LVAL;
4721 /* tricky: if saved lvalue, then we can go back to lvalue */
4722 if ((vtop->r & VT_VALMASK) == VT_LLOCAL)
4723 vtop->r = (vtop->r & ~(VT_VALMASK | VT_LVAL_TYPE)) | VT_LOCAL | VT_LVAL;
4726 #ifdef CONFIG_TCC_BCHECK
4727 /* generate lvalue bound code */
4728 void gbound(void)
4730 int lval_type;
4731 CType type1;
4733 vtop->r &= ~VT_MUSTBOUND;
4734 /* if lvalue, then use checking code before dereferencing */
4735 if (vtop->r & VT_LVAL) {
4736 /* if not VT_BOUNDED value, then make one */
4737 if (!(vtop->r & VT_BOUNDED)) {
4738 lval_type = vtop->r & (VT_LVAL_TYPE | VT_LVAL);
4739 /* must save type because we must set it to int to get pointer */
4740 type1 = vtop->type;
4741 vtop->type.t = VT_INT;
4742 gaddrof();
4743 vpushi(0);
4744 gen_bounded_ptr_add();
4745 vtop->r |= lval_type;
4746 vtop->type = type1;
4748 /* then check for dereferencing */
4749 gen_bounded_ptr_deref();
4752 #endif
4754 /* store vtop a register belonging to class 'rc'. lvalues are
4755 converted to values. Cannot be used if cannot be converted to
4756 register value (such as structures). */
4757 int gv(int rc)
4759 int r, r2, rc2, bit_pos, bit_size, size, align, i;
4760 unsigned long long ll;
4762 /* NOTE: get_reg can modify vstack[] */
4763 if (vtop->type.t & VT_BITFIELD) {
4764 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
4765 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
4766 /* remove bit field info to avoid loops */
4767 vtop->type.t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
4768 /* generate shifts */
4769 vpushi(32 - (bit_pos + bit_size));
4770 gen_op(TOK_SHL);
4771 vpushi(32 - bit_size);
4772 /* NOTE: transformed to SHR if unsigned */
4773 gen_op(TOK_SAR);
4774 r = gv(rc);
4775 } else {
4776 if (is_float(vtop->type.t) &&
4777 (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4778 Sym *sym;
4779 int *ptr;
4780 unsigned long offset;
4782 /* XXX: unify with initializers handling ? */
4783 /* CPUs usually cannot use float constants, so we store them
4784 generically in data segment */
4785 size = type_size(&vtop->type, &align);
4786 offset = (data_section->data_offset + align - 1) & -align;
4787 data_section->data_offset = offset;
4788 /* XXX: not portable yet */
4789 ptr = section_ptr_add(data_section, size);
4790 size = size >> 2;
4791 for(i=0;i<size;i++)
4792 ptr[i] = vtop->c.tab[i];
4793 sym = get_sym_ref(&vtop->type, data_section, offset, size << 2);
4794 vtop->r |= VT_LVAL | VT_SYM;
4795 vtop->sym = sym;
4796 vtop->c.ul = 0;
4798 #ifdef CONFIG_TCC_BCHECK
4799 if (vtop->r & VT_MUSTBOUND)
4800 gbound();
4801 #endif
4803 r = vtop->r & VT_VALMASK;
4804 /* need to reload if:
4805 - constant
4806 - lvalue (need to dereference pointer)
4807 - already a register, but not in the right class */
4808 if (r >= VT_CONST ||
4809 (vtop->r & VT_LVAL) ||
4810 !(reg_classes[r] & rc) ||
4811 ((vtop->type.t & VT_BTYPE) == VT_LLONG &&
4812 !(reg_classes[vtop->r2] & rc))) {
4813 r = get_reg(rc);
4814 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
4815 /* two register type load : expand to two words
4816 temporarily */
4817 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4818 /* load constant */
4819 ll = vtop->c.ull;
4820 vtop->c.ui = ll; /* first word */
4821 load(r, vtop);
4822 vtop->r = r; /* save register value */
4823 vpushi(ll >> 32); /* second word */
4824 } else if (r >= VT_CONST || /* XXX: test to VT_CONST incorrect ? */
4825 (vtop->r & VT_LVAL)) {
4826 /* We do not want to modifier the long long
4827 pointer here, so the safest (and less
4828 efficient) is to save all the other registers
4829 in the stack. XXX: totally inefficient. */
4830 save_regs(1);
4831 /* load from memory */
4832 load(r, vtop);
4833 vdup();
4834 vtop[-1].r = r; /* save register value */
4835 /* increment pointer to get second word */
4836 vtop->type.t = VT_INT;
4837 gaddrof();
4838 vpushi(4);
4839 gen_op('+');
4840 vtop->r |= VT_LVAL;
4841 } else {
4842 /* move registers */
4843 load(r, vtop);
4844 vdup();
4845 vtop[-1].r = r; /* save register value */
4846 vtop->r = vtop[-1].r2;
4848 /* allocate second register */
4849 rc2 = RC_INT;
4850 if (rc == RC_IRET)
4851 rc2 = RC_LRET;
4852 r2 = get_reg(rc2);
4853 load(r2, vtop);
4854 vpop();
4855 /* write second register */
4856 vtop->r2 = r2;
4857 } else if ((vtop->r & VT_LVAL) && !is_float(vtop->type.t)) {
4858 int t1, t;
4859 /* lvalue of scalar type : need to use lvalue type
4860 because of possible cast */
4861 t = vtop->type.t;
4862 t1 = t;
4863 /* compute memory access type */
4864 if (vtop->r & VT_LVAL_BYTE)
4865 t = VT_BYTE;
4866 else if (vtop->r & VT_LVAL_SHORT)
4867 t = VT_SHORT;
4868 if (vtop->r & VT_LVAL_UNSIGNED)
4869 t |= VT_UNSIGNED;
4870 vtop->type.t = t;
4871 load(r, vtop);
4872 /* restore wanted type */
4873 vtop->type.t = t1;
4874 } else {
4875 /* one register type load */
4876 load(r, vtop);
4879 vtop->r = r;
4880 #ifdef TCC_TARGET_C67
4881 /* uses register pairs for doubles */
4882 if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE)
4883 vtop->r2 = r+1;
4884 #endif
4886 return r;
4889 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
4890 void gv2(int rc1, int rc2)
4892 int v;
4894 /* generate more generic register first. But VT_JMP or VT_CMP
4895 values must be generated first in all cases to avoid possible
4896 reload errors */
4897 v = vtop[0].r & VT_VALMASK;
4898 if (v != VT_CMP && (v & ~1) != VT_JMP && rc1 <= rc2) {
4899 vswap();
4900 gv(rc1);
4901 vswap();
4902 gv(rc2);
4903 /* test if reload is needed for first register */
4904 if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
4905 vswap();
4906 gv(rc1);
4907 vswap();
4909 } else {
4910 gv(rc2);
4911 vswap();
4912 gv(rc1);
4913 vswap();
4914 /* test if reload is needed for first register */
4915 if ((vtop[0].r & VT_VALMASK) >= VT_CONST) {
4916 gv(rc2);
4921 /* expand long long on stack in two int registers */
4922 void lexpand(void)
4924 int u;
4926 u = vtop->type.t & VT_UNSIGNED;
4927 gv(RC_INT);
4928 vdup();
4929 vtop[0].r = vtop[-1].r2;
4930 vtop[0].r2 = VT_CONST;
4931 vtop[-1].r2 = VT_CONST;
4932 vtop[0].type.t = VT_INT | u;
4933 vtop[-1].type.t = VT_INT | u;
4936 #ifdef TCC_TARGET_ARM
4937 /* expand long long on stack */
4938 void lexpand_nr(void)
4940 int u,v;
4942 u = vtop->type.t & VT_UNSIGNED;
4943 vdup();
4944 vtop->r2 = VT_CONST;
4945 vtop->type.t = VT_INT | u;
4946 v=vtop[-1].r & (VT_VALMASK | VT_LVAL);
4947 if (v == VT_CONST) {
4948 vtop[-1].c.ui = vtop->c.ull;
4949 vtop->c.ui = vtop->c.ull >> 32;
4950 vtop->r = VT_CONST;
4951 } else if (v == (VT_LVAL|VT_CONST) || v == (VT_LVAL|VT_LOCAL)) {
4952 vtop->c.ui += 4;
4953 vtop->r = vtop[-1].r;
4954 } else if (v > VT_CONST) {
4955 vtop--;
4956 lexpand();
4957 } else
4958 vtop->r = vtop[-1].r2;
4959 vtop[-1].r2 = VT_CONST;
4960 vtop[-1].type.t = VT_INT | u;
4962 #endif
4964 /* build a long long from two ints */
4965 void lbuild(int t)
4967 gv2(RC_INT, RC_INT);
4968 vtop[-1].r2 = vtop[0].r;
4969 vtop[-1].type.t = t;
4970 vpop();
4973 /* rotate n first stack elements to the bottom
4974 I1 ... In -> I2 ... In I1 [top is right]
4976 void vrotb(int n)
4978 int i;
4979 SValue tmp;
4981 tmp = vtop[-n + 1];
4982 for(i=-n+1;i!=0;i++)
4983 vtop[i] = vtop[i+1];
4984 vtop[0] = tmp;
4987 /* rotate n first stack elements to the top
4988 I1 ... In -> In I1 ... I(n-1) [top is right]
4990 void vrott(int n)
4992 int i;
4993 SValue tmp;
4995 tmp = vtop[0];
4996 for(i = 0;i < n - 1; i++)
4997 vtop[-i] = vtop[-i - 1];
4998 vtop[-n + 1] = tmp;
5001 #ifdef TCC_TARGET_ARM
5002 /* like vrott but in other direction
5003 In ... I1 -> I(n-1) ... I1 In [top is right]
5005 void vnrott(int n)
5007 int i;
5008 SValue tmp;
5010 tmp = vtop[-n + 1];
5011 for(i = n - 1; i > 0; i--)
5012 vtop[-i] = vtop[-i + 1];
5013 vtop[0] = tmp;
5015 #endif
5017 /* pop stack value */
5018 void vpop(void)
5020 int v;
5021 v = vtop->r & VT_VALMASK;
5022 #ifdef TCC_TARGET_I386
5023 /* for x86, we need to pop the FP stack */
5024 if (v == TREG_ST0 && !nocode_wanted) {
5025 o(0xd9dd); /* fstp %st(1) */
5026 } else
5027 #endif
5028 if (v == VT_JMP || v == VT_JMPI) {
5029 /* need to put correct jump if && or || without test */
5030 gsym(vtop->c.ul);
5032 vtop--;
5035 /* convert stack entry to register and duplicate its value in another
5036 register */
5037 void gv_dup(void)
5039 int rc, t, r, r1;
5040 SValue sv;
5042 t = vtop->type.t;
5043 if ((t & VT_BTYPE) == VT_LLONG) {
5044 lexpand();
5045 gv_dup();
5046 vswap();
5047 vrotb(3);
5048 gv_dup();
5049 vrotb(4);
5050 /* stack: H L L1 H1 */
5051 lbuild(t);
5052 vrotb(3);
5053 vrotb(3);
5054 vswap();
5055 lbuild(t);
5056 vswap();
5057 } else {
5058 /* duplicate value */
5059 rc = RC_INT;
5060 sv.type.t = VT_INT;
5061 if (is_float(t)) {
5062 rc = RC_FLOAT;
5063 sv.type.t = t;
5065 r = gv(rc);
5066 r1 = get_reg(rc);
5067 sv.r = r;
5068 sv.c.ul = 0;
5069 load(r1, &sv); /* move r to r1 */
5070 vdup();
5071 /* duplicates value */
5072 vtop->r = r1;
5076 /* generate CPU independent (unsigned) long long operations */
5077 void gen_opl(int op)
5079 int t, a, b, op1, c, i;
5080 int func;
5081 SValue tmp;
5083 switch(op) {
5084 case '/':
5085 case TOK_PDIV:
5086 func = TOK___divdi3;
5087 goto gen_func;
5088 case TOK_UDIV:
5089 func = TOK___udivdi3;
5090 goto gen_func;
5091 case '%':
5092 func = TOK___moddi3;
5093 goto gen_func;
5094 case TOK_UMOD:
5095 func = TOK___umoddi3;
5096 gen_func:
5097 /* call generic long long function */
5098 vpush_global_sym(&func_old_type, func);
5099 vrott(3);
5100 gfunc_call(2);
5101 vpushi(0);
5102 vtop->r = REG_IRET;
5103 vtop->r2 = REG_LRET;
5104 break;
5105 case '^':
5106 case '&':
5107 case '|':
5108 case '*':
5109 case '+':
5110 case '-':
5111 t = vtop->type.t;
5112 vswap();
5113 lexpand();
5114 vrotb(3);
5115 lexpand();
5116 /* stack: L1 H1 L2 H2 */
5117 tmp = vtop[0];
5118 vtop[0] = vtop[-3];
5119 vtop[-3] = tmp;
5120 tmp = vtop[-2];
5121 vtop[-2] = vtop[-3];
5122 vtop[-3] = tmp;
5123 vswap();
5124 /* stack: H1 H2 L1 L2 */
5125 if (op == '*') {
5126 vpushv(vtop - 1);
5127 vpushv(vtop - 1);
5128 gen_op(TOK_UMULL);
5129 lexpand();
5130 /* stack: H1 H2 L1 L2 ML MH */
5131 for(i=0;i<4;i++)
5132 vrotb(6);
5133 /* stack: ML MH H1 H2 L1 L2 */
5134 tmp = vtop[0];
5135 vtop[0] = vtop[-2];
5136 vtop[-2] = tmp;
5137 /* stack: ML MH H1 L2 H2 L1 */
5138 gen_op('*');
5139 vrotb(3);
5140 vrotb(3);
5141 gen_op('*');
5142 /* stack: ML MH M1 M2 */
5143 gen_op('+');
5144 gen_op('+');
5145 } else if (op == '+' || op == '-') {
5146 /* XXX: add non carry method too (for MIPS or alpha) */
5147 if (op == '+')
5148 op1 = TOK_ADDC1;
5149 else
5150 op1 = TOK_SUBC1;
5151 gen_op(op1);
5152 /* stack: H1 H2 (L1 op L2) */
5153 vrotb(3);
5154 vrotb(3);
5155 gen_op(op1 + 1); /* TOK_xxxC2 */
5156 } else {
5157 gen_op(op);
5158 /* stack: H1 H2 (L1 op L2) */
5159 vrotb(3);
5160 vrotb(3);
5161 /* stack: (L1 op L2) H1 H2 */
5162 gen_op(op);
5163 /* stack: (L1 op L2) (H1 op H2) */
5165 /* stack: L H */
5166 lbuild(t);
5167 break;
5168 case TOK_SAR:
5169 case TOK_SHR:
5170 case TOK_SHL:
5171 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
5172 t = vtop[-1].type.t;
5173 vswap();
5174 lexpand();
5175 vrotb(3);
5176 /* stack: L H shift */
5177 c = (int)vtop->c.i;
5178 /* constant: simpler */
5179 /* NOTE: all comments are for SHL. the other cases are
5180 done by swaping words */
5181 vpop();
5182 if (op != TOK_SHL)
5183 vswap();
5184 if (c >= 32) {
5185 /* stack: L H */
5186 vpop();
5187 if (c > 32) {
5188 vpushi(c - 32);
5189 gen_op(op);
5191 if (op != TOK_SAR) {
5192 vpushi(0);
5193 } else {
5194 gv_dup();
5195 vpushi(31);
5196 gen_op(TOK_SAR);
5198 vswap();
5199 } else {
5200 vswap();
5201 gv_dup();
5202 /* stack: H L L */
5203 vpushi(c);
5204 gen_op(op);
5205 vswap();
5206 vpushi(32 - c);
5207 if (op == TOK_SHL)
5208 gen_op(TOK_SHR);
5209 else
5210 gen_op(TOK_SHL);
5211 vrotb(3);
5212 /* stack: L L H */
5213 vpushi(c);
5214 if (op == TOK_SHL)
5215 gen_op(TOK_SHL);
5216 else
5217 gen_op(TOK_SHR);
5218 gen_op('|');
5220 if (op != TOK_SHL)
5221 vswap();
5222 lbuild(t);
5223 } else {
5224 /* XXX: should provide a faster fallback on x86 ? */
5225 switch(op) {
5226 case TOK_SAR:
5227 func = TOK___sardi3;
5228 goto gen_func;
5229 case TOK_SHR:
5230 func = TOK___shrdi3;
5231 goto gen_func;
5232 case TOK_SHL:
5233 func = TOK___shldi3;
5234 goto gen_func;
5237 break;
5238 default:
5239 /* compare operations */
5240 t = vtop->type.t;
5241 vswap();
5242 lexpand();
5243 vrotb(3);
5244 lexpand();
5245 /* stack: L1 H1 L2 H2 */
5246 tmp = vtop[-1];
5247 vtop[-1] = vtop[-2];
5248 vtop[-2] = tmp;
5249 /* stack: L1 L2 H1 H2 */
5250 /* compare high */
5251 op1 = op;
5252 /* when values are equal, we need to compare low words. since
5253 the jump is inverted, we invert the test too. */
5254 if (op1 == TOK_LT)
5255 op1 = TOK_LE;
5256 else if (op1 == TOK_GT)
5257 op1 = TOK_GE;
5258 else if (op1 == TOK_ULT)
5259 op1 = TOK_ULE;
5260 else if (op1 == TOK_UGT)
5261 op1 = TOK_UGE;
5262 a = 0;
5263 b = 0;
5264 gen_op(op1);
5265 if (op1 != TOK_NE) {
5266 a = gtst(1, 0);
5268 if (op != TOK_EQ) {
5269 /* generate non equal test */
5270 /* XXX: NOT PORTABLE yet */
5271 if (a == 0) {
5272 b = gtst(0, 0);
5273 } else {
5274 #if defined(TCC_TARGET_I386)
5275 b = psym(0x850f, 0);
5276 #elif defined(TCC_TARGET_ARM)
5277 b = ind;
5278 o(0x1A000000 | encbranch(ind, 0, 1));
5279 #elif defined(TCC_TARGET_C67)
5280 error("not implemented");
5281 #else
5282 #error not supported
5283 #endif
5286 /* compare low. Always unsigned */
5287 op1 = op;
5288 if (op1 == TOK_LT)
5289 op1 = TOK_ULT;
5290 else if (op1 == TOK_LE)
5291 op1 = TOK_ULE;
5292 else if (op1 == TOK_GT)
5293 op1 = TOK_UGT;
5294 else if (op1 == TOK_GE)
5295 op1 = TOK_UGE;
5296 gen_op(op1);
5297 a = gtst(1, a);
5298 gsym(b);
5299 vseti(VT_JMPI, a);
5300 break;
5304 /* handle integer constant optimizations and various machine
5305 independent opt */
5306 void gen_opic(int op)
5308 int fc, c1, c2, n;
5309 SValue *v1, *v2;
5311 v1 = vtop - 1;
5312 v2 = vtop;
5313 /* currently, we cannot do computations with forward symbols */
5314 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5315 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5316 if (c1 && c2) {
5317 fc = v2->c.i;
5318 switch(op) {
5319 case '+': v1->c.i += fc; break;
5320 case '-': v1->c.i -= fc; break;
5321 case '&': v1->c.i &= fc; break;
5322 case '^': v1->c.i ^= fc; break;
5323 case '|': v1->c.i |= fc; break;
5324 case '*': v1->c.i *= fc; break;
5326 case TOK_PDIV:
5327 case '/':
5328 case '%':
5329 case TOK_UDIV:
5330 case TOK_UMOD:
5331 /* if division by zero, generate explicit division */
5332 if (fc == 0) {
5333 if (const_wanted)
5334 error("division by zero in constant");
5335 goto general_case;
5337 switch(op) {
5338 default: v1->c.i /= fc; break;
5339 case '%': v1->c.i %= fc; break;
5340 case TOK_UDIV: v1->c.i = (unsigned)v1->c.i / fc; break;
5341 case TOK_UMOD: v1->c.i = (unsigned)v1->c.i % fc; break;
5343 break;
5344 case TOK_SHL: v1->c.i <<= fc; break;
5345 case TOK_SHR: v1->c.i = (unsigned)v1->c.i >> fc; break;
5346 case TOK_SAR: v1->c.i >>= fc; break;
5347 /* tests */
5348 case TOK_ULT: v1->c.i = (unsigned)v1->c.i < (unsigned)fc; break;
5349 case TOK_UGE: v1->c.i = (unsigned)v1->c.i >= (unsigned)fc; break;
5350 case TOK_EQ: v1->c.i = v1->c.i == fc; break;
5351 case TOK_NE: v1->c.i = v1->c.i != fc; break;
5352 case TOK_ULE: v1->c.i = (unsigned)v1->c.i <= (unsigned)fc; break;
5353 case TOK_UGT: v1->c.i = (unsigned)v1->c.i > (unsigned)fc; break;
5354 case TOK_LT: v1->c.i = v1->c.i < fc; break;
5355 case TOK_GE: v1->c.i = v1->c.i >= fc; break;
5356 case TOK_LE: v1->c.i = v1->c.i <= fc; break;
5357 case TOK_GT: v1->c.i = v1->c.i > fc; break;
5358 /* logical */
5359 case TOK_LAND: v1->c.i = v1->c.i && fc; break;
5360 case TOK_LOR: v1->c.i = v1->c.i || fc; break;
5361 default:
5362 goto general_case;
5364 vtop--;
5365 } else {
5366 /* if commutative ops, put c2 as constant */
5367 if (c1 && (op == '+' || op == '&' || op == '^' ||
5368 op == '|' || op == '*')) {
5369 vswap();
5370 swap(&c1, &c2);
5372 fc = vtop->c.i;
5373 if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
5374 op == TOK_PDIV) &&
5375 fc == 1) ||
5376 ((op == '+' || op == '-' || op == '|' || op == '^' ||
5377 op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
5378 fc == 0) ||
5379 (op == '&' &&
5380 fc == -1))) {
5381 /* nothing to do */
5382 vtop--;
5383 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
5384 /* try to use shifts instead of muls or divs */
5385 if (fc > 0 && (fc & (fc - 1)) == 0) {
5386 n = -1;
5387 while (fc) {
5388 fc >>= 1;
5389 n++;
5391 vtop->c.i = n;
5392 if (op == '*')
5393 op = TOK_SHL;
5394 else if (op == TOK_PDIV)
5395 op = TOK_SAR;
5396 else
5397 op = TOK_SHR;
5399 goto general_case;
5400 } else if (c2 && (op == '+' || op == '-') &&
5401 (vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) ==
5402 (VT_CONST | VT_SYM)) {
5403 /* symbol + constant case */
5404 if (op == '-')
5405 fc = -fc;
5406 vtop--;
5407 vtop->c.i += fc;
5408 } else {
5409 general_case:
5410 if (!nocode_wanted) {
5411 /* call low level op generator */
5412 gen_opi(op);
5413 } else {
5414 vtop--;
5420 /* generate a floating point operation with constant propagation */
5421 void gen_opif(int op)
5423 int c1, c2;
5424 SValue *v1, *v2;
5425 long double f1, f2;
5427 v1 = vtop - 1;
5428 v2 = vtop;
5429 /* currently, we cannot do computations with forward symbols */
5430 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5431 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5432 if (c1 && c2) {
5433 if (v1->type.t == VT_FLOAT) {
5434 f1 = v1->c.f;
5435 f2 = v2->c.f;
5436 } else if (v1->type.t == VT_DOUBLE) {
5437 f1 = v1->c.d;
5438 f2 = v2->c.d;
5439 } else {
5440 f1 = v1->c.ld;
5441 f2 = v2->c.ld;
5444 /* NOTE: we only do constant propagation if finite number (not
5445 NaN or infinity) (ANSI spec) */
5446 if (!ieee_finite(f1) || !ieee_finite(f2))
5447 goto general_case;
5449 switch(op) {
5450 case '+': f1 += f2; break;
5451 case '-': f1 -= f2; break;
5452 case '*': f1 *= f2; break;
5453 case '/':
5454 if (f2 == 0.0) {
5455 if (const_wanted)
5456 error("division by zero in constant");
5457 goto general_case;
5459 f1 /= f2;
5460 break;
5461 /* XXX: also handles tests ? */
5462 default:
5463 goto general_case;
5465 /* XXX: overflow test ? */
5466 if (v1->type.t == VT_FLOAT) {
5467 v1->c.f = f1;
5468 } else if (v1->type.t == VT_DOUBLE) {
5469 v1->c.d = f1;
5470 } else {
5471 v1->c.ld = f1;
5473 vtop--;
5474 } else {
5475 general_case:
5476 if (!nocode_wanted) {
5477 gen_opf(op);
5478 } else {
5479 vtop--;
5484 static int pointed_size(CType *type)
5486 int align;
5487 return type_size(pointed_type(type), &align);
5490 static inline int is_null_pointer(SValue *p)
5492 if ((p->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
5493 return 0;
5494 return ((p->type.t & VT_BTYPE) == VT_INT && p->c.i == 0) ||
5495 ((p->type.t & VT_BTYPE) == VT_LLONG && p->c.ll == 0);
5498 static inline int is_integer_btype(int bt)
5500 return (bt == VT_BYTE || bt == VT_SHORT ||
5501 bt == VT_INT || bt == VT_LLONG);
5504 /* check types for comparison or substraction of pointers */
5505 static void check_comparison_pointer_types(SValue *p1, SValue *p2, int op)
5507 CType *type1, *type2, tmp_type1, tmp_type2;
5508 int bt1, bt2;
5510 /* null pointers are accepted for all comparisons as gcc */
5511 if (is_null_pointer(p1) || is_null_pointer(p2))
5512 return;
5513 type1 = &p1->type;
5514 type2 = &p2->type;
5515 bt1 = type1->t & VT_BTYPE;
5516 bt2 = type2->t & VT_BTYPE;
5517 /* accept comparison between pointer and integer with a warning */
5518 if ((is_integer_btype(bt1) || is_integer_btype(bt2)) && op != '-') {
5519 warning("comparison between pointer and integer");
5520 return;
5523 /* both must be pointers or implicit function pointers */
5524 if (bt1 == VT_PTR) {
5525 type1 = pointed_type(type1);
5526 } else if (bt1 != VT_FUNC)
5527 goto invalid_operands;
5529 if (bt2 == VT_PTR) {
5530 type2 = pointed_type(type2);
5531 } else if (bt2 != VT_FUNC) {
5532 invalid_operands:
5533 error("invalid operands to binary %s", get_tok_str(op, NULL));
5535 if ((type1->t & VT_BTYPE) == VT_VOID ||
5536 (type2->t & VT_BTYPE) == VT_VOID)
5537 return;
5538 tmp_type1 = *type1;
5539 tmp_type2 = *type2;
5540 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5541 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5542 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
5543 /* gcc-like error if '-' is used */
5544 if (op == '-')
5545 goto invalid_operands;
5546 else
5547 warning("comparison of distinct pointer types lacks a cast");
5551 /* generic gen_op: handles types problems */
5552 void gen_op(int op)
5554 int u, t1, t2, bt1, bt2, t;
5555 CType type1;
5557 t1 = vtop[-1].type.t;
5558 t2 = vtop[0].type.t;
5559 bt1 = t1 & VT_BTYPE;
5560 bt2 = t2 & VT_BTYPE;
5562 if (bt1 == VT_PTR || bt2 == VT_PTR) {
5563 /* at least one operand is a pointer */
5564 /* relationnal op: must be both pointers */
5565 if (op >= TOK_ULT && op <= TOK_GT) {
5566 check_comparison_pointer_types(vtop - 1, vtop, op);
5567 /* pointers are handled are unsigned */
5568 t = VT_INT | VT_UNSIGNED;
5569 goto std_op;
5571 /* if both pointers, then it must be the '-' op */
5572 if (bt1 == VT_PTR && bt2 == VT_PTR) {
5573 if (op != '-')
5574 error("cannot use pointers here");
5575 check_comparison_pointer_types(vtop - 1, vtop, op);
5576 /* XXX: check that types are compatible */
5577 u = pointed_size(&vtop[-1].type);
5578 gen_opic(op);
5579 /* set to integer type */
5580 vtop->type.t = VT_INT;
5581 vpushi(u);
5582 gen_op(TOK_PDIV);
5583 } else {
5584 /* exactly one pointer : must be '+' or '-'. */
5585 if (op != '-' && op != '+')
5586 error("cannot use pointers here");
5587 /* Put pointer as first operand */
5588 if (bt2 == VT_PTR) {
5589 vswap();
5590 swap(&t1, &t2);
5592 type1 = vtop[-1].type;
5593 /* XXX: cast to int ? (long long case) */
5594 vpushi(pointed_size(&vtop[-1].type));
5595 gen_op('*');
5596 #ifdef CONFIG_TCC_BCHECK
5597 /* if evaluating constant expression, no code should be
5598 generated, so no bound check */
5599 if (do_bounds_check && !const_wanted) {
5600 /* if bounded pointers, we generate a special code to
5601 test bounds */
5602 if (op == '-') {
5603 vpushi(0);
5604 vswap();
5605 gen_op('-');
5607 gen_bounded_ptr_add();
5608 } else
5609 #endif
5611 gen_opic(op);
5613 /* put again type if gen_opic() swaped operands */
5614 vtop->type = type1;
5616 } else if (is_float(bt1) || is_float(bt2)) {
5617 /* compute bigger type and do implicit casts */
5618 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
5619 t = VT_LDOUBLE;
5620 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
5621 t = VT_DOUBLE;
5622 } else {
5623 t = VT_FLOAT;
5625 /* floats can only be used for a few operations */
5626 if (op != '+' && op != '-' && op != '*' && op != '/' &&
5627 (op < TOK_ULT || op > TOK_GT))
5628 error("invalid operands for binary operation");
5629 goto std_op;
5630 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
5631 /* cast to biggest op */
5632 t = VT_LLONG;
5633 /* convert to unsigned if it does not fit in a long long */
5634 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
5635 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
5636 t |= VT_UNSIGNED;
5637 goto std_op;
5638 } else {
5639 /* integer operations */
5640 t = VT_INT;
5641 /* convert to unsigned if it does not fit in an integer */
5642 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
5643 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
5644 t |= VT_UNSIGNED;
5645 std_op:
5646 /* XXX: currently, some unsigned operations are explicit, so
5647 we modify them here */
5648 if (t & VT_UNSIGNED) {
5649 if (op == TOK_SAR)
5650 op = TOK_SHR;
5651 else if (op == '/')
5652 op = TOK_UDIV;
5653 else if (op == '%')
5654 op = TOK_UMOD;
5655 else if (op == TOK_LT)
5656 op = TOK_ULT;
5657 else if (op == TOK_GT)
5658 op = TOK_UGT;
5659 else if (op == TOK_LE)
5660 op = TOK_ULE;
5661 else if (op == TOK_GE)
5662 op = TOK_UGE;
5664 vswap();
5665 type1.t = t;
5666 gen_cast(&type1);
5667 vswap();
5668 /* special case for shifts and long long: we keep the shift as
5669 an integer */
5670 if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL)
5671 type1.t = VT_INT;
5672 gen_cast(&type1);
5673 if (is_float(t))
5674 gen_opif(op);
5675 else if ((t & VT_BTYPE) == VT_LLONG)
5676 gen_opl(op);
5677 else
5678 gen_opic(op);
5679 if (op >= TOK_ULT && op <= TOK_GT) {
5680 /* relationnal op: the result is an int */
5681 vtop->type.t = VT_INT;
5682 } else {
5683 vtop->type.t = t;
5688 /* generic itof for unsigned long long case */
5689 void gen_cvt_itof1(int t)
5691 if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
5692 (VT_LLONG | VT_UNSIGNED)) {
5694 if (t == VT_FLOAT)
5695 vpush_global_sym(&func_old_type, TOK___ulltof);
5696 else if (t == VT_DOUBLE)
5697 vpush_global_sym(&func_old_type, TOK___ulltod);
5698 else
5699 vpush_global_sym(&func_old_type, TOK___ulltold);
5700 vrott(2);
5701 gfunc_call(1);
5702 vpushi(0);
5703 vtop->r = REG_FRET;
5704 } else {
5705 gen_cvt_itof(t);
5709 /* generic ftoi for unsigned long long case */
5710 void gen_cvt_ftoi1(int t)
5712 int st;
5714 if (t == (VT_LLONG | VT_UNSIGNED)) {
5715 /* not handled natively */
5716 st = vtop->type.t & VT_BTYPE;
5717 if (st == VT_FLOAT)
5718 vpush_global_sym(&func_old_type, TOK___fixunssfdi);
5719 else if (st == VT_DOUBLE)
5720 vpush_global_sym(&func_old_type, TOK___fixunsdfdi);
5721 else
5722 vpush_global_sym(&func_old_type, TOK___fixunsxfdi);
5723 vrott(2);
5724 gfunc_call(1);
5725 vpushi(0);
5726 vtop->r = REG_IRET;
5727 vtop->r2 = REG_LRET;
5728 } else {
5729 gen_cvt_ftoi(t);
5733 /* force char or short cast */
5734 void force_charshort_cast(int t)
5736 int bits, dbt;
5737 dbt = t & VT_BTYPE;
5738 /* XXX: add optimization if lvalue : just change type and offset */
5739 if (dbt == VT_BYTE)
5740 bits = 8;
5741 else
5742 bits = 16;
5743 if (t & VT_UNSIGNED) {
5744 vpushi((1 << bits) - 1);
5745 gen_op('&');
5746 } else {
5747 bits = 32 - bits;
5748 vpushi(bits);
5749 gen_op(TOK_SHL);
5750 vpushi(bits);
5751 gen_op(TOK_SAR);
5755 /* cast 'vtop' to 'type'. Casting to bitfields is forbidden. */
5756 static void gen_cast(CType *type)
5758 int sbt, dbt, sf, df, c;
5760 /* special delayed cast for char/short */
5761 /* XXX: in some cases (multiple cascaded casts), it may still
5762 be incorrect */
5763 if (vtop->r & VT_MUSTCAST) {
5764 vtop->r &= ~VT_MUSTCAST;
5765 force_charshort_cast(vtop->type.t);
5768 /* bitfields first get cast to ints */
5769 if (vtop->type.t & VT_BITFIELD) {
5770 gv(RC_INT);
5773 dbt = type->t & (VT_BTYPE | VT_UNSIGNED);
5774 sbt = vtop->type.t & (VT_BTYPE | VT_UNSIGNED);
5776 if (sbt != dbt && !nocode_wanted) {
5777 sf = is_float(sbt);
5778 df = is_float(dbt);
5779 c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5780 if (sf && df) {
5781 /* convert from fp to fp */
5782 if (c) {
5783 /* constant case: we can do it now */
5784 /* XXX: in ISOC, cannot do it if error in convert */
5785 if (dbt == VT_FLOAT && sbt == VT_DOUBLE)
5786 vtop->c.f = (float)vtop->c.d;
5787 else if (dbt == VT_FLOAT && sbt == VT_LDOUBLE)
5788 vtop->c.f = (float)vtop->c.ld;
5789 else if (dbt == VT_DOUBLE && sbt == VT_FLOAT)
5790 vtop->c.d = (double)vtop->c.f;
5791 else if (dbt == VT_DOUBLE && sbt == VT_LDOUBLE)
5792 vtop->c.d = (double)vtop->c.ld;
5793 else if (dbt == VT_LDOUBLE && sbt == VT_FLOAT)
5794 vtop->c.ld = (long double)vtop->c.f;
5795 else if (dbt == VT_LDOUBLE && sbt == VT_DOUBLE)
5796 vtop->c.ld = (long double)vtop->c.d;
5797 } else {
5798 /* non constant case: generate code */
5799 gen_cvt_ftof(dbt);
5801 } else if (df) {
5802 /* convert int to fp */
5803 if (c) {
5804 switch(sbt) {
5805 case VT_LLONG | VT_UNSIGNED:
5806 case VT_LLONG:
5807 /* XXX: add const cases for long long */
5808 goto do_itof;
5809 case VT_INT | VT_UNSIGNED:
5810 switch(dbt) {
5811 case VT_FLOAT: vtop->c.f = (float)vtop->c.ui; break;
5812 case VT_DOUBLE: vtop->c.d = (double)vtop->c.ui; break;
5813 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.ui; break;
5815 break;
5816 default:
5817 switch(dbt) {
5818 case VT_FLOAT: vtop->c.f = (float)vtop->c.i; break;
5819 case VT_DOUBLE: vtop->c.d = (double)vtop->c.i; break;
5820 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.i; break;
5822 break;
5824 } else {
5825 do_itof:
5826 #if !defined(TCC_TARGET_ARM)
5827 gen_cvt_itof1(dbt);
5828 #else
5829 gen_cvt_itof(dbt);
5830 #endif
5832 } else if (sf) {
5833 /* convert fp to int */
5834 /* we handle char/short/etc... with generic code */
5835 if (dbt != (VT_INT | VT_UNSIGNED) &&
5836 dbt != (VT_LLONG | VT_UNSIGNED) &&
5837 dbt != VT_LLONG)
5838 dbt = VT_INT;
5839 if (c) {
5840 switch(dbt) {
5841 case VT_LLONG | VT_UNSIGNED:
5842 case VT_LLONG:
5843 /* XXX: add const cases for long long */
5844 goto do_ftoi;
5845 case VT_INT | VT_UNSIGNED:
5846 switch(sbt) {
5847 case VT_FLOAT: vtop->c.ui = (unsigned int)vtop->c.d; break;
5848 case VT_DOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
5849 case VT_LDOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
5851 break;
5852 default:
5853 /* int case */
5854 switch(sbt) {
5855 case VT_FLOAT: vtop->c.i = (int)vtop->c.d; break;
5856 case VT_DOUBLE: vtop->c.i = (int)vtop->c.d; break;
5857 case VT_LDOUBLE: vtop->c.i = (int)vtop->c.d; break;
5859 break;
5861 } else {
5862 do_ftoi:
5863 gen_cvt_ftoi1(dbt);
5865 if (dbt == VT_INT && (type->t & (VT_BTYPE | VT_UNSIGNED)) != dbt) {
5866 /* additional cast for char/short/bool... */
5867 vtop->type.t = dbt;
5868 gen_cast(type);
5870 } else if ((dbt & VT_BTYPE) == VT_LLONG) {
5871 if ((sbt & VT_BTYPE) != VT_LLONG) {
5872 /* scalar to long long */
5873 if (c) {
5874 if (sbt == (VT_INT | VT_UNSIGNED))
5875 vtop->c.ll = vtop->c.ui;
5876 else
5877 vtop->c.ll = vtop->c.i;
5878 } else {
5879 /* machine independent conversion */
5880 gv(RC_INT);
5881 /* generate high word */
5882 if (sbt == (VT_INT | VT_UNSIGNED)) {
5883 vpushi(0);
5884 gv(RC_INT);
5885 } else {
5886 gv_dup();
5887 vpushi(31);
5888 gen_op(TOK_SAR);
5890 /* patch second register */
5891 vtop[-1].r2 = vtop->r;
5892 vpop();
5895 } else if (dbt == VT_BOOL) {
5896 /* scalar to bool */
5897 vpushi(0);
5898 gen_op(TOK_NE);
5899 } else if ((dbt & VT_BTYPE) == VT_BYTE ||
5900 (dbt & VT_BTYPE) == VT_SHORT) {
5901 force_charshort_cast(dbt);
5902 } else if ((dbt & VT_BTYPE) == VT_INT) {
5903 /* scalar to int */
5904 if (sbt == VT_LLONG) {
5905 /* from long long: just take low order word */
5906 lexpand();
5907 vpop();
5909 /* if lvalue and single word type, nothing to do because
5910 the lvalue already contains the real type size (see
5911 VT_LVAL_xxx constants) */
5914 vtop->type = *type;
5917 /* return type size. Put alignment at 'a' */
5918 static int type_size(CType *type, int *a)
5920 Sym *s;
5921 int bt;
5923 bt = type->t & VT_BTYPE;
5924 if (bt == VT_STRUCT) {
5925 /* struct/union */
5926 s = type->ref;
5927 *a = s->r;
5928 return s->c;
5929 } else if (bt == VT_PTR) {
5930 if (type->t & VT_ARRAY) {
5931 s = type->ref;
5932 return type_size(&s->type, a) * s->c;
5933 } else {
5934 *a = PTR_SIZE;
5935 return PTR_SIZE;
5937 } else if (bt == VT_LDOUBLE) {
5938 *a = LDOUBLE_ALIGN;
5939 return LDOUBLE_SIZE;
5940 } else if (bt == VT_DOUBLE || bt == VT_LLONG) {
5941 #ifdef TCC_TARGET_I386
5942 *a = 4;
5943 #else
5944 *a = 8;
5945 #endif
5946 return 8;
5947 } else if (bt == VT_INT || bt == VT_ENUM || bt == VT_FLOAT) {
5948 *a = 4;
5949 return 4;
5950 } else if (bt == VT_SHORT) {
5951 *a = 2;
5952 return 2;
5953 } else {
5954 /* char, void, function, _Bool */
5955 *a = 1;
5956 return 1;
5960 /* return the pointed type of t */
5961 static inline CType *pointed_type(CType *type)
5963 return &type->ref->type;
5966 /* modify type so that its it is a pointer to type. */
5967 static void mk_pointer(CType *type)
5969 Sym *s;
5970 s = sym_push(SYM_FIELD, type, 0, -1);
5971 type->t = VT_PTR | (type->t & ~VT_TYPE);
5972 type->ref = s;
5975 /* compare function types. OLD functions match any new functions */
5976 static int is_compatible_func(CType *type1, CType *type2)
5978 Sym *s1, *s2;
5980 s1 = type1->ref;
5981 s2 = type2->ref;
5982 if (!is_compatible_types(&s1->type, &s2->type))
5983 return 0;
5984 /* check func_call */
5985 if (s1->r != s2->r)
5986 return 0;
5987 /* XXX: not complete */
5988 if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
5989 return 1;
5990 if (s1->c != s2->c)
5991 return 0;
5992 while (s1 != NULL) {
5993 if (s2 == NULL)
5994 return 0;
5995 if (!is_compatible_types(&s1->type, &s2->type))
5996 return 0;
5997 s1 = s1->next;
5998 s2 = s2->next;
6000 if (s2)
6001 return 0;
6002 return 1;
6005 /* return true if type1 and type2 are exactly the same (including
6006 qualifiers).
6008 - enums are not checked as gcc __builtin_types_compatible_p ()
6010 static int is_compatible_types(CType *type1, CType *type2)
6012 int bt1, t1, t2;
6014 t1 = type1->t & VT_TYPE;
6015 t2 = type2->t & VT_TYPE;
6016 /* XXX: bitfields ? */
6017 if (t1 != t2)
6018 return 0;
6019 /* test more complicated cases */
6020 bt1 = t1 & VT_BTYPE;
6021 if (bt1 == VT_PTR) {
6022 type1 = pointed_type(type1);
6023 type2 = pointed_type(type2);
6024 return is_compatible_types(type1, type2);
6025 } else if (bt1 == VT_STRUCT) {
6026 return (type1->ref == type2->ref);
6027 } else if (bt1 == VT_FUNC) {
6028 return is_compatible_func(type1, type2);
6029 } else {
6030 return 1;
6034 /* print a type. If 'varstr' is not NULL, then the variable is also
6035 printed in the type */
6036 /* XXX: union */
6037 /* XXX: add array and function pointers */
6038 void type_to_str(char *buf, int buf_size,
6039 CType *type, const char *varstr)
6041 int bt, v, t;
6042 Sym *s, *sa;
6043 char buf1[256];
6044 const char *tstr;
6046 t = type->t & VT_TYPE;
6047 bt = t & VT_BTYPE;
6048 buf[0] = '\0';
6049 if (t & VT_CONSTANT)
6050 pstrcat(buf, buf_size, "const ");
6051 if (t & VT_VOLATILE)
6052 pstrcat(buf, buf_size, "volatile ");
6053 if (t & VT_UNSIGNED)
6054 pstrcat(buf, buf_size, "unsigned ");
6055 switch(bt) {
6056 case VT_VOID:
6057 tstr = "void";
6058 goto add_tstr;
6059 case VT_BOOL:
6060 tstr = "_Bool";
6061 goto add_tstr;
6062 case VT_BYTE:
6063 tstr = "char";
6064 goto add_tstr;
6065 case VT_SHORT:
6066 tstr = "short";
6067 goto add_tstr;
6068 case VT_INT:
6069 tstr = "int";
6070 goto add_tstr;
6071 case VT_LONG:
6072 tstr = "long";
6073 goto add_tstr;
6074 case VT_LLONG:
6075 tstr = "long long";
6076 goto add_tstr;
6077 case VT_FLOAT:
6078 tstr = "float";
6079 goto add_tstr;
6080 case VT_DOUBLE:
6081 tstr = "double";
6082 goto add_tstr;
6083 case VT_LDOUBLE:
6084 tstr = "long double";
6085 add_tstr:
6086 pstrcat(buf, buf_size, tstr);
6087 break;
6088 case VT_ENUM:
6089 case VT_STRUCT:
6090 if (bt == VT_STRUCT)
6091 tstr = "struct ";
6092 else
6093 tstr = "enum ";
6094 pstrcat(buf, buf_size, tstr);
6095 v = type->ref->v & ~SYM_STRUCT;
6096 if (v >= SYM_FIRST_ANOM)
6097 pstrcat(buf, buf_size, "<anonymous>");
6098 else
6099 pstrcat(buf, buf_size, get_tok_str(v, NULL));
6100 break;
6101 case VT_FUNC:
6102 s = type->ref;
6103 type_to_str(buf, buf_size, &s->type, varstr);
6104 pstrcat(buf, buf_size, "(");
6105 sa = s->next;
6106 while (sa != NULL) {
6107 type_to_str(buf1, sizeof(buf1), &sa->type, NULL);
6108 pstrcat(buf, buf_size, buf1);
6109 sa = sa->next;
6110 if (sa)
6111 pstrcat(buf, buf_size, ", ");
6113 pstrcat(buf, buf_size, ")");
6114 goto no_var;
6115 case VT_PTR:
6116 s = type->ref;
6117 pstrcpy(buf1, sizeof(buf1), "*");
6118 if (varstr)
6119 pstrcat(buf1, sizeof(buf1), varstr);
6120 type_to_str(buf, buf_size, &s->type, buf1);
6121 goto no_var;
6123 if (varstr) {
6124 pstrcat(buf, buf_size, " ");
6125 pstrcat(buf, buf_size, varstr);
6127 no_var: ;
6130 /* verify type compatibility to store vtop in 'dt' type, and generate
6131 casts if needed. */
6132 static void gen_assign_cast(CType *dt)
6134 CType *st, *type1, *type2, tmp_type1, tmp_type2;
6135 char buf1[256], buf2[256];
6136 int dbt, sbt;
6138 st = &vtop->type; /* source type */
6139 dbt = dt->t & VT_BTYPE;
6140 sbt = st->t & VT_BTYPE;
6141 if (dt->t & VT_CONSTANT)
6142 warning("assignment of read-only location");
6143 switch(dbt) {
6144 case VT_PTR:
6145 /* special cases for pointers */
6146 /* '0' can also be a pointer */
6147 if (is_null_pointer(vtop))
6148 goto type_ok;
6149 /* accept implicit pointer to integer cast with warning */
6150 if (is_integer_btype(sbt)) {
6151 warning("assignment makes pointer from integer without a cast");
6152 goto type_ok;
6154 type1 = pointed_type(dt);
6155 /* a function is implicitely a function pointer */
6156 if (sbt == VT_FUNC) {
6157 if ((type1->t & VT_BTYPE) != VT_VOID &&
6158 !is_compatible_types(pointed_type(dt), st))
6159 goto error;
6160 else
6161 goto type_ok;
6163 if (sbt != VT_PTR)
6164 goto error;
6165 type2 = pointed_type(st);
6166 if ((type1->t & VT_BTYPE) == VT_VOID ||
6167 (type2->t & VT_BTYPE) == VT_VOID) {
6168 /* void * can match anything */
6169 } else {
6170 /* exact type match, except for unsigned */
6171 tmp_type1 = *type1;
6172 tmp_type2 = *type2;
6173 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
6174 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
6175 if (!is_compatible_types(&tmp_type1, &tmp_type2))
6176 goto error;
6178 /* check const and volatile */
6179 if ((!(type1->t & VT_CONSTANT) && (type2->t & VT_CONSTANT)) ||
6180 (!(type1->t & VT_VOLATILE) && (type2->t & VT_VOLATILE)))
6181 warning("assignment discards qualifiers from pointer target type");
6182 break;
6183 case VT_BYTE:
6184 case VT_SHORT:
6185 case VT_INT:
6186 case VT_LLONG:
6187 if (sbt == VT_PTR || sbt == VT_FUNC) {
6188 warning("assignment makes integer from pointer without a cast");
6190 /* XXX: more tests */
6191 break;
6192 case VT_STRUCT:
6193 tmp_type1 = *dt;
6194 tmp_type2 = *st;
6195 tmp_type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
6196 tmp_type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
6197 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
6198 error:
6199 type_to_str(buf1, sizeof(buf1), st, NULL);
6200 type_to_str(buf2, sizeof(buf2), dt, NULL);
6201 error("cannot cast '%s' to '%s'", buf1, buf2);
6203 break;
6205 type_ok:
6206 gen_cast(dt);
6209 /* store vtop in lvalue pushed on stack */
6210 void vstore(void)
6212 int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
6214 ft = vtop[-1].type.t;
6215 sbt = vtop->type.t & VT_BTYPE;
6216 dbt = ft & VT_BTYPE;
6217 if (((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
6218 (sbt == VT_INT && dbt == VT_SHORT)) {
6219 /* optimize char/short casts */
6220 delayed_cast = VT_MUSTCAST;
6221 vtop->type.t = ft & VT_TYPE;
6222 /* XXX: factorize */
6223 if (ft & VT_CONSTANT)
6224 warning("assignment of read-only location");
6225 } else {
6226 delayed_cast = 0;
6227 if (!(ft & VT_BITFIELD))
6228 gen_assign_cast(&vtop[-1].type);
6231 if (sbt == VT_STRUCT) {
6232 /* if structure, only generate pointer */
6233 /* structure assignment : generate memcpy */
6234 /* XXX: optimize if small size */
6235 if (!nocode_wanted) {
6236 size = type_size(&vtop->type, &align);
6238 vpush_global_sym(&func_old_type, TOK_memcpy);
6240 /* destination */
6241 vpushv(vtop - 2);
6242 vtop->type.t = VT_INT;
6243 gaddrof();
6244 /* source */
6245 vpushv(vtop - 2);
6246 vtop->type.t = VT_INT;
6247 gaddrof();
6248 /* type size */
6249 vpushi(size);
6250 gfunc_call(3);
6252 vswap();
6253 vpop();
6254 } else {
6255 vswap();
6256 vpop();
6258 /* leave source on stack */
6259 } else if (ft & VT_BITFIELD) {
6260 /* bitfield store handling */
6261 bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
6262 bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
6263 /* remove bit field info to avoid loops */
6264 vtop[-1].type.t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
6266 /* duplicate destination */
6267 vdup();
6268 vtop[-1] = vtop[-2];
6270 /* mask and shift source */
6271 vpushi((1 << bit_size) - 1);
6272 gen_op('&');
6273 vpushi(bit_pos);
6274 gen_op(TOK_SHL);
6275 /* load destination, mask and or with source */
6276 vswap();
6277 vpushi(~(((1 << bit_size) - 1) << bit_pos));
6278 gen_op('&');
6279 gen_op('|');
6280 /* store result */
6281 vstore();
6282 } else {
6283 #ifdef CONFIG_TCC_BCHECK
6284 /* bound check case */
6285 if (vtop[-1].r & VT_MUSTBOUND) {
6286 vswap();
6287 gbound();
6288 vswap();
6290 #endif
6291 if (!nocode_wanted) {
6292 rc = RC_INT;
6293 if (is_float(ft))
6294 rc = RC_FLOAT;
6295 r = gv(rc); /* generate value */
6296 /* if lvalue was saved on stack, must read it */
6297 if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
6298 SValue sv;
6299 t = get_reg(RC_INT);
6300 sv.type.t = VT_INT;
6301 sv.r = VT_LOCAL | VT_LVAL;
6302 sv.c.ul = vtop[-1].c.ul;
6303 load(t, &sv);
6304 vtop[-1].r = t | VT_LVAL;
6306 store(r, vtop - 1);
6307 /* two word case handling : store second register at word + 4 */
6308 if ((ft & VT_BTYPE) == VT_LLONG) {
6309 vswap();
6310 /* convert to int to increment easily */
6311 vtop->type.t = VT_INT;
6312 gaddrof();
6313 vpushi(4);
6314 gen_op('+');
6315 vtop->r |= VT_LVAL;
6316 vswap();
6317 /* XXX: it works because r2 is spilled last ! */
6318 store(vtop->r2, vtop - 1);
6321 vswap();
6322 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
6323 vtop->r |= delayed_cast;
6327 /* post defines POST/PRE add. c is the token ++ or -- */
6328 void inc(int post, int c)
6330 test_lvalue();
6331 vdup(); /* save lvalue */
6332 if (post) {
6333 gv_dup(); /* duplicate value */
6334 vrotb(3);
6335 vrotb(3);
6337 /* add constant */
6338 vpushi(c - TOK_MID);
6339 gen_op('+');
6340 vstore(); /* store value */
6341 if (post)
6342 vpop(); /* if post op, return saved value */
6345 /* Parse GNUC __attribute__ extension. Currently, the following
6346 extensions are recognized:
6347 - aligned(n) : set data/function alignment.
6348 - packed : force data alignment to 1
6349 - section(x) : generate data/code in this section.
6350 - unused : currently ignored, but may be used someday.
6351 - regparm(n) : pass function parameters in registers (i386 only)
6353 static void parse_attribute(AttributeDef *ad)
6355 int t, n;
6357 while (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) {
6358 next();
6359 skip('(');
6360 skip('(');
6361 while (tok != ')') {
6362 if (tok < TOK_IDENT)
6363 expect("attribute name");
6364 t = tok;
6365 next();
6366 switch(t) {
6367 case TOK_SECTION1:
6368 case TOK_SECTION2:
6369 skip('(');
6370 if (tok != TOK_STR)
6371 expect("section name");
6372 ad->section = find_section(tcc_state, (char *)tokc.cstr->data);
6373 next();
6374 skip(')');
6375 break;
6376 case TOK_ALIGNED1:
6377 case TOK_ALIGNED2:
6378 if (tok == '(') {
6379 next();
6380 n = expr_const();
6381 if (n <= 0 || (n & (n - 1)) != 0)
6382 error("alignment must be a positive power of two");
6383 skip(')');
6384 } else {
6385 n = MAX_ALIGN;
6387 ad->aligned = n;
6388 break;
6389 case TOK_PACKED1:
6390 case TOK_PACKED2:
6391 ad->packed = 1;
6392 break;
6393 case TOK_UNUSED1:
6394 case TOK_UNUSED2:
6395 /* currently, no need to handle it because tcc does not
6396 track unused objects */
6397 break;
6398 case TOK_NORETURN1:
6399 case TOK_NORETURN2:
6400 /* currently, no need to handle it because tcc does not
6401 track unused objects */
6402 break;
6403 case TOK_CDECL1:
6404 case TOK_CDECL2:
6405 case TOK_CDECL3:
6406 ad->func_call = FUNC_CDECL;
6407 break;
6408 case TOK_STDCALL1:
6409 case TOK_STDCALL2:
6410 case TOK_STDCALL3:
6411 ad->func_call = FUNC_STDCALL;
6412 break;
6413 #ifdef TCC_TARGET_I386
6414 case TOK_REGPARM1:
6415 case TOK_REGPARM2:
6416 skip('(');
6417 n = expr_const();
6418 if (n > 3)
6419 n = 3;
6420 else if (n < 0)
6421 n = 0;
6422 if (n > 0)
6423 ad->func_call = FUNC_FASTCALL1 + n - 1;
6424 skip(')');
6425 break;
6426 #endif
6427 case TOK_DLLEXPORT:
6428 ad->dllexport = 1;
6429 break;
6430 default:
6431 if (tcc_state->warn_unsupported)
6432 warning("'%s' attribute ignored", get_tok_str(t, NULL));
6433 /* skip parameters */
6434 /* XXX: skip parenthesis too */
6435 if (tok == '(') {
6436 next();
6437 while (tok != ')' && tok != -1)
6438 next();
6439 next();
6441 break;
6443 if (tok != ',')
6444 break;
6445 next();
6447 skip(')');
6448 skip(')');
6452 /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
6453 static void struct_decl(CType *type, int u)
6455 int a, v, size, align, maxalign, c, offset;
6456 int bit_size, bit_pos, bsize, bt, lbit_pos;
6457 Sym *s, *ss, **ps;
6458 AttributeDef ad;
6459 CType type1, btype;
6461 a = tok; /* save decl type */
6462 next();
6463 if (tok != '{') {
6464 v = tok;
6465 next();
6466 /* struct already defined ? return it */
6467 if (v < TOK_IDENT)
6468 expect("struct/union/enum name");
6469 s = struct_find(v);
6470 if (s) {
6471 if (s->type.t != a)
6472 error("invalid type");
6473 goto do_decl;
6475 } else {
6476 v = anon_sym++;
6478 type1.t = a;
6479 /* we put an undefined size for struct/union */
6480 s = sym_push(v | SYM_STRUCT, &type1, 0, -1);
6481 s->r = 0; /* default alignment is zero as gcc */
6482 /* put struct/union/enum name in type */
6483 do_decl:
6484 type->t = u;
6485 type->ref = s;
6487 if (tok == '{') {
6488 next();
6489 if (s->c != -1)
6490 error("struct/union/enum already defined");
6491 /* cannot be empty */
6492 c = 0;
6493 /* non empty enums are not allowed */
6494 if (a == TOK_ENUM) {
6495 for(;;) {
6496 v = tok;
6497 if (v < TOK_UIDENT)
6498 expect("identifier");
6499 next();
6500 if (tok == '=') {
6501 next();
6502 c = expr_const();
6504 /* enum symbols have static storage */
6505 ss = sym_push(v, &int_type, VT_CONST, c);
6506 ss->type.t |= VT_STATIC;
6507 if (tok != ',')
6508 break;
6509 next();
6510 c++;
6511 /* NOTE: we accept a trailing comma */
6512 if (tok == '}')
6513 break;
6515 skip('}');
6516 } else {
6517 maxalign = 1;
6518 ps = &s->next;
6519 bit_pos = 0;
6520 offset = 0;
6521 while (tok != '}') {
6522 parse_btype(&btype, &ad);
6523 while (1) {
6524 bit_size = -1;
6525 v = 0;
6526 type1 = btype;
6527 if (tok != ':') {
6528 type_decl(&type1, &ad, &v, TYPE_DIRECT);
6529 if ((type1.t & VT_BTYPE) == VT_FUNC ||
6530 (type1.t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN | VT_INLINE)))
6531 error("invalid type for '%s'",
6532 get_tok_str(v, NULL));
6534 if (tok == ':') {
6535 next();
6536 bit_size = expr_const();
6537 /* XXX: handle v = 0 case for messages */
6538 if (bit_size < 0)
6539 error("negative width in bit-field '%s'",
6540 get_tok_str(v, NULL));
6541 if (v && bit_size == 0)
6542 error("zero width for bit-field '%s'",
6543 get_tok_str(v, NULL));
6545 size = type_size(&type1, &align);
6546 if (ad.aligned) {
6547 if (align < ad.aligned)
6548 align = ad.aligned;
6549 } else if (ad.packed) {
6550 align = 1;
6551 } else if (*tcc_state->pack_stack_ptr) {
6552 if (align > *tcc_state->pack_stack_ptr)
6553 align = *tcc_state->pack_stack_ptr;
6555 lbit_pos = 0;
6556 if (bit_size >= 0) {
6557 bt = type1.t & VT_BTYPE;
6558 if (bt != VT_INT &&
6559 bt != VT_BYTE &&
6560 bt != VT_SHORT &&
6561 bt != VT_BOOL &&
6562 bt != VT_ENUM)
6563 error("bitfields must have scalar type");
6564 bsize = size * 8;
6565 if (bit_size > bsize) {
6566 error("width of '%s' exceeds its type",
6567 get_tok_str(v, NULL));
6568 } else if (bit_size == bsize) {
6569 /* no need for bit fields */
6570 bit_pos = 0;
6571 } else if (bit_size == 0) {
6572 /* XXX: what to do if only padding in a
6573 structure ? */
6574 /* zero size: means to pad */
6575 if (bit_pos > 0)
6576 bit_pos = bsize;
6577 } else {
6578 /* we do not have enough room ? */
6579 if ((bit_pos + bit_size) > bsize)
6580 bit_pos = 0;
6581 lbit_pos = bit_pos;
6582 /* XXX: handle LSB first */
6583 type1.t |= VT_BITFIELD |
6584 (bit_pos << VT_STRUCT_SHIFT) |
6585 (bit_size << (VT_STRUCT_SHIFT + 6));
6586 bit_pos += bit_size;
6588 } else {
6589 bit_pos = 0;
6591 if (v) {
6592 /* add new memory data only if starting
6593 bit field */
6594 if (lbit_pos == 0) {
6595 if (a == TOK_STRUCT) {
6596 c = (c + align - 1) & -align;
6597 offset = c;
6598 c += size;
6599 } else {
6600 offset = 0;
6601 if (size > c)
6602 c = size;
6604 if (align > maxalign)
6605 maxalign = align;
6607 #if 0
6608 printf("add field %s offset=%d",
6609 get_tok_str(v, NULL), offset);
6610 if (type1.t & VT_BITFIELD) {
6611 printf(" pos=%d size=%d",
6612 (type1.t >> VT_STRUCT_SHIFT) & 0x3f,
6613 (type1.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
6615 printf("\n");
6616 #endif
6617 ss = sym_push(v | SYM_FIELD, &type1, 0, offset);
6618 *ps = ss;
6619 ps = &ss->next;
6621 if (tok == ';' || tok == TOK_EOF)
6622 break;
6623 skip(',');
6625 skip(';');
6627 skip('}');
6628 /* store size and alignment */
6629 s->c = (c + maxalign - 1) & -maxalign;
6630 s->r = maxalign;
6635 /* return 0 if no type declaration. otherwise, return the basic type
6636 and skip it.
6638 static int parse_btype(CType *type, AttributeDef *ad)
6640 int t, u, type_found, typespec_found;
6641 Sym *s;
6642 CType type1;
6644 memset(ad, 0, sizeof(AttributeDef));
6645 type_found = 0;
6646 typespec_found = 0;
6647 t = 0;
6648 while(1) {
6649 switch(tok) {
6650 case TOK_EXTENSION:
6651 /* currently, we really ignore extension */
6652 next();
6653 continue;
6655 /* basic types */
6656 case TOK_CHAR:
6657 u = VT_BYTE;
6658 basic_type:
6659 next();
6660 basic_type1:
6661 if ((t & VT_BTYPE) != 0)
6662 error("too many basic types");
6663 t |= u;
6664 typespec_found = 1;
6665 break;
6666 case TOK_VOID:
6667 u = VT_VOID;
6668 goto basic_type;
6669 case TOK_SHORT:
6670 u = VT_SHORT;
6671 goto basic_type;
6672 case TOK_INT:
6673 next();
6674 typespec_found = 1;
6675 break;
6676 case TOK_LONG:
6677 next();
6678 if ((t & VT_BTYPE) == VT_DOUBLE) {
6679 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6680 } else if ((t & VT_BTYPE) == VT_LONG) {
6681 t = (t & ~VT_BTYPE) | VT_LLONG;
6682 } else {
6683 u = VT_LONG;
6684 goto basic_type1;
6686 break;
6687 case TOK_BOOL:
6688 u = VT_BOOL;
6689 goto basic_type;
6690 case TOK_FLOAT:
6691 u = VT_FLOAT;
6692 goto basic_type;
6693 case TOK_DOUBLE:
6694 next();
6695 if ((t & VT_BTYPE) == VT_LONG) {
6696 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6697 } else {
6698 u = VT_DOUBLE;
6699 goto basic_type1;
6701 break;
6702 case TOK_ENUM:
6703 struct_decl(&type1, VT_ENUM);
6704 basic_type2:
6705 u = type1.t;
6706 type->ref = type1.ref;
6707 goto basic_type1;
6708 case TOK_STRUCT:
6709 case TOK_UNION:
6710 struct_decl(&type1, VT_STRUCT);
6711 goto basic_type2;
6713 /* type modifiers */
6714 case TOK_CONST1:
6715 case TOK_CONST2:
6716 case TOK_CONST3:
6717 t |= VT_CONSTANT;
6718 next();
6719 break;
6720 case TOK_VOLATILE1:
6721 case TOK_VOLATILE2:
6722 case TOK_VOLATILE3:
6723 t |= VT_VOLATILE;
6724 next();
6725 break;
6726 case TOK_SIGNED1:
6727 case TOK_SIGNED2:
6728 case TOK_SIGNED3:
6729 typespec_found = 1;
6730 t |= VT_SIGNED;
6731 next();
6732 break;
6733 case TOK_REGISTER:
6734 case TOK_AUTO:
6735 case TOK_RESTRICT1:
6736 case TOK_RESTRICT2:
6737 case TOK_RESTRICT3:
6738 next();
6739 break;
6740 case TOK_UNSIGNED:
6741 t |= VT_UNSIGNED;
6742 next();
6743 typespec_found = 1;
6744 break;
6746 /* storage */
6747 case TOK_EXTERN:
6748 t |= VT_EXTERN;
6749 next();
6750 break;
6751 case TOK_STATIC:
6752 t |= VT_STATIC;
6753 next();
6754 break;
6755 case TOK_TYPEDEF:
6756 t |= VT_TYPEDEF;
6757 next();
6758 break;
6759 case TOK_INLINE1:
6760 case TOK_INLINE2:
6761 case TOK_INLINE3:
6762 t |= VT_INLINE;
6763 next();
6764 break;
6766 /* GNUC attribute */
6767 case TOK_ATTRIBUTE1:
6768 case TOK_ATTRIBUTE2:
6769 parse_attribute(ad);
6770 break;
6771 /* GNUC typeof */
6772 case TOK_TYPEOF1:
6773 case TOK_TYPEOF2:
6774 case TOK_TYPEOF3:
6775 next();
6776 parse_expr_type(&type1);
6777 goto basic_type2;
6778 default:
6779 if (typespec_found)
6780 goto the_end;
6781 s = sym_find(tok);
6782 if (!s || !(s->type.t & VT_TYPEDEF))
6783 goto the_end;
6784 t |= (s->type.t & ~VT_TYPEDEF);
6785 type->ref = s->type.ref;
6786 next();
6787 break;
6789 type_found = 1;
6791 the_end:
6792 if ((t & (VT_SIGNED|VT_UNSIGNED)) == (VT_SIGNED|VT_UNSIGNED))
6793 error("signed and unsigned modifier");
6794 if (tcc_state->char_is_unsigned) {
6795 if ((t & (VT_SIGNED|VT_UNSIGNED|VT_BTYPE)) == VT_BYTE)
6796 t |= VT_UNSIGNED;
6798 t &= ~VT_SIGNED;
6800 /* long is never used as type */
6801 if ((t & VT_BTYPE) == VT_LONG)
6802 t = (t & ~VT_BTYPE) | VT_INT;
6803 type->t = t;
6804 return type_found;
6807 /* convert a function parameter type (array to pointer and function to
6808 function pointer) */
6809 static inline void convert_parameter_type(CType *pt)
6811 /* remove const and volatile qualifiers (XXX: const could be used
6812 to indicate a const function parameter */
6813 pt->t &= ~(VT_CONSTANT | VT_VOLATILE);
6814 /* array must be transformed to pointer according to ANSI C */
6815 pt->t &= ~VT_ARRAY;
6816 if ((pt->t & VT_BTYPE) == VT_FUNC) {
6817 mk_pointer(pt);
6821 static void post_type(CType *type, AttributeDef *ad)
6823 int n, l, t1;
6824 Sym **plast, *s, *first;
6825 AttributeDef ad1;
6826 CType pt;
6828 if (tok == '(') {
6829 /* function declaration */
6830 next();
6831 l = 0;
6832 first = NULL;
6833 plast = &first;
6834 while (tok != ')') {
6835 /* read param name and compute offset */
6836 if (l != FUNC_OLD) {
6837 if (!parse_btype(&pt, &ad1)) {
6838 if (l) {
6839 error("invalid type");
6840 } else {
6841 l = FUNC_OLD;
6842 goto old_proto;
6845 l = FUNC_NEW;
6846 if ((pt.t & VT_BTYPE) == VT_VOID && tok == ')')
6847 break;
6848 type_decl(&pt, &ad1, &n, TYPE_DIRECT | TYPE_ABSTRACT);
6849 if ((pt.t & VT_BTYPE) == VT_VOID)
6850 error("parameter declared as void");
6851 } else {
6852 old_proto:
6853 n = tok;
6854 pt.t = VT_INT;
6855 next();
6857 convert_parameter_type(&pt);
6858 s = sym_push(n | SYM_FIELD, &pt, 0, 0);
6859 *plast = s;
6860 plast = &s->next;
6861 if (tok == ',') {
6862 next();
6863 if (l == FUNC_NEW && tok == TOK_DOTS) {
6864 l = FUNC_ELLIPSIS;
6865 next();
6866 break;
6870 /* if no parameters, then old type prototype */
6871 if (l == 0)
6872 l = FUNC_OLD;
6873 skip(')');
6874 t1 = type->t & VT_STORAGE;
6875 /* NOTE: const is ignored in returned type as it has a special
6876 meaning in gcc / C++ */
6877 type->t &= ~(VT_STORAGE | VT_CONSTANT);
6878 post_type(type, ad);
6879 /* we push a anonymous symbol which will contain the function prototype */
6880 s = sym_push(SYM_FIELD, type, ad->func_call, l);
6881 s->next = first;
6882 type->t = t1 | VT_FUNC;
6883 type->ref = s;
6884 } else if (tok == '[') {
6885 /* array definition */
6886 next();
6887 n = -1;
6888 if (tok != ']') {
6889 n = expr_const();
6890 if (n < 0)
6891 error("invalid array size");
6893 skip(']');
6894 /* parse next post type */
6895 t1 = type->t & VT_STORAGE;
6896 type->t &= ~VT_STORAGE;
6897 post_type(type, ad);
6899 /* we push a anonymous symbol which will contain the array
6900 element type */
6901 s = sym_push(SYM_FIELD, type, 0, n);
6902 type->t = t1 | VT_ARRAY | VT_PTR;
6903 type->ref = s;
6907 /* Parse a type declaration (except basic type), and return the type
6908 in 'type'. 'td' is a bitmask indicating which kind of type decl is
6909 expected. 'type' should contain the basic type. 'ad' is the
6910 attribute definition of the basic type. It can be modified by
6911 type_decl().
6913 static void type_decl(CType *type, AttributeDef *ad, int *v, int td)
6915 Sym *s;
6916 CType type1, *type2;
6917 int qualifiers;
6919 while (tok == '*') {
6920 qualifiers = 0;
6921 redo:
6922 next();
6923 switch(tok) {
6924 case TOK_CONST1:
6925 case TOK_CONST2:
6926 case TOK_CONST3:
6927 qualifiers |= VT_CONSTANT;
6928 goto redo;
6929 case TOK_VOLATILE1:
6930 case TOK_VOLATILE2:
6931 case TOK_VOLATILE3:
6932 qualifiers |= VT_VOLATILE;
6933 goto redo;
6934 case TOK_RESTRICT1:
6935 case TOK_RESTRICT2:
6936 case TOK_RESTRICT3:
6937 goto redo;
6939 mk_pointer(type);
6940 type->t |= qualifiers;
6943 /* XXX: clarify attribute handling */
6944 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6945 parse_attribute(ad);
6947 /* recursive type */
6948 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
6949 type1.t = 0; /* XXX: same as int */
6950 if (tok == '(') {
6951 next();
6952 /* XXX: this is not correct to modify 'ad' at this point, but
6953 the syntax is not clear */
6954 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6955 parse_attribute(ad);
6956 type_decl(&type1, ad, v, td);
6957 skip(')');
6958 } else {
6959 /* type identifier */
6960 if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
6961 *v = tok;
6962 next();
6963 } else {
6964 if (!(td & TYPE_ABSTRACT))
6965 expect("identifier");
6966 *v = 0;
6969 post_type(type, ad);
6970 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6971 parse_attribute(ad);
6972 if (!type1.t)
6973 return;
6974 /* append type at the end of type1 */
6975 type2 = &type1;
6976 for(;;) {
6977 s = type2->ref;
6978 type2 = &s->type;
6979 if (!type2->t) {
6980 *type2 = *type;
6981 break;
6984 *type = type1;
6987 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
6988 static int lvalue_type(int t)
6990 int bt, r;
6991 r = VT_LVAL;
6992 bt = t & VT_BTYPE;
6993 if (bt == VT_BYTE || bt == VT_BOOL)
6994 r |= VT_LVAL_BYTE;
6995 else if (bt == VT_SHORT)
6996 r |= VT_LVAL_SHORT;
6997 else
6998 return r;
6999 if (t & VT_UNSIGNED)
7000 r |= VT_LVAL_UNSIGNED;
7001 return r;
7004 /* indirection with full error checking and bound check */
7005 static void indir(void)
7007 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
7008 expect("pointer");
7009 if ((vtop->r & VT_LVAL) && !nocode_wanted)
7010 gv(RC_INT);
7011 vtop->type = *pointed_type(&vtop->type);
7012 /* an array is never an lvalue */
7013 if (!(vtop->type.t & VT_ARRAY)) {
7014 vtop->r |= lvalue_type(vtop->type.t);
7015 /* if bound checking, the referenced pointer must be checked */
7016 if (do_bounds_check)
7017 vtop->r |= VT_MUSTBOUND;
7021 /* pass a parameter to a function and do type checking and casting */
7022 static void gfunc_param_typed(Sym *func, Sym *arg)
7024 int func_type;
7025 CType type;
7027 func_type = func->c;
7028 if (func_type == FUNC_OLD ||
7029 (func_type == FUNC_ELLIPSIS && arg == NULL)) {
7030 /* default casting : only need to convert float to double */
7031 if ((vtop->type.t & VT_BTYPE) == VT_FLOAT) {
7032 type.t = VT_DOUBLE;
7033 gen_cast(&type);
7035 } else if (arg == NULL) {
7036 error("too many arguments to function");
7037 } else {
7038 type = arg->type;
7039 type.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
7040 gen_assign_cast(&type);
7044 /* parse an expression of the form '(type)' or '(expr)' and return its
7045 type */
7046 static void parse_expr_type(CType *type)
7048 int n;
7049 AttributeDef ad;
7051 skip('(');
7052 if (parse_btype(type, &ad)) {
7053 type_decl(type, &ad, &n, TYPE_ABSTRACT);
7054 } else {
7055 expr_type(type);
7057 skip(')');
7060 static void parse_type(CType *type)
7062 AttributeDef ad;
7063 int n;
7065 if (!parse_btype(type, &ad)) {
7066 expect("type");
7068 type_decl(type, &ad, &n, TYPE_ABSTRACT);
7071 static void vpush_tokc(int t)
7073 CType type;
7074 type.t = t;
7075 vsetc(&type, VT_CONST, &tokc);
7078 static void unary(void)
7080 int n, t, align, size, r;
7081 CType type;
7082 Sym *s;
7083 AttributeDef ad;
7085 /* XXX: GCC 2.95.3 does not generate a table although it should be
7086 better here */
7087 tok_next:
7088 switch(tok) {
7089 case TOK_EXTENSION:
7090 next();
7091 goto tok_next;
7092 case TOK_CINT:
7093 case TOK_CCHAR:
7094 case TOK_LCHAR:
7095 vpushi(tokc.i);
7096 next();
7097 break;
7098 case TOK_CUINT:
7099 vpush_tokc(VT_INT | VT_UNSIGNED);
7100 next();
7101 break;
7102 case TOK_CLLONG:
7103 vpush_tokc(VT_LLONG);
7104 next();
7105 break;
7106 case TOK_CULLONG:
7107 vpush_tokc(VT_LLONG | VT_UNSIGNED);
7108 next();
7109 break;
7110 case TOK_CFLOAT:
7111 vpush_tokc(VT_FLOAT);
7112 next();
7113 break;
7114 case TOK_CDOUBLE:
7115 vpush_tokc(VT_DOUBLE);
7116 next();
7117 break;
7118 case TOK_CLDOUBLE:
7119 vpush_tokc(VT_LDOUBLE);
7120 next();
7121 break;
7122 case TOK___FUNCTION__:
7123 if (!gnu_ext)
7124 goto tok_identifier;
7125 /* fall thru */
7126 case TOK___FUNC__:
7128 void *ptr;
7129 int len;
7130 /* special function name identifier */
7131 len = strlen(funcname) + 1;
7132 /* generate char[len] type */
7133 type.t = VT_BYTE;
7134 mk_pointer(&type);
7135 type.t |= VT_ARRAY;
7136 type.ref->c = len;
7137 vpush_ref(&type, data_section, data_section->data_offset, len);
7138 ptr = section_ptr_add(data_section, len);
7139 memcpy(ptr, funcname, len);
7140 next();
7142 break;
7143 case TOK_LSTR:
7144 #ifdef TCC_TARGET_PE
7145 t = VT_SHORT | VT_UNSIGNED;
7146 #else
7147 t = VT_INT;
7148 #endif
7149 goto str_init;
7150 case TOK_STR:
7151 /* string parsing */
7152 t = VT_BYTE;
7153 str_init:
7154 if (tcc_state->warn_write_strings)
7155 t |= VT_CONSTANT;
7156 type.t = t;
7157 mk_pointer(&type);
7158 type.t |= VT_ARRAY;
7159 memset(&ad, 0, sizeof(AttributeDef));
7160 decl_initializer_alloc(&type, &ad, VT_CONST, 2, 0, 0);
7161 break;
7162 case '(':
7163 next();
7164 /* cast ? */
7165 if (parse_btype(&type, &ad)) {
7166 type_decl(&type, &ad, &n, TYPE_ABSTRACT);
7167 skip(')');
7168 /* check ISOC99 compound literal */
7169 if (tok == '{') {
7170 /* data is allocated locally by default */
7171 if (global_expr)
7172 r = VT_CONST;
7173 else
7174 r = VT_LOCAL;
7175 /* all except arrays are lvalues */
7176 if (!(type.t & VT_ARRAY))
7177 r |= lvalue_type(type.t);
7178 memset(&ad, 0, sizeof(AttributeDef));
7179 decl_initializer_alloc(&type, &ad, r, 1, 0, 0);
7180 } else {
7181 unary();
7182 gen_cast(&type);
7184 } else if (tok == '{') {
7185 /* save all registers */
7186 save_regs(0);
7187 /* statement expression : we do not accept break/continue
7188 inside as GCC does */
7189 block(NULL, NULL, NULL, NULL, 0, 1);
7190 skip(')');
7191 } else {
7192 gexpr();
7193 skip(')');
7195 break;
7196 case '*':
7197 next();
7198 unary();
7199 indir();
7200 break;
7201 case '&':
7202 next();
7203 unary();
7204 /* functions names must be treated as function pointers,
7205 except for unary '&' and sizeof. Since we consider that
7206 functions are not lvalues, we only have to handle it
7207 there and in function calls. */
7208 /* arrays can also be used although they are not lvalues */
7209 if ((vtop->type.t & VT_BTYPE) != VT_FUNC &&
7210 !(vtop->type.t & VT_ARRAY))
7211 test_lvalue();
7212 mk_pointer(&vtop->type);
7213 gaddrof();
7214 break;
7215 case '!':
7216 next();
7217 unary();
7218 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST)
7219 vtop->c.i = !vtop->c.i;
7220 else if ((vtop->r & VT_VALMASK) == VT_CMP)
7221 vtop->c.i = vtop->c.i ^ 1;
7222 else
7223 vseti(VT_JMP, gtst(1, 0));
7224 break;
7225 case '~':
7226 next();
7227 unary();
7228 vpushi(-1);
7229 gen_op('^');
7230 break;
7231 case '+':
7232 next();
7233 /* in order to force cast, we add zero */
7234 unary();
7235 if ((vtop->type.t & VT_BTYPE) == VT_PTR)
7236 error("pointer not accepted for unary plus");
7237 vpushi(0);
7238 gen_op('+');
7239 break;
7240 case TOK_SIZEOF:
7241 case TOK_ALIGNOF1:
7242 case TOK_ALIGNOF2:
7243 t = tok;
7244 next();
7245 if (tok == '(') {
7246 parse_expr_type(&type);
7247 } else {
7248 unary_type(&type);
7250 size = type_size(&type, &align);
7251 if (t == TOK_SIZEOF) {
7252 if (size < 0)
7253 error("sizeof applied to an incomplete type");
7254 vpushi(size);
7255 } else {
7256 vpushi(align);
7258 break;
7260 case TOK_builtin_types_compatible_p:
7262 CType type1, type2;
7263 next();
7264 skip('(');
7265 parse_type(&type1);
7266 skip(',');
7267 parse_type(&type2);
7268 skip(')');
7269 type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
7270 type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
7271 vpushi(is_compatible_types(&type1, &type2));
7273 break;
7274 case TOK_builtin_constant_p:
7276 int saved_nocode_wanted, res;
7277 next();
7278 skip('(');
7279 saved_nocode_wanted = nocode_wanted;
7280 nocode_wanted = 1;
7281 gexpr();
7282 res = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
7283 vpop();
7284 nocode_wanted = saved_nocode_wanted;
7285 skip(')');
7286 vpushi(res);
7288 break;
7289 case TOK_INC:
7290 case TOK_DEC:
7291 t = tok;
7292 next();
7293 unary();
7294 inc(0, t);
7295 break;
7296 case '-':
7297 next();
7298 vpushi(0);
7299 unary();
7300 gen_op('-');
7301 break;
7302 case TOK_LAND:
7303 if (!gnu_ext)
7304 goto tok_identifier;
7305 next();
7306 /* allow to take the address of a label */
7307 if (tok < TOK_UIDENT)
7308 expect("label identifier");
7309 s = label_find(tok);
7310 if (!s) {
7311 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
7312 } else {
7313 if (s->r == LABEL_DECLARED)
7314 s->r = LABEL_FORWARD;
7316 if (!s->type.t) {
7317 s->type.t = VT_VOID;
7318 mk_pointer(&s->type);
7319 s->type.t |= VT_STATIC;
7321 vset(&s->type, VT_CONST | VT_SYM, 0);
7322 vtop->sym = s;
7323 next();
7324 break;
7325 default:
7326 tok_identifier:
7327 t = tok;
7328 next();
7329 if (t < TOK_UIDENT)
7330 expect("identifier");
7331 s = sym_find(t);
7332 if (!s) {
7333 if (tok != '(')
7334 error("'%s' undeclared", get_tok_str(t, NULL));
7335 /* for simple function calls, we tolerate undeclared
7336 external reference to int() function */
7337 if (tcc_state->warn_implicit_function_declaration)
7338 warning("implicit declaration of function '%s'",
7339 get_tok_str(t, NULL));
7340 s = external_global_sym(t, &func_old_type, 0);
7342 if ((s->type.t & (VT_STATIC | VT_INLINE | VT_BTYPE)) ==
7343 (VT_STATIC | VT_INLINE | VT_FUNC)) {
7344 /* if referencing an inline function, then we generate a
7345 symbol to it if not already done. It will have the
7346 effect to generate code for it at the end of the
7347 compilation unit. Inline function as always
7348 generated in the text section. */
7349 if (!s->c)
7350 put_extern_sym(s, text_section, 0, 0);
7351 r = VT_SYM | VT_CONST;
7352 } else {
7353 r = s->r;
7355 vset(&s->type, r, s->c);
7356 /* if forward reference, we must point to s */
7357 if (vtop->r & VT_SYM) {
7358 vtop->sym = s;
7359 vtop->c.ul = 0;
7361 break;
7364 /* post operations */
7365 while (1) {
7366 if (tok == TOK_INC || tok == TOK_DEC) {
7367 inc(1, tok);
7368 next();
7369 } else if (tok == '.' || tok == TOK_ARROW) {
7370 /* field */
7371 if (tok == TOK_ARROW)
7372 indir();
7373 test_lvalue();
7374 gaddrof();
7375 next();
7376 /* expect pointer on structure */
7377 if ((vtop->type.t & VT_BTYPE) != VT_STRUCT)
7378 expect("struct or union");
7379 s = vtop->type.ref;
7380 /* find field */
7381 tok |= SYM_FIELD;
7382 while ((s = s->next) != NULL) {
7383 if (s->v == tok)
7384 break;
7386 if (!s)
7387 error("field not found");
7388 /* add field offset to pointer */
7389 vtop->type = char_pointer_type; /* change type to 'char *' */
7390 vpushi(s->c);
7391 gen_op('+');
7392 /* change type to field type, and set to lvalue */
7393 vtop->type = s->type;
7394 /* an array is never an lvalue */
7395 if (!(vtop->type.t & VT_ARRAY)) {
7396 vtop->r |= lvalue_type(vtop->type.t);
7397 /* if bound checking, the referenced pointer must be checked */
7398 if (do_bounds_check)
7399 vtop->r |= VT_MUSTBOUND;
7401 next();
7402 } else if (tok == '[') {
7403 next();
7404 gexpr();
7405 gen_op('+');
7406 indir();
7407 skip(']');
7408 } else if (tok == '(') {
7409 SValue ret;
7410 Sym *sa;
7411 int nb_args;
7413 /* function call */
7414 if ((vtop->type.t & VT_BTYPE) != VT_FUNC) {
7415 /* pointer test (no array accepted) */
7416 if ((vtop->type.t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
7417 vtop->type = *pointed_type(&vtop->type);
7418 if ((vtop->type.t & VT_BTYPE) != VT_FUNC)
7419 goto error_func;
7420 } else {
7421 error_func:
7422 expect("function pointer");
7424 } else {
7425 vtop->r &= ~VT_LVAL; /* no lvalue */
7427 /* get return type */
7428 s = vtop->type.ref;
7429 next();
7430 sa = s->next; /* first parameter */
7431 nb_args = 0;
7432 /* compute first implicit argument if a structure is returned */
7433 if ((s->type.t & VT_BTYPE) == VT_STRUCT) {
7434 /* get some space for the returned structure */
7435 size = type_size(&s->type, &align);
7436 loc = (loc - size) & -align;
7437 ret.type = s->type;
7438 ret.r = VT_LOCAL | VT_LVAL;
7439 /* pass it as 'int' to avoid structure arg passing
7440 problems */
7441 vseti(VT_LOCAL, loc);
7442 ret.c = vtop->c;
7443 nb_args++;
7444 } else {
7445 ret.type = s->type;
7446 ret.r2 = VT_CONST;
7447 /* return in register */
7448 if (is_float(ret.type.t)) {
7449 ret.r = REG_FRET;
7450 } else {
7451 if ((ret.type.t & VT_BTYPE) == VT_LLONG)
7452 ret.r2 = REG_LRET;
7453 ret.r = REG_IRET;
7455 ret.c.i = 0;
7457 if (tok != ')') {
7458 for(;;) {
7459 expr_eq();
7460 gfunc_param_typed(s, sa);
7461 nb_args++;
7462 if (sa)
7463 sa = sa->next;
7464 if (tok == ')')
7465 break;
7466 skip(',');
7469 if (sa)
7470 error("too few arguments to function");
7471 skip(')');
7472 if (!nocode_wanted) {
7473 gfunc_call(nb_args);
7474 } else {
7475 vtop -= (nb_args + 1);
7477 /* return value */
7478 vsetc(&ret.type, ret.r, &ret.c);
7479 vtop->r2 = ret.r2;
7480 } else {
7481 break;
7486 static void uneq(void)
7488 int t;
7490 unary();
7491 if (tok == '=' ||
7492 (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
7493 tok == TOK_A_XOR || tok == TOK_A_OR ||
7494 tok == TOK_A_SHL || tok == TOK_A_SAR) {
7495 test_lvalue();
7496 t = tok;
7497 next();
7498 if (t == '=') {
7499 expr_eq();
7500 } else {
7501 vdup();
7502 expr_eq();
7503 gen_op(t & 0x7f);
7505 vstore();
7509 static void expr_prod(void)
7511 int t;
7513 uneq();
7514 while (tok == '*' || tok == '/' || tok == '%') {
7515 t = tok;
7516 next();
7517 uneq();
7518 gen_op(t);
7522 static void expr_sum(void)
7524 int t;
7526 expr_prod();
7527 while (tok == '+' || tok == '-') {
7528 t = tok;
7529 next();
7530 expr_prod();
7531 gen_op(t);
7535 static void expr_shift(void)
7537 int t;
7539 expr_sum();
7540 while (tok == TOK_SHL || tok == TOK_SAR) {
7541 t = tok;
7542 next();
7543 expr_sum();
7544 gen_op(t);
7548 static void expr_cmp(void)
7550 int t;
7552 expr_shift();
7553 while ((tok >= TOK_ULE && tok <= TOK_GT) ||
7554 tok == TOK_ULT || tok == TOK_UGE) {
7555 t = tok;
7556 next();
7557 expr_shift();
7558 gen_op(t);
7562 static void expr_cmpeq(void)
7564 int t;
7566 expr_cmp();
7567 while (tok == TOK_EQ || tok == TOK_NE) {
7568 t = tok;
7569 next();
7570 expr_cmp();
7571 gen_op(t);
7575 static void expr_and(void)
7577 expr_cmpeq();
7578 while (tok == '&') {
7579 next();
7580 expr_cmpeq();
7581 gen_op('&');
7585 static void expr_xor(void)
7587 expr_and();
7588 while (tok == '^') {
7589 next();
7590 expr_and();
7591 gen_op('^');
7595 static void expr_or(void)
7597 expr_xor();
7598 while (tok == '|') {
7599 next();
7600 expr_xor();
7601 gen_op('|');
7605 /* XXX: fix this mess */
7606 static void expr_land_const(void)
7608 expr_or();
7609 while (tok == TOK_LAND) {
7610 next();
7611 expr_or();
7612 gen_op(TOK_LAND);
7616 /* XXX: fix this mess */
7617 static void expr_lor_const(void)
7619 expr_land_const();
7620 while (tok == TOK_LOR) {
7621 next();
7622 expr_land_const();
7623 gen_op(TOK_LOR);
7627 /* only used if non constant */
7628 static void expr_land(void)
7630 int t;
7632 expr_or();
7633 if (tok == TOK_LAND) {
7634 t = 0;
7635 for(;;) {
7636 t = gtst(1, t);
7637 if (tok != TOK_LAND) {
7638 vseti(VT_JMPI, t);
7639 break;
7641 next();
7642 expr_or();
7647 static void expr_lor(void)
7649 int t;
7651 expr_land();
7652 if (tok == TOK_LOR) {
7653 t = 0;
7654 for(;;) {
7655 t = gtst(0, t);
7656 if (tok != TOK_LOR) {
7657 vseti(VT_JMP, t);
7658 break;
7660 next();
7661 expr_land();
7666 /* XXX: better constant handling */
7667 static void expr_eq(void)
7669 int tt, u, r1, r2, rc, t1, t2, bt1, bt2;
7670 SValue sv;
7671 CType type, type1, type2;
7673 if (const_wanted) {
7674 int c1, c;
7675 expr_lor_const();
7676 if (tok == '?') {
7677 c = vtop->c.i;
7678 vpop();
7679 next();
7680 if (tok == ':' && gnu_ext) {
7681 c1 = c;
7682 } else {
7683 gexpr();
7684 c1 = vtop->c.i;
7685 vpop();
7687 skip(':');
7688 expr_eq();
7689 if (c)
7690 vtop->c.i = c1;
7692 } else {
7693 expr_lor();
7694 if (tok == '?') {
7695 next();
7696 if (vtop != vstack) {
7697 /* needed to avoid having different registers saved in
7698 each branch */
7699 if (is_float(vtop->type.t))
7700 rc = RC_FLOAT;
7701 else
7702 rc = RC_INT;
7703 gv(rc);
7704 save_regs(1);
7706 if (tok == ':' && gnu_ext) {
7707 gv_dup();
7708 tt = gtst(1, 0);
7709 } else {
7710 tt = gtst(1, 0);
7711 gexpr();
7713 type1 = vtop->type;
7714 sv = *vtop; /* save value to handle it later */
7715 vtop--; /* no vpop so that FP stack is not flushed */
7716 skip(':');
7717 u = gjmp(0);
7718 gsym(tt);
7719 expr_eq();
7720 type2 = vtop->type;
7722 t1 = type1.t;
7723 bt1 = t1 & VT_BTYPE;
7724 t2 = type2.t;
7725 bt2 = t2 & VT_BTYPE;
7726 /* cast operands to correct type according to ISOC rules */
7727 if (is_float(bt1) || is_float(bt2)) {
7728 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
7729 type.t = VT_LDOUBLE;
7730 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
7731 type.t = VT_DOUBLE;
7732 } else {
7733 type.t = VT_FLOAT;
7735 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
7736 /* cast to biggest op */
7737 type.t = VT_LLONG;
7738 /* convert to unsigned if it does not fit in a long long */
7739 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
7740 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
7741 type.t |= VT_UNSIGNED;
7742 } else if (bt1 == VT_PTR || bt2 == VT_PTR) {
7743 /* XXX: test pointer compatibility */
7744 type = type1;
7745 } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
7746 /* XXX: test structure compatibility */
7747 type = type1;
7748 } else if (bt1 == VT_VOID || bt2 == VT_VOID) {
7749 /* NOTE: as an extension, we accept void on only one side */
7750 type.t = VT_VOID;
7751 } else {
7752 /* integer operations */
7753 type.t = VT_INT;
7754 /* convert to unsigned if it does not fit in an integer */
7755 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
7756 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
7757 type.t |= VT_UNSIGNED;
7760 /* now we convert second operand */
7761 gen_cast(&type);
7762 rc = RC_INT;
7763 if (is_float(type.t)) {
7764 rc = RC_FLOAT;
7765 } else if ((type.t & VT_BTYPE) == VT_LLONG) {
7766 /* for long longs, we use fixed registers to avoid having
7767 to handle a complicated move */
7768 rc = RC_IRET;
7771 r2 = gv(rc);
7772 /* this is horrible, but we must also convert first
7773 operand */
7774 tt = gjmp(0);
7775 gsym(u);
7776 /* put again first value and cast it */
7777 *vtop = sv;
7778 gen_cast(&type);
7779 r1 = gv(rc);
7780 move_reg(r2, r1);
7781 vtop->r = r2;
7782 gsym(tt);
7787 static void gexpr(void)
7789 while (1) {
7790 expr_eq();
7791 if (tok != ',')
7792 break;
7793 vpop();
7794 next();
7798 /* parse an expression and return its type without any side effect. */
7799 static void expr_type(CType *type)
7801 int saved_nocode_wanted;
7803 saved_nocode_wanted = nocode_wanted;
7804 nocode_wanted = 1;
7805 gexpr();
7806 *type = vtop->type;
7807 vpop();
7808 nocode_wanted = saved_nocode_wanted;
7811 /* parse a unary expression and return its type without any side
7812 effect. */
7813 static void unary_type(CType *type)
7815 int a;
7817 a = nocode_wanted;
7818 nocode_wanted = 1;
7819 unary();
7820 *type = vtop->type;
7821 vpop();
7822 nocode_wanted = a;
7825 /* parse a constant expression and return value in vtop. */
7826 static void expr_const1(void)
7828 int a;
7829 a = const_wanted;
7830 const_wanted = 1;
7831 expr_eq();
7832 const_wanted = a;
7835 /* parse an integer constant and return its value. */
7836 static int expr_const(void)
7838 int c;
7839 expr_const1();
7840 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
7841 expect("constant expression");
7842 c = vtop->c.i;
7843 vpop();
7844 return c;
7847 /* return the label token if current token is a label, otherwise
7848 return zero */
7849 static int is_label(void)
7851 int last_tok;
7853 /* fast test first */
7854 if (tok < TOK_UIDENT)
7855 return 0;
7856 /* no need to save tokc because tok is an identifier */
7857 last_tok = tok;
7858 next();
7859 if (tok == ':') {
7860 next();
7861 return last_tok;
7862 } else {
7863 unget_tok(last_tok);
7864 return 0;
7868 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
7869 int case_reg, int is_expr)
7871 int a, b, c, d;
7872 Sym *s;
7874 /* generate line number info */
7875 if (do_debug &&
7876 (last_line_num != file->line_num || last_ind != ind)) {
7877 put_stabn(N_SLINE, 0, file->line_num, ind - func_ind);
7878 last_ind = ind;
7879 last_line_num = file->line_num;
7882 if (is_expr) {
7883 /* default return value is (void) */
7884 vpushi(0);
7885 vtop->type.t = VT_VOID;
7888 if (tok == TOK_IF) {
7889 /* if test */
7890 next();
7891 skip('(');
7892 gexpr();
7893 skip(')');
7894 a = gtst(1, 0);
7895 block(bsym, csym, case_sym, def_sym, case_reg, 0);
7896 c = tok;
7897 if (c == TOK_ELSE) {
7898 next();
7899 d = gjmp(0);
7900 gsym(a);
7901 block(bsym, csym, case_sym, def_sym, case_reg, 0);
7902 gsym(d); /* patch else jmp */
7903 } else
7904 gsym(a);
7905 } else if (tok == TOK_WHILE) {
7906 next();
7907 d = ind;
7908 skip('(');
7909 gexpr();
7910 skip(')');
7911 a = gtst(1, 0);
7912 b = 0;
7913 block(&a, &b, case_sym, def_sym, case_reg, 0);
7914 gjmp_addr(d);
7915 gsym(a);
7916 gsym_addr(b, d);
7917 } else if (tok == '{') {
7918 Sym *llabel;
7920 next();
7921 /* record local declaration stack position */
7922 s = local_stack;
7923 llabel = local_label_stack;
7924 /* handle local labels declarations */
7925 if (tok == TOK_LABEL) {
7926 next();
7927 for(;;) {
7928 if (tok < TOK_UIDENT)
7929 expect("label identifier");
7930 label_push(&local_label_stack, tok, LABEL_DECLARED);
7931 next();
7932 if (tok == ',') {
7933 next();
7934 } else {
7935 skip(';');
7936 break;
7940 while (tok != '}') {
7941 decl(VT_LOCAL);
7942 if (tok != '}') {
7943 if (is_expr)
7944 vpop();
7945 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
7948 /* pop locally defined labels */
7949 label_pop(&local_label_stack, llabel);
7950 /* pop locally defined symbols */
7951 sym_pop(&local_stack, s);
7952 next();
7953 } else if (tok == TOK_RETURN) {
7954 next();
7955 if (tok != ';') {
7956 gexpr();
7957 gen_assign_cast(&func_vt);
7958 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
7959 CType type;
7960 /* if returning structure, must copy it to implicit
7961 first pointer arg location */
7962 type = func_vt;
7963 mk_pointer(&type);
7964 vset(&type, VT_LOCAL | VT_LVAL, func_vc);
7965 indir();
7966 vswap();
7967 /* copy structure value to pointer */
7968 vstore();
7969 } else if (is_float(func_vt.t)) {
7970 gv(RC_FRET);
7971 } else {
7972 gv(RC_IRET);
7974 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
7976 skip(';');
7977 rsym = gjmp(rsym); /* jmp */
7978 } else if (tok == TOK_BREAK) {
7979 /* compute jump */
7980 if (!bsym)
7981 error("cannot break");
7982 *bsym = gjmp(*bsym);
7983 next();
7984 skip(';');
7985 } else if (tok == TOK_CONTINUE) {
7986 /* compute jump */
7987 if (!csym)
7988 error("cannot continue");
7989 *csym = gjmp(*csym);
7990 next();
7991 skip(';');
7992 } else if (tok == TOK_FOR) {
7993 int e;
7994 next();
7995 skip('(');
7996 if (tok != ';') {
7997 gexpr();
7998 vpop();
8000 skip(';');
8001 d = ind;
8002 c = ind;
8003 a = 0;
8004 b = 0;
8005 if (tok != ';') {
8006 gexpr();
8007 a = gtst(1, 0);
8009 skip(';');
8010 if (tok != ')') {
8011 e = gjmp(0);
8012 c = ind;
8013 gexpr();
8014 vpop();
8015 gjmp_addr(d);
8016 gsym(e);
8018 skip(')');
8019 block(&a, &b, case_sym, def_sym, case_reg, 0);
8020 gjmp_addr(c);
8021 gsym(a);
8022 gsym_addr(b, c);
8023 } else
8024 if (tok == TOK_DO) {
8025 next();
8026 a = 0;
8027 b = 0;
8028 d = ind;
8029 block(&a, &b, case_sym, def_sym, case_reg, 0);
8030 skip(TOK_WHILE);
8031 skip('(');
8032 gsym(b);
8033 gexpr();
8034 c = gtst(0, 0);
8035 gsym_addr(c, d);
8036 skip(')');
8037 gsym(a);
8038 skip(';');
8039 } else
8040 if (tok == TOK_SWITCH) {
8041 next();
8042 skip('(');
8043 gexpr();
8044 /* XXX: other types than integer */
8045 case_reg = gv(RC_INT);
8046 vpop();
8047 skip(')');
8048 a = 0;
8049 b = gjmp(0); /* jump to first case */
8050 c = 0;
8051 block(&a, csym, &b, &c, case_reg, 0);
8052 /* if no default, jmp after switch */
8053 if (c == 0)
8054 c = ind;
8055 /* default label */
8056 gsym_addr(b, c);
8057 /* break label */
8058 gsym(a);
8059 } else
8060 if (tok == TOK_CASE) {
8061 int v1, v2;
8062 if (!case_sym)
8063 expect("switch");
8064 next();
8065 v1 = expr_const();
8066 v2 = v1;
8067 if (gnu_ext && tok == TOK_DOTS) {
8068 next();
8069 v2 = expr_const();
8070 if (v2 < v1)
8071 warning("empty case range");
8073 /* since a case is like a label, we must skip it with a jmp */
8074 b = gjmp(0);
8075 gsym(*case_sym);
8076 vseti(case_reg, 0);
8077 vpushi(v1);
8078 if (v1 == v2) {
8079 gen_op(TOK_EQ);
8080 *case_sym = gtst(1, 0);
8081 } else {
8082 gen_op(TOK_GE);
8083 *case_sym = gtst(1, 0);
8084 vseti(case_reg, 0);
8085 vpushi(v2);
8086 gen_op(TOK_LE);
8087 *case_sym = gtst(1, *case_sym);
8089 gsym(b);
8090 skip(':');
8091 is_expr = 0;
8092 goto block_after_label;
8093 } else
8094 if (tok == TOK_DEFAULT) {
8095 next();
8096 skip(':');
8097 if (!def_sym)
8098 expect("switch");
8099 if (*def_sym)
8100 error("too many 'default'");
8101 *def_sym = ind;
8102 is_expr = 0;
8103 goto block_after_label;
8104 } else
8105 if (tok == TOK_GOTO) {
8106 next();
8107 if (tok == '*' && gnu_ext) {
8108 /* computed goto */
8109 next();
8110 gexpr();
8111 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
8112 expect("pointer");
8113 ggoto();
8114 } else if (tok >= TOK_UIDENT) {
8115 s = label_find(tok);
8116 /* put forward definition if needed */
8117 if (!s) {
8118 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
8119 } else {
8120 if (s->r == LABEL_DECLARED)
8121 s->r = LABEL_FORWARD;
8123 /* label already defined */
8124 if (s->r & LABEL_FORWARD)
8125 s->next = (void *)gjmp((long)s->next);
8126 else
8127 gjmp_addr((long)s->next);
8128 next();
8129 } else {
8130 expect("label identifier");
8132 skip(';');
8133 } else if (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3) {
8134 asm_instr();
8135 } else {
8136 b = is_label();
8137 if (b) {
8138 /* label case */
8139 s = label_find(b);
8140 if (s) {
8141 if (s->r == LABEL_DEFINED)
8142 error("duplicate label '%s'", get_tok_str(s->v, NULL));
8143 gsym((long)s->next);
8144 s->r = LABEL_DEFINED;
8145 } else {
8146 s = label_push(&global_label_stack, b, LABEL_DEFINED);
8148 s->next = (void *)ind;
8149 /* we accept this, but it is a mistake */
8150 block_after_label:
8151 if (tok == '}') {
8152 warning("deprecated use of label at end of compound statement");
8153 } else {
8154 if (is_expr)
8155 vpop();
8156 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
8158 } else {
8159 /* expression case */
8160 if (tok != ';') {
8161 if (is_expr) {
8162 vpop();
8163 gexpr();
8164 } else {
8165 gexpr();
8166 vpop();
8169 skip(';');
8174 /* t is the array or struct type. c is the array or struct
8175 address. cur_index/cur_field is the pointer to the current
8176 value. 'size_only' is true if only size info is needed (only used
8177 in arrays) */
8178 static void decl_designator(CType *type, Section *sec, unsigned long c,
8179 int *cur_index, Sym **cur_field,
8180 int size_only)
8182 Sym *s, *f;
8183 int notfirst, index, index_last, align, l, nb_elems, elem_size;
8184 CType type1;
8186 notfirst = 0;
8187 elem_size = 0;
8188 nb_elems = 1;
8189 if (gnu_ext && (l = is_label()) != 0)
8190 goto struct_field;
8191 while (tok == '[' || tok == '.') {
8192 if (tok == '[') {
8193 if (!(type->t & VT_ARRAY))
8194 expect("array type");
8195 s = type->ref;
8196 next();
8197 index = expr_const();
8198 if (index < 0 || (s->c >= 0 && index >= s->c))
8199 expect("invalid index");
8200 if (tok == TOK_DOTS && gnu_ext) {
8201 next();
8202 index_last = expr_const();
8203 if (index_last < 0 ||
8204 (s->c >= 0 && index_last >= s->c) ||
8205 index_last < index)
8206 expect("invalid index");
8207 } else {
8208 index_last = index;
8210 skip(']');
8211 if (!notfirst)
8212 *cur_index = index_last;
8213 type = pointed_type(type);
8214 elem_size = type_size(type, &align);
8215 c += index * elem_size;
8216 /* NOTE: we only support ranges for last designator */
8217 nb_elems = index_last - index + 1;
8218 if (nb_elems != 1) {
8219 notfirst = 1;
8220 break;
8222 } else {
8223 next();
8224 l = tok;
8225 next();
8226 struct_field:
8227 if ((type->t & VT_BTYPE) != VT_STRUCT)
8228 expect("struct/union type");
8229 s = type->ref;
8230 l |= SYM_FIELD;
8231 f = s->next;
8232 while (f) {
8233 if (f->v == l)
8234 break;
8235 f = f->next;
8237 if (!f)
8238 expect("field");
8239 if (!notfirst)
8240 *cur_field = f;
8241 /* XXX: fix this mess by using explicit storage field */
8242 type1 = f->type;
8243 type1.t |= (type->t & ~VT_TYPE);
8244 type = &type1;
8245 c += f->c;
8247 notfirst = 1;
8249 if (notfirst) {
8250 if (tok == '=') {
8251 next();
8252 } else {
8253 if (!gnu_ext)
8254 expect("=");
8256 } else {
8257 if (type->t & VT_ARRAY) {
8258 index = *cur_index;
8259 type = pointed_type(type);
8260 c += index * type_size(type, &align);
8261 } else {
8262 f = *cur_field;
8263 if (!f)
8264 error("too many field init");
8265 /* XXX: fix this mess by using explicit storage field */
8266 type1 = f->type;
8267 type1.t |= (type->t & ~VT_TYPE);
8268 type = &type1;
8269 c += f->c;
8272 decl_initializer(type, sec, c, 0, size_only);
8274 /* XXX: make it more general */
8275 if (!size_only && nb_elems > 1) {
8276 unsigned long c_end;
8277 uint8_t *src, *dst;
8278 int i;
8280 if (!sec)
8281 error("range init not supported yet for dynamic storage");
8282 c_end = c + nb_elems * elem_size;
8283 if (c_end > sec->data_allocated)
8284 section_realloc(sec, c_end);
8285 src = sec->data + c;
8286 dst = src;
8287 for(i = 1; i < nb_elems; i++) {
8288 dst += elem_size;
8289 memcpy(dst, src, elem_size);
8294 #define EXPR_VAL 0
8295 #define EXPR_CONST 1
8296 #define EXPR_ANY 2
8298 /* store a value or an expression directly in global data or in local array */
8299 static void init_putv(CType *type, Section *sec, unsigned long c,
8300 int v, int expr_type)
8302 int saved_global_expr, bt, bit_pos, bit_size;
8303 void *ptr;
8304 unsigned long long bit_mask;
8305 CType dtype;
8307 switch(expr_type) {
8308 case EXPR_VAL:
8309 vpushi(v);
8310 break;
8311 case EXPR_CONST:
8312 /* compound literals must be allocated globally in this case */
8313 saved_global_expr = global_expr;
8314 global_expr = 1;
8315 expr_const1();
8316 global_expr = saved_global_expr;
8317 /* NOTE: symbols are accepted */
8318 if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST)
8319 error("initializer element is not constant");
8320 break;
8321 case EXPR_ANY:
8322 expr_eq();
8323 break;
8326 dtype = *type;
8327 dtype.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
8329 if (sec) {
8330 /* XXX: not portable */
8331 /* XXX: generate error if incorrect relocation */
8332 gen_assign_cast(&dtype);
8333 bt = type->t & VT_BTYPE;
8334 ptr = sec->data + c;
8335 /* XXX: make code faster ? */
8336 if (!(type->t & VT_BITFIELD)) {
8337 bit_pos = 0;
8338 bit_size = 32;
8339 bit_mask = -1LL;
8340 } else {
8341 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
8342 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
8343 bit_mask = (1LL << bit_size) - 1;
8345 if ((vtop->r & VT_SYM) &&
8346 (bt == VT_BYTE ||
8347 bt == VT_SHORT ||
8348 bt == VT_DOUBLE ||
8349 bt == VT_LDOUBLE ||
8350 bt == VT_LLONG ||
8351 (bt == VT_INT && bit_size != 32)))
8352 error("initializer element is not computable at load time");
8353 switch(bt) {
8354 case VT_BYTE:
8355 *(char *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8356 break;
8357 case VT_SHORT:
8358 *(short *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8359 break;
8360 case VT_DOUBLE:
8361 *(double *)ptr = vtop->c.d;
8362 break;
8363 case VT_LDOUBLE:
8364 *(long double *)ptr = vtop->c.ld;
8365 break;
8366 case VT_LLONG:
8367 *(long long *)ptr |= (vtop->c.ll & bit_mask) << bit_pos;
8368 break;
8369 default:
8370 if (vtop->r & VT_SYM) {
8371 greloc(sec, vtop->sym, c, R_DATA_32);
8373 *(int *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8374 break;
8376 vtop--;
8377 } else {
8378 vset(&dtype, VT_LOCAL, c);
8379 vswap();
8380 vstore();
8381 vpop();
8385 /* put zeros for variable based init */
8386 static void init_putz(CType *t, Section *sec, unsigned long c, int size)
8388 if (sec) {
8389 /* nothing to do because globals are already set to zero */
8390 } else {
8391 vpush_global_sym(&func_old_type, TOK_memset);
8392 vseti(VT_LOCAL, c);
8393 vpushi(0);
8394 vpushi(size);
8395 gfunc_call(3);
8399 /* 't' contains the type and storage info. 'c' is the offset of the
8400 object in section 'sec'. If 'sec' is NULL, it means stack based
8401 allocation. 'first' is true if array '{' must be read (multi
8402 dimension implicit array init handling). 'size_only' is true if
8403 size only evaluation is wanted (only for arrays). */
8404 static void decl_initializer(CType *type, Section *sec, unsigned long c,
8405 int first, int size_only)
8407 int index, array_length, n, no_oblock, nb, parlevel, i;
8408 int size1, align1, expr_type;
8409 Sym *s, *f;
8410 CType *t1;
8412 if (type->t & VT_ARRAY) {
8413 s = type->ref;
8414 n = s->c;
8415 array_length = 0;
8416 t1 = pointed_type(type);
8417 size1 = type_size(t1, &align1);
8419 no_oblock = 1;
8420 if ((first && tok != TOK_LSTR && tok != TOK_STR) ||
8421 tok == '{') {
8422 skip('{');
8423 no_oblock = 0;
8426 /* only parse strings here if correct type (otherwise: handle
8427 them as ((w)char *) expressions */
8428 if ((tok == TOK_LSTR &&
8429 #ifdef TCC_TARGET_PE
8430 (t1->t & VT_BTYPE) == VT_SHORT && (t1->t & VT_UNSIGNED)) ||
8431 #else
8432 (t1->t & VT_BTYPE) == VT_INT) ||
8433 #endif
8434 (tok == TOK_STR &&
8435 (t1->t & VT_BTYPE) == VT_BYTE)) {
8436 while (tok == TOK_STR || tok == TOK_LSTR) {
8437 int cstr_len, ch;
8438 CString *cstr;
8440 cstr = tokc.cstr;
8441 /* compute maximum number of chars wanted */
8442 if (tok == TOK_STR)
8443 cstr_len = cstr->size;
8444 else
8445 cstr_len = cstr->size / sizeof(nwchar_t);
8446 cstr_len--;
8447 nb = cstr_len;
8448 if (n >= 0 && nb > (n - array_length))
8449 nb = n - array_length;
8450 if (!size_only) {
8451 if (cstr_len > nb)
8452 warning("initializer-string for array is too long");
8453 /* in order to go faster for common case (char
8454 string in global variable, we handle it
8455 specifically */
8456 if (sec && tok == TOK_STR && size1 == 1) {
8457 memcpy(sec->data + c + array_length, cstr->data, nb);
8458 } else {
8459 for(i=0;i<nb;i++) {
8460 if (tok == TOK_STR)
8461 ch = ((unsigned char *)cstr->data)[i];
8462 else
8463 ch = ((nwchar_t *)cstr->data)[i];
8464 init_putv(t1, sec, c + (array_length + i) * size1,
8465 ch, EXPR_VAL);
8469 array_length += nb;
8470 next();
8472 /* only add trailing zero if enough storage (no
8473 warning in this case since it is standard) */
8474 if (n < 0 || array_length < n) {
8475 if (!size_only) {
8476 init_putv(t1, sec, c + (array_length * size1), 0, EXPR_VAL);
8478 array_length++;
8480 } else {
8481 index = 0;
8482 while (tok != '}') {
8483 decl_designator(type, sec, c, &index, NULL, size_only);
8484 if (n >= 0 && index >= n)
8485 error("index too large");
8486 /* must put zero in holes (note that doing it that way
8487 ensures that it even works with designators) */
8488 if (!size_only && array_length < index) {
8489 init_putz(t1, sec, c + array_length * size1,
8490 (index - array_length) * size1);
8492 index++;
8493 if (index > array_length)
8494 array_length = index;
8495 /* special test for multi dimensional arrays (may not
8496 be strictly correct if designators are used at the
8497 same time) */
8498 if (index >= n && no_oblock)
8499 break;
8500 if (tok == '}')
8501 break;
8502 skip(',');
8505 if (!no_oblock)
8506 skip('}');
8507 /* put zeros at the end */
8508 if (!size_only && n >= 0 && array_length < n) {
8509 init_putz(t1, sec, c + array_length * size1,
8510 (n - array_length) * size1);
8512 /* patch type size if needed */
8513 if (n < 0)
8514 s->c = array_length;
8515 } else if ((type->t & VT_BTYPE) == VT_STRUCT &&
8516 (sec || !first || tok == '{')) {
8517 int par_count;
8519 /* NOTE: the previous test is a specific case for automatic
8520 struct/union init */
8521 /* XXX: union needs only one init */
8523 /* XXX: this test is incorrect for local initializers
8524 beginning with ( without {. It would be much more difficult
8525 to do it correctly (ideally, the expression parser should
8526 be used in all cases) */
8527 par_count = 0;
8528 if (tok == '(') {
8529 AttributeDef ad1;
8530 CType type1;
8531 next();
8532 while (tok == '(') {
8533 par_count++;
8534 next();
8536 if (!parse_btype(&type1, &ad1))
8537 expect("cast");
8538 type_decl(&type1, &ad1, &n, TYPE_ABSTRACT);
8539 #if 0
8540 if (!is_assignable_types(type, &type1))
8541 error("invalid type for cast");
8542 #endif
8543 skip(')');
8545 no_oblock = 1;
8546 if (first || tok == '{') {
8547 skip('{');
8548 no_oblock = 0;
8550 s = type->ref;
8551 f = s->next;
8552 array_length = 0;
8553 index = 0;
8554 n = s->c;
8555 while (tok != '}') {
8556 decl_designator(type, sec, c, NULL, &f, size_only);
8557 index = f->c;
8558 if (!size_only && array_length < index) {
8559 init_putz(type, sec, c + array_length,
8560 index - array_length);
8562 index = index + type_size(&f->type, &align1);
8563 if (index > array_length)
8564 array_length = index;
8565 f = f->next;
8566 if (no_oblock && f == NULL)
8567 break;
8568 if (tok == '}')
8569 break;
8570 skip(',');
8572 /* put zeros at the end */
8573 if (!size_only && array_length < n) {
8574 init_putz(type, sec, c + array_length,
8575 n - array_length);
8577 if (!no_oblock)
8578 skip('}');
8579 while (par_count) {
8580 skip(')');
8581 par_count--;
8583 } else if (tok == '{') {
8584 next();
8585 decl_initializer(type, sec, c, first, size_only);
8586 skip('}');
8587 } else if (size_only) {
8588 /* just skip expression */
8589 parlevel = 0;
8590 while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
8591 tok != -1) {
8592 if (tok == '(')
8593 parlevel++;
8594 else if (tok == ')')
8595 parlevel--;
8596 next();
8598 } else {
8599 /* currently, we always use constant expression for globals
8600 (may change for scripting case) */
8601 expr_type = EXPR_CONST;
8602 if (!sec)
8603 expr_type = EXPR_ANY;
8604 init_putv(type, sec, c, 0, expr_type);
8608 /* parse an initializer for type 't' if 'has_init' is non zero, and
8609 allocate space in local or global data space ('r' is either
8610 VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
8611 variable 'v' of scope 'scope' is declared before initializers are
8612 parsed. If 'v' is zero, then a reference to the new object is put
8613 in the value stack. If 'has_init' is 2, a special parsing is done
8614 to handle string constants. */
8615 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
8616 int has_init, int v, int scope)
8618 int size, align, addr, data_offset;
8619 int level;
8620 ParseState saved_parse_state;
8621 TokenString init_str;
8622 Section *sec;
8624 size = type_size(type, &align);
8625 /* If unknown size, we must evaluate it before
8626 evaluating initializers because
8627 initializers can generate global data too
8628 (e.g. string pointers or ISOC99 compound
8629 literals). It also simplifies local
8630 initializers handling */
8631 tok_str_new(&init_str);
8632 if (size < 0) {
8633 if (!has_init)
8634 error("unknown type size");
8635 /* get all init string */
8636 if (has_init == 2) {
8637 /* only get strings */
8638 while (tok == TOK_STR || tok == TOK_LSTR) {
8639 tok_str_add_tok(&init_str);
8640 next();
8642 } else {
8643 level = 0;
8644 while (level > 0 || (tok != ',' && tok != ';')) {
8645 if (tok < 0)
8646 error("unexpected end of file in initializer");
8647 tok_str_add_tok(&init_str);
8648 if (tok == '{')
8649 level++;
8650 else if (tok == '}') {
8651 if (level == 0)
8652 break;
8653 level--;
8655 next();
8658 tok_str_add(&init_str, -1);
8659 tok_str_add(&init_str, 0);
8661 /* compute size */
8662 save_parse_state(&saved_parse_state);
8664 macro_ptr = init_str.str;
8665 next();
8666 decl_initializer(type, NULL, 0, 1, 1);
8667 /* prepare second initializer parsing */
8668 macro_ptr = init_str.str;
8669 next();
8671 /* if still unknown size, error */
8672 size = type_size(type, &align);
8673 if (size < 0)
8674 error("unknown type size");
8676 /* take into account specified alignment if bigger */
8677 if (ad->aligned) {
8678 if (ad->aligned > align)
8679 align = ad->aligned;
8680 } else if (ad->packed) {
8681 align = 1;
8683 if ((r & VT_VALMASK) == VT_LOCAL) {
8684 sec = NULL;
8685 if (do_bounds_check && (type->t & VT_ARRAY))
8686 loc--;
8687 loc = (loc - size) & -align;
8688 addr = loc;
8689 /* handles bounds */
8690 /* XXX: currently, since we do only one pass, we cannot track
8691 '&' operators, so we add only arrays */
8692 if (do_bounds_check && (type->t & VT_ARRAY)) {
8693 unsigned long *bounds_ptr;
8694 /* add padding between regions */
8695 loc--;
8696 /* then add local bound info */
8697 bounds_ptr = section_ptr_add(lbounds_section, 2 * sizeof(unsigned long));
8698 bounds_ptr[0] = addr;
8699 bounds_ptr[1] = size;
8701 if (v) {
8702 /* local variable */
8703 sym_push(v, type, r, addr);
8704 } else {
8705 /* push local reference */
8706 vset(type, r, addr);
8708 } else {
8709 Sym *sym;
8711 sym = NULL;
8712 if (v && scope == VT_CONST) {
8713 /* see if the symbol was already defined */
8714 sym = sym_find(v);
8715 if (sym) {
8716 if (!is_compatible_types(&sym->type, type))
8717 error("incompatible types for redefinition of '%s'",
8718 get_tok_str(v, NULL));
8719 if (sym->type.t & VT_EXTERN) {
8720 /* if the variable is extern, it was not allocated */
8721 sym->type.t &= ~VT_EXTERN;
8722 /* set array size if it was ommited in extern
8723 declaration */
8724 if ((sym->type.t & VT_ARRAY) &&
8725 sym->type.ref->c < 0 &&
8726 type->ref->c >= 0)
8727 sym->type.ref->c = type->ref->c;
8728 } else {
8729 /* we accept several definitions of the same
8730 global variable. this is tricky, because we
8731 must play with the SHN_COMMON type of the symbol */
8732 /* XXX: should check if the variable was already
8733 initialized. It is incorrect to initialized it
8734 twice */
8735 /* no init data, we won't add more to the symbol */
8736 if (!has_init)
8737 goto no_alloc;
8742 /* allocate symbol in corresponding section */
8743 sec = ad->section;
8744 if (!sec) {
8745 if (has_init)
8746 sec = data_section;
8747 else if (tcc_state->nocommon)
8748 sec = bss_section;
8750 if (sec) {
8751 data_offset = sec->data_offset;
8752 data_offset = (data_offset + align - 1) & -align;
8753 addr = data_offset;
8754 /* very important to increment global pointer at this time
8755 because initializers themselves can create new initializers */
8756 data_offset += size;
8757 /* add padding if bound check */
8758 if (do_bounds_check)
8759 data_offset++;
8760 sec->data_offset = data_offset;
8761 /* allocate section space to put the data */
8762 if (sec->sh_type != SHT_NOBITS &&
8763 data_offset > sec->data_allocated)
8764 section_realloc(sec, data_offset);
8765 /* align section if needed */
8766 if (align > sec->sh_addralign)
8767 sec->sh_addralign = align;
8768 } else {
8769 addr = 0; /* avoid warning */
8772 if (v) {
8773 if (scope == VT_CONST) {
8774 if (!sym)
8775 goto do_def;
8776 } else {
8777 do_def:
8778 sym = sym_push(v, type, r | VT_SYM, 0);
8780 /* update symbol definition */
8781 if (sec) {
8782 put_extern_sym(sym, sec, addr, size);
8783 } else {
8784 Elf32_Sym *esym;
8785 /* put a common area */
8786 put_extern_sym(sym, NULL, align, size);
8787 /* XXX: find a nicer way */
8788 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
8789 esym->st_shndx = SHN_COMMON;
8791 } else {
8792 CValue cval;
8794 /* push global reference */
8795 sym = get_sym_ref(type, sec, addr, size);
8796 cval.ul = 0;
8797 vsetc(type, VT_CONST | VT_SYM, &cval);
8798 vtop->sym = sym;
8801 /* handles bounds now because the symbol must be defined
8802 before for the relocation */
8803 if (do_bounds_check) {
8804 unsigned long *bounds_ptr;
8806 greloc(bounds_section, sym, bounds_section->data_offset, R_DATA_32);
8807 /* then add global bound info */
8808 bounds_ptr = section_ptr_add(bounds_section, 2 * sizeof(long));
8809 bounds_ptr[0] = 0; /* relocated */
8810 bounds_ptr[1] = size;
8813 if (has_init) {
8814 decl_initializer(type, sec, addr, 1, 0);
8815 /* restore parse state if needed */
8816 if (init_str.str) {
8817 tok_str_free(init_str.str);
8818 restore_parse_state(&saved_parse_state);
8821 no_alloc: ;
8824 void put_func_debug(Sym *sym)
8826 char buf[512];
8828 /* stabs info */
8829 /* XXX: we put here a dummy type */
8830 snprintf(buf, sizeof(buf), "%s:%c1",
8831 funcname, sym->type.t & VT_STATIC ? 'f' : 'F');
8832 put_stabs_r(buf, N_FUN, 0, file->line_num, 0,
8833 cur_text_section, sym->c);
8834 last_ind = 0;
8835 last_line_num = 0;
8838 /* parse an old style function declaration list */
8839 /* XXX: check multiple parameter */
8840 static void func_decl_list(Sym *func_sym)
8842 AttributeDef ad;
8843 int v;
8844 Sym *s;
8845 CType btype, type;
8847 /* parse each declaration */
8848 while (tok != '{' && tok != ';' && tok != ',' && tok != TOK_EOF) {
8849 if (!parse_btype(&btype, &ad))
8850 expect("declaration list");
8851 if (((btype.t & VT_BTYPE) == VT_ENUM ||
8852 (btype.t & VT_BTYPE) == VT_STRUCT) &&
8853 tok == ';') {
8854 /* we accept no variable after */
8855 } else {
8856 for(;;) {
8857 type = btype;
8858 type_decl(&type, &ad, &v, TYPE_DIRECT);
8859 /* find parameter in function parameter list */
8860 s = func_sym->next;
8861 while (s != NULL) {
8862 if ((s->v & ~SYM_FIELD) == v)
8863 goto found;
8864 s = s->next;
8866 error("declaration for parameter '%s' but no such parameter",
8867 get_tok_str(v, NULL));
8868 found:
8869 /* check that no storage specifier except 'register' was given */
8870 if (type.t & VT_STORAGE)
8871 error("storage class specified for '%s'", get_tok_str(v, NULL));
8872 convert_parameter_type(&type);
8873 /* we can add the type (NOTE: it could be local to the function) */
8874 s->type = type;
8875 /* accept other parameters */
8876 if (tok == ',')
8877 next();
8878 else
8879 break;
8882 skip(';');
8886 /* parse a function defined by symbol 'sym' and generate its code in
8887 'cur_text_section' */
8888 static void gen_function(Sym *sym)
8890 ind = cur_text_section->data_offset;
8891 /* NOTE: we patch the symbol size later */
8892 put_extern_sym(sym, cur_text_section, ind, 0);
8893 funcname = get_tok_str(sym->v, NULL);
8894 func_ind = ind;
8895 /* put debug symbol */
8896 if (do_debug)
8897 put_func_debug(sym);
8898 /* push a dummy symbol to enable local sym storage */
8899 sym_push2(&local_stack, SYM_FIELD, 0, 0);
8900 gfunc_prolog(&sym->type);
8901 rsym = 0;
8902 block(NULL, NULL, NULL, NULL, 0, 0);
8903 gsym(rsym);
8904 gfunc_epilog();
8905 cur_text_section->data_offset = ind;
8906 label_pop(&global_label_stack, NULL);
8907 sym_pop(&local_stack, NULL); /* reset local stack */
8908 /* end of function */
8909 /* patch symbol size */
8910 ((Elf32_Sym *)symtab_section->data)[sym->c].st_size =
8911 ind - func_ind;
8912 if (do_debug) {
8913 put_stabn(N_FUN, 0, 0, ind - func_ind);
8915 funcname = ""; /* for safety */
8916 func_vt.t = VT_VOID; /* for safety */
8917 ind = 0; /* for safety */
8920 static void gen_inline_functions(void)
8922 Sym *sym;
8923 CType *type;
8924 int *str, inline_generated;
8926 /* iterate while inline function are referenced */
8927 for(;;) {
8928 inline_generated = 0;
8929 for(sym = global_stack; sym != NULL; sym = sym->prev) {
8930 type = &sym->type;
8931 if (((type->t & VT_BTYPE) == VT_FUNC) &&
8932 (type->t & (VT_STATIC | VT_INLINE)) ==
8933 (VT_STATIC | VT_INLINE) &&
8934 sym->c != 0) {
8935 /* the function was used: generate its code and
8936 convert it to a normal function */
8937 str = (int *)sym->r;
8938 sym->r = VT_SYM | VT_CONST;
8939 type->t &= ~VT_INLINE;
8941 macro_ptr = str;
8942 next();
8943 cur_text_section = text_section;
8944 gen_function(sym);
8945 macro_ptr = NULL; /* fail safe */
8947 tok_str_free(str);
8948 inline_generated = 1;
8951 if (!inline_generated)
8952 break;
8955 /* free all remaining inline function tokens */
8956 for(sym = global_stack; sym != NULL; sym = sym->prev) {
8957 type = &sym->type;
8958 if (((type->t & VT_BTYPE) == VT_FUNC) &&
8959 (type->t & (VT_STATIC | VT_INLINE)) ==
8960 (VT_STATIC | VT_INLINE)) {
8961 str = (int *)sym->r;
8962 tok_str_free(str);
8963 sym->r = 0; /* fail safe */
8968 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
8969 static void decl(int l)
8971 int v, has_init, r;
8972 CType type, btype;
8973 Sym *sym;
8974 AttributeDef ad;
8976 while (1) {
8977 if (!parse_btype(&btype, &ad)) {
8978 /* skip redundant ';' */
8979 /* XXX: find more elegant solution */
8980 if (tok == ';') {
8981 next();
8982 continue;
8984 if (l == VT_CONST &&
8985 (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3)) {
8986 /* global asm block */
8987 asm_global_instr();
8988 continue;
8990 /* special test for old K&R protos without explicit int
8991 type. Only accepted when defining global data */
8992 if (l == VT_LOCAL || tok < TOK_DEFINE)
8993 break;
8994 btype.t = VT_INT;
8996 if (((btype.t & VT_BTYPE) == VT_ENUM ||
8997 (btype.t & VT_BTYPE) == VT_STRUCT) &&
8998 tok == ';') {
8999 /* we accept no variable after */
9000 next();
9001 continue;
9003 while (1) { /* iterate thru each declaration */
9004 type = btype;
9005 type_decl(&type, &ad, &v, TYPE_DIRECT);
9006 #if 0
9008 char buf[500];
9009 type_to_str(buf, sizeof(buf), &type, get_tok_str(v, NULL));
9010 printf("type = '%s'\n", buf);
9012 #endif
9013 if ((type.t & VT_BTYPE) == VT_FUNC) {
9014 /* if old style function prototype, we accept a
9015 declaration list */
9016 sym = type.ref;
9017 if (sym->c == FUNC_OLD)
9018 func_decl_list(sym);
9021 if (tok == '{') {
9022 if (l == VT_LOCAL)
9023 error("cannot use local functions");
9024 if ((type.t & VT_BTYPE) != VT_FUNC)
9025 expect("function definition");
9027 /* reject abstract declarators in function definition */
9028 sym = type.ref;
9029 while ((sym = sym->next) != NULL)
9030 if (!(sym->v & ~SYM_FIELD))
9031 expect("identifier");
9033 /* XXX: cannot do better now: convert extern line to static inline */
9034 if ((type.t & (VT_EXTERN | VT_INLINE)) == (VT_EXTERN | VT_INLINE))
9035 type.t = (type.t & ~VT_EXTERN) | VT_STATIC;
9037 sym = sym_find(v);
9038 if (sym) {
9039 if ((sym->type.t & VT_BTYPE) != VT_FUNC)
9040 goto func_error1;
9041 /* specific case: if not func_call defined, we put
9042 the one of the prototype */
9043 /* XXX: should have default value */
9044 if (sym->type.ref->r != FUNC_CDECL &&
9045 type.ref->r == FUNC_CDECL)
9046 type.ref->r = sym->type.ref->r;
9047 if (!is_compatible_types(&sym->type, &type)) {
9048 func_error1:
9049 error("incompatible types for redefinition of '%s'",
9050 get_tok_str(v, NULL));
9052 /* if symbol is already defined, then put complete type */
9053 sym->type = type;
9054 } else {
9055 /* put function symbol */
9056 sym = global_identifier_push(v, type.t, 0);
9057 sym->type.ref = type.ref;
9060 /* static inline functions are just recorded as a kind
9061 of macro. Their code will be emitted at the end of
9062 the compilation unit only if they are used */
9063 if ((type.t & (VT_INLINE | VT_STATIC)) ==
9064 (VT_INLINE | VT_STATIC)) {
9065 TokenString func_str;
9066 int block_level;
9068 tok_str_new(&func_str);
9070 block_level = 0;
9071 for(;;) {
9072 int t;
9073 if (tok == TOK_EOF)
9074 error("unexpected end of file");
9075 tok_str_add_tok(&func_str);
9076 t = tok;
9077 next();
9078 if (t == '{') {
9079 block_level++;
9080 } else if (t == '}') {
9081 block_level--;
9082 if (block_level == 0)
9083 break;
9086 tok_str_add(&func_str, -1);
9087 tok_str_add(&func_str, 0);
9088 sym->r = (int)func_str.str;
9089 } else {
9090 /* compute text section */
9091 cur_text_section = ad.section;
9092 if (!cur_text_section)
9093 cur_text_section = text_section;
9094 sym->r = VT_SYM | VT_CONST;
9095 gen_function(sym);
9096 #ifdef TCC_TARGET_PE
9097 if (ad.dllexport) {
9098 ((Elf32_Sym *)symtab_section->data)[sym->c].st_other |= 1;
9100 #endif
9102 break;
9103 } else {
9104 if (btype.t & VT_TYPEDEF) {
9105 /* save typedefed type */
9106 /* XXX: test storage specifiers ? */
9107 sym = sym_push(v, &type, 0, 0);
9108 sym->type.t |= VT_TYPEDEF;
9109 } else if ((type.t & VT_BTYPE) == VT_FUNC) {
9110 /* external function definition */
9111 /* specific case for func_call attribute */
9112 if (ad.func_call)
9113 type.ref->r = ad.func_call;
9114 external_sym(v, &type, 0);
9115 } else {
9116 /* not lvalue if array */
9117 r = 0;
9118 if (!(type.t & VT_ARRAY))
9119 r |= lvalue_type(type.t);
9120 has_init = (tok == '=');
9121 if ((btype.t & VT_EXTERN) ||
9122 ((type.t & VT_ARRAY) && (type.t & VT_STATIC) &&
9123 !has_init && l == VT_CONST && type.ref->c < 0)) {
9124 /* external variable */
9125 /* NOTE: as GCC, uninitialized global static
9126 arrays of null size are considered as
9127 extern */
9128 external_sym(v, &type, r);
9129 } else {
9130 if (type.t & VT_STATIC)
9131 r |= VT_CONST;
9132 else
9133 r |= l;
9134 if (has_init)
9135 next();
9136 decl_initializer_alloc(&type, &ad, r,
9137 has_init, v, l);
9140 if (tok != ',') {
9141 skip(';');
9142 break;
9144 next();
9150 /* better than nothing, but needs extension to handle '-E' option
9151 correctly too */
9152 static void preprocess_init(TCCState *s1)
9154 s1->include_stack_ptr = s1->include_stack;
9155 /* XXX: move that before to avoid having to initialize
9156 file->ifdef_stack_ptr ? */
9157 s1->ifdef_stack_ptr = s1->ifdef_stack;
9158 file->ifdef_stack_ptr = s1->ifdef_stack_ptr;
9160 /* XXX: not ANSI compliant: bound checking says error */
9161 vtop = vstack - 1;
9162 s1->pack_stack[0] = 0;
9163 s1->pack_stack_ptr = s1->pack_stack;
9166 /* compile the C file opened in 'file'. Return non zero if errors. */
9167 static int tcc_compile(TCCState *s1)
9169 Sym *define_start;
9170 char buf[512];
9171 volatile int section_sym;
9173 #ifdef INC_DEBUG
9174 printf("%s: **** new file\n", file->filename);
9175 #endif
9176 preprocess_init(s1);
9178 funcname = "";
9179 anon_sym = SYM_FIRST_ANOM;
9181 /* file info: full path + filename */
9182 section_sym = 0; /* avoid warning */
9183 if (do_debug) {
9184 section_sym = put_elf_sym(symtab_section, 0, 0,
9185 ELF32_ST_INFO(STB_LOCAL, STT_SECTION), 0,
9186 text_section->sh_num, NULL);
9187 getcwd(buf, sizeof(buf));
9188 pstrcat(buf, sizeof(buf), "/");
9189 put_stabs_r(buf, N_SO, 0, 0,
9190 text_section->data_offset, text_section, section_sym);
9191 put_stabs_r(file->filename, N_SO, 0, 0,
9192 text_section->data_offset, text_section, section_sym);
9194 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
9195 symbols can be safely used */
9196 put_elf_sym(symtab_section, 0, 0,
9197 ELF32_ST_INFO(STB_LOCAL, STT_FILE), 0,
9198 SHN_ABS, file->filename);
9200 /* define some often used types */
9201 int_type.t = VT_INT;
9203 char_pointer_type.t = VT_BYTE;
9204 mk_pointer(&char_pointer_type);
9206 func_old_type.t = VT_FUNC;
9207 func_old_type.ref = sym_push(SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD);
9209 #if 0
9210 /* define 'void *alloca(unsigned int)' builtin function */
9212 Sym *s1;
9214 p = anon_sym++;
9215 sym = sym_push(p, mk_pointer(VT_VOID), FUNC_CDECL, FUNC_NEW);
9216 s1 = sym_push(SYM_FIELD, VT_UNSIGNED | VT_INT, 0, 0);
9217 s1->next = NULL;
9218 sym->next = s1;
9219 sym_push(TOK_alloca, VT_FUNC | (p << VT_STRUCT_SHIFT), VT_CONST, 0);
9221 #endif
9223 define_start = define_stack;
9225 if (setjmp(s1->error_jmp_buf) == 0) {
9226 s1->nb_errors = 0;
9227 s1->error_set_jmp_enabled = 1;
9229 ch = file->buf_ptr[0];
9230 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
9231 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM;
9232 next();
9233 decl(VT_CONST);
9234 if (tok != TOK_EOF)
9235 expect("declaration");
9237 /* end of translation unit info */
9238 if (do_debug) {
9239 put_stabs_r(NULL, N_SO, 0, 0,
9240 text_section->data_offset, text_section, section_sym);
9243 s1->error_set_jmp_enabled = 0;
9245 /* reset define stack, but leave -Dsymbols (may be incorrect if
9246 they are undefined) */
9247 free_defines(define_start);
9249 gen_inline_functions();
9251 sym_pop(&global_stack, NULL);
9253 return s1->nb_errors != 0 ? -1 : 0;
9256 #ifdef LIBTCC
9257 int tcc_compile_string(TCCState *s, const char *str)
9259 BufferedFile bf1, *bf = &bf1;
9260 int ret, len;
9261 char *buf;
9263 /* init file structure */
9264 bf->fd = -1;
9265 /* XXX: avoid copying */
9266 len = strlen(str);
9267 buf = tcc_malloc(len + 1);
9268 if (!buf)
9269 return -1;
9270 memcpy(buf, str, len);
9271 buf[len] = CH_EOB;
9272 bf->buf_ptr = buf;
9273 bf->buf_end = buf + len;
9274 pstrcpy(bf->filename, sizeof(bf->filename), "<string>");
9275 bf->line_num = 1;
9276 file = bf;
9278 ret = tcc_compile(s);
9280 tcc_free(buf);
9282 /* currently, no need to close */
9283 return ret;
9285 #endif
9287 /* define a preprocessor symbol. A value can also be provided with the '=' operator */
9288 void tcc_define_symbol(TCCState *s1, const char *sym, const char *value)
9290 BufferedFile bf1, *bf = &bf1;
9292 pstrcpy(bf->buffer, IO_BUF_SIZE, sym);
9293 pstrcat(bf->buffer, IO_BUF_SIZE, " ");
9294 /* default value */
9295 if (!value)
9296 value = "1";
9297 pstrcat(bf->buffer, IO_BUF_SIZE, value);
9299 /* init file structure */
9300 bf->fd = -1;
9301 bf->buf_ptr = bf->buffer;
9302 bf->buf_end = bf->buffer + strlen(bf->buffer);
9303 *bf->buf_end = CH_EOB;
9304 bf->filename[0] = '\0';
9305 bf->line_num = 1;
9306 file = bf;
9308 s1->include_stack_ptr = s1->include_stack;
9310 /* parse with define parser */
9311 ch = file->buf_ptr[0];
9312 next_nomacro();
9313 parse_define();
9314 file = NULL;
9317 /* undefine a preprocessor symbol */
9318 void tcc_undefine_symbol(TCCState *s1, const char *sym)
9320 TokenSym *ts;
9321 Sym *s;
9322 ts = tok_alloc(sym, strlen(sym));
9323 s = define_find(ts->tok);
9324 /* undefine symbol by putting an invalid name */
9325 if (s)
9326 define_undef(s);
9329 #ifdef CONFIG_TCC_ASM
9331 #ifdef TCC_TARGET_I386
9332 #include "i386-asm.c"
9333 #endif
9334 #include "tccasm.c"
9336 #else
9337 static void asm_instr(void)
9339 error("inline asm() not supported");
9341 static void asm_global_instr(void)
9343 error("inline asm() not supported");
9345 #endif
9347 #include "tccelf.c"
9349 #ifdef TCC_TARGET_COFF
9350 #include "tcccoff.c"
9351 #endif
9353 #ifdef TCC_TARGET_PE
9354 #include "tccpe.c"
9355 #endif
9357 /* print the position in the source file of PC value 'pc' by reading
9358 the stabs debug information */
9359 static void rt_printline(unsigned long wanted_pc)
9361 Stab_Sym *sym, *sym_end;
9362 char func_name[128], last_func_name[128];
9363 unsigned long func_addr, last_pc, pc;
9364 const char *incl_files[INCLUDE_STACK_SIZE];
9365 int incl_index, len, last_line_num, i;
9366 const char *str, *p;
9368 fprintf(stderr, "0x%08lx:", wanted_pc);
9370 func_name[0] = '\0';
9371 func_addr = 0;
9372 incl_index = 0;
9373 last_func_name[0] = '\0';
9374 last_pc = 0xffffffff;
9375 last_line_num = 1;
9376 sym = (Stab_Sym *)stab_section->data + 1;
9377 sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset);
9378 while (sym < sym_end) {
9379 switch(sym->n_type) {
9380 /* function start or end */
9381 case N_FUN:
9382 if (sym->n_strx == 0) {
9383 /* we test if between last line and end of function */
9384 pc = sym->n_value + func_addr;
9385 if (wanted_pc >= last_pc && wanted_pc < pc)
9386 goto found;
9387 func_name[0] = '\0';
9388 func_addr = 0;
9389 } else {
9390 str = stabstr_section->data + sym->n_strx;
9391 p = strchr(str, ':');
9392 if (!p) {
9393 pstrcpy(func_name, sizeof(func_name), str);
9394 } else {
9395 len = p - str;
9396 if (len > sizeof(func_name) - 1)
9397 len = sizeof(func_name) - 1;
9398 memcpy(func_name, str, len);
9399 func_name[len] = '\0';
9401 func_addr = sym->n_value;
9403 break;
9404 /* line number info */
9405 case N_SLINE:
9406 pc = sym->n_value + func_addr;
9407 if (wanted_pc >= last_pc && wanted_pc < pc)
9408 goto found;
9409 last_pc = pc;
9410 last_line_num = sym->n_desc;
9411 /* XXX: slow! */
9412 strcpy(last_func_name, func_name);
9413 break;
9414 /* include files */
9415 case N_BINCL:
9416 str = stabstr_section->data + sym->n_strx;
9417 add_incl:
9418 if (incl_index < INCLUDE_STACK_SIZE) {
9419 incl_files[incl_index++] = str;
9421 break;
9422 case N_EINCL:
9423 if (incl_index > 1)
9424 incl_index--;
9425 break;
9426 case N_SO:
9427 if (sym->n_strx == 0) {
9428 incl_index = 0; /* end of translation unit */
9429 } else {
9430 str = stabstr_section->data + sym->n_strx;
9431 /* do not add path */
9432 len = strlen(str);
9433 if (len > 0 && str[len - 1] != '/')
9434 goto add_incl;
9436 break;
9438 sym++;
9441 /* second pass: we try symtab symbols (no line number info) */
9442 incl_index = 0;
9444 Elf32_Sym *sym, *sym_end;
9445 int type;
9447 sym_end = (Elf32_Sym *)(symtab_section->data + symtab_section->data_offset);
9448 for(sym = (Elf32_Sym *)symtab_section->data + 1;
9449 sym < sym_end;
9450 sym++) {
9451 type = ELF32_ST_TYPE(sym->st_info);
9452 if (type == STT_FUNC) {
9453 if (wanted_pc >= sym->st_value &&
9454 wanted_pc < sym->st_value + sym->st_size) {
9455 pstrcpy(last_func_name, sizeof(last_func_name),
9456 strtab_section->data + sym->st_name);
9457 goto found;
9462 /* did not find any info: */
9463 fprintf(stderr, " ???\n");
9464 return;
9465 found:
9466 if (last_func_name[0] != '\0') {
9467 fprintf(stderr, " %s()", last_func_name);
9469 if (incl_index > 0) {
9470 fprintf(stderr, " (%s:%d",
9471 incl_files[incl_index - 1], last_line_num);
9472 for(i = incl_index - 2; i >= 0; i--)
9473 fprintf(stderr, ", included from %s", incl_files[i]);
9474 fprintf(stderr, ")");
9476 fprintf(stderr, "\n");
9479 #if !defined(WIN32) && !defined(CONFIG_TCCBOOT)
9481 #ifdef __i386__
9483 /* fix for glibc 2.1 */
9484 #ifndef REG_EIP
9485 #define REG_EIP EIP
9486 #define REG_EBP EBP
9487 #endif
9489 /* return the PC at frame level 'level'. Return non zero if not found */
9490 static int rt_get_caller_pc(unsigned long *paddr,
9491 ucontext_t *uc, int level)
9493 unsigned long fp;
9494 int i;
9496 if (level == 0) {
9497 #if defined(__FreeBSD__)
9498 *paddr = uc->uc_mcontext.mc_eip;
9499 #elif defined(__dietlibc__)
9500 *paddr = uc->uc_mcontext.eip;
9501 #else
9502 *paddr = uc->uc_mcontext.gregs[REG_EIP];
9503 #endif
9504 return 0;
9505 } else {
9506 #if defined(__FreeBSD__)
9507 fp = uc->uc_mcontext.mc_ebp;
9508 #elif defined(__dietlibc__)
9509 fp = uc->uc_mcontext.ebp;
9510 #else
9511 fp = uc->uc_mcontext.gregs[REG_EBP];
9512 #endif
9513 for(i=1;i<level;i++) {
9514 /* XXX: check address validity with program info */
9515 if (fp <= 0x1000 || fp >= 0xc0000000)
9516 return -1;
9517 fp = ((unsigned long *)fp)[0];
9519 *paddr = ((unsigned long *)fp)[1];
9520 return 0;
9523 #else
9525 #warning add arch specific rt_get_caller_pc()
9527 static int rt_get_caller_pc(unsigned long *paddr,
9528 ucontext_t *uc, int level)
9530 return -1;
9532 #endif
9534 /* emit a run time error at position 'pc' */
9535 void rt_error(ucontext_t *uc, const char *fmt, ...)
9537 va_list ap;
9538 unsigned long pc;
9539 int i;
9541 va_start(ap, fmt);
9542 fprintf(stderr, "Runtime error: ");
9543 vfprintf(stderr, fmt, ap);
9544 fprintf(stderr, "\n");
9545 for(i=0;i<num_callers;i++) {
9546 if (rt_get_caller_pc(&pc, uc, i) < 0)
9547 break;
9548 if (i == 0)
9549 fprintf(stderr, "at ");
9550 else
9551 fprintf(stderr, "by ");
9552 rt_printline(pc);
9554 exit(255);
9555 va_end(ap);
9558 /* signal handler for fatal errors */
9559 static void sig_error(int signum, siginfo_t *siginf, void *puc)
9561 ucontext_t *uc = puc;
9563 switch(signum) {
9564 case SIGFPE:
9565 switch(siginf->si_code) {
9566 case FPE_INTDIV:
9567 case FPE_FLTDIV:
9568 rt_error(uc, "division by zero");
9569 break;
9570 default:
9571 rt_error(uc, "floating point exception");
9572 break;
9574 break;
9575 case SIGBUS:
9576 case SIGSEGV:
9577 if (rt_bound_error_msg && *rt_bound_error_msg)
9578 rt_error(uc, *rt_bound_error_msg);
9579 else
9580 rt_error(uc, "dereferencing invalid pointer");
9581 break;
9582 case SIGILL:
9583 rt_error(uc, "illegal instruction");
9584 break;
9585 case SIGABRT:
9586 rt_error(uc, "abort() called");
9587 break;
9588 default:
9589 rt_error(uc, "caught signal %d", signum);
9590 break;
9592 exit(255);
9594 #endif
9596 /* do all relocations (needed before using tcc_get_symbol()) */
9597 int tcc_relocate(TCCState *s1)
9599 Section *s;
9600 int i;
9602 s1->nb_errors = 0;
9604 #ifdef TCC_TARGET_PE
9605 pe_add_runtime(s1);
9606 #else
9607 tcc_add_runtime(s1);
9608 #endif
9610 relocate_common_syms();
9612 tcc_add_linker_symbols(s1);
9614 build_got_entries(s1);
9616 /* compute relocation address : section are relocated in place. We
9617 also alloc the bss space */
9618 for(i = 1; i < s1->nb_sections; i++) {
9619 s = s1->sections[i];
9620 if (s->sh_flags & SHF_ALLOC) {
9621 if (s->sh_type == SHT_NOBITS)
9622 s->data = tcc_mallocz(s->data_offset);
9623 s->sh_addr = (unsigned long)s->data;
9627 relocate_syms(s1, 1);
9629 if (s1->nb_errors != 0)
9630 return -1;
9632 /* relocate each section */
9633 for(i = 1; i < s1->nb_sections; i++) {
9634 s = s1->sections[i];
9635 if (s->reloc)
9636 relocate_section(s1, s);
9639 /* mark executable sections as executable in memory */
9640 for(i = 1; i < s1->nb_sections; i++) {
9641 s = s1->sections[i];
9642 if ((s->sh_flags & (SHF_ALLOC | SHF_EXECINSTR)) ==
9643 (SHF_ALLOC | SHF_EXECINSTR)) {
9644 #ifdef WIN32
9646 DWORD old_protect;
9647 VirtualProtect(s->data, s->data_offset,
9648 PAGE_EXECUTE_READWRITE, &old_protect);
9650 #else
9652 unsigned long start, end;
9653 start = (unsigned long)(s->data) & ~(PAGESIZE - 1);
9654 end = (unsigned long)(s->data + s->data_offset);
9655 end = (end + PAGESIZE - 1) & ~(PAGESIZE - 1);
9656 mprotect((void *)start, end - start,
9657 PROT_READ | PROT_WRITE | PROT_EXEC);
9659 #endif
9662 return 0;
9665 /* launch the compiled program with the given arguments */
9666 int tcc_run(TCCState *s1, int argc, char **argv)
9668 int (*prog_main)(int, char **);
9670 if (tcc_relocate(s1) < 0)
9671 return -1;
9673 prog_main = tcc_get_symbol_err(s1, "main");
9675 if (do_debug) {
9676 #if defined(WIN32) || defined(CONFIG_TCCBOOT)
9677 error("debug mode currently not available for Windows");
9678 #else
9679 struct sigaction sigact;
9680 /* install TCC signal handlers to print debug info on fatal
9681 runtime errors */
9682 sigact.sa_flags = SA_SIGINFO | SA_RESETHAND;
9683 sigact.sa_sigaction = sig_error;
9684 sigemptyset(&sigact.sa_mask);
9685 sigaction(SIGFPE, &sigact, NULL);
9686 sigaction(SIGILL, &sigact, NULL);
9687 sigaction(SIGSEGV, &sigact, NULL);
9688 sigaction(SIGBUS, &sigact, NULL);
9689 sigaction(SIGABRT, &sigact, NULL);
9690 #endif
9693 #ifdef CONFIG_TCC_BCHECK
9694 if (do_bounds_check) {
9695 void (*bound_init)(void);
9697 /* set error function */
9698 rt_bound_error_msg = (void *)tcc_get_symbol_err(s1,
9699 "__bound_error_msg");
9701 /* XXX: use .init section so that it also work in binary ? */
9702 bound_init = (void *)tcc_get_symbol_err(s1, "__bound_init");
9703 bound_init();
9705 #endif
9706 return (*prog_main)(argc, argv);
9709 TCCState *tcc_new(void)
9711 const char *p, *r;
9712 TCCState *s;
9713 TokenSym *ts;
9714 int i, c;
9716 s = tcc_mallocz(sizeof(TCCState));
9717 if (!s)
9718 return NULL;
9719 tcc_state = s;
9720 s->output_type = TCC_OUTPUT_MEMORY;
9722 /* init isid table */
9723 for(i=0;i<256;i++)
9724 isidnum_table[i] = isid(i) || isnum(i);
9726 /* add all tokens */
9727 table_ident = NULL;
9728 memset(hash_ident, 0, TOK_HASH_SIZE * sizeof(TokenSym *));
9730 tok_ident = TOK_IDENT;
9731 p = tcc_keywords;
9732 while (*p) {
9733 r = p;
9734 for(;;) {
9735 c = *r++;
9736 if (c == '\0')
9737 break;
9739 ts = tok_alloc(p, r - p - 1);
9740 p = r;
9743 /* we add dummy defines for some special macros to speed up tests
9744 and to have working defined() */
9745 define_push(TOK___LINE__, MACRO_OBJ, NULL, NULL);
9746 define_push(TOK___FILE__, MACRO_OBJ, NULL, NULL);
9747 define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL);
9748 define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL);
9750 /* standard defines */
9751 tcc_define_symbol(s, "__STDC__", NULL);
9752 #if defined(TCC_TARGET_I386)
9753 tcc_define_symbol(s, "__i386__", NULL);
9754 #endif
9755 #if defined(TCC_TARGET_ARM)
9756 tcc_define_symbol(s, "__ARM_ARCH_4__", NULL);
9757 tcc_define_symbol(s, "__arm_elf__", NULL);
9758 tcc_define_symbol(s, "__arm_elf", NULL);
9759 tcc_define_symbol(s, "arm_elf", NULL);
9760 tcc_define_symbol(s, "__arm__", NULL);
9761 tcc_define_symbol(s, "__arm", NULL);
9762 tcc_define_symbol(s, "arm", NULL);
9763 tcc_define_symbol(s, "__APCS_32__", NULL);
9764 #endif
9765 #if defined(linux)
9766 tcc_define_symbol(s, "__linux__", NULL);
9767 tcc_define_symbol(s, "linux", NULL);
9768 #endif
9769 /* tiny C specific defines */
9770 tcc_define_symbol(s, "__TINYC__", NULL);
9772 /* tiny C & gcc defines */
9773 tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned int");
9774 tcc_define_symbol(s, "__PTRDIFF_TYPE__", "int");
9775 #ifdef TCC_TARGET_PE
9776 tcc_define_symbol(s, "__WCHAR_TYPE__", "unsigned short");
9777 #else
9778 tcc_define_symbol(s, "__WCHAR_TYPE__", "int");
9779 #endif
9781 /* default library paths */
9782 #ifdef TCC_TARGET_PE
9784 char buf[1024];
9785 snprintf(buf, sizeof(buf), "%s/lib", tcc_lib_path);
9786 tcc_add_library_path(s, buf);
9788 #else
9789 tcc_add_library_path(s, "/usr/local/lib");
9790 tcc_add_library_path(s, "/usr/lib");
9791 tcc_add_library_path(s, "/lib");
9792 #endif
9794 /* no section zero */
9795 dynarray_add((void ***)&s->sections, &s->nb_sections, NULL);
9797 /* create standard sections */
9798 text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
9799 data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
9800 bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
9802 /* symbols are always generated for linking stage */
9803 symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0,
9804 ".strtab",
9805 ".hashtab", SHF_PRIVATE);
9806 strtab_section = symtab_section->link;
9808 /* private symbol table for dynamic symbols */
9809 s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE,
9810 ".dynstrtab",
9811 ".dynhashtab", SHF_PRIVATE);
9812 s->alacarte_link = 1;
9814 #ifdef CHAR_IS_UNSIGNED
9815 s->char_is_unsigned = 1;
9816 #endif
9817 #if defined(TCC_TARGET_PE) && 0
9818 /* XXX: currently the PE linker is not ready to support that */
9819 s->leading_underscore = 1;
9820 #endif
9821 return s;
9824 void tcc_delete(TCCState *s1)
9826 int i, n;
9828 /* free -D defines */
9829 free_defines(NULL);
9831 /* free tokens */
9832 n = tok_ident - TOK_IDENT;
9833 for(i = 0; i < n; i++)
9834 tcc_free(table_ident[i]);
9835 tcc_free(table_ident);
9837 /* free all sections */
9839 free_section(symtab_section->hash);
9841 free_section(s1->dynsymtab_section->hash);
9842 free_section(s1->dynsymtab_section->link);
9843 free_section(s1->dynsymtab_section);
9845 for(i = 1; i < s1->nb_sections; i++)
9846 free_section(s1->sections[i]);
9847 tcc_free(s1->sections);
9849 /* free loaded dlls array */
9850 for(i = 0; i < s1->nb_loaded_dlls; i++)
9851 tcc_free(s1->loaded_dlls[i]);
9852 tcc_free(s1->loaded_dlls);
9854 /* library paths */
9855 for(i = 0; i < s1->nb_library_paths; i++)
9856 tcc_free(s1->library_paths[i]);
9857 tcc_free(s1->library_paths);
9859 /* cached includes */
9860 for(i = 0; i < s1->nb_cached_includes; i++)
9861 tcc_free(s1->cached_includes[i]);
9862 tcc_free(s1->cached_includes);
9864 for(i = 0; i < s1->nb_include_paths; i++)
9865 tcc_free(s1->include_paths[i]);
9866 tcc_free(s1->include_paths);
9868 for(i = 0; i < s1->nb_sysinclude_paths; i++)
9869 tcc_free(s1->sysinclude_paths[i]);
9870 tcc_free(s1->sysinclude_paths);
9872 tcc_free(s1);
9875 int tcc_add_include_path(TCCState *s1, const char *pathname)
9877 char *pathname1;
9879 pathname1 = tcc_strdup(pathname);
9880 dynarray_add((void ***)&s1->include_paths, &s1->nb_include_paths, pathname1);
9881 return 0;
9884 int tcc_add_sysinclude_path(TCCState *s1, const char *pathname)
9886 char *pathname1;
9888 pathname1 = tcc_strdup(pathname);
9889 dynarray_add((void ***)&s1->sysinclude_paths, &s1->nb_sysinclude_paths, pathname1);
9890 return 0;
9893 static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
9895 const char *ext, *filename1;
9896 Elf32_Ehdr ehdr;
9897 int fd, ret;
9898 BufferedFile *saved_file;
9900 /* find source file type with extension */
9901 filename1 = strrchr(filename, '/');
9902 if (filename1)
9903 filename1++;
9904 else
9905 filename1 = filename;
9906 ext = strrchr(filename1, '.');
9907 if (ext)
9908 ext++;
9910 /* open the file */
9911 saved_file = file;
9912 file = tcc_open(s1, filename);
9913 if (!file) {
9914 if (flags & AFF_PRINT_ERROR) {
9915 error_noabort("file '%s' not found", filename);
9917 ret = -1;
9918 goto fail1;
9921 if (!ext || !strcmp(ext, "c")) {
9922 /* C file assumed */
9923 ret = tcc_compile(s1);
9924 } else
9925 #ifdef CONFIG_TCC_ASM
9926 if (!strcmp(ext, "S")) {
9927 /* preprocessed assembler */
9928 ret = tcc_assemble(s1, 1);
9929 } else if (!strcmp(ext, "s")) {
9930 /* non preprocessed assembler */
9931 ret = tcc_assemble(s1, 0);
9932 } else
9933 #endif
9934 #ifdef TCC_TARGET_PE
9935 if (!strcmp(ext, "def")) {
9936 ret = pe_load_def_file(s1, fdopen(file->fd, "rb"));
9937 } else
9938 #endif
9940 fd = file->fd;
9941 /* assume executable format: auto guess file type */
9942 ret = read(fd, &ehdr, sizeof(ehdr));
9943 lseek(fd, 0, SEEK_SET);
9944 if (ret <= 0) {
9945 error_noabort("could not read header");
9946 goto fail;
9947 } else if (ret != sizeof(ehdr)) {
9948 goto try_load_script;
9951 if (ehdr.e_ident[0] == ELFMAG0 &&
9952 ehdr.e_ident[1] == ELFMAG1 &&
9953 ehdr.e_ident[2] == ELFMAG2 &&
9954 ehdr.e_ident[3] == ELFMAG3) {
9955 file->line_num = 0; /* do not display line number if error */
9956 if (ehdr.e_type == ET_REL) {
9957 ret = tcc_load_object_file(s1, fd, 0);
9958 } else if (ehdr.e_type == ET_DYN) {
9959 if (s1->output_type == TCC_OUTPUT_MEMORY) {
9960 #ifdef TCC_TARGET_PE
9961 ret = -1;
9962 #else
9963 void *h;
9964 h = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY);
9965 if (h)
9966 ret = 0;
9967 else
9968 ret = -1;
9969 #endif
9970 } else {
9971 ret = tcc_load_dll(s1, fd, filename,
9972 (flags & AFF_REFERENCED_DLL) != 0);
9974 } else {
9975 error_noabort("unrecognized ELF file");
9976 goto fail;
9978 } else if (memcmp((char *)&ehdr, ARMAG, 8) == 0) {
9979 file->line_num = 0; /* do not display line number if error */
9980 ret = tcc_load_archive(s1, fd);
9981 } else
9982 #ifdef TCC_TARGET_COFF
9983 if (*(uint16_t *)(&ehdr) == COFF_C67_MAGIC) {
9984 ret = tcc_load_coff(s1, fd);
9985 } else
9986 #endif
9988 /* as GNU ld, consider it is an ld script if not recognized */
9989 try_load_script:
9990 ret = tcc_load_ldscript(s1);
9991 if (ret < 0) {
9992 error_noabort("unrecognized file type");
9993 goto fail;
9997 the_end:
9998 tcc_close(file);
9999 fail1:
10000 file = saved_file;
10001 return ret;
10002 fail:
10003 ret = -1;
10004 goto the_end;
10007 int tcc_add_file(TCCState *s, const char *filename)
10009 return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR);
10012 int tcc_add_library_path(TCCState *s, const char *pathname)
10014 char *pathname1;
10016 pathname1 = tcc_strdup(pathname);
10017 dynarray_add((void ***)&s->library_paths, &s->nb_library_paths, pathname1);
10018 return 0;
10021 /* find and load a dll. Return non zero if not found */
10022 /* XXX: add '-rpath' option support ? */
10023 static int tcc_add_dll(TCCState *s, const char *filename, int flags)
10025 char buf[1024];
10026 int i;
10028 for(i = 0; i < s->nb_library_paths; i++) {
10029 snprintf(buf, sizeof(buf), "%s/%s",
10030 s->library_paths[i], filename);
10031 if (tcc_add_file_internal(s, buf, flags) == 0)
10032 return 0;
10034 return -1;
10037 /* the library name is the same as the argument of the '-l' option */
10038 int tcc_add_library(TCCState *s, const char *libraryname)
10040 char buf[1024];
10041 int i;
10043 /* first we look for the dynamic library if not static linking */
10044 if (!s->static_link) {
10045 #ifdef TCC_TARGET_PE
10046 snprintf(buf, sizeof(buf), "%s.def", libraryname);
10047 #else
10048 snprintf(buf, sizeof(buf), "lib%s.so", libraryname);
10049 #endif
10050 if (tcc_add_dll(s, buf, 0) == 0)
10051 return 0;
10054 /* then we look for the static library */
10055 for(i = 0; i < s->nb_library_paths; i++) {
10056 snprintf(buf, sizeof(buf), "%s/lib%s.a",
10057 s->library_paths[i], libraryname);
10058 if (tcc_add_file_internal(s, buf, 0) == 0)
10059 return 0;
10061 return -1;
10064 int tcc_add_symbol(TCCState *s, const char *name, unsigned long val)
10066 add_elf_sym(symtab_section, val, 0,
10067 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
10068 SHN_ABS, name);
10069 return 0;
10072 int tcc_set_output_type(TCCState *s, int output_type)
10074 s->output_type = output_type;
10076 if (!s->nostdinc) {
10077 char buf[1024];
10079 /* default include paths */
10080 /* XXX: reverse order needed if -isystem support */
10081 #ifndef TCC_TARGET_PE
10082 tcc_add_sysinclude_path(s, "/usr/local/include");
10083 tcc_add_sysinclude_path(s, "/usr/include");
10084 #endif
10085 snprintf(buf, sizeof(buf), "%s/include", tcc_lib_path);
10086 tcc_add_sysinclude_path(s, buf);
10087 #ifdef TCC_TARGET_PE
10088 snprintf(buf, sizeof(buf), "%s/include/winapi", tcc_lib_path);
10089 tcc_add_sysinclude_path(s, buf);
10090 #endif
10093 /* if bound checking, then add corresponding sections */
10094 #ifdef CONFIG_TCC_BCHECK
10095 if (do_bounds_check) {
10096 /* define symbol */
10097 tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL);
10098 /* create bounds sections */
10099 bounds_section = new_section(s, ".bounds",
10100 SHT_PROGBITS, SHF_ALLOC);
10101 lbounds_section = new_section(s, ".lbounds",
10102 SHT_PROGBITS, SHF_ALLOC);
10104 #endif
10106 if (s->char_is_unsigned) {
10107 tcc_define_symbol(s, "__CHAR_UNSIGNED__", NULL);
10110 /* add debug sections */
10111 if (do_debug) {
10112 /* stab symbols */
10113 stab_section = new_section(s, ".stab", SHT_PROGBITS, 0);
10114 stab_section->sh_entsize = sizeof(Stab_Sym);
10115 stabstr_section = new_section(s, ".stabstr", SHT_STRTAB, 0);
10116 put_elf_str(stabstr_section, "");
10117 stab_section->link = stabstr_section;
10118 /* put first entry */
10119 put_stabs("", 0, 0, 0, 0);
10122 /* add libc crt1/crti objects */
10123 #ifndef TCC_TARGET_PE
10124 if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) &&
10125 !s->nostdlib) {
10126 if (output_type != TCC_OUTPUT_DLL)
10127 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crt1.o");
10128 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crti.o");
10130 #endif
10131 return 0;
10134 #define WD_ALL 0x0001 /* warning is activated when using -Wall */
10135 #define FD_INVERT 0x0002 /* invert value before storing */
10137 typedef struct FlagDef {
10138 uint16_t offset;
10139 uint16_t flags;
10140 const char *name;
10141 } FlagDef;
10143 static const FlagDef warning_defs[] = {
10144 { offsetof(TCCState, warn_unsupported), 0, "unsupported" },
10145 { offsetof(TCCState, warn_write_strings), 0, "write-strings" },
10146 { offsetof(TCCState, warn_error), 0, "error" },
10147 { offsetof(TCCState, warn_implicit_function_declaration), WD_ALL,
10148 "implicit-function-declaration" },
10151 static int set_flag(TCCState *s, const FlagDef *flags, int nb_flags,
10152 const char *name, int value)
10154 int i;
10155 const FlagDef *p;
10156 const char *r;
10158 r = name;
10159 if (r[0] == 'n' && r[1] == 'o' && r[2] == '-') {
10160 r += 3;
10161 value = !value;
10163 for(i = 0, p = flags; i < nb_flags; i++, p++) {
10164 if (!strcmp(r, p->name))
10165 goto found;
10167 return -1;
10168 found:
10169 if (p->flags & FD_INVERT)
10170 value = !value;
10171 *(int *)((uint8_t *)s + p->offset) = value;
10172 return 0;
10176 /* set/reset a warning */
10177 int tcc_set_warning(TCCState *s, const char *warning_name, int value)
10179 int i;
10180 const FlagDef *p;
10182 if (!strcmp(warning_name, "all")) {
10183 for(i = 0, p = warning_defs; i < countof(warning_defs); i++, p++) {
10184 if (p->flags & WD_ALL)
10185 *(int *)((uint8_t *)s + p->offset) = 1;
10187 return 0;
10188 } else {
10189 return set_flag(s, warning_defs, countof(warning_defs),
10190 warning_name, value);
10194 static const FlagDef flag_defs[] = {
10195 { offsetof(TCCState, char_is_unsigned), 0, "unsigned-char" },
10196 { offsetof(TCCState, char_is_unsigned), FD_INVERT, "signed-char" },
10197 { offsetof(TCCState, nocommon), FD_INVERT, "common" },
10198 { offsetof(TCCState, leading_underscore), 0, "leading-underscore" },
10201 /* set/reset a flag */
10202 int tcc_set_flag(TCCState *s, const char *flag_name, int value)
10204 return set_flag(s, flag_defs, countof(flag_defs),
10205 flag_name, value);
10208 #if !defined(LIBTCC)
10210 /* extract the basename of a file */
10211 static const char *tcc_basename(const char *name)
10213 const char *p;
10214 p = strrchr(name, '/');
10215 #ifdef WIN32
10216 if (!p)
10217 p = strrchr(name, '\\');
10218 #endif
10219 if (!p)
10220 p = name;
10221 else
10222 p++;
10223 return p;
10226 static int64_t getclock_us(void)
10228 #ifdef WIN32
10229 struct _timeb tb;
10230 _ftime(&tb);
10231 return (tb.time * 1000LL + tb.millitm) * 1000LL;
10232 #else
10233 struct timeval tv;
10234 gettimeofday(&tv, NULL);
10235 return tv.tv_sec * 1000000LL + tv.tv_usec;
10236 #endif
10239 void help(void)
10241 printf("tcc version " TCC_VERSION " - Tiny C Compiler - Copyright (C) 2001-2005 Fabrice Bellard\n"
10242 "usage: tcc [-v] [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
10243 " [-Wwarn] [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-static]\n"
10244 " [infile1 infile2...] [-run infile args...]\n"
10245 "\n"
10246 "General options:\n"
10247 " -v display current version\n"
10248 " -c compile only - generate an object file\n"
10249 " -o outfile set output filename\n"
10250 " -Bdir set tcc internal library path\n"
10251 " -bench output compilation statistics\n"
10252 " -run run compiled source\n"
10253 " -fflag set or reset (with 'no-' prefix) 'flag' (see man page)\n"
10254 " -Wwarning set or reset (with 'no-' prefix) 'warning' (see man page)\n"
10255 " -w disable all warnings\n"
10256 "Preprocessor options:\n"
10257 " -Idir add include path 'dir'\n"
10258 " -Dsym[=val] define 'sym' with value 'val'\n"
10259 " -Usym undefine 'sym'\n"
10260 "Linker options:\n"
10261 " -Ldir add library path 'dir'\n"
10262 " -llib link with dynamic or static library 'lib'\n"
10263 " -shared generate a shared library\n"
10264 " -static static linking\n"
10265 " -rdynamic export all global symbols to dynamic linker\n"
10266 " -r relocatable output\n"
10267 "Debugger options:\n"
10268 " -g generate runtime debug info\n"
10269 #ifdef CONFIG_TCC_BCHECK
10270 " -b compile with built-in memory and bounds checker (implies -g)\n"
10271 #endif
10272 " -bt N show N callers in stack traces\n"
10276 #define TCC_OPTION_HAS_ARG 0x0001
10277 #define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
10279 typedef struct TCCOption {
10280 const char *name;
10281 uint16_t index;
10282 uint16_t flags;
10283 } TCCOption;
10285 enum {
10286 TCC_OPTION_HELP,
10287 TCC_OPTION_I,
10288 TCC_OPTION_D,
10289 TCC_OPTION_U,
10290 TCC_OPTION_L,
10291 TCC_OPTION_B,
10292 TCC_OPTION_l,
10293 TCC_OPTION_bench,
10294 TCC_OPTION_bt,
10295 TCC_OPTION_b,
10296 TCC_OPTION_g,
10297 TCC_OPTION_c,
10298 TCC_OPTION_static,
10299 TCC_OPTION_shared,
10300 TCC_OPTION_o,
10301 TCC_OPTION_r,
10302 TCC_OPTION_Wl,
10303 TCC_OPTION_W,
10304 TCC_OPTION_O,
10305 TCC_OPTION_m,
10306 TCC_OPTION_f,
10307 TCC_OPTION_nostdinc,
10308 TCC_OPTION_nostdlib,
10309 TCC_OPTION_print_search_dirs,
10310 TCC_OPTION_rdynamic,
10311 TCC_OPTION_run,
10312 TCC_OPTION_v,
10313 TCC_OPTION_w,
10314 TCC_OPTION_pipe,
10317 static const TCCOption tcc_options[] = {
10318 { "h", TCC_OPTION_HELP, 0 },
10319 { "?", TCC_OPTION_HELP, 0 },
10320 { "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG },
10321 { "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG },
10322 { "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG },
10323 { "L", TCC_OPTION_L, TCC_OPTION_HAS_ARG },
10324 { "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG },
10325 { "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10326 { "bench", TCC_OPTION_bench, 0 },
10327 { "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG },
10328 #ifdef CONFIG_TCC_BCHECK
10329 { "b", TCC_OPTION_b, 0 },
10330 #endif
10331 { "g", TCC_OPTION_g, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10332 { "c", TCC_OPTION_c, 0 },
10333 { "static", TCC_OPTION_static, 0 },
10334 { "shared", TCC_OPTION_shared, 0 },
10335 { "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG },
10336 { "run", TCC_OPTION_run, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10337 { "rdynamic", TCC_OPTION_rdynamic, 0 },
10338 { "r", TCC_OPTION_r, 0 },
10339 { "Wl,", TCC_OPTION_Wl, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10340 { "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10341 { "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10342 { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG },
10343 { "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10344 { "nostdinc", TCC_OPTION_nostdinc, 0 },
10345 { "nostdlib", TCC_OPTION_nostdlib, 0 },
10346 { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 },
10347 { "v", TCC_OPTION_v, 0 },
10348 { "w", TCC_OPTION_w, 0 },
10349 { "pipe", TCC_OPTION_pipe, 0},
10350 { NULL },
10353 /* convert 'str' into an array of space separated strings */
10354 static int expand_args(char ***pargv, const char *str)
10356 const char *s1;
10357 char **argv, *arg;
10358 int argc, len;
10360 argc = 0;
10361 argv = NULL;
10362 for(;;) {
10363 while (is_space(*str))
10364 str++;
10365 if (*str == '\0')
10366 break;
10367 s1 = str;
10368 while (*str != '\0' && !is_space(*str))
10369 str++;
10370 len = str - s1;
10371 arg = tcc_malloc(len + 1);
10372 memcpy(arg, s1, len);
10373 arg[len] = '\0';
10374 dynarray_add((void ***)&argv, &argc, arg);
10376 *pargv = argv;
10377 return argc;
10380 static char **files;
10381 static int nb_files, nb_libraries;
10382 static int multiple_files;
10383 static int print_search_dirs;
10384 static int output_type;
10385 static int reloc_output;
10386 static const char *outfile;
10388 int parse_args(TCCState *s, int argc, char **argv)
10390 int optind;
10391 const TCCOption *popt;
10392 const char *optarg, *p1, *r1;
10393 char *r;
10395 optind = 0;
10396 while (1) {
10397 if (optind >= argc) {
10398 if (nb_files == 0 && !print_search_dirs)
10399 goto show_help;
10400 else
10401 break;
10403 r = argv[optind++];
10404 if (r[0] != '-') {
10405 /* add a new file */
10406 dynarray_add((void ***)&files, &nb_files, r);
10407 if (!multiple_files) {
10408 optind--;
10409 /* argv[0] will be this file */
10410 break;
10412 } else {
10413 /* find option in table (match only the first chars */
10414 popt = tcc_options;
10415 for(;;) {
10416 p1 = popt->name;
10417 if (p1 == NULL)
10418 error("invalid option -- '%s'", r);
10419 r1 = r + 1;
10420 for(;;) {
10421 if (*p1 == '\0')
10422 goto option_found;
10423 if (*r1 != *p1)
10424 break;
10425 p1++;
10426 r1++;
10428 popt++;
10430 option_found:
10431 if (popt->flags & TCC_OPTION_HAS_ARG) {
10432 if (*r1 != '\0' || (popt->flags & TCC_OPTION_NOSEP)) {
10433 optarg = r1;
10434 } else {
10435 if (optind >= argc)
10436 error("argument to '%s' is missing", r);
10437 optarg = argv[optind++];
10439 } else {
10440 if (*r1 != '\0')
10441 goto show_help;
10442 optarg = NULL;
10445 switch(popt->index) {
10446 case TCC_OPTION_HELP:
10447 show_help:
10448 help();
10449 exit(1);
10450 case TCC_OPTION_I:
10451 if (tcc_add_include_path(s, optarg) < 0)
10452 error("too many include paths");
10453 break;
10454 case TCC_OPTION_D:
10456 char *sym, *value;
10457 sym = (char *)optarg;
10458 value = strchr(sym, '=');
10459 if (value) {
10460 *value = '\0';
10461 value++;
10463 tcc_define_symbol(s, sym, value);
10465 break;
10466 case TCC_OPTION_U:
10467 tcc_undefine_symbol(s, optarg);
10468 break;
10469 case TCC_OPTION_L:
10470 tcc_add_library_path(s, optarg);
10471 break;
10472 case TCC_OPTION_B:
10473 /* set tcc utilities path (mainly for tcc development) */
10474 tcc_lib_path = optarg;
10475 break;
10476 case TCC_OPTION_l:
10477 dynarray_add((void ***)&files, &nb_files, r);
10478 nb_libraries++;
10479 break;
10480 case TCC_OPTION_bench:
10481 do_bench = 1;
10482 break;
10483 case TCC_OPTION_bt:
10484 num_callers = atoi(optarg);
10485 break;
10486 #ifdef CONFIG_TCC_BCHECK
10487 case TCC_OPTION_b:
10488 do_bounds_check = 1;
10489 do_debug = 1;
10490 break;
10491 #endif
10492 case TCC_OPTION_g:
10493 do_debug = 1;
10494 break;
10495 case TCC_OPTION_c:
10496 multiple_files = 1;
10497 output_type = TCC_OUTPUT_OBJ;
10498 break;
10499 case TCC_OPTION_static:
10500 s->static_link = 1;
10501 break;
10502 case TCC_OPTION_shared:
10503 output_type = TCC_OUTPUT_DLL;
10504 break;
10505 case TCC_OPTION_o:
10506 multiple_files = 1;
10507 outfile = optarg;
10508 break;
10509 case TCC_OPTION_r:
10510 /* generate a .o merging several output files */
10511 reloc_output = 1;
10512 output_type = TCC_OUTPUT_OBJ;
10513 break;
10514 case TCC_OPTION_nostdinc:
10515 s->nostdinc = 1;
10516 break;
10517 case TCC_OPTION_nostdlib:
10518 s->nostdlib = 1;
10519 break;
10520 case TCC_OPTION_print_search_dirs:
10521 print_search_dirs = 1;
10522 break;
10523 case TCC_OPTION_run:
10525 int argc1;
10526 char **argv1;
10527 argc1 = expand_args(&argv1, optarg);
10528 if (argc1 > 0) {
10529 parse_args(s, argc1, argv1);
10531 multiple_files = 0;
10532 output_type = TCC_OUTPUT_MEMORY;
10534 break;
10535 case TCC_OPTION_v:
10536 printf("tcc version %s\n", TCC_VERSION);
10537 exit(0);
10538 case TCC_OPTION_f:
10539 if (tcc_set_flag(s, optarg, 1) < 0 && s->warn_unsupported)
10540 goto unsupported_option;
10541 break;
10542 case TCC_OPTION_W:
10543 if (tcc_set_warning(s, optarg, 1) < 0 &&
10544 s->warn_unsupported)
10545 goto unsupported_option;
10546 break;
10547 case TCC_OPTION_w:
10548 s->warn_none = 1;
10549 break;
10550 case TCC_OPTION_rdynamic:
10551 s->rdynamic = 1;
10552 break;
10553 case TCC_OPTION_Wl:
10555 const char *p;
10556 if (strstart(optarg, "-Ttext,", &p)) {
10557 s->text_addr = strtoul(p, NULL, 16);
10558 s->has_text_addr = 1;
10559 } else if (strstart(optarg, "--oformat,", &p)) {
10560 if (strstart(p, "elf32-", NULL)) {
10561 s->output_format = TCC_OUTPUT_FORMAT_ELF;
10562 } else if (!strcmp(p, "binary")) {
10563 s->output_format = TCC_OUTPUT_FORMAT_BINARY;
10564 } else
10565 #ifdef TCC_TARGET_COFF
10566 if (!strcmp(p, "coff")) {
10567 s->output_format = TCC_OUTPUT_FORMAT_COFF;
10568 } else
10569 #endif
10571 error("target %s not found", p);
10573 } else {
10574 error("unsupported linker option '%s'", optarg);
10577 break;
10578 default:
10579 if (s->warn_unsupported) {
10580 unsupported_option:
10581 warning("unsupported option '%s'", r);
10583 break;
10587 return optind;
10590 int main(int argc, char **argv)
10592 int i;
10593 TCCState *s;
10594 int nb_objfiles, ret, optind;
10595 char objfilename[1024];
10596 int64_t start_time = 0;
10598 #ifdef WIN32
10599 /* on win32, we suppose the lib and includes are at the location
10600 of 'tcc.exe' */
10602 static char path[1024];
10603 char *p, *d;
10605 GetModuleFileNameA(NULL, path, sizeof path);
10606 p = d = strlwr(path);
10607 while (*d)
10609 if (*d == '\\') *d = '/', p = d;
10610 ++d;
10612 *p = '\0';
10613 tcc_lib_path = path;
10615 #endif
10617 s = tcc_new();
10618 output_type = TCC_OUTPUT_EXE;
10619 outfile = NULL;
10620 multiple_files = 1;
10621 files = NULL;
10622 nb_files = 0;
10623 nb_libraries = 0;
10624 reloc_output = 0;
10625 print_search_dirs = 0;
10627 optind = parse_args(s, argc - 1, argv + 1) + 1;
10629 if (print_search_dirs) {
10630 /* enough for Linux kernel */
10631 printf("install: %s/\n", tcc_lib_path);
10632 return 0;
10635 nb_objfiles = nb_files - nb_libraries;
10637 /* if outfile provided without other options, we output an
10638 executable */
10639 if (outfile && output_type == TCC_OUTPUT_MEMORY)
10640 output_type = TCC_OUTPUT_EXE;
10642 /* check -c consistency : only single file handled. XXX: checks file type */
10643 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
10644 /* accepts only a single input file */
10645 if (nb_objfiles != 1)
10646 error("cannot specify multiple files with -c");
10647 if (nb_libraries != 0)
10648 error("cannot specify libraries with -c");
10651 if (output_type != TCC_OUTPUT_MEMORY) {
10652 if (!outfile) {
10653 /* compute default outfile name */
10654 pstrcpy(objfilename, sizeof(objfilename) - 1,
10655 /* strip path */
10656 tcc_basename(files[0]));
10657 #ifdef TCC_TARGET_PE
10658 pe_guess_outfile(objfilename, output_type);
10659 #else
10660 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
10661 char *ext = strrchr(objfilename, '.');
10662 if (!ext)
10663 goto default_outfile;
10664 /* add .o extension */
10665 strcpy(ext + 1, "o");
10666 } else {
10667 default_outfile:
10668 pstrcpy(objfilename, sizeof(objfilename), "a.out");
10670 #endif
10671 outfile = objfilename;
10675 if (do_bench) {
10676 start_time = getclock_us();
10679 tcc_set_output_type(s, output_type);
10681 /* compile or add each files or library */
10682 for(i = 0;i < nb_files; i++) {
10683 const char *filename;
10685 filename = files[i];
10686 if (filename[0] == '-') {
10687 if (tcc_add_library(s, filename + 2) < 0)
10688 error("cannot find %s", filename);
10689 } else {
10690 if (tcc_add_file(s, filename) < 0) {
10691 ret = 1;
10692 goto the_end;
10697 /* free all files */
10698 tcc_free(files);
10700 if (do_bench) {
10701 double total_time;
10702 total_time = (double)(getclock_us() - start_time) / 1000000.0;
10703 if (total_time < 0.001)
10704 total_time = 0.001;
10705 if (total_bytes < 1)
10706 total_bytes = 1;
10707 printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
10708 tok_ident - TOK_IDENT, total_lines, total_bytes,
10709 total_time, (int)(total_lines / total_time),
10710 total_bytes / total_time / 1000000.0);
10713 if (s->output_type == TCC_OUTPUT_MEMORY) {
10714 ret = tcc_run(s, argc - optind, argv + optind);
10715 } else
10716 #ifdef TCC_TARGET_PE
10717 if (s->output_type != TCC_OUTPUT_OBJ) {
10718 ret = tcc_output_pe(s, outfile);
10719 } else
10720 #endif
10722 tcc_output_file(s, outfile);
10723 ret = 0;
10725 the_end:
10726 /* XXX: cannot do it with bound checking because of the malloc hooks */
10727 if (!do_bounds_check)
10728 tcc_delete(s);
10730 #ifdef MEM_DEBUG
10731 if (do_bench) {
10732 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size, mem_max_size);
10734 #endif
10735 return ret;
10738 #endif