Fix 'tcc -static' with recent glibc
[tinycc/daniel.git] / tcc.c
blob1fc29581fc26f75a1cbe70dbe99e2ea7cf622a79
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 int func_attr; /* calling convention, exports, ... */
234 } AttributeDef;
236 /* -------------------------------------------------- */
237 /* gr: wrappers for casting sym->r for other purposes */
238 typedef struct {
239 unsigned
240 func_call : 8,
241 func_args : 8,
242 func_export : 1;
243 } func_attr_t;
245 #define FUNC_CALL(r) (((func_attr_t*)&(r))->func_call)
246 #define FUNC_EXPORT(r) (((func_attr_t*)&(r))->func_export)
247 #define FUNC_ARGS(r) (((func_attr_t*)&(r))->func_args)
248 #define INLINE_DEF(r) (*(int **)&(r))
249 /* -------------------------------------------------- */
251 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
252 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
253 #define SYM_FIRST_ANOM 0x10000000 /* first anonymous sym */
255 /* stored in 'Sym.c' field */
256 #define FUNC_NEW 1 /* ansi function prototype */
257 #define FUNC_OLD 2 /* old function prototype */
258 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
260 /* stored in 'Sym.r' field */
261 #define FUNC_CDECL 0 /* standard c call */
262 #define FUNC_STDCALL 1 /* pascal c call */
263 #define FUNC_FASTCALL1 2 /* first param in %eax */
264 #define FUNC_FASTCALL2 3 /* first parameters in %eax, %edx */
265 #define FUNC_FASTCALL3 4 /* first parameter in %eax, %edx, %ecx */
266 #define FUNC_FASTCALLW 5 /* first parameter in %ecx, %edx */
268 /* field 'Sym.t' for macros */
269 #define MACRO_OBJ 0 /* object like macro */
270 #define MACRO_FUNC 1 /* function like macro */
272 /* field 'Sym.r' for C labels */
273 #define LABEL_DEFINED 0 /* label is defined */
274 #define LABEL_FORWARD 1 /* label is forward defined */
275 #define LABEL_DECLARED 2 /* label is declared but never used */
277 /* type_decl() types */
278 #define TYPE_ABSTRACT 1 /* type without variable */
279 #define TYPE_DIRECT 2 /* type with variable */
281 #define IO_BUF_SIZE 8192
283 typedef struct BufferedFile {
284 uint8_t *buf_ptr;
285 uint8_t *buf_end;
286 int fd;
287 int line_num; /* current line number - here to simplify code */
288 int ifndef_macro; /* #ifndef macro / #endif search */
289 int ifndef_macro_saved; /* saved ifndef_macro */
290 int *ifdef_stack_ptr; /* ifdef_stack value at the start of the file */
291 char inc_type; /* type of include */
292 char inc_filename[512]; /* filename specified by the user */
293 char filename[1024]; /* current filename - here to simplify code */
294 unsigned char buffer[IO_BUF_SIZE + 1]; /* extra size for CH_EOB char */
295 } BufferedFile;
297 #define CH_EOB '\\' /* end of buffer or '\0' char in file */
298 #define CH_EOF (-1) /* end of file */
300 /* parsing state (used to save parser state to reparse part of the
301 source several times) */
302 typedef struct ParseState {
303 int *macro_ptr;
304 int line_num;
305 int tok;
306 CValue tokc;
307 } ParseState;
309 /* used to record tokens */
310 typedef struct TokenString {
311 int *str;
312 int len;
313 int allocated_len;
314 int last_line_num;
315 } TokenString;
317 /* include file cache, used to find files faster and also to eliminate
318 inclusion if the include file is protected by #ifndef ... #endif */
319 typedef struct CachedInclude {
320 int ifndef_macro;
321 int hash_next; /* -1 if none */
322 char type; /* '"' or '>' to give include type */
323 char filename[1]; /* path specified in #include */
324 } CachedInclude;
326 #define CACHED_INCLUDES_HASH_SIZE 512
328 /* parser */
329 static struct BufferedFile *file;
330 static int ch, tok;
331 static CValue tokc;
332 static CString tokcstr; /* current parsed string, if any */
333 /* additional informations about token */
334 static int tok_flags;
335 #define TOK_FLAG_BOL 0x0001 /* beginning of line before */
336 #define TOK_FLAG_BOF 0x0002 /* beginning of file before */
337 #define TOK_FLAG_ENDIF 0x0004 /* a endif was found matching starting #ifdef */
338 #define TOK_FLAG_EOF 0x0008 /* end of file */
340 static int *macro_ptr, *macro_ptr_allocated;
341 static int *unget_saved_macro_ptr;
342 static int unget_saved_buffer[TOK_MAX_SIZE + 1];
343 static int unget_buffer_enabled;
344 static int parse_flags;
345 #define PARSE_FLAG_PREPROCESS 0x0001 /* activate preprocessing */
346 #define PARSE_FLAG_TOK_NUM 0x0002 /* return numbers instead of TOK_PPNUM */
347 #define PARSE_FLAG_LINEFEED 0x0004 /* line feed is returned as a
348 token. line feed is also
349 returned at eof */
350 #define PARSE_FLAG_ASM_COMMENTS 0x0008 /* '#' can be used for line comment */
352 static Section *text_section, *data_section, *bss_section; /* predefined sections */
353 static Section *cur_text_section; /* current section where function code is
354 generated */
355 #ifdef CONFIG_TCC_ASM
356 static Section *last_text_section; /* to handle .previous asm directive */
357 #endif
358 /* bound check related sections */
359 static Section *bounds_section; /* contains global data bound description */
360 static Section *lbounds_section; /* contains local data bound description */
361 /* symbol sections */
362 static Section *symtab_section, *strtab_section;
364 /* debug sections */
365 static Section *stab_section, *stabstr_section;
367 /* loc : local variable index
368 ind : output code index
369 rsym: return symbol
370 anon_sym: anonymous symbol index
372 static int rsym, anon_sym, ind, loc;
373 /* expression generation modifiers */
374 static int const_wanted; /* true if constant wanted */
375 static int nocode_wanted; /* true if no code generation wanted for an expression */
376 static int global_expr; /* true if compound literals must be allocated
377 globally (used during initializers parsing */
378 static CType func_vt; /* current function return type (used by return
379 instruction) */
380 static int func_vc;
381 static int last_line_num, last_ind, func_ind; /* debug last line number and pc */
382 static int tok_ident;
383 static TokenSym **table_ident;
384 static TokenSym *hash_ident[TOK_HASH_SIZE];
385 static char token_buf[STRING_MAX_SIZE + 1];
386 static char *funcname;
387 static Sym *global_stack, *local_stack;
388 static Sym *define_stack;
389 static Sym *global_label_stack, *local_label_stack;
390 /* symbol allocator */
391 #define SYM_POOL_NB (8192 / sizeof(Sym))
392 static Sym *sym_free_first;
394 static SValue vstack[VSTACK_SIZE], *vtop;
395 /* some predefined types */
396 static CType char_pointer_type, func_old_type, int_type;
397 /* true if isid(c) || isnum(c) */
398 static unsigned char isidnum_table[256];
400 /* display some information during compilation */
401 static int verbose = 0;
403 /* compile with debug symbol (and use them if error during execution) */
404 static int do_debug = 0;
406 /* compile with built-in memory and bounds checker */
407 static int do_bounds_check = 0;
409 /* display benchmark infos */
410 #if !defined(LIBTCC)
411 static int do_bench = 0;
412 #endif
413 static int total_lines;
414 static int total_bytes;
416 /* use GNU C extensions */
417 static int gnu_ext = 1;
419 /* use Tiny C extensions */
420 static int tcc_ext = 1;
422 /* max number of callers shown if error */
423 static int num_callers = 6;
424 static const char **rt_bound_error_msg;
426 /* XXX: get rid of this ASAP */
427 static struct TCCState *tcc_state;
429 /* give the path of the tcc libraries */
430 static const char *tcc_lib_path = CONFIG_TCCDIR;
432 struct TCCState {
433 int output_type;
435 BufferedFile **include_stack_ptr;
436 int *ifdef_stack_ptr;
438 /* include file handling */
439 char **include_paths;
440 int nb_include_paths;
441 char **sysinclude_paths;
442 int nb_sysinclude_paths;
443 CachedInclude **cached_includes;
444 int nb_cached_includes;
446 char **library_paths;
447 int nb_library_paths;
449 /* array of all loaded dlls (including those referenced by loaded
450 dlls) */
451 DLLReference **loaded_dlls;
452 int nb_loaded_dlls;
454 /* sections */
455 Section **sections;
456 int nb_sections; /* number of sections, including first dummy section */
458 /* got handling */
459 Section *got;
460 Section *plt;
461 unsigned long *got_offsets;
462 int nb_got_offsets;
463 /* give the correspondance from symtab indexes to dynsym indexes */
464 int *symtab_to_dynsym;
466 /* temporary dynamic symbol sections (for dll loading) */
467 Section *dynsymtab_section;
468 /* exported dynamic symbol section */
469 Section *dynsym;
471 int nostdinc; /* if true, no standard headers are added */
472 int nostdlib; /* if true, no standard libraries are added */
474 int nocommon; /* if true, do not use common symbols for .bss data */
476 /* if true, static linking is performed */
477 int static_link;
479 /* if true, all symbols are exported */
480 int rdynamic;
482 /* if true, only link in referenced objects from archive */
483 int alacarte_link;
485 /* address of text section */
486 unsigned long text_addr;
487 int has_text_addr;
489 /* output format, see TCC_OUTPUT_FORMAT_xxx */
490 int output_format;
492 /* C language options */
493 int char_is_unsigned;
494 int leading_underscore;
496 /* warning switches */
497 int warn_write_strings;
498 int warn_unsupported;
499 int warn_error;
500 int warn_none;
501 int warn_implicit_function_declaration;
503 /* error handling */
504 void *error_opaque;
505 void (*error_func)(void *opaque, const char *msg);
506 int error_set_jmp_enabled;
507 jmp_buf error_jmp_buf;
508 int nb_errors;
510 /* tiny assembler state */
511 Sym *asm_labels;
513 /* see include_stack_ptr */
514 BufferedFile *include_stack[INCLUDE_STACK_SIZE];
516 /* see ifdef_stack_ptr */
517 int ifdef_stack[IFDEF_STACK_SIZE];
519 /* see cached_includes */
520 int cached_includes_hash[CACHED_INCLUDES_HASH_SIZE];
522 /* pack stack */
523 int pack_stack[PACK_STACK_SIZE];
524 int *pack_stack_ptr;
526 /* output file for preprocessing */
527 FILE *outfile;
530 /* The current value can be: */
531 #define VT_VALMASK 0x00ff
532 #define VT_CONST 0x00f0 /* constant in vc
533 (must be first non register value) */
534 #define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */
535 #define VT_LOCAL 0x00f2 /* offset on stack */
536 #define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */
537 #define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */
538 #define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */
539 #define VT_LVAL 0x0100 /* var is an lvalue */
540 #define VT_SYM 0x0200 /* a symbol value is added */
541 #define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for
542 char/short stored in integer registers) */
543 #define VT_MUSTBOUND 0x0800 /* bound checking must be done before
544 dereferencing value */
545 #define VT_BOUNDED 0x8000 /* value is bounded. The address of the
546 bounding function call point is in vc */
547 #define VT_LVAL_BYTE 0x1000 /* lvalue is a byte */
548 #define VT_LVAL_SHORT 0x2000 /* lvalue is a short */
549 #define VT_LVAL_UNSIGNED 0x4000 /* lvalue is unsigned */
550 #define VT_LVAL_TYPE (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)
552 /* types */
553 #define VT_INT 0 /* integer type */
554 #define VT_BYTE 1 /* signed byte type */
555 #define VT_SHORT 2 /* short type */
556 #define VT_VOID 3 /* void type */
557 #define VT_PTR 4 /* pointer */
558 #define VT_ENUM 5 /* enum definition */
559 #define VT_FUNC 6 /* function type */
560 #define VT_STRUCT 7 /* struct/union definition */
561 #define VT_FLOAT 8 /* IEEE float */
562 #define VT_DOUBLE 9 /* IEEE double */
563 #define VT_LDOUBLE 10 /* IEEE long double */
564 #define VT_BOOL 11 /* ISOC99 boolean type */
565 #define VT_LLONG 12 /* 64 bit integer */
566 #define VT_LONG 13 /* long integer (NEVER USED as type, only
567 during parsing) */
568 #define VT_BTYPE 0x000f /* mask for basic type */
569 #define VT_UNSIGNED 0x0010 /* unsigned type */
570 #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
571 #define VT_BITFIELD 0x0040 /* bitfield modifier */
572 #define VT_CONSTANT 0x0800 /* const modifier */
573 #define VT_VOLATILE 0x1000 /* volatile modifier */
574 #define VT_SIGNED 0x2000 /* signed type */
576 /* storage */
577 #define VT_EXTERN 0x00000080 /* extern definition */
578 #define VT_STATIC 0x00000100 /* static variable */
579 #define VT_TYPEDEF 0x00000200 /* typedef definition */
580 #define VT_INLINE 0x00000400 /* inline definition */
582 #define VT_STRUCT_SHIFT 16 /* shift for bitfield shift values */
584 /* type mask (except storage) */
585 #define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE)
586 #define VT_TYPE (~(VT_STORAGE))
588 /* token values */
590 /* warning: the following compare tokens depend on i386 asm code */
591 #define TOK_ULT 0x92
592 #define TOK_UGE 0x93
593 #define TOK_EQ 0x94
594 #define TOK_NE 0x95
595 #define TOK_ULE 0x96
596 #define TOK_UGT 0x97
597 #define TOK_Nset 0x98
598 #define TOK_Nclear 0x99
599 #define TOK_LT 0x9c
600 #define TOK_GE 0x9d
601 #define TOK_LE 0x9e
602 #define TOK_GT 0x9f
604 #define TOK_LAND 0xa0
605 #define TOK_LOR 0xa1
607 #define TOK_DEC 0xa2
608 #define TOK_MID 0xa3 /* inc/dec, to void constant */
609 #define TOK_INC 0xa4
610 #define TOK_UDIV 0xb0 /* unsigned division */
611 #define TOK_UMOD 0xb1 /* unsigned modulo */
612 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
613 #define TOK_CINT 0xb3 /* number in tokc */
614 #define TOK_CCHAR 0xb4 /* char constant in tokc */
615 #define TOK_STR 0xb5 /* pointer to string in tokc */
616 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
617 #define TOK_LCHAR 0xb7
618 #define TOK_LSTR 0xb8
619 #define TOK_CFLOAT 0xb9 /* float constant */
620 #define TOK_LINENUM 0xba /* line number info */
621 #define TOK_CDOUBLE 0xc0 /* double constant */
622 #define TOK_CLDOUBLE 0xc1 /* long double constant */
623 #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
624 #define TOK_ADDC1 0xc3 /* add with carry generation */
625 #define TOK_ADDC2 0xc4 /* add with carry use */
626 #define TOK_SUBC1 0xc5 /* add with carry generation */
627 #define TOK_SUBC2 0xc6 /* add with carry use */
628 #define TOK_CUINT 0xc8 /* unsigned int constant */
629 #define TOK_CLLONG 0xc9 /* long long constant */
630 #define TOK_CULLONG 0xca /* unsigned long long constant */
631 #define TOK_ARROW 0xcb
632 #define TOK_DOTS 0xcc /* three dots */
633 #define TOK_SHR 0xcd /* unsigned shift right */
634 #define TOK_PPNUM 0xce /* preprocessor number */
636 #define TOK_SHL 0x01 /* shift left */
637 #define TOK_SAR 0x02 /* signed shift right */
639 /* assignement operators : normal operator or 0x80 */
640 #define TOK_A_MOD 0xa5
641 #define TOK_A_AND 0xa6
642 #define TOK_A_MUL 0xaa
643 #define TOK_A_ADD 0xab
644 #define TOK_A_SUB 0xad
645 #define TOK_A_DIV 0xaf
646 #define TOK_A_XOR 0xde
647 #define TOK_A_OR 0xfc
648 #define TOK_A_SHL 0x81
649 #define TOK_A_SAR 0x82
651 #ifndef offsetof
652 #define offsetof(type, field) ((size_t) &((type *)0)->field)
653 #endif
655 #ifndef countof
656 #define countof(tab) (sizeof(tab) / sizeof((tab)[0]))
657 #endif
659 /* WARNING: the content of this string encodes token numbers */
660 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";
662 #define TOK_EOF (-1) /* end of file */
663 #define TOK_LINEFEED 10 /* line feed */
665 /* all identificators and strings have token above that */
666 #define TOK_IDENT 256
668 /* only used for i386 asm opcodes definitions */
669 #define DEF_ASM(x) DEF(TOK_ASM_ ## x, #x)
671 #define DEF_BWL(x) \
672 DEF(TOK_ASM_ ## x ## b, #x "b") \
673 DEF(TOK_ASM_ ## x ## w, #x "w") \
674 DEF(TOK_ASM_ ## x ## l, #x "l") \
675 DEF(TOK_ASM_ ## x, #x)
677 #define DEF_WL(x) \
678 DEF(TOK_ASM_ ## x ## w, #x "w") \
679 DEF(TOK_ASM_ ## x ## l, #x "l") \
680 DEF(TOK_ASM_ ## x, #x)
682 #define DEF_FP1(x) \
683 DEF(TOK_ASM_ ## f ## x ## s, "f" #x "s") \
684 DEF(TOK_ASM_ ## fi ## x ## l, "fi" #x "l") \
685 DEF(TOK_ASM_ ## f ## x ## l, "f" #x "l") \
686 DEF(TOK_ASM_ ## fi ## x ## s, "fi" #x "s")
688 #define DEF_FP(x) \
689 DEF(TOK_ASM_ ## f ## x, "f" #x ) \
690 DEF(TOK_ASM_ ## f ## x ## p, "f" #x "p") \
691 DEF_FP1(x)
693 #define DEF_ASMTEST(x) \
694 DEF_ASM(x ## o) \
695 DEF_ASM(x ## no) \
696 DEF_ASM(x ## b) \
697 DEF_ASM(x ## c) \
698 DEF_ASM(x ## nae) \
699 DEF_ASM(x ## nb) \
700 DEF_ASM(x ## nc) \
701 DEF_ASM(x ## ae) \
702 DEF_ASM(x ## e) \
703 DEF_ASM(x ## z) \
704 DEF_ASM(x ## ne) \
705 DEF_ASM(x ## nz) \
706 DEF_ASM(x ## be) \
707 DEF_ASM(x ## na) \
708 DEF_ASM(x ## nbe) \
709 DEF_ASM(x ## a) \
710 DEF_ASM(x ## s) \
711 DEF_ASM(x ## ns) \
712 DEF_ASM(x ## p) \
713 DEF_ASM(x ## pe) \
714 DEF_ASM(x ## np) \
715 DEF_ASM(x ## po) \
716 DEF_ASM(x ## l) \
717 DEF_ASM(x ## nge) \
718 DEF_ASM(x ## nl) \
719 DEF_ASM(x ## ge) \
720 DEF_ASM(x ## le) \
721 DEF_ASM(x ## ng) \
722 DEF_ASM(x ## nle) \
723 DEF_ASM(x ## g)
725 #define TOK_ASM_int TOK_INT
727 enum tcc_token {
728 TOK_LAST = TOK_IDENT - 1,
729 #define DEF(id, str) id,
730 #include "tcctok.h"
731 #undef DEF
734 static const char tcc_keywords[] =
735 #define DEF(id, str) str "\0"
736 #include "tcctok.h"
737 #undef DEF
740 #define TOK_UIDENT TOK_DEFINE
742 #ifdef _WIN32
743 #define snprintf _snprintf
744 #define vsnprintf _vsnprintf
745 #ifndef __GNUC__
746 #define strtold (long double)strtod
747 #define strtof (float)strtod
748 #define strtoll (long long)strtol
749 #endif
750 #elif defined(TCC_UCLIBC) || defined(__FreeBSD__) || defined(__DragonFly__) \
751 || defined(__OpenBSD__)
752 /* currently incorrect */
753 long double strtold(const char *nptr, char **endptr)
755 return (long double)strtod(nptr, endptr);
757 float strtof(const char *nptr, char **endptr)
759 return (float)strtod(nptr, endptr);
761 #else
762 /* XXX: need to define this to use them in non ISOC99 context */
763 extern float strtof (const char *__nptr, char **__endptr);
764 extern long double strtold (const char *__nptr, char **__endptr);
765 #endif
767 static char *pstrcpy(char *buf, int buf_size, const char *s);
768 static char *pstrcat(char *buf, int buf_size, const char *s);
769 static char *tcc_basename(const char *name);
770 static char *tcc_fileextension (const char *p);
772 static void next(void);
773 static void next_nomacro(void);
774 static void parse_expr_type(CType *type);
775 static void expr_type(CType *type);
776 static void unary_type(CType *type);
777 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
778 int case_reg, int is_expr);
779 static int expr_const(void);
780 static void expr_eq(void);
781 static void gexpr(void);
782 static void gen_inline_functions(void);
783 static void decl(int l);
784 static void decl_initializer(CType *type, Section *sec, unsigned long c,
785 int first, int size_only);
786 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
787 int has_init, int v, int scope);
788 int gv(int rc);
789 void gv2(int rc1, int rc2);
790 void move_reg(int r, int s);
791 void save_regs(int n);
792 void save_reg(int r);
793 void vpop(void);
794 void vswap(void);
795 void vdup(void);
796 int get_reg(int rc);
797 int get_reg_ex(int rc,int rc2);
799 struct macro_level {
800 struct macro_level *prev;
801 int *p;
804 static void macro_subst(TokenString *tok_str, Sym **nested_list,
805 const int *macro_str, struct macro_level **can_read_stream);
806 void gen_op(int op);
807 void force_charshort_cast(int t);
808 static void gen_cast(CType *type);
809 void vstore(void);
810 static Sym *sym_find(int v);
811 static Sym *sym_push(int v, CType *type, int r, int c);
813 /* type handling */
814 static int type_size(CType *type, int *a);
815 static inline CType *pointed_type(CType *type);
816 static int pointed_size(CType *type);
817 static int lvalue_type(int t);
818 static int parse_btype(CType *type, AttributeDef *ad);
819 static void type_decl(CType *type, AttributeDef *ad, int *v, int td);
820 static int compare_types(CType *type1, CType *type2, int unqualified);
821 static int is_compatible_types(CType *type1, CType *type2);
822 static int is_compatible_parameter_types(CType *type1, CType *type2);
824 int ieee_finite(double d);
825 void error(const char *fmt, ...);
826 void vpushi(int v);
827 void vrott(int n);
828 void vnrott(int n);
829 void lexpand_nr(void);
830 static void vpush_global_sym(CType *type, int v);
831 void vset(CType *type, int r, int v);
832 void type_to_str(char *buf, int buf_size,
833 CType *type, const char *varstr);
834 char *get_tok_str(int v, CValue *cv);
835 static Sym *get_sym_ref(CType *type, Section *sec,
836 unsigned long offset, unsigned long size);
837 static Sym *external_global_sym(int v, CType *type, int r);
839 /* section generation */
840 static void section_realloc(Section *sec, unsigned long new_size);
841 static void *section_ptr_add(Section *sec, unsigned long size);
842 static void put_extern_sym(Sym *sym, Section *section,
843 unsigned long value, unsigned long size);
844 static void greloc(Section *s, Sym *sym, unsigned long addr, int type);
845 static int put_elf_str(Section *s, const char *sym);
846 static int put_elf_sym(Section *s,
847 unsigned long value, unsigned long size,
848 int info, int other, int shndx, const char *name);
849 static int add_elf_sym(Section *s, unsigned long value, unsigned long size,
850 int info, int other, int sh_num, const char *name);
851 static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
852 int type, int symbol);
853 static void put_stabs(const char *str, int type, int other, int desc,
854 unsigned long value);
855 static void put_stabs_r(const char *str, int type, int other, int desc,
856 unsigned long value, Section *sec, int sym_index);
857 static void put_stabn(int type, int other, int desc, int value);
858 static void put_stabd(int type, int other, int desc);
859 static int tcc_add_dll(TCCState *s, const char *filename, int flags);
861 #define AFF_PRINT_ERROR 0x0001 /* print error if file not found */
862 #define AFF_REFERENCED_DLL 0x0002 /* load a referenced dll from another dll */
863 #define AFF_PREPROCESS 0x0004 /* preprocess file */
864 static int tcc_add_file_internal(TCCState *s, const char *filename, int flags);
866 /* tcccoff.c */
867 int tcc_output_coff(TCCState *s1, FILE *f);
869 /* tccpe.c */
870 void *resolve_sym(TCCState *s1, const char *sym, int type);
871 int pe_load_def_file(struct TCCState *s1, int fd);
872 int pe_test_res_file(void *v, int size);
873 int pe_load_res_file(struct TCCState *s1, int fd);
874 void pe_add_runtime(struct TCCState *s1);
875 void pe_guess_outfile(char *objfilename, int output_type);
876 int pe_output_file(struct TCCState *s1, const char *filename);
878 /* tccasm.c */
880 #ifdef CONFIG_TCC_ASM
882 typedef struct ExprValue {
883 uint32_t v;
884 Sym *sym;
885 } ExprValue;
887 #define MAX_ASM_OPERANDS 30
889 typedef struct ASMOperand {
890 int id; /* GCC 3 optionnal identifier (0 if number only supported */
891 char *constraint;
892 char asm_str[16]; /* computed asm string for operand */
893 SValue *vt; /* C value of the expression */
894 int ref_index; /* if >= 0, gives reference to a output constraint */
895 int input_index; /* if >= 0, gives reference to an input constraint */
896 int priority; /* priority, used to assign registers */
897 int reg; /* if >= 0, register number used for this operand */
898 int is_llong; /* true if double register value */
899 int is_memory; /* true if memory operand */
900 int is_rw; /* for '+' modifier */
901 } ASMOperand;
903 static void asm_expr(TCCState *s1, ExprValue *pe);
904 static int asm_int_expr(TCCState *s1);
905 static int find_constraint(ASMOperand *operands, int nb_operands,
906 const char *name, const char **pp);
908 static int tcc_assemble(TCCState *s1, int do_preprocess);
910 #endif
912 static void asm_instr(void);
913 static void asm_global_instr(void);
915 /* true if float/double/long double type */
916 static inline int is_float(int t)
918 int bt;
919 bt = t & VT_BTYPE;
920 return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT;
923 #ifdef TCC_TARGET_I386
924 #include "i386-gen.c"
925 #endif
927 #ifdef TCC_TARGET_ARM
928 #include "arm-gen.c"
929 #endif
931 #ifdef TCC_TARGET_C67
932 #include "c67-gen.c"
933 #endif
935 #ifdef CONFIG_TCC_STATIC
937 #define RTLD_LAZY 0x001
938 #define RTLD_NOW 0x002
939 #define RTLD_GLOBAL 0x100
940 #define RTLD_DEFAULT NULL
942 /* dummy function for profiling */
943 void *dlopen(const char *filename, int flag)
945 return NULL;
948 const char *dlerror(void)
950 return "error";
953 typedef struct TCCSyms {
954 char *str;
955 void *ptr;
956 } TCCSyms;
958 #define TCCSYM(a) { #a, &a, },
960 /* add the symbol you want here if no dynamic linking is done */
961 static TCCSyms tcc_syms[] = {
962 #if !defined(CONFIG_TCCBOOT)
963 TCCSYM(printf)
964 TCCSYM(fprintf)
965 TCCSYM(fopen)
966 TCCSYM(fclose)
967 #endif
968 { NULL, NULL },
971 void *resolve_sym(TCCState *s1, const char *symbol, int type)
973 TCCSyms *p;
974 p = tcc_syms;
975 while (p->str != NULL) {
976 if (!strcmp(p->str, symbol))
977 return p->ptr;
978 p++;
980 return NULL;
983 #elif !defined(_WIN32)
985 #include <dlfcn.h>
987 void *resolve_sym(TCCState *s1, const char *sym, int type)
989 return dlsym(RTLD_DEFAULT, sym);
992 #endif
994 /********************************************************/
996 /* we use our own 'finite' function to avoid potential problems with
997 non standard math libs */
998 /* XXX: endianness dependent */
999 int ieee_finite(double d)
1001 int *p = (int *)&d;
1002 return ((unsigned)((p[1] | 0x800fffff) + 1)) >> 31;
1005 /* copy a string and truncate it. */
1006 static char *pstrcpy(char *buf, int buf_size, const char *s)
1008 char *q, *q_end;
1009 int c;
1011 if (buf_size > 0) {
1012 q = buf;
1013 q_end = buf + buf_size - 1;
1014 while (q < q_end) {
1015 c = *s++;
1016 if (c == '\0')
1017 break;
1018 *q++ = c;
1020 *q = '\0';
1022 return buf;
1025 /* strcat and truncate. */
1026 static char *pstrcat(char *buf, int buf_size, const char *s)
1028 int len;
1029 len = strlen(buf);
1030 if (len < buf_size)
1031 pstrcpy(buf + len, buf_size - len, s);
1032 return buf;
1035 static int strstart(const char *str, const char *val, const char **ptr)
1037 const char *p, *q;
1038 p = str;
1039 q = val;
1040 while (*q != '\0') {
1041 if (*p != *q)
1042 return 0;
1043 p++;
1044 q++;
1046 if (ptr)
1047 *ptr = p;
1048 return 1;
1051 /* extract the basename of a file */
1052 static char *tcc_basename(const char *name)
1054 char *p = strchr(name, 0);
1055 while (p > name
1056 && p[-1] != '/'
1057 #ifdef _WIN32
1058 && p[-1] != '\\'
1059 #endif
1061 --p;
1062 return p;
1065 static char *tcc_fileextension (const char *name)
1067 char *b = tcc_basename(name);
1068 char *e = strrchr(b, '.');
1069 return e ? e : strchr(b, 0);
1072 #ifdef _WIN32
1073 char *normalize_slashes(char *path)
1075 char *p;
1076 for (p = path; *p; ++p)
1077 if (*p == '\\')
1078 *p = '/';
1079 return path;
1082 char *w32_tcc_lib_path(void)
1084 /* on win32, we suppose the lib and includes are at the location
1085 of 'tcc.exe' */
1086 char path[1024], *p;
1087 GetModuleFileNameA(NULL, path, sizeof path);
1088 p = tcc_basename(normalize_slashes(strlwr(path)));
1089 if (p - 5 > path && 0 == strncmp(p - 5, "/bin/", 5))
1090 p -= 5;
1091 else if (p > path)
1092 p--;
1093 *p = 0;
1094 return strdup(path);
1096 #endif
1098 void set_pages_executable(void *ptr, unsigned long length)
1100 #ifdef _WIN32
1101 unsigned long old_protect;
1102 VirtualProtect(ptr, length, PAGE_EXECUTE_READWRITE, &old_protect);
1103 #else
1104 unsigned long start, end;
1105 start = (unsigned long)ptr & ~(PAGESIZE - 1);
1106 end = (unsigned long)ptr + length;
1107 end = (end + PAGESIZE - 1) & ~(PAGESIZE - 1);
1108 mprotect((void *)start, end - start, PROT_READ | PROT_WRITE | PROT_EXEC);
1109 #endif
1112 /* memory management */
1113 #ifdef MEM_DEBUG
1114 int mem_cur_size;
1115 int mem_max_size;
1116 #endif
1118 static inline void tcc_free(void *ptr)
1120 #ifdef MEM_DEBUG
1121 mem_cur_size -= malloc_usable_size(ptr);
1122 #endif
1123 free(ptr);
1126 static void *tcc_malloc(unsigned long size)
1128 void *ptr;
1129 ptr = malloc(size);
1130 if (!ptr && size)
1131 error("memory full");
1132 #ifdef MEM_DEBUG
1133 mem_cur_size += malloc_usable_size(ptr);
1134 if (mem_cur_size > mem_max_size)
1135 mem_max_size = mem_cur_size;
1136 #endif
1137 return ptr;
1140 static void *tcc_mallocz(unsigned long size)
1142 void *ptr;
1143 ptr = tcc_malloc(size);
1144 memset(ptr, 0, size);
1145 return ptr;
1148 static inline void *tcc_realloc(void *ptr, unsigned long size)
1150 void *ptr1;
1151 #ifdef MEM_DEBUG
1152 mem_cur_size -= malloc_usable_size(ptr);
1153 #endif
1154 ptr1 = realloc(ptr, size);
1155 #ifdef MEM_DEBUG
1156 /* NOTE: count not correct if alloc error, but not critical */
1157 mem_cur_size += malloc_usable_size(ptr1);
1158 if (mem_cur_size > mem_max_size)
1159 mem_max_size = mem_cur_size;
1160 #endif
1161 return ptr1;
1164 static char *tcc_strdup(const char *str)
1166 char *ptr;
1167 ptr = tcc_malloc(strlen(str) + 1);
1168 strcpy(ptr, str);
1169 return ptr;
1172 #define free(p) use_tcc_free(p)
1173 #define malloc(s) use_tcc_malloc(s)
1174 #define realloc(p, s) use_tcc_realloc(p, s)
1176 static void dynarray_add(void ***ptab, int *nb_ptr, void *data)
1178 int nb, nb_alloc;
1179 void **pp;
1181 nb = *nb_ptr;
1182 pp = *ptab;
1183 /* every power of two we double array size */
1184 if ((nb & (nb - 1)) == 0) {
1185 if (!nb)
1186 nb_alloc = 1;
1187 else
1188 nb_alloc = nb * 2;
1189 pp = tcc_realloc(pp, nb_alloc * sizeof(void *));
1190 if (!pp)
1191 error("memory full");
1192 *ptab = pp;
1194 pp[nb++] = data;
1195 *nb_ptr = nb;
1198 static void dynarray_reset(void *pp, int *n)
1200 void **p;
1201 for (p = *(void***)pp; *n; ++p, --*n)
1202 if (*p)
1203 tcc_free(*p);
1204 tcc_free(*(void**)pp);
1205 *(void**)pp = NULL;
1208 /* symbol allocator */
1209 static Sym *__sym_malloc(void)
1211 Sym *sym_pool, *sym, *last_sym;
1212 int i;
1214 sym_pool = tcc_malloc(SYM_POOL_NB * sizeof(Sym));
1216 last_sym = sym_free_first;
1217 sym = sym_pool;
1218 for(i = 0; i < SYM_POOL_NB; i++) {
1219 sym->next = last_sym;
1220 last_sym = sym;
1221 sym++;
1223 sym_free_first = last_sym;
1224 return last_sym;
1227 static inline Sym *sym_malloc(void)
1229 Sym *sym;
1230 sym = sym_free_first;
1231 if (!sym)
1232 sym = __sym_malloc();
1233 sym_free_first = sym->next;
1234 return sym;
1237 static inline void sym_free(Sym *sym)
1239 sym->next = sym_free_first;
1240 sym_free_first = sym;
1243 Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags)
1245 Section *sec;
1247 sec = tcc_mallocz(sizeof(Section) + strlen(name));
1248 strcpy(sec->name, name);
1249 sec->sh_type = sh_type;
1250 sec->sh_flags = sh_flags;
1251 switch(sh_type) {
1252 case SHT_HASH:
1253 case SHT_REL:
1254 case SHT_DYNSYM:
1255 case SHT_SYMTAB:
1256 case SHT_DYNAMIC:
1257 sec->sh_addralign = 4;
1258 break;
1259 case SHT_STRTAB:
1260 sec->sh_addralign = 1;
1261 break;
1262 default:
1263 sec->sh_addralign = 32; /* default conservative alignment */
1264 break;
1267 /* only add section if not private */
1268 if (!(sh_flags & SHF_PRIVATE)) {
1269 sec->sh_num = s1->nb_sections;
1270 dynarray_add((void ***)&s1->sections, &s1->nb_sections, sec);
1272 return sec;
1275 static void free_section(Section *s)
1277 tcc_free(s->data);
1278 tcc_free(s);
1281 /* realloc section and set its content to zero */
1282 static void section_realloc(Section *sec, unsigned long new_size)
1284 unsigned long size;
1285 unsigned char *data;
1287 size = sec->data_allocated;
1288 if (size == 0)
1289 size = 1;
1290 while (size < new_size)
1291 size = size * 2;
1292 data = tcc_realloc(sec->data, size);
1293 if (!data)
1294 error("memory full");
1295 memset(data + sec->data_allocated, 0, size - sec->data_allocated);
1296 sec->data = data;
1297 sec->data_allocated = size;
1300 /* reserve at least 'size' bytes in section 'sec' from
1301 sec->data_offset. */
1302 static void *section_ptr_add(Section *sec, unsigned long size)
1304 unsigned long offset, offset1;
1306 offset = sec->data_offset;
1307 offset1 = offset + size;
1308 if (offset1 > sec->data_allocated)
1309 section_realloc(sec, offset1);
1310 sec->data_offset = offset1;
1311 return sec->data + offset;
1314 /* return a reference to a section, and create it if it does not
1315 exists */
1316 Section *find_section(TCCState *s1, const char *name)
1318 Section *sec;
1319 int i;
1320 for(i = 1; i < s1->nb_sections; i++) {
1321 sec = s1->sections[i];
1322 if (!strcmp(name, sec->name))
1323 return sec;
1325 /* sections are created as PROGBITS */
1326 return new_section(s1, name, SHT_PROGBITS, SHF_ALLOC);
1329 #define SECTION_ABS ((void *)1)
1331 /* update sym->c so that it points to an external symbol in section
1332 'section' with value 'value' */
1333 static void put_extern_sym2(Sym *sym, Section *section,
1334 unsigned long value, unsigned long size,
1335 int can_add_underscore)
1337 int sym_type, sym_bind, sh_num, info, other, attr;
1338 Elf32_Sym *esym;
1339 const char *name;
1340 char buf1[256];
1342 if (section == NULL)
1343 sh_num = SHN_UNDEF;
1344 else if (section == SECTION_ABS)
1345 sh_num = SHN_ABS;
1346 else
1347 sh_num = section->sh_num;
1349 other = attr = 0;
1351 if ((sym->type.t & VT_BTYPE) == VT_FUNC) {
1352 sym_type = STT_FUNC;
1353 #ifdef TCC_TARGET_PE
1354 if (sym->type.ref)
1355 attr = sym->type.ref->r;
1356 if (FUNC_EXPORT(attr))
1357 other |= 1;
1358 if (FUNC_CALL(attr) == FUNC_STDCALL)
1359 other |= 2;
1360 #endif
1361 } else {
1362 sym_type = STT_OBJECT;
1365 if (sym->type.t & VT_STATIC)
1366 sym_bind = STB_LOCAL;
1367 else
1368 sym_bind = STB_GLOBAL;
1370 if (!sym->c) {
1371 name = get_tok_str(sym->v, NULL);
1372 #ifdef CONFIG_TCC_BCHECK
1373 if (do_bounds_check) {
1374 char buf[32];
1376 /* XXX: avoid doing that for statics ? */
1377 /* if bound checking is activated, we change some function
1378 names by adding the "__bound" prefix */
1379 switch(sym->v) {
1380 #if 0
1381 /* XXX: we rely only on malloc hooks */
1382 case TOK_malloc:
1383 case TOK_free:
1384 case TOK_realloc:
1385 case TOK_memalign:
1386 case TOK_calloc:
1387 #endif
1388 case TOK_memcpy:
1389 case TOK_memmove:
1390 case TOK_memset:
1391 case TOK_strlen:
1392 case TOK_strcpy:
1393 case TOK__alloca:
1394 strcpy(buf, "__bound_");
1395 strcat(buf, name);
1396 name = buf;
1397 break;
1400 #endif
1402 #ifdef TCC_TARGET_PE
1403 if ((other & 2) && can_add_underscore) {
1404 sprintf(buf1, "_%s@%d", name, FUNC_ARGS(attr));
1405 name = buf1;
1406 } else
1407 #endif
1408 if (tcc_state->leading_underscore && can_add_underscore) {
1409 buf1[0] = '_';
1410 pstrcpy(buf1 + 1, sizeof(buf1) - 1, name);
1411 name = buf1;
1413 info = ELF32_ST_INFO(sym_bind, sym_type);
1414 sym->c = add_elf_sym(symtab_section, value, size, info, other, sh_num, name);
1415 } else {
1416 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
1417 esym->st_value = value;
1418 esym->st_size = size;
1419 esym->st_shndx = sh_num;
1420 esym->st_other |= other;
1424 static void put_extern_sym(Sym *sym, Section *section,
1425 unsigned long value, unsigned long size)
1427 put_extern_sym2(sym, section, value, size, 1);
1430 /* add a new relocation entry to symbol 'sym' in section 's' */
1431 static void greloc(Section *s, Sym *sym, unsigned long offset, int type)
1433 if (!sym->c)
1434 put_extern_sym(sym, NULL, 0, 0);
1435 /* now we can add ELF relocation info */
1436 put_elf_reloc(symtab_section, s, offset, type, sym->c);
1439 static inline int isid(int c)
1441 return (c >= 'a' && c <= 'z') ||
1442 (c >= 'A' && c <= 'Z') ||
1443 c == '_';
1446 static inline int isnum(int c)
1448 return c >= '0' && c <= '9';
1451 static inline int isoct(int c)
1453 return c >= '0' && c <= '7';
1456 static inline int toup(int c)
1458 if (c >= 'a' && c <= 'z')
1459 return c - 'a' + 'A';
1460 else
1461 return c;
1464 static void strcat_vprintf(char *buf, int buf_size, const char *fmt, va_list ap)
1466 int len;
1467 len = strlen(buf);
1468 vsnprintf(buf + len, buf_size - len, fmt, ap);
1471 static void strcat_printf(char *buf, int buf_size, const char *fmt, ...)
1473 va_list ap;
1474 va_start(ap, fmt);
1475 strcat_vprintf(buf, buf_size, fmt, ap);
1476 va_end(ap);
1479 void error1(TCCState *s1, int is_warning, const char *fmt, va_list ap)
1481 char buf[2048];
1482 BufferedFile **f;
1484 buf[0] = '\0';
1485 if (file) {
1486 for(f = s1->include_stack; f < s1->include_stack_ptr; f++)
1487 strcat_printf(buf, sizeof(buf), "In file included from %s:%d:\n",
1488 (*f)->filename, (*f)->line_num);
1489 if (file->line_num > 0) {
1490 strcat_printf(buf, sizeof(buf),
1491 "%s:%d: ", file->filename, file->line_num);
1492 } else {
1493 strcat_printf(buf, sizeof(buf),
1494 "%s: ", file->filename);
1496 } else {
1497 strcat_printf(buf, sizeof(buf),
1498 "tcc: ");
1500 if (is_warning)
1501 strcat_printf(buf, sizeof(buf), "warning: ");
1502 strcat_vprintf(buf, sizeof(buf), fmt, ap);
1504 if (!s1->error_func) {
1505 /* default case: stderr */
1506 fprintf(stderr, "%s\n", buf);
1507 } else {
1508 s1->error_func(s1->error_opaque, buf);
1510 if (!is_warning || s1->warn_error)
1511 s1->nb_errors++;
1514 #ifdef LIBTCC
1515 void tcc_set_error_func(TCCState *s, void *error_opaque,
1516 void (*error_func)(void *opaque, const char *msg))
1518 s->error_opaque = error_opaque;
1519 s->error_func = error_func;
1521 #endif
1523 /* error without aborting current compilation */
1524 void error_noabort(const char *fmt, ...)
1526 TCCState *s1 = tcc_state;
1527 va_list ap;
1529 va_start(ap, fmt);
1530 error1(s1, 0, fmt, ap);
1531 va_end(ap);
1534 void error(const char *fmt, ...)
1536 TCCState *s1 = tcc_state;
1537 va_list ap;
1539 va_start(ap, fmt);
1540 error1(s1, 0, fmt, ap);
1541 va_end(ap);
1542 /* better than nothing: in some cases, we accept to handle errors */
1543 if (s1->error_set_jmp_enabled) {
1544 longjmp(s1->error_jmp_buf, 1);
1545 } else {
1546 /* XXX: eliminate this someday */
1547 exit(1);
1551 void expect(const char *msg)
1553 error("%s expected", msg);
1556 void warning(const char *fmt, ...)
1558 TCCState *s1 = tcc_state;
1559 va_list ap;
1561 if (s1->warn_none)
1562 return;
1564 va_start(ap, fmt);
1565 error1(s1, 1, fmt, ap);
1566 va_end(ap);
1569 void skip(int c)
1571 if (tok != c)
1572 error("'%c' expected", c);
1573 next();
1576 static void test_lvalue(void)
1578 if (!(vtop->r & VT_LVAL))
1579 expect("lvalue");
1582 /* allocate a new token */
1583 static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len)
1585 TokenSym *ts, **ptable;
1586 int i;
1588 if (tok_ident >= SYM_FIRST_ANOM)
1589 error("memory full");
1591 /* expand token table if needed */
1592 i = tok_ident - TOK_IDENT;
1593 if ((i % TOK_ALLOC_INCR) == 0) {
1594 ptable = tcc_realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *));
1595 if (!ptable)
1596 error("memory full");
1597 table_ident = ptable;
1600 ts = tcc_malloc(sizeof(TokenSym) + len);
1601 table_ident[i] = ts;
1602 ts->tok = tok_ident++;
1603 ts->sym_define = NULL;
1604 ts->sym_label = NULL;
1605 ts->sym_struct = NULL;
1606 ts->sym_identifier = NULL;
1607 ts->len = len;
1608 ts->hash_next = NULL;
1609 memcpy(ts->str, str, len);
1610 ts->str[len] = '\0';
1611 *pts = ts;
1612 return ts;
1615 #define TOK_HASH_INIT 1
1616 #define TOK_HASH_FUNC(h, c) ((h) * 263 + (c))
1618 /* find a token and add it if not found */
1619 static TokenSym *tok_alloc(const char *str, int len)
1621 TokenSym *ts, **pts;
1622 int i;
1623 unsigned int h;
1625 h = TOK_HASH_INIT;
1626 for(i=0;i<len;i++)
1627 h = TOK_HASH_FUNC(h, ((unsigned char *)str)[i]);
1628 h &= (TOK_HASH_SIZE - 1);
1630 pts = &hash_ident[h];
1631 for(;;) {
1632 ts = *pts;
1633 if (!ts)
1634 break;
1635 if (ts->len == len && !memcmp(ts->str, str, len))
1636 return ts;
1637 pts = &(ts->hash_next);
1639 return tok_alloc_new(pts, str, len);
1642 /* CString handling */
1644 static void cstr_realloc(CString *cstr, int new_size)
1646 int size;
1647 void *data;
1649 size = cstr->size_allocated;
1650 if (size == 0)
1651 size = 8; /* no need to allocate a too small first string */
1652 while (size < new_size)
1653 size = size * 2;
1654 data = tcc_realloc(cstr->data_allocated, size);
1655 if (!data)
1656 error("memory full");
1657 cstr->data_allocated = data;
1658 cstr->size_allocated = size;
1659 cstr->data = data;
1662 /* add a byte */
1663 static inline void cstr_ccat(CString *cstr, int ch)
1665 int size;
1666 size = cstr->size + 1;
1667 if (size > cstr->size_allocated)
1668 cstr_realloc(cstr, size);
1669 ((unsigned char *)cstr->data)[size - 1] = ch;
1670 cstr->size = size;
1673 static void cstr_cat(CString *cstr, const char *str)
1675 int c;
1676 for(;;) {
1677 c = *str;
1678 if (c == '\0')
1679 break;
1680 cstr_ccat(cstr, c);
1681 str++;
1685 /* add a wide char */
1686 static void cstr_wccat(CString *cstr, int ch)
1688 int size;
1689 size = cstr->size + sizeof(nwchar_t);
1690 if (size > cstr->size_allocated)
1691 cstr_realloc(cstr, size);
1692 *(nwchar_t *)(((unsigned char *)cstr->data) + size - sizeof(nwchar_t)) = ch;
1693 cstr->size = size;
1696 static void cstr_new(CString *cstr)
1698 memset(cstr, 0, sizeof(CString));
1701 /* free string and reset it to NULL */
1702 static void cstr_free(CString *cstr)
1704 tcc_free(cstr->data_allocated);
1705 cstr_new(cstr);
1708 #define cstr_reset(cstr) cstr_free(cstr)
1710 /* XXX: unicode ? */
1711 static void add_char(CString *cstr, int c)
1713 if (c == '\'' || c == '\"' || c == '\\') {
1714 /* XXX: could be more precise if char or string */
1715 cstr_ccat(cstr, '\\');
1717 if (c >= 32 && c <= 126) {
1718 cstr_ccat(cstr, c);
1719 } else {
1720 cstr_ccat(cstr, '\\');
1721 if (c == '\n') {
1722 cstr_ccat(cstr, 'n');
1723 } else {
1724 cstr_ccat(cstr, '0' + ((c >> 6) & 7));
1725 cstr_ccat(cstr, '0' + ((c >> 3) & 7));
1726 cstr_ccat(cstr, '0' + (c & 7));
1731 /* XXX: buffer overflow */
1732 /* XXX: float tokens */
1733 char *get_tok_str(int v, CValue *cv)
1735 static char buf[STRING_MAX_SIZE + 1];
1736 static CString cstr_buf;
1737 CString *cstr;
1738 unsigned char *q;
1739 char *p;
1740 int i, len;
1742 /* NOTE: to go faster, we give a fixed buffer for small strings */
1743 cstr_reset(&cstr_buf);
1744 cstr_buf.data = buf;
1745 cstr_buf.size_allocated = sizeof(buf);
1746 p = buf;
1748 switch(v) {
1749 case TOK_CINT:
1750 case TOK_CUINT:
1751 /* XXX: not quite exact, but only useful for testing */
1752 sprintf(p, "%u", cv->ui);
1753 break;
1754 case TOK_CLLONG:
1755 case TOK_CULLONG:
1756 /* XXX: not quite exact, but only useful for testing */
1757 sprintf(p, "%Lu", cv->ull);
1758 break;
1759 case TOK_CCHAR:
1760 case TOK_LCHAR:
1761 cstr_ccat(&cstr_buf, '\'');
1762 add_char(&cstr_buf, cv->i);
1763 cstr_ccat(&cstr_buf, '\'');
1764 cstr_ccat(&cstr_buf, '\0');
1765 break;
1766 case TOK_PPNUM:
1767 cstr = cv->cstr;
1768 len = cstr->size - 1;
1769 for(i=0;i<len;i++)
1770 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1771 cstr_ccat(&cstr_buf, '\0');
1772 break;
1773 case TOK_STR:
1774 case TOK_LSTR:
1775 cstr = cv->cstr;
1776 cstr_ccat(&cstr_buf, '\"');
1777 if (v == TOK_STR) {
1778 len = cstr->size - 1;
1779 for(i=0;i<len;i++)
1780 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1781 } else {
1782 len = (cstr->size / sizeof(nwchar_t)) - 1;
1783 for(i=0;i<len;i++)
1784 add_char(&cstr_buf, ((nwchar_t *)cstr->data)[i]);
1786 cstr_ccat(&cstr_buf, '\"');
1787 cstr_ccat(&cstr_buf, '\0');
1788 break;
1789 case TOK_LT:
1790 v = '<';
1791 goto addv;
1792 case TOK_GT:
1793 v = '>';
1794 goto addv;
1795 case TOK_DOTS:
1796 return strcpy(p, "...");
1797 case TOK_A_SHL:
1798 return strcpy(p, "<<=");
1799 case TOK_A_SAR:
1800 return strcpy(p, ">>=");
1801 default:
1802 if (v < TOK_IDENT) {
1803 /* search in two bytes table */
1804 q = tok_two_chars;
1805 while (*q) {
1806 if (q[2] == v) {
1807 *p++ = q[0];
1808 *p++ = q[1];
1809 *p = '\0';
1810 return buf;
1812 q += 3;
1814 addv:
1815 *p++ = v;
1816 *p = '\0';
1817 } else if (v < tok_ident) {
1818 return table_ident[v - TOK_IDENT]->str;
1819 } else if (v >= SYM_FIRST_ANOM) {
1820 /* special name for anonymous symbol */
1821 sprintf(p, "L.%u", v - SYM_FIRST_ANOM);
1822 } else {
1823 /* should never happen */
1824 return NULL;
1826 break;
1828 return cstr_buf.data;
1831 /* push, without hashing */
1832 static Sym *sym_push2(Sym **ps, int v, int t, int c)
1834 Sym *s;
1835 s = sym_malloc();
1836 s->v = v;
1837 s->type.t = t;
1838 s->c = c;
1839 s->next = NULL;
1840 /* add in stack */
1841 s->prev = *ps;
1842 *ps = s;
1843 return s;
1846 /* find a symbol and return its associated structure. 's' is the top
1847 of the symbol stack */
1848 static Sym *sym_find2(Sym *s, int v)
1850 while (s) {
1851 if (s->v == v)
1852 return s;
1853 s = s->prev;
1855 return NULL;
1858 /* structure lookup */
1859 static inline Sym *struct_find(int v)
1861 v -= TOK_IDENT;
1862 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1863 return NULL;
1864 return table_ident[v]->sym_struct;
1867 /* find an identifier */
1868 static inline Sym *sym_find(int v)
1870 v -= TOK_IDENT;
1871 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1872 return NULL;
1873 return table_ident[v]->sym_identifier;
1876 /* push a given symbol on the symbol stack */
1877 static Sym *sym_push(int v, CType *type, int r, int c)
1879 Sym *s, **ps;
1880 TokenSym *ts;
1882 if (local_stack)
1883 ps = &local_stack;
1884 else
1885 ps = &global_stack;
1886 s = sym_push2(ps, v, type->t, c);
1887 s->type.ref = type->ref;
1888 s->r = r;
1889 /* don't record fields or anonymous symbols */
1890 /* XXX: simplify */
1891 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1892 /* record symbol in token array */
1893 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1894 if (v & SYM_STRUCT)
1895 ps = &ts->sym_struct;
1896 else
1897 ps = &ts->sym_identifier;
1898 s->prev_tok = *ps;
1899 *ps = s;
1901 return s;
1904 /* push a global identifier */
1905 static Sym *global_identifier_push(int v, int t, int c)
1907 Sym *s, **ps;
1908 s = sym_push2(&global_stack, v, t, c);
1909 /* don't record anonymous symbol */
1910 if (v < SYM_FIRST_ANOM) {
1911 ps = &table_ident[v - TOK_IDENT]->sym_identifier;
1912 /* modify the top most local identifier, so that
1913 sym_identifier will point to 's' when popped */
1914 while (*ps != NULL)
1915 ps = &(*ps)->prev_tok;
1916 s->prev_tok = NULL;
1917 *ps = s;
1919 return s;
1922 /* pop symbols until top reaches 'b' */
1923 static void sym_pop(Sym **ptop, Sym *b)
1925 Sym *s, *ss, **ps;
1926 TokenSym *ts;
1927 int v;
1929 s = *ptop;
1930 while(s != b) {
1931 ss = s->prev;
1932 v = s->v;
1933 /* remove symbol in token array */
1934 /* XXX: simplify */
1935 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1936 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1937 if (v & SYM_STRUCT)
1938 ps = &ts->sym_struct;
1939 else
1940 ps = &ts->sym_identifier;
1941 *ps = s->prev_tok;
1943 sym_free(s);
1944 s = ss;
1946 *ptop = b;
1949 /* I/O layer */
1951 BufferedFile *tcc_open(TCCState *s1, const char *filename)
1953 int fd;
1954 BufferedFile *bf;
1956 fd = open(filename, O_RDONLY | O_BINARY);
1957 if (fd < 0)
1958 return NULL;
1959 bf = tcc_malloc(sizeof(BufferedFile));
1960 if (!bf) {
1961 close(fd);
1962 return NULL;
1964 bf->fd = fd;
1965 bf->buf_ptr = bf->buffer;
1966 bf->buf_end = bf->buffer;
1967 bf->buffer[0] = CH_EOB; /* put eob symbol */
1968 pstrcpy(bf->filename, sizeof(bf->filename), filename);
1969 #ifdef _WIN32
1970 normalize_slashes(bf->filename);
1971 #endif
1972 bf->line_num = 1;
1973 bf->ifndef_macro = 0;
1974 bf->ifdef_stack_ptr = s1->ifdef_stack_ptr;
1975 // printf("opening '%s'\n", filename);
1976 return bf;
1979 void tcc_close(BufferedFile *bf)
1981 total_lines += bf->line_num;
1982 close(bf->fd);
1983 tcc_free(bf);
1986 /* fill input buffer and peek next char */
1987 static int tcc_peekc_slow(BufferedFile *bf)
1989 int len;
1990 /* only tries to read if really end of buffer */
1991 if (bf->buf_ptr >= bf->buf_end) {
1992 if (bf->fd != -1) {
1993 #if defined(PARSE_DEBUG)
1994 len = 8;
1995 #else
1996 len = IO_BUF_SIZE;
1997 #endif
1998 len = read(bf->fd, bf->buffer, len);
1999 if (len < 0)
2000 len = 0;
2001 } else {
2002 len = 0;
2004 total_bytes += len;
2005 bf->buf_ptr = bf->buffer;
2006 bf->buf_end = bf->buffer + len;
2007 *bf->buf_end = CH_EOB;
2009 if (bf->buf_ptr < bf->buf_end) {
2010 return bf->buf_ptr[0];
2011 } else {
2012 bf->buf_ptr = bf->buf_end;
2013 return CH_EOF;
2017 /* return the current character, handling end of block if necessary
2018 (but not stray) */
2019 static int handle_eob(void)
2021 return tcc_peekc_slow(file);
2024 /* read next char from current input file and handle end of input buffer */
2025 static inline void inp(void)
2027 ch = *(++(file->buf_ptr));
2028 /* end of buffer/file handling */
2029 if (ch == CH_EOB)
2030 ch = handle_eob();
2033 /* handle '\[\r]\n' */
2034 static int handle_stray_noerror(void)
2036 while (ch == '\\') {
2037 inp();
2038 if (ch == '\n') {
2039 file->line_num++;
2040 inp();
2041 } else if (ch == '\r') {
2042 inp();
2043 if (ch != '\n')
2044 goto fail;
2045 file->line_num++;
2046 inp();
2047 } else {
2048 fail:
2049 return 1;
2052 return 0;
2055 static void handle_stray(void)
2057 if (handle_stray_noerror())
2058 error("stray '\\' in program");
2061 /* skip the stray and handle the \\n case. Output an error if
2062 incorrect char after the stray */
2063 static int handle_stray1(uint8_t *p)
2065 int c;
2067 if (p >= file->buf_end) {
2068 file->buf_ptr = p;
2069 c = handle_eob();
2070 p = file->buf_ptr;
2071 if (c == '\\')
2072 goto parse_stray;
2073 } else {
2074 parse_stray:
2075 file->buf_ptr = p;
2076 ch = *p;
2077 handle_stray();
2078 p = file->buf_ptr;
2079 c = *p;
2081 return c;
2084 /* handle just the EOB case, but not stray */
2085 #define PEEKC_EOB(c, p)\
2087 p++;\
2088 c = *p;\
2089 if (c == '\\') {\
2090 file->buf_ptr = p;\
2091 c = handle_eob();\
2092 p = file->buf_ptr;\
2096 /* handle the complicated stray case */
2097 #define PEEKC(c, p)\
2099 p++;\
2100 c = *p;\
2101 if (c == '\\') {\
2102 c = handle_stray1(p);\
2103 p = file->buf_ptr;\
2107 /* input with '\[\r]\n' handling. Note that this function cannot
2108 handle other characters after '\', so you cannot call it inside
2109 strings or comments */
2110 static void minp(void)
2112 inp();
2113 if (ch == '\\')
2114 handle_stray();
2118 /* single line C++ comments */
2119 static uint8_t *parse_line_comment(uint8_t *p)
2121 int c;
2123 p++;
2124 for(;;) {
2125 c = *p;
2126 redo:
2127 if (c == '\n' || c == CH_EOF) {
2128 break;
2129 } else if (c == '\\') {
2130 file->buf_ptr = p;
2131 c = handle_eob();
2132 p = file->buf_ptr;
2133 if (c == '\\') {
2134 PEEKC_EOB(c, p);
2135 if (c == '\n') {
2136 file->line_num++;
2137 PEEKC_EOB(c, p);
2138 } else if (c == '\r') {
2139 PEEKC_EOB(c, p);
2140 if (c == '\n') {
2141 file->line_num++;
2142 PEEKC_EOB(c, p);
2145 } else {
2146 goto redo;
2148 } else {
2149 p++;
2152 return p;
2155 /* C comments */
2156 static uint8_t *parse_comment(uint8_t *p)
2158 int c;
2160 p++;
2161 for(;;) {
2162 /* fast skip loop */
2163 for(;;) {
2164 c = *p;
2165 if (c == '\n' || c == '*' || c == '\\')
2166 break;
2167 p++;
2168 c = *p;
2169 if (c == '\n' || c == '*' || c == '\\')
2170 break;
2171 p++;
2173 /* now we can handle all the cases */
2174 if (c == '\n') {
2175 file->line_num++;
2176 p++;
2177 } else if (c == '*') {
2178 p++;
2179 for(;;) {
2180 c = *p;
2181 if (c == '*') {
2182 p++;
2183 } else if (c == '/') {
2184 goto end_of_comment;
2185 } else if (c == '\\') {
2186 file->buf_ptr = p;
2187 c = handle_eob();
2188 p = file->buf_ptr;
2189 if (c == '\\') {
2190 /* skip '\[\r]\n', otherwise just skip the stray */
2191 while (c == '\\') {
2192 PEEKC_EOB(c, p);
2193 if (c == '\n') {
2194 file->line_num++;
2195 PEEKC_EOB(c, p);
2196 } else if (c == '\r') {
2197 PEEKC_EOB(c, p);
2198 if (c == '\n') {
2199 file->line_num++;
2200 PEEKC_EOB(c, p);
2202 } else {
2203 goto after_star;
2207 } else {
2208 break;
2211 after_star: ;
2212 } else {
2213 /* stray, eob or eof */
2214 file->buf_ptr = p;
2215 c = handle_eob();
2216 p = file->buf_ptr;
2217 if (c == CH_EOF) {
2218 error("unexpected end of file in comment");
2219 } else if (c == '\\') {
2220 p++;
2224 end_of_comment:
2225 p++;
2226 return p;
2229 #define cinp minp
2231 /* space exlcuding newline */
2232 static inline int is_space(int ch)
2234 return ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f' || ch == '\r';
2237 static inline void skip_spaces(void)
2239 while (is_space(ch))
2240 cinp();
2243 /* parse a string without interpreting escapes */
2244 static uint8_t *parse_pp_string(uint8_t *p,
2245 int sep, CString *str)
2247 int c;
2248 p++;
2249 for(;;) {
2250 c = *p;
2251 if (c == sep) {
2252 break;
2253 } else if (c == '\\') {
2254 file->buf_ptr = p;
2255 c = handle_eob();
2256 p = file->buf_ptr;
2257 if (c == CH_EOF) {
2258 unterminated_string:
2259 /* XXX: indicate line number of start of string */
2260 error("missing terminating %c character", sep);
2261 } else if (c == '\\') {
2262 /* escape : just skip \[\r]\n */
2263 PEEKC_EOB(c, p);
2264 if (c == '\n') {
2265 file->line_num++;
2266 p++;
2267 } else if (c == '\r') {
2268 PEEKC_EOB(c, p);
2269 if (c != '\n')
2270 expect("'\n' after '\r'");
2271 file->line_num++;
2272 p++;
2273 } else if (c == CH_EOF) {
2274 goto unterminated_string;
2275 } else {
2276 if (str) {
2277 cstr_ccat(str, '\\');
2278 cstr_ccat(str, c);
2280 p++;
2283 } else if (c == '\n') {
2284 file->line_num++;
2285 goto add_char;
2286 } else if (c == '\r') {
2287 PEEKC_EOB(c, p);
2288 if (c != '\n') {
2289 if (str)
2290 cstr_ccat(str, '\r');
2291 } else {
2292 file->line_num++;
2293 goto add_char;
2295 } else {
2296 add_char:
2297 if (str)
2298 cstr_ccat(str, c);
2299 p++;
2302 p++;
2303 return p;
2306 /* skip block of text until #else, #elif or #endif. skip also pairs of
2307 #if/#endif */
2308 void preprocess_skip(void)
2310 int a, start_of_line, c, in_warn_or_error;
2311 uint8_t *p;
2313 p = file->buf_ptr;
2314 a = 0;
2315 redo_start:
2316 start_of_line = 1;
2317 in_warn_or_error = 0;
2318 for(;;) {
2319 redo_no_start:
2320 c = *p;
2321 switch(c) {
2322 case ' ':
2323 case '\t':
2324 case '\f':
2325 case '\v':
2326 case '\r':
2327 p++;
2328 goto redo_no_start;
2329 case '\n':
2330 file->line_num++;
2331 p++;
2332 goto redo_start;
2333 case '\\':
2334 file->buf_ptr = p;
2335 c = handle_eob();
2336 if (c == CH_EOF) {
2337 expect("#endif");
2338 } else if (c == '\\') {
2339 ch = file->buf_ptr[0];
2340 handle_stray_noerror();
2342 p = file->buf_ptr;
2343 goto redo_no_start;
2344 /* skip strings */
2345 case '\"':
2346 case '\'':
2347 if (in_warn_or_error)
2348 goto _default;
2349 p = parse_pp_string(p, c, NULL);
2350 break;
2351 /* skip comments */
2352 case '/':
2353 if (in_warn_or_error)
2354 goto _default;
2355 file->buf_ptr = p;
2356 ch = *p;
2357 minp();
2358 p = file->buf_ptr;
2359 if (ch == '*') {
2360 p = parse_comment(p);
2361 } else if (ch == '/') {
2362 p = parse_line_comment(p);
2364 break;
2365 case '#':
2366 p++;
2367 if (start_of_line) {
2368 file->buf_ptr = p;
2369 next_nomacro();
2370 p = file->buf_ptr;
2371 if (a == 0 &&
2372 (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
2373 goto the_end;
2374 if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
2375 a++;
2376 else if (tok == TOK_ENDIF)
2377 a--;
2378 else if( tok == TOK_ERROR || tok == TOK_WARNING)
2379 in_warn_or_error = 1;
2381 break;
2382 _default:
2383 default:
2384 p++;
2385 break;
2387 start_of_line = 0;
2389 the_end: ;
2390 file->buf_ptr = p;
2393 /* ParseState handling */
2395 /* XXX: currently, no include file info is stored. Thus, we cannot display
2396 accurate messages if the function or data definition spans multiple
2397 files */
2399 /* save current parse state in 's' */
2400 void save_parse_state(ParseState *s)
2402 s->line_num = file->line_num;
2403 s->macro_ptr = macro_ptr;
2404 s->tok = tok;
2405 s->tokc = tokc;
2408 /* restore parse state from 's' */
2409 void restore_parse_state(ParseState *s)
2411 file->line_num = s->line_num;
2412 macro_ptr = s->macro_ptr;
2413 tok = s->tok;
2414 tokc = s->tokc;
2417 /* return the number of additional 'ints' necessary to store the
2418 token */
2419 static inline int tok_ext_size(int t)
2421 switch(t) {
2422 /* 4 bytes */
2423 case TOK_CINT:
2424 case TOK_CUINT:
2425 case TOK_CCHAR:
2426 case TOK_LCHAR:
2427 case TOK_CFLOAT:
2428 case TOK_LINENUM:
2429 return 1;
2430 case TOK_STR:
2431 case TOK_LSTR:
2432 case TOK_PPNUM:
2433 error("unsupported token");
2434 return 1;
2435 case TOK_CDOUBLE:
2436 case TOK_CLLONG:
2437 case TOK_CULLONG:
2438 return 2;
2439 case TOK_CLDOUBLE:
2440 return LDOUBLE_SIZE / 4;
2441 default:
2442 return 0;
2446 /* token string handling */
2448 static inline void tok_str_new(TokenString *s)
2450 s->str = NULL;
2451 s->len = 0;
2452 s->allocated_len = 0;
2453 s->last_line_num = -1;
2456 static void tok_str_free(int *str)
2458 tcc_free(str);
2461 static int *tok_str_realloc(TokenString *s)
2463 int *str, len;
2465 if (s->allocated_len == 0) {
2466 len = 8;
2467 } else {
2468 len = s->allocated_len * 2;
2470 str = tcc_realloc(s->str, len * sizeof(int));
2471 if (!str)
2472 error("memory full");
2473 s->allocated_len = len;
2474 s->str = str;
2475 return str;
2478 static void tok_str_add(TokenString *s, int t)
2480 int len, *str;
2482 len = s->len;
2483 str = s->str;
2484 if (len >= s->allocated_len)
2485 str = tok_str_realloc(s);
2486 str[len++] = t;
2487 s->len = len;
2490 static void tok_str_add2(TokenString *s, int t, CValue *cv)
2492 int len, *str;
2494 len = s->len;
2495 str = s->str;
2497 /* allocate space for worst case */
2498 if (len + TOK_MAX_SIZE > s->allocated_len)
2499 str = tok_str_realloc(s);
2500 str[len++] = t;
2501 switch(t) {
2502 case TOK_CINT:
2503 case TOK_CUINT:
2504 case TOK_CCHAR:
2505 case TOK_LCHAR:
2506 case TOK_CFLOAT:
2507 case TOK_LINENUM:
2508 str[len++] = cv->tab[0];
2509 break;
2510 case TOK_PPNUM:
2511 case TOK_STR:
2512 case TOK_LSTR:
2514 int nb_words;
2515 CString *cstr;
2517 nb_words = (sizeof(CString) + cv->cstr->size + 3) >> 2;
2518 while ((len + nb_words) > s->allocated_len)
2519 str = tok_str_realloc(s);
2520 cstr = (CString *)(str + len);
2521 cstr->data = NULL;
2522 cstr->size = cv->cstr->size;
2523 cstr->data_allocated = NULL;
2524 cstr->size_allocated = cstr->size;
2525 memcpy((char *)cstr + sizeof(CString),
2526 cv->cstr->data, cstr->size);
2527 len += nb_words;
2529 break;
2530 case TOK_CDOUBLE:
2531 case TOK_CLLONG:
2532 case TOK_CULLONG:
2533 #if LDOUBLE_SIZE == 8
2534 case TOK_CLDOUBLE:
2535 #endif
2536 str[len++] = cv->tab[0];
2537 str[len++] = cv->tab[1];
2538 break;
2539 #if LDOUBLE_SIZE == 12
2540 case TOK_CLDOUBLE:
2541 str[len++] = cv->tab[0];
2542 str[len++] = cv->tab[1];
2543 str[len++] = cv->tab[2];
2544 #elif LDOUBLE_SIZE != 8
2545 #error add long double size support
2546 #endif
2547 break;
2548 default:
2549 break;
2551 s->len = len;
2554 /* add the current parse token in token string 's' */
2555 static void tok_str_add_tok(TokenString *s)
2557 CValue cval;
2559 /* save line number info */
2560 if (file->line_num != s->last_line_num) {
2561 s->last_line_num = file->line_num;
2562 cval.i = s->last_line_num;
2563 tok_str_add2(s, TOK_LINENUM, &cval);
2565 tok_str_add2(s, tok, &tokc);
2568 #if LDOUBLE_SIZE == 12
2569 #define LDOUBLE_GET(p, cv) \
2570 cv.tab[0] = p[0]; \
2571 cv.tab[1] = p[1]; \
2572 cv.tab[2] = p[2];
2573 #elif LDOUBLE_SIZE == 8
2574 #define LDOUBLE_GET(p, cv) \
2575 cv.tab[0] = p[0]; \
2576 cv.tab[1] = p[1];
2577 #else
2578 #error add long double size support
2579 #endif
2582 /* get a token from an integer array and increment pointer
2583 accordingly. we code it as a macro to avoid pointer aliasing. */
2584 #define TOK_GET(t, p, cv) \
2586 t = *p++; \
2587 switch(t) { \
2588 case TOK_CINT: \
2589 case TOK_CUINT: \
2590 case TOK_CCHAR: \
2591 case TOK_LCHAR: \
2592 case TOK_CFLOAT: \
2593 case TOK_LINENUM: \
2594 cv.tab[0] = *p++; \
2595 break; \
2596 case TOK_STR: \
2597 case TOK_LSTR: \
2598 case TOK_PPNUM: \
2599 cv.cstr = (CString *)p; \
2600 cv.cstr->data = (char *)p + sizeof(CString);\
2601 p += (sizeof(CString) + cv.cstr->size + 3) >> 2;\
2602 break; \
2603 case TOK_CDOUBLE: \
2604 case TOK_CLLONG: \
2605 case TOK_CULLONG: \
2606 cv.tab[0] = p[0]; \
2607 cv.tab[1] = p[1]; \
2608 p += 2; \
2609 break; \
2610 case TOK_CLDOUBLE: \
2611 LDOUBLE_GET(p, cv); \
2612 p += LDOUBLE_SIZE / 4; \
2613 break; \
2614 default: \
2615 break; \
2619 /* defines handling */
2620 static inline void define_push(int v, int macro_type, int *str, Sym *first_arg)
2622 Sym *s;
2624 s = sym_push2(&define_stack, v, macro_type, (int)str);
2625 s->next = first_arg;
2626 table_ident[v - TOK_IDENT]->sym_define = s;
2629 /* undefined a define symbol. Its name is just set to zero */
2630 static void define_undef(Sym *s)
2632 int v;
2633 v = s->v;
2634 if (v >= TOK_IDENT && v < tok_ident)
2635 table_ident[v - TOK_IDENT]->sym_define = NULL;
2636 s->v = 0;
2639 static inline Sym *define_find(int v)
2641 v -= TOK_IDENT;
2642 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2643 return NULL;
2644 return table_ident[v]->sym_define;
2647 /* free define stack until top reaches 'b' */
2648 static void free_defines(Sym *b)
2650 Sym *top, *top1;
2651 int v;
2653 top = define_stack;
2654 while (top != b) {
2655 top1 = top->prev;
2656 /* do not free args or predefined defines */
2657 if (top->c)
2658 tok_str_free((int *)top->c);
2659 v = top->v;
2660 if (v >= TOK_IDENT && v < tok_ident)
2661 table_ident[v - TOK_IDENT]->sym_define = NULL;
2662 sym_free(top);
2663 top = top1;
2665 define_stack = b;
2668 /* label lookup */
2669 static Sym *label_find(int v)
2671 v -= TOK_IDENT;
2672 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2673 return NULL;
2674 return table_ident[v]->sym_label;
2677 static Sym *label_push(Sym **ptop, int v, int flags)
2679 Sym *s, **ps;
2680 s = sym_push2(ptop, v, 0, 0);
2681 s->r = flags;
2682 ps = &table_ident[v - TOK_IDENT]->sym_label;
2683 if (ptop == &global_label_stack) {
2684 /* modify the top most local identifier, so that
2685 sym_identifier will point to 's' when popped */
2686 while (*ps != NULL)
2687 ps = &(*ps)->prev_tok;
2689 s->prev_tok = *ps;
2690 *ps = s;
2691 return s;
2694 /* pop labels until element last is reached. Look if any labels are
2695 undefined. Define symbols if '&&label' was used. */
2696 static void label_pop(Sym **ptop, Sym *slast)
2698 Sym *s, *s1;
2699 for(s = *ptop; s != slast; s = s1) {
2700 s1 = s->prev;
2701 if (s->r == LABEL_DECLARED) {
2702 warning("label '%s' declared but not used", get_tok_str(s->v, NULL));
2703 } else if (s->r == LABEL_FORWARD) {
2704 error("label '%s' used but not defined",
2705 get_tok_str(s->v, NULL));
2706 } else {
2707 if (s->c) {
2708 /* define corresponding symbol. A size of
2709 1 is put. */
2710 put_extern_sym(s, cur_text_section, (long)s->next, 1);
2713 /* remove label */
2714 table_ident[s->v - TOK_IDENT]->sym_label = s->prev_tok;
2715 sym_free(s);
2717 *ptop = slast;
2720 /* eval an expression for #if/#elif */
2721 static int expr_preprocess(void)
2723 int c, t;
2724 TokenString str;
2726 tok_str_new(&str);
2727 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2728 next(); /* do macro subst */
2729 if (tok == TOK_DEFINED) {
2730 next_nomacro();
2731 t = tok;
2732 if (t == '(')
2733 next_nomacro();
2734 c = define_find(tok) != 0;
2735 if (t == '(')
2736 next_nomacro();
2737 tok = TOK_CINT;
2738 tokc.i = c;
2739 } else if (tok >= TOK_IDENT) {
2740 /* if undefined macro */
2741 tok = TOK_CINT;
2742 tokc.i = 0;
2744 tok_str_add_tok(&str);
2746 tok_str_add(&str, -1); /* simulate end of file */
2747 tok_str_add(&str, 0);
2748 /* now evaluate C constant expression */
2749 macro_ptr = str.str;
2750 next();
2751 c = expr_const();
2752 macro_ptr = NULL;
2753 tok_str_free(str.str);
2754 return c != 0;
2757 #if defined(PARSE_DEBUG) || defined(PP_DEBUG)
2758 static void tok_print(int *str)
2760 int t;
2761 CValue cval;
2763 while (1) {
2764 TOK_GET(t, str, cval);
2765 if (!t)
2766 break;
2767 printf(" %s", get_tok_str(t, &cval));
2769 printf("\n");
2771 #endif
2773 /* parse after #define */
2774 static void parse_define(void)
2776 Sym *s, *first, **ps;
2777 int v, t, varg, is_vaargs, c;
2778 TokenString str;
2780 v = tok;
2781 if (v < TOK_IDENT)
2782 error("invalid macro name '%s'", get_tok_str(tok, &tokc));
2783 /* XXX: should check if same macro (ANSI) */
2784 first = NULL;
2785 t = MACRO_OBJ;
2786 /* '(' must be just after macro definition for MACRO_FUNC */
2787 c = file->buf_ptr[0];
2788 if (c == '\\')
2789 c = handle_stray1(file->buf_ptr);
2790 if (c == '(') {
2791 next_nomacro();
2792 next_nomacro();
2793 ps = &first;
2794 while (tok != ')') {
2795 varg = tok;
2796 next_nomacro();
2797 is_vaargs = 0;
2798 if (varg == TOK_DOTS) {
2799 varg = TOK___VA_ARGS__;
2800 is_vaargs = 1;
2801 } else if (tok == TOK_DOTS && gnu_ext) {
2802 is_vaargs = 1;
2803 next_nomacro();
2805 if (varg < TOK_IDENT)
2806 error("badly punctuated parameter list");
2807 s = sym_push2(&define_stack, varg | SYM_FIELD, is_vaargs, 0);
2808 *ps = s;
2809 ps = &s->next;
2810 if (tok != ',')
2811 break;
2812 next_nomacro();
2814 t = MACRO_FUNC;
2816 tok_str_new(&str);
2817 next_nomacro();
2818 /* EOF testing necessary for '-D' handling */
2819 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2820 tok_str_add2(&str, tok, &tokc);
2821 next_nomacro();
2823 tok_str_add(&str, 0);
2824 #ifdef PP_DEBUG
2825 printf("define %s %d: ", get_tok_str(v, NULL), t);
2826 tok_print(str.str);
2827 #endif
2828 define_push(v, t, str.str, first);
2831 static inline int hash_cached_include(int type, const char *filename)
2833 const unsigned char *s;
2834 unsigned int h;
2836 h = TOK_HASH_INIT;
2837 h = TOK_HASH_FUNC(h, type);
2838 s = filename;
2839 while (*s) {
2840 h = TOK_HASH_FUNC(h, *s);
2841 s++;
2843 h &= (CACHED_INCLUDES_HASH_SIZE - 1);
2844 return h;
2847 /* XXX: use a token or a hash table to accelerate matching ? */
2848 static CachedInclude *search_cached_include(TCCState *s1,
2849 int type, const char *filename)
2851 CachedInclude *e;
2852 int i, h;
2853 h = hash_cached_include(type, filename);
2854 i = s1->cached_includes_hash[h];
2855 for(;;) {
2856 if (i == 0)
2857 break;
2858 e = s1->cached_includes[i - 1];
2859 if (e->type == type && !strcmp(e->filename, filename))
2860 return e;
2861 i = e->hash_next;
2863 return NULL;
2866 static inline void add_cached_include(TCCState *s1, int type,
2867 const char *filename, int ifndef_macro)
2869 CachedInclude *e;
2870 int h;
2872 if (search_cached_include(s1, type, filename))
2873 return;
2874 #ifdef INC_DEBUG
2875 printf("adding cached '%s' %s\n", filename, get_tok_str(ifndef_macro, NULL));
2876 #endif
2877 e = tcc_malloc(sizeof(CachedInclude) + strlen(filename));
2878 if (!e)
2879 return;
2880 e->type = type;
2881 strcpy(e->filename, filename);
2882 e->ifndef_macro = ifndef_macro;
2883 dynarray_add((void ***)&s1->cached_includes, &s1->nb_cached_includes, e);
2884 /* add in hash table */
2885 h = hash_cached_include(type, filename);
2886 e->hash_next = s1->cached_includes_hash[h];
2887 s1->cached_includes_hash[h] = s1->nb_cached_includes;
2890 static void pragma_parse(TCCState *s1)
2892 int val;
2894 next();
2895 if (tok == TOK_pack) {
2897 This may be:
2898 #pragma pack(1) // set
2899 #pragma pack() // reset to default
2900 #pragma pack(push,1) // push & set
2901 #pragma pack(pop) // restore previous
2903 next();
2904 skip('(');
2905 if (tok == TOK_ASM_pop) {
2906 next();
2907 if (s1->pack_stack_ptr <= s1->pack_stack) {
2908 stk_error:
2909 error("out of pack stack");
2911 s1->pack_stack_ptr--;
2912 } else {
2913 val = 0;
2914 if (tok != ')') {
2915 if (tok == TOK_ASM_push) {
2916 next();
2917 if (s1->pack_stack_ptr >= s1->pack_stack + PACK_STACK_SIZE - 1)
2918 goto stk_error;
2919 s1->pack_stack_ptr++;
2920 skip(',');
2922 if (tok != TOK_CINT) {
2923 pack_error:
2924 error("invalid pack pragma");
2926 val = tokc.i;
2927 if (val < 1 || val > 16 || (val & (val - 1)) != 0)
2928 goto pack_error;
2929 next();
2931 *s1->pack_stack_ptr = val;
2932 skip(')');
2937 /* is_bof is true if first non space token at beginning of file */
2938 static void preprocess(int is_bof)
2940 TCCState *s1 = tcc_state;
2941 int size, i, c, n, saved_parse_flags;
2942 char buf[1024], *q;
2943 char buf1[1024];
2944 BufferedFile *f;
2945 Sym *s;
2946 CachedInclude *e;
2948 saved_parse_flags = parse_flags;
2949 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM |
2950 PARSE_FLAG_LINEFEED;
2951 next_nomacro();
2952 redo:
2953 switch(tok) {
2954 case TOK_DEFINE:
2955 next_nomacro();
2956 parse_define();
2957 break;
2958 case TOK_UNDEF:
2959 next_nomacro();
2960 s = define_find(tok);
2961 /* undefine symbol by putting an invalid name */
2962 if (s)
2963 define_undef(s);
2964 break;
2965 case TOK_INCLUDE:
2966 case TOK_INCLUDE_NEXT:
2967 ch = file->buf_ptr[0];
2968 /* XXX: incorrect if comments : use next_nomacro with a special mode */
2969 skip_spaces();
2970 if (ch == '<') {
2971 c = '>';
2972 goto read_name;
2973 } else if (ch == '\"') {
2974 c = ch;
2975 read_name:
2976 inp();
2977 q = buf;
2978 while (ch != c && ch != '\n' && ch != CH_EOF) {
2979 if ((q - buf) < sizeof(buf) - 1)
2980 *q++ = ch;
2981 if (ch == '\\') {
2982 if (handle_stray_noerror() == 0)
2983 --q;
2984 } else
2985 inp();
2987 *q = '\0';
2988 minp();
2989 #if 0
2990 /* eat all spaces and comments after include */
2991 /* XXX: slightly incorrect */
2992 while (ch1 != '\n' && ch1 != CH_EOF)
2993 inp();
2994 #endif
2995 } else {
2996 /* computed #include : either we have only strings or
2997 we have anything enclosed in '<>' */
2998 next();
2999 buf[0] = '\0';
3000 if (tok == TOK_STR) {
3001 while (tok != TOK_LINEFEED) {
3002 if (tok != TOK_STR) {
3003 include_syntax:
3004 error("'#include' expects \"FILENAME\" or <FILENAME>");
3006 pstrcat(buf, sizeof(buf), (char *)tokc.cstr->data);
3007 next();
3009 c = '\"';
3010 } else {
3011 int len;
3012 while (tok != TOK_LINEFEED) {
3013 pstrcat(buf, sizeof(buf), get_tok_str(tok, &tokc));
3014 next();
3016 len = strlen(buf);
3017 /* check syntax and remove '<>' */
3018 if (len < 2 || buf[0] != '<' || buf[len - 1] != '>')
3019 goto include_syntax;
3020 memmove(buf, buf + 1, len - 2);
3021 buf[len - 2] = '\0';
3022 c = '>';
3026 e = search_cached_include(s1, c, buf);
3027 if (e && define_find(e->ifndef_macro)) {
3028 /* no need to parse the include because the 'ifndef macro'
3029 is defined */
3030 #ifdef INC_DEBUG
3031 printf("%s: skipping %s\n", file->filename, buf);
3032 #endif
3033 } else {
3034 if (c == '\"') {
3035 /* first search in current dir if "header.h" */
3036 size = tcc_basename(file->filename) - file->filename;
3037 if (size > sizeof(buf1) - 1)
3038 size = sizeof(buf1) - 1;
3039 memcpy(buf1, file->filename, size);
3040 buf1[size] = '\0';
3041 pstrcat(buf1, sizeof(buf1), buf);
3042 f = tcc_open(s1, buf1);
3043 if (f) {
3044 if (tok == TOK_INCLUDE_NEXT)
3045 tok = TOK_INCLUDE;
3046 else
3047 goto found;
3050 if (s1->include_stack_ptr >= s1->include_stack + INCLUDE_STACK_SIZE)
3051 error("#include recursion too deep");
3052 /* now search in all the include paths */
3053 n = s1->nb_include_paths + s1->nb_sysinclude_paths;
3054 for(i = 0; i < n; i++) {
3055 const char *path;
3056 if (i < s1->nb_include_paths)
3057 path = s1->include_paths[i];
3058 else
3059 path = s1->sysinclude_paths[i - s1->nb_include_paths];
3060 pstrcpy(buf1, sizeof(buf1), path);
3061 pstrcat(buf1, sizeof(buf1), "/");
3062 pstrcat(buf1, sizeof(buf1), buf);
3063 f = tcc_open(s1, buf1);
3064 if (f) {
3065 if (tok == TOK_INCLUDE_NEXT)
3066 tok = TOK_INCLUDE;
3067 else
3068 goto found;
3071 error("include file '%s' not found", buf);
3072 f = NULL;
3073 found:
3074 #ifdef INC_DEBUG
3075 printf("%s: including %s\n", file->filename, buf1);
3076 #endif
3077 f->inc_type = c;
3078 pstrcpy(f->inc_filename, sizeof(f->inc_filename), buf);
3079 /* push current file in stack */
3080 /* XXX: fix current line init */
3081 *s1->include_stack_ptr++ = file;
3082 file = f;
3083 /* add include file debug info */
3084 if (do_debug) {
3085 put_stabs(file->filename, N_BINCL, 0, 0, 0);
3087 tok_flags |= TOK_FLAG_BOF | TOK_FLAG_BOL;
3088 ch = file->buf_ptr[0];
3089 goto the_end;
3091 break;
3092 case TOK_IFNDEF:
3093 c = 1;
3094 goto do_ifdef;
3095 case TOK_IF:
3096 c = expr_preprocess();
3097 goto do_if;
3098 case TOK_IFDEF:
3099 c = 0;
3100 do_ifdef:
3101 next_nomacro();
3102 if (tok < TOK_IDENT)
3103 error("invalid argument for '#if%sdef'", c ? "n" : "");
3104 if (is_bof) {
3105 if (c) {
3106 #ifdef INC_DEBUG
3107 printf("#ifndef %s\n", get_tok_str(tok, NULL));
3108 #endif
3109 file->ifndef_macro = tok;
3112 c = (define_find(tok) != 0) ^ c;
3113 do_if:
3114 if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE)
3115 error("memory full");
3116 *s1->ifdef_stack_ptr++ = c;
3117 goto test_skip;
3118 case TOK_ELSE:
3119 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
3120 error("#else without matching #if");
3121 if (s1->ifdef_stack_ptr[-1] & 2)
3122 error("#else after #else");
3123 c = (s1->ifdef_stack_ptr[-1] ^= 3);
3124 goto test_skip;
3125 case TOK_ELIF:
3126 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
3127 error("#elif without matching #if");
3128 c = s1->ifdef_stack_ptr[-1];
3129 if (c > 1)
3130 error("#elif after #else");
3131 /* last #if/#elif expression was true: we skip */
3132 if (c == 1)
3133 goto skip;
3134 c = expr_preprocess();
3135 s1->ifdef_stack_ptr[-1] = c;
3136 test_skip:
3137 if (!(c & 1)) {
3138 skip:
3139 preprocess_skip();
3140 is_bof = 0;
3141 goto redo;
3143 break;
3144 case TOK_ENDIF:
3145 if (s1->ifdef_stack_ptr <= file->ifdef_stack_ptr)
3146 error("#endif without matching #if");
3147 s1->ifdef_stack_ptr--;
3148 /* '#ifndef macro' was at the start of file. Now we check if
3149 an '#endif' is exactly at the end of file */
3150 if (file->ifndef_macro &&
3151 s1->ifdef_stack_ptr == file->ifdef_stack_ptr) {
3152 file->ifndef_macro_saved = file->ifndef_macro;
3153 /* need to set to zero to avoid false matches if another
3154 #ifndef at middle of file */
3155 file->ifndef_macro = 0;
3156 while (tok != TOK_LINEFEED)
3157 next_nomacro();
3158 tok_flags |= TOK_FLAG_ENDIF;
3159 goto the_end;
3161 break;
3162 case TOK_LINE:
3163 next();
3164 if (tok != TOK_CINT)
3165 error("#line");
3166 file->line_num = tokc.i - 1; /* the line number will be incremented after */
3167 next();
3168 if (tok != TOK_LINEFEED) {
3169 if (tok != TOK_STR)
3170 error("#line");
3171 pstrcpy(file->filename, sizeof(file->filename),
3172 (char *)tokc.cstr->data);
3174 break;
3175 case TOK_ERROR:
3176 case TOK_WARNING:
3177 c = tok;
3178 ch = file->buf_ptr[0];
3179 skip_spaces();
3180 q = buf;
3181 while (ch != '\n' && ch != CH_EOF) {
3182 if ((q - buf) < sizeof(buf) - 1)
3183 *q++ = ch;
3184 if (ch == '\\') {
3185 if (handle_stray_noerror() == 0)
3186 --q;
3187 } else
3188 inp();
3190 *q = '\0';
3191 if (c == TOK_ERROR)
3192 error("#error %s", buf);
3193 else
3194 warning("#warning %s", buf);
3195 break;
3196 case TOK_PRAGMA:
3197 pragma_parse(s1);
3198 break;
3199 default:
3200 if (tok == TOK_LINEFEED || tok == '!' || tok == TOK_CINT) {
3201 /* '!' is ignored to allow C scripts. numbers are ignored
3202 to emulate cpp behaviour */
3203 } else {
3204 if (!(saved_parse_flags & PARSE_FLAG_ASM_COMMENTS))
3205 warning("Ignoring unknown preprocessing directive #%s", get_tok_str(tok, &tokc));
3207 break;
3209 /* ignore other preprocess commands or #! for C scripts */
3210 while (tok != TOK_LINEFEED)
3211 next_nomacro();
3212 the_end:
3213 parse_flags = saved_parse_flags;
3216 /* evaluate escape codes in a string. */
3217 static void parse_escape_string(CString *outstr, const uint8_t *buf, int is_long)
3219 int c, n;
3220 const uint8_t *p;
3222 p = buf;
3223 for(;;) {
3224 c = *p;
3225 if (c == '\0')
3226 break;
3227 if (c == '\\') {
3228 p++;
3229 /* escape */
3230 c = *p;
3231 switch(c) {
3232 case '0': case '1': case '2': case '3':
3233 case '4': case '5': case '6': case '7':
3234 /* at most three octal digits */
3235 n = c - '0';
3236 p++;
3237 c = *p;
3238 if (isoct(c)) {
3239 n = n * 8 + c - '0';
3240 p++;
3241 c = *p;
3242 if (isoct(c)) {
3243 n = n * 8 + c - '0';
3244 p++;
3247 c = n;
3248 goto add_char_nonext;
3249 case 'x':
3250 case 'u':
3251 case 'U':
3252 p++;
3253 n = 0;
3254 for(;;) {
3255 c = *p;
3256 if (c >= 'a' && c <= 'f')
3257 c = c - 'a' + 10;
3258 else if (c >= 'A' && c <= 'F')
3259 c = c - 'A' + 10;
3260 else if (isnum(c))
3261 c = c - '0';
3262 else
3263 break;
3264 n = n * 16 + c;
3265 p++;
3267 c = n;
3268 goto add_char_nonext;
3269 case 'a':
3270 c = '\a';
3271 break;
3272 case 'b':
3273 c = '\b';
3274 break;
3275 case 'f':
3276 c = '\f';
3277 break;
3278 case 'n':
3279 c = '\n';
3280 break;
3281 case 'r':
3282 c = '\r';
3283 break;
3284 case 't':
3285 c = '\t';
3286 break;
3287 case 'v':
3288 c = '\v';
3289 break;
3290 case 'e':
3291 if (!gnu_ext)
3292 goto invalid_escape;
3293 c = 27;
3294 break;
3295 case '\'':
3296 case '\"':
3297 case '\\':
3298 case '?':
3299 break;
3300 default:
3301 invalid_escape:
3302 if (c >= '!' && c <= '~')
3303 warning("unknown escape sequence: \'\\%c\'", c);
3304 else
3305 warning("unknown escape sequence: \'\\x%x\'", c);
3306 break;
3309 p++;
3310 add_char_nonext:
3311 if (!is_long)
3312 cstr_ccat(outstr, c);
3313 else
3314 cstr_wccat(outstr, c);
3316 /* add a trailing '\0' */
3317 if (!is_long)
3318 cstr_ccat(outstr, '\0');
3319 else
3320 cstr_wccat(outstr, '\0');
3323 /* we use 64 bit numbers */
3324 #define BN_SIZE 2
3326 /* bn = (bn << shift) | or_val */
3327 void bn_lshift(unsigned int *bn, int shift, int or_val)
3329 int i;
3330 unsigned int v;
3331 for(i=0;i<BN_SIZE;i++) {
3332 v = bn[i];
3333 bn[i] = (v << shift) | or_val;
3334 or_val = v >> (32 - shift);
3338 void bn_zero(unsigned int *bn)
3340 int i;
3341 for(i=0;i<BN_SIZE;i++) {
3342 bn[i] = 0;
3346 /* parse number in null terminated string 'p' and return it in the
3347 current token */
3348 void parse_number(const char *p)
3350 int b, t, shift, frac_bits, s, exp_val, ch;
3351 char *q;
3352 unsigned int bn[BN_SIZE];
3353 double d;
3355 /* number */
3356 q = token_buf;
3357 ch = *p++;
3358 t = ch;
3359 ch = *p++;
3360 *q++ = t;
3361 b = 10;
3362 if (t == '.') {
3363 goto float_frac_parse;
3364 } else if (t == '0') {
3365 if (ch == 'x' || ch == 'X') {
3366 q--;
3367 ch = *p++;
3368 b = 16;
3369 } else if (tcc_ext && (ch == 'b' || ch == 'B')) {
3370 q--;
3371 ch = *p++;
3372 b = 2;
3375 /* parse all digits. cannot check octal numbers at this stage
3376 because of floating point constants */
3377 while (1) {
3378 if (ch >= 'a' && ch <= 'f')
3379 t = ch - 'a' + 10;
3380 else if (ch >= 'A' && ch <= 'F')
3381 t = ch - 'A' + 10;
3382 else if (isnum(ch))
3383 t = ch - '0';
3384 else
3385 break;
3386 if (t >= b)
3387 break;
3388 if (q >= token_buf + STRING_MAX_SIZE) {
3389 num_too_long:
3390 error("number too long");
3392 *q++ = ch;
3393 ch = *p++;
3395 if (ch == '.' ||
3396 ((ch == 'e' || ch == 'E') && b == 10) ||
3397 ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
3398 if (b != 10) {
3399 /* NOTE: strtox should support that for hexa numbers, but
3400 non ISOC99 libcs do not support it, so we prefer to do
3401 it by hand */
3402 /* hexadecimal or binary floats */
3403 /* XXX: handle overflows */
3404 *q = '\0';
3405 if (b == 16)
3406 shift = 4;
3407 else
3408 shift = 2;
3409 bn_zero(bn);
3410 q = token_buf;
3411 while (1) {
3412 t = *q++;
3413 if (t == '\0') {
3414 break;
3415 } else if (t >= 'a') {
3416 t = t - 'a' + 10;
3417 } else if (t >= 'A') {
3418 t = t - 'A' + 10;
3419 } else {
3420 t = t - '0';
3422 bn_lshift(bn, shift, t);
3424 frac_bits = 0;
3425 if (ch == '.') {
3426 ch = *p++;
3427 while (1) {
3428 t = ch;
3429 if (t >= 'a' && t <= 'f') {
3430 t = t - 'a' + 10;
3431 } else if (t >= 'A' && t <= 'F') {
3432 t = t - 'A' + 10;
3433 } else if (t >= '0' && t <= '9') {
3434 t = t - '0';
3435 } else {
3436 break;
3438 if (t >= b)
3439 error("invalid digit");
3440 bn_lshift(bn, shift, t);
3441 frac_bits += shift;
3442 ch = *p++;
3445 if (ch != 'p' && ch != 'P')
3446 expect("exponent");
3447 ch = *p++;
3448 s = 1;
3449 exp_val = 0;
3450 if (ch == '+') {
3451 ch = *p++;
3452 } else if (ch == '-') {
3453 s = -1;
3454 ch = *p++;
3456 if (ch < '0' || ch > '9')
3457 expect("exponent digits");
3458 while (ch >= '0' && ch <= '9') {
3459 exp_val = exp_val * 10 + ch - '0';
3460 ch = *p++;
3462 exp_val = exp_val * s;
3464 /* now we can generate the number */
3465 /* XXX: should patch directly float number */
3466 d = (double)bn[1] * 4294967296.0 + (double)bn[0];
3467 d = ldexp(d, exp_val - frac_bits);
3468 t = toup(ch);
3469 if (t == 'F') {
3470 ch = *p++;
3471 tok = TOK_CFLOAT;
3472 /* float : should handle overflow */
3473 tokc.f = (float)d;
3474 } else if (t == 'L') {
3475 ch = *p++;
3476 tok = TOK_CLDOUBLE;
3477 /* XXX: not large enough */
3478 tokc.ld = (long double)d;
3479 } else {
3480 tok = TOK_CDOUBLE;
3481 tokc.d = d;
3483 } else {
3484 /* decimal floats */
3485 if (ch == '.') {
3486 if (q >= token_buf + STRING_MAX_SIZE)
3487 goto num_too_long;
3488 *q++ = ch;
3489 ch = *p++;
3490 float_frac_parse:
3491 while (ch >= '0' && ch <= '9') {
3492 if (q >= token_buf + STRING_MAX_SIZE)
3493 goto num_too_long;
3494 *q++ = ch;
3495 ch = *p++;
3498 if (ch == 'e' || ch == 'E') {
3499 if (q >= token_buf + STRING_MAX_SIZE)
3500 goto num_too_long;
3501 *q++ = ch;
3502 ch = *p++;
3503 if (ch == '-' || ch == '+') {
3504 if (q >= token_buf + STRING_MAX_SIZE)
3505 goto num_too_long;
3506 *q++ = ch;
3507 ch = *p++;
3509 if (ch < '0' || ch > '9')
3510 expect("exponent digits");
3511 while (ch >= '0' && ch <= '9') {
3512 if (q >= token_buf + STRING_MAX_SIZE)
3513 goto num_too_long;
3514 *q++ = ch;
3515 ch = *p++;
3518 *q = '\0';
3519 t = toup(ch);
3520 errno = 0;
3521 if (t == 'F') {
3522 ch = *p++;
3523 tok = TOK_CFLOAT;
3524 tokc.f = strtof(token_buf, NULL);
3525 } else if (t == 'L') {
3526 ch = *p++;
3527 tok = TOK_CLDOUBLE;
3528 tokc.ld = strtold(token_buf, NULL);
3529 } else {
3530 tok = TOK_CDOUBLE;
3531 tokc.d = strtod(token_buf, NULL);
3534 } else {
3535 unsigned long long n, n1;
3536 int lcount, ucount;
3538 /* integer number */
3539 *q = '\0';
3540 q = token_buf;
3541 if (b == 10 && *q == '0') {
3542 b = 8;
3543 q++;
3545 n = 0;
3546 while(1) {
3547 t = *q++;
3548 /* no need for checks except for base 10 / 8 errors */
3549 if (t == '\0') {
3550 break;
3551 } else if (t >= 'a') {
3552 t = t - 'a' + 10;
3553 } else if (t >= 'A') {
3554 t = t - 'A' + 10;
3555 } else {
3556 t = t - '0';
3557 if (t >= b)
3558 error("invalid digit");
3560 n1 = n;
3561 n = n * b + t;
3562 /* detect overflow */
3563 /* XXX: this test is not reliable */
3564 if (n < n1)
3565 error("integer constant overflow");
3568 /* XXX: not exactly ANSI compliant */
3569 if ((n & 0xffffffff00000000LL) != 0) {
3570 if ((n >> 63) != 0)
3571 tok = TOK_CULLONG;
3572 else
3573 tok = TOK_CLLONG;
3574 } else if (n > 0x7fffffff) {
3575 tok = TOK_CUINT;
3576 } else {
3577 tok = TOK_CINT;
3579 lcount = 0;
3580 ucount = 0;
3581 for(;;) {
3582 t = toup(ch);
3583 if (t == 'L') {
3584 if (lcount >= 2)
3585 error("three 'l's in integer constant");
3586 lcount++;
3587 if (lcount == 2) {
3588 if (tok == TOK_CINT)
3589 tok = TOK_CLLONG;
3590 else if (tok == TOK_CUINT)
3591 tok = TOK_CULLONG;
3593 ch = *p++;
3594 } else if (t == 'U') {
3595 if (ucount >= 1)
3596 error("two 'u's in integer constant");
3597 ucount++;
3598 if (tok == TOK_CINT)
3599 tok = TOK_CUINT;
3600 else if (tok == TOK_CLLONG)
3601 tok = TOK_CULLONG;
3602 ch = *p++;
3603 } else {
3604 break;
3607 if (tok == TOK_CINT || tok == TOK_CUINT)
3608 tokc.ui = n;
3609 else
3610 tokc.ull = n;
3615 #define PARSE2(c1, tok1, c2, tok2) \
3616 case c1: \
3617 PEEKC(c, p); \
3618 if (c == c2) { \
3619 p++; \
3620 tok = tok2; \
3621 } else { \
3622 tok = tok1; \
3624 break;
3626 /* return next token without macro substitution */
3627 static inline void next_nomacro1(void)
3629 int t, c, is_long;
3630 TokenSym *ts;
3631 uint8_t *p, *p1;
3632 unsigned int h;
3634 p = file->buf_ptr;
3635 redo_no_start:
3636 c = *p;
3637 switch(c) {
3638 case ' ':
3639 case '\t':
3640 case '\f':
3641 case '\v':
3642 case '\r':
3643 p++;
3644 goto redo_no_start;
3646 case '\\':
3647 /* first look if it is in fact an end of buffer */
3648 if (p >= file->buf_end) {
3649 file->buf_ptr = p;
3650 handle_eob();
3651 p = file->buf_ptr;
3652 if (p >= file->buf_end)
3653 goto parse_eof;
3654 else
3655 goto redo_no_start;
3656 } else {
3657 file->buf_ptr = p;
3658 ch = *p;
3659 handle_stray();
3660 p = file->buf_ptr;
3661 goto redo_no_start;
3663 parse_eof:
3665 TCCState *s1 = tcc_state;
3666 if ((parse_flags & PARSE_FLAG_LINEFEED)
3667 && !(tok_flags & TOK_FLAG_EOF)) {
3668 tok_flags |= TOK_FLAG_EOF;
3669 tok = TOK_LINEFEED;
3670 goto keep_tok_flags;
3671 } else if (s1->include_stack_ptr == s1->include_stack ||
3672 !(parse_flags & PARSE_FLAG_PREPROCESS)) {
3673 /* no include left : end of file. */
3674 tok = TOK_EOF;
3675 } else {
3676 tok_flags &= ~TOK_FLAG_EOF;
3677 /* pop include file */
3679 /* test if previous '#endif' was after a #ifdef at
3680 start of file */
3681 if (tok_flags & TOK_FLAG_ENDIF) {
3682 #ifdef INC_DEBUG
3683 printf("#endif %s\n", get_tok_str(file->ifndef_macro_saved, NULL));
3684 #endif
3685 add_cached_include(s1, file->inc_type, file->inc_filename,
3686 file->ifndef_macro_saved);
3689 /* add end of include file debug info */
3690 if (do_debug) {
3691 put_stabd(N_EINCL, 0, 0);
3693 /* pop include stack */
3694 tcc_close(file);
3695 s1->include_stack_ptr--;
3696 file = *s1->include_stack_ptr;
3697 p = file->buf_ptr;
3698 goto redo_no_start;
3701 break;
3703 case '\n':
3704 file->line_num++;
3705 tok_flags |= TOK_FLAG_BOL;
3706 p++;
3707 if (0 == (parse_flags & PARSE_FLAG_LINEFEED))
3708 goto redo_no_start;
3709 tok = TOK_LINEFEED;
3710 goto keep_tok_flags;
3712 case '#':
3713 /* XXX: simplify */
3714 PEEKC(c, p);
3715 if ((tok_flags & TOK_FLAG_BOL) &&
3716 (parse_flags & PARSE_FLAG_PREPROCESS)) {
3717 file->buf_ptr = p;
3718 preprocess(tok_flags & TOK_FLAG_BOF);
3719 p = file->buf_ptr;
3720 goto redo_no_start;
3721 } else {
3722 if (c == '#') {
3723 p++;
3724 tok = TOK_TWOSHARPS;
3725 } else {
3726 if (parse_flags & PARSE_FLAG_ASM_COMMENTS) {
3727 p = parse_line_comment(p - 1);
3728 goto redo_no_start;
3729 } else {
3730 tok = '#';
3734 break;
3736 case 'a': case 'b': case 'c': case 'd':
3737 case 'e': case 'f': case 'g': case 'h':
3738 case 'i': case 'j': case 'k': case 'l':
3739 case 'm': case 'n': case 'o': case 'p':
3740 case 'q': case 'r': case 's': case 't':
3741 case 'u': case 'v': case 'w': case 'x':
3742 case 'y': case 'z':
3743 case 'A': case 'B': case 'C': case 'D':
3744 case 'E': case 'F': case 'G': case 'H':
3745 case 'I': case 'J': case 'K':
3746 case 'M': case 'N': case 'O': case 'P':
3747 case 'Q': case 'R': case 'S': case 'T':
3748 case 'U': case 'V': case 'W': case 'X':
3749 case 'Y': case 'Z':
3750 case '_':
3751 parse_ident_fast:
3752 p1 = p;
3753 h = TOK_HASH_INIT;
3754 h = TOK_HASH_FUNC(h, c);
3755 p++;
3756 for(;;) {
3757 c = *p;
3758 if (!isidnum_table[c])
3759 break;
3760 h = TOK_HASH_FUNC(h, c);
3761 p++;
3763 if (c != '\\') {
3764 TokenSym **pts;
3765 int len;
3767 /* fast case : no stray found, so we have the full token
3768 and we have already hashed it */
3769 len = p - p1;
3770 h &= (TOK_HASH_SIZE - 1);
3771 pts = &hash_ident[h];
3772 for(;;) {
3773 ts = *pts;
3774 if (!ts)
3775 break;
3776 if (ts->len == len && !memcmp(ts->str, p1, len))
3777 goto token_found;
3778 pts = &(ts->hash_next);
3780 ts = tok_alloc_new(pts, p1, len);
3781 token_found: ;
3782 } else {
3783 /* slower case */
3784 cstr_reset(&tokcstr);
3786 while (p1 < p) {
3787 cstr_ccat(&tokcstr, *p1);
3788 p1++;
3790 p--;
3791 PEEKC(c, p);
3792 parse_ident_slow:
3793 while (isidnum_table[c]) {
3794 cstr_ccat(&tokcstr, c);
3795 PEEKC(c, p);
3797 ts = tok_alloc(tokcstr.data, tokcstr.size);
3799 tok = ts->tok;
3800 break;
3801 case 'L':
3802 t = p[1];
3803 if (t != '\\' && t != '\'' && t != '\"') {
3804 /* fast case */
3805 goto parse_ident_fast;
3806 } else {
3807 PEEKC(c, p);
3808 if (c == '\'' || c == '\"') {
3809 is_long = 1;
3810 goto str_const;
3811 } else {
3812 cstr_reset(&tokcstr);
3813 cstr_ccat(&tokcstr, 'L');
3814 goto parse_ident_slow;
3817 break;
3818 case '0': case '1': case '2': case '3':
3819 case '4': case '5': case '6': case '7':
3820 case '8': case '9':
3822 cstr_reset(&tokcstr);
3823 /* after the first digit, accept digits, alpha, '.' or sign if
3824 prefixed by 'eEpP' */
3825 parse_num:
3826 for(;;) {
3827 t = c;
3828 cstr_ccat(&tokcstr, c);
3829 PEEKC(c, p);
3830 if (!(isnum(c) || isid(c) || c == '.' ||
3831 ((c == '+' || c == '-') &&
3832 (t == 'e' || t == 'E' || t == 'p' || t == 'P'))))
3833 break;
3835 /* We add a trailing '\0' to ease parsing */
3836 cstr_ccat(&tokcstr, '\0');
3837 tokc.cstr = &tokcstr;
3838 tok = TOK_PPNUM;
3839 break;
3840 case '.':
3841 /* special dot handling because it can also start a number */
3842 PEEKC(c, p);
3843 if (isnum(c)) {
3844 cstr_reset(&tokcstr);
3845 cstr_ccat(&tokcstr, '.');
3846 goto parse_num;
3847 } else if (c == '.') {
3848 PEEKC(c, p);
3849 if (c != '.')
3850 expect("'.'");
3851 PEEKC(c, p);
3852 tok = TOK_DOTS;
3853 } else {
3854 tok = '.';
3856 break;
3857 case '\'':
3858 case '\"':
3859 is_long = 0;
3860 str_const:
3862 CString str;
3863 int sep;
3865 sep = c;
3867 /* parse the string */
3868 cstr_new(&str);
3869 p = parse_pp_string(p, sep, &str);
3870 cstr_ccat(&str, '\0');
3872 /* eval the escape (should be done as TOK_PPNUM) */
3873 cstr_reset(&tokcstr);
3874 parse_escape_string(&tokcstr, str.data, is_long);
3875 cstr_free(&str);
3877 if (sep == '\'') {
3878 int char_size;
3879 /* XXX: make it portable */
3880 if (!is_long)
3881 char_size = 1;
3882 else
3883 char_size = sizeof(nwchar_t);
3884 if (tokcstr.size <= char_size)
3885 error("empty character constant");
3886 if (tokcstr.size > 2 * char_size)
3887 warning("multi-character character constant");
3888 if (!is_long) {
3889 tokc.i = *(int8_t *)tokcstr.data;
3890 tok = TOK_CCHAR;
3891 } else {
3892 tokc.i = *(nwchar_t *)tokcstr.data;
3893 tok = TOK_LCHAR;
3895 } else {
3896 tokc.cstr = &tokcstr;
3897 if (!is_long)
3898 tok = TOK_STR;
3899 else
3900 tok = TOK_LSTR;
3903 break;
3905 case '<':
3906 PEEKC(c, p);
3907 if (c == '=') {
3908 p++;
3909 tok = TOK_LE;
3910 } else if (c == '<') {
3911 PEEKC(c, p);
3912 if (c == '=') {
3913 p++;
3914 tok = TOK_A_SHL;
3915 } else {
3916 tok = TOK_SHL;
3918 } else {
3919 tok = TOK_LT;
3921 break;
3923 case '>':
3924 PEEKC(c, p);
3925 if (c == '=') {
3926 p++;
3927 tok = TOK_GE;
3928 } else if (c == '>') {
3929 PEEKC(c, p);
3930 if (c == '=') {
3931 p++;
3932 tok = TOK_A_SAR;
3933 } else {
3934 tok = TOK_SAR;
3936 } else {
3937 tok = TOK_GT;
3939 break;
3941 case '&':
3942 PEEKC(c, p);
3943 if (c == '&') {
3944 p++;
3945 tok = TOK_LAND;
3946 } else if (c == '=') {
3947 p++;
3948 tok = TOK_A_AND;
3949 } else {
3950 tok = '&';
3952 break;
3954 case '|':
3955 PEEKC(c, p);
3956 if (c == '|') {
3957 p++;
3958 tok = TOK_LOR;
3959 } else if (c == '=') {
3960 p++;
3961 tok = TOK_A_OR;
3962 } else {
3963 tok = '|';
3965 break;
3967 case '+':
3968 PEEKC(c, p);
3969 if (c == '+') {
3970 p++;
3971 tok = TOK_INC;
3972 } else if (c == '=') {
3973 p++;
3974 tok = TOK_A_ADD;
3975 } else {
3976 tok = '+';
3978 break;
3980 case '-':
3981 PEEKC(c, p);
3982 if (c == '-') {
3983 p++;
3984 tok = TOK_DEC;
3985 } else if (c == '=') {
3986 p++;
3987 tok = TOK_A_SUB;
3988 } else if (c == '>') {
3989 p++;
3990 tok = TOK_ARROW;
3991 } else {
3992 tok = '-';
3994 break;
3996 PARSE2('!', '!', '=', TOK_NE)
3997 PARSE2('=', '=', '=', TOK_EQ)
3998 PARSE2('*', '*', '=', TOK_A_MUL)
3999 PARSE2('%', '%', '=', TOK_A_MOD)
4000 PARSE2('^', '^', '=', TOK_A_XOR)
4002 /* comments or operator */
4003 case '/':
4004 PEEKC(c, p);
4005 if (c == '*') {
4006 p = parse_comment(p);
4007 goto redo_no_start;
4008 } else if (c == '/') {
4009 p = parse_line_comment(p);
4010 goto redo_no_start;
4011 } else if (c == '=') {
4012 p++;
4013 tok = TOK_A_DIV;
4014 } else {
4015 tok = '/';
4017 break;
4019 /* simple tokens */
4020 case '(':
4021 case ')':
4022 case '[':
4023 case ']':
4024 case '{':
4025 case '}':
4026 case ',':
4027 case ';':
4028 case ':':
4029 case '?':
4030 case '~':
4031 case '$': /* only used in assembler */
4032 case '@': /* dito */
4033 tok = c;
4034 p++;
4035 break;
4036 default:
4037 error("unrecognized character \\x%02x", c);
4038 break;
4040 tok_flags = 0;
4041 keep_tok_flags:
4042 file->buf_ptr = p;
4043 #if defined(PARSE_DEBUG)
4044 printf("token = %s\n", get_tok_str(tok, &tokc));
4045 #endif
4048 /* return next token without macro substitution. Can read input from
4049 macro_ptr buffer */
4050 static void next_nomacro(void)
4052 if (macro_ptr) {
4053 redo:
4054 tok = *macro_ptr;
4055 if (tok) {
4056 TOK_GET(tok, macro_ptr, tokc);
4057 if (tok == TOK_LINENUM) {
4058 file->line_num = tokc.i;
4059 goto redo;
4062 } else {
4063 next_nomacro1();
4067 /* substitute args in macro_str and return allocated string */
4068 static int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
4070 int *st, last_tok, t, notfirst;
4071 Sym *s;
4072 CValue cval;
4073 TokenString str;
4074 CString cstr;
4076 tok_str_new(&str);
4077 last_tok = 0;
4078 while(1) {
4079 TOK_GET(t, macro_str, cval);
4080 if (!t)
4081 break;
4082 if (t == '#') {
4083 /* stringize */
4084 TOK_GET(t, macro_str, cval);
4085 if (!t)
4086 break;
4087 s = sym_find2(args, t);
4088 if (s) {
4089 cstr_new(&cstr);
4090 st = (int *)s->c;
4091 notfirst = 0;
4092 while (*st) {
4093 if (notfirst)
4094 cstr_ccat(&cstr, ' ');
4095 TOK_GET(t, st, cval);
4096 cstr_cat(&cstr, get_tok_str(t, &cval));
4097 #ifndef PP_NOSPACES
4098 notfirst = 1;
4099 #endif
4101 cstr_ccat(&cstr, '\0');
4102 #ifdef PP_DEBUG
4103 printf("stringize: %s\n", (char *)cstr.data);
4104 #endif
4105 /* add string */
4106 cval.cstr = &cstr;
4107 tok_str_add2(&str, TOK_STR, &cval);
4108 cstr_free(&cstr);
4109 } else {
4110 tok_str_add2(&str, t, &cval);
4112 } else if (t >= TOK_IDENT) {
4113 s = sym_find2(args, t);
4114 if (s) {
4115 st = (int *)s->c;
4116 /* if '##' is present before or after, no arg substitution */
4117 if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) {
4118 /* special case for var arg macros : ## eats the
4119 ',' if empty VA_ARGS variable. */
4120 /* XXX: test of the ',' is not 100%
4121 reliable. should fix it to avoid security
4122 problems */
4123 if (gnu_ext && s->type.t &&
4124 last_tok == TOK_TWOSHARPS &&
4125 str.len >= 2 && str.str[str.len - 2] == ',') {
4126 if (*st == 0) {
4127 /* suppress ',' '##' */
4128 str.len -= 2;
4129 } else {
4130 /* suppress '##' and add variable */
4131 str.len--;
4132 goto add_var;
4134 } else {
4135 int t1;
4136 add_var:
4137 for(;;) {
4138 TOK_GET(t1, st, cval);
4139 if (!t1)
4140 break;
4141 tok_str_add2(&str, t1, &cval);
4144 } else {
4145 /* NOTE: the stream cannot be read when macro
4146 substituing an argument */
4147 macro_subst(&str, nested_list, st, NULL);
4149 } else {
4150 tok_str_add(&str, t);
4152 } else {
4153 tok_str_add2(&str, t, &cval);
4155 last_tok = t;
4157 tok_str_add(&str, 0);
4158 return str.str;
4161 static char const ab_month_name[12][4] =
4163 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
4164 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
4167 /* do macro substitution of current token with macro 's' and add
4168 result to (tok_str,tok_len). 'nested_list' is the list of all
4169 macros we got inside to avoid recursing. Return non zero if no
4170 substitution needs to be done */
4171 static int macro_subst_tok(TokenString *tok_str,
4172 Sym **nested_list, Sym *s, struct macro_level **can_read_stream)
4174 Sym *args, *sa, *sa1;
4175 int mstr_allocated, parlevel, *mstr, t, t1;
4176 TokenString str;
4177 char *cstrval;
4178 CValue cval;
4179 CString cstr;
4180 char buf[32];
4182 /* if symbol is a macro, prepare substitution */
4183 /* special macros */
4184 if (tok == TOK___LINE__) {
4185 snprintf(buf, sizeof(buf), "%d", file->line_num);
4186 cstrval = buf;
4187 t1 = TOK_PPNUM;
4188 goto add_cstr1;
4189 } else if (tok == TOK___FILE__) {
4190 cstrval = file->filename;
4191 goto add_cstr;
4192 } else if (tok == TOK___DATE__ || tok == TOK___TIME__) {
4193 time_t ti;
4194 struct tm *tm;
4196 time(&ti);
4197 tm = localtime(&ti);
4198 if (tok == TOK___DATE__) {
4199 snprintf(buf, sizeof(buf), "%s %2d %d",
4200 ab_month_name[tm->tm_mon], tm->tm_mday, tm->tm_year + 1900);
4201 } else {
4202 snprintf(buf, sizeof(buf), "%02d:%02d:%02d",
4203 tm->tm_hour, tm->tm_min, tm->tm_sec);
4205 cstrval = buf;
4206 add_cstr:
4207 t1 = TOK_STR;
4208 add_cstr1:
4209 cstr_new(&cstr);
4210 cstr_cat(&cstr, cstrval);
4211 cstr_ccat(&cstr, '\0');
4212 cval.cstr = &cstr;
4213 tok_str_add2(tok_str, t1, &cval);
4214 cstr_free(&cstr);
4215 } else {
4216 mstr = (int *)s->c;
4217 mstr_allocated = 0;
4218 if (s->type.t == MACRO_FUNC) {
4219 /* NOTE: we do not use next_nomacro to avoid eating the
4220 next token. XXX: find better solution */
4221 redo:
4222 if (macro_ptr) {
4223 t = *macro_ptr;
4224 if (t == 0 && can_read_stream) {
4225 /* end of macro stream: we must look at the token
4226 after in the file */
4227 struct macro_level *ml = *can_read_stream;
4228 macro_ptr = NULL;
4229 if (ml)
4231 macro_ptr = ml->p;
4232 ml->p = NULL;
4233 *can_read_stream = ml -> prev;
4235 goto redo;
4237 } else {
4238 /* XXX: incorrect with comments */
4239 ch = file->buf_ptr[0];
4240 while (is_space(ch) || ch == '\n')
4241 cinp();
4242 t = ch;
4244 if (t != '(') /* no macro subst */
4245 return -1;
4247 /* argument macro */
4248 next_nomacro();
4249 next_nomacro();
4250 args = NULL;
4251 sa = s->next;
4252 /* NOTE: empty args are allowed, except if no args */
4253 for(;;) {
4254 /* handle '()' case */
4255 if (!args && !sa && tok == ')')
4256 break;
4257 if (!sa)
4258 error("macro '%s' used with too many args",
4259 get_tok_str(s->v, 0));
4260 tok_str_new(&str);
4261 parlevel = 0;
4262 /* NOTE: non zero sa->t indicates VA_ARGS */
4263 while ((parlevel > 0 ||
4264 (tok != ')' &&
4265 (tok != ',' || sa->type.t))) &&
4266 tok != -1) {
4267 if (tok == '(')
4268 parlevel++;
4269 else if (tok == ')')
4270 parlevel--;
4271 if (tok != TOK_LINEFEED)
4272 tok_str_add2(&str, tok, &tokc);
4273 next_nomacro();
4275 tok_str_add(&str, 0);
4276 sym_push2(&args, sa->v & ~SYM_FIELD, sa->type.t, (int)str.str);
4277 sa = sa->next;
4278 if (tok == ')') {
4279 /* special case for gcc var args: add an empty
4280 var arg argument if it is omitted */
4281 if (sa && sa->type.t && gnu_ext)
4282 continue;
4283 else
4284 break;
4286 if (tok != ',')
4287 expect(",");
4288 next_nomacro();
4290 if (sa) {
4291 error("macro '%s' used with too few args",
4292 get_tok_str(s->v, 0));
4295 /* now subst each arg */
4296 mstr = macro_arg_subst(nested_list, mstr, args);
4297 /* free memory */
4298 sa = args;
4299 while (sa) {
4300 sa1 = sa->prev;
4301 tok_str_free((int *)sa->c);
4302 sym_free(sa);
4303 sa = sa1;
4305 mstr_allocated = 1;
4307 sym_push2(nested_list, s->v, 0, 0);
4308 macro_subst(tok_str, nested_list, mstr, can_read_stream);
4309 /* pop nested defined symbol */
4310 sa1 = *nested_list;
4311 *nested_list = sa1->prev;
4312 sym_free(sa1);
4313 if (mstr_allocated)
4314 tok_str_free(mstr);
4316 return 0;
4319 /* handle the '##' operator. Return NULL if no '##' seen. Otherwise
4320 return the resulting string (which must be freed). */
4321 static inline int *macro_twosharps(const int *macro_str)
4323 TokenSym *ts;
4324 const int *macro_ptr1, *start_macro_ptr, *ptr, *saved_macro_ptr;
4325 int t;
4326 const char *p1, *p2;
4327 CValue cval;
4328 TokenString macro_str1;
4329 CString cstr;
4331 start_macro_ptr = macro_str;
4332 /* we search the first '##' */
4333 for(;;) {
4334 macro_ptr1 = macro_str;
4335 TOK_GET(t, macro_str, cval);
4336 /* nothing more to do if end of string */
4337 if (t == 0)
4338 return NULL;
4339 if (*macro_str == TOK_TWOSHARPS)
4340 break;
4343 /* we saw '##', so we need more processing to handle it */
4344 cstr_new(&cstr);
4345 tok_str_new(&macro_str1);
4346 tok = t;
4347 tokc = cval;
4349 /* add all tokens seen so far */
4350 for(ptr = start_macro_ptr; ptr < macro_ptr1;) {
4351 TOK_GET(t, ptr, cval);
4352 tok_str_add2(&macro_str1, t, &cval);
4354 saved_macro_ptr = macro_ptr;
4355 /* XXX: get rid of the use of macro_ptr here */
4356 macro_ptr = (int *)macro_str;
4357 for(;;) {
4358 while (*macro_ptr == TOK_TWOSHARPS) {
4359 macro_ptr++;
4360 macro_ptr1 = macro_ptr;
4361 t = *macro_ptr;
4362 if (t) {
4363 TOK_GET(t, macro_ptr, cval);
4364 /* We concatenate the two tokens if we have an
4365 identifier or a preprocessing number */
4366 cstr_reset(&cstr);
4367 p1 = get_tok_str(tok, &tokc);
4368 cstr_cat(&cstr, p1);
4369 p2 = get_tok_str(t, &cval);
4370 cstr_cat(&cstr, p2);
4371 cstr_ccat(&cstr, '\0');
4373 if ((tok >= TOK_IDENT || tok == TOK_PPNUM) &&
4374 (t >= TOK_IDENT || t == TOK_PPNUM)) {
4375 if (tok == TOK_PPNUM) {
4376 /* if number, then create a number token */
4377 /* NOTE: no need to allocate because
4378 tok_str_add2() does it */
4379 cstr_reset(&tokcstr);
4380 tokcstr = cstr;
4381 cstr_new(&cstr);
4382 tokc.cstr = &tokcstr;
4383 } else {
4384 /* if identifier, we must do a test to
4385 validate we have a correct identifier */
4386 if (t == TOK_PPNUM) {
4387 const char *p;
4388 int c;
4390 p = p2;
4391 for(;;) {
4392 c = *p;
4393 if (c == '\0')
4394 break;
4395 p++;
4396 if (!isnum(c) && !isid(c))
4397 goto error_pasting;
4400 ts = tok_alloc(cstr.data, strlen(cstr.data));
4401 tok = ts->tok; /* modify current token */
4403 } else {
4404 const char *str = cstr.data;
4405 const unsigned char *q;
4407 /* we look for a valid token */
4408 /* XXX: do more extensive checks */
4409 if (!strcmp(str, ">>=")) {
4410 tok = TOK_A_SAR;
4411 } else if (!strcmp(str, "<<=")) {
4412 tok = TOK_A_SHL;
4413 } else if (strlen(str) == 2) {
4414 /* search in two bytes table */
4415 q = tok_two_chars;
4416 for(;;) {
4417 if (!*q)
4418 goto error_pasting;
4419 if (q[0] == str[0] && q[1] == str[1])
4420 break;
4421 q += 3;
4423 tok = q[2];
4424 } else {
4425 error_pasting:
4426 /* NOTE: because get_tok_str use a static buffer,
4427 we must save it */
4428 cstr_reset(&cstr);
4429 p1 = get_tok_str(tok, &tokc);
4430 cstr_cat(&cstr, p1);
4431 cstr_ccat(&cstr, '\0');
4432 p2 = get_tok_str(t, &cval);
4433 warning("pasting \"%s\" and \"%s\" does not give a valid preprocessing token", cstr.data, p2);
4434 /* cannot merge tokens: just add them separately */
4435 tok_str_add2(&macro_str1, tok, &tokc);
4436 /* XXX: free associated memory ? */
4437 tok = t;
4438 tokc = cval;
4443 tok_str_add2(&macro_str1, tok, &tokc);
4444 next_nomacro();
4445 if (tok == 0)
4446 break;
4448 macro_ptr = (int *)saved_macro_ptr;
4449 cstr_free(&cstr);
4450 tok_str_add(&macro_str1, 0);
4451 return macro_str1.str;
4455 /* do macro substitution of macro_str and add result to
4456 (tok_str,tok_len). 'nested_list' is the list of all macros we got
4457 inside to avoid recursing. */
4458 static void macro_subst(TokenString *tok_str, Sym **nested_list,
4459 const int *macro_str, struct macro_level ** can_read_stream)
4461 Sym *s;
4462 int *macro_str1;
4463 const int *ptr;
4464 int t, ret;
4465 CValue cval;
4466 struct macro_level ml;
4468 /* first scan for '##' operator handling */
4469 ptr = macro_str;
4470 macro_str1 = macro_twosharps(ptr);
4471 if (macro_str1)
4472 ptr = macro_str1;
4473 while (1) {
4474 /* NOTE: ptr == NULL can only happen if tokens are read from
4475 file stream due to a macro function call */
4476 if (ptr == NULL)
4477 break;
4478 TOK_GET(t, ptr, cval);
4479 if (t == 0)
4480 break;
4481 s = define_find(t);
4482 if (s != NULL) {
4483 /* if nested substitution, do nothing */
4484 if (sym_find2(*nested_list, t))
4485 goto no_subst;
4486 ml.p = macro_ptr;
4487 if (can_read_stream)
4488 ml.prev = *can_read_stream, *can_read_stream = &ml;
4489 macro_ptr = (int *)ptr;
4490 tok = t;
4491 ret = macro_subst_tok(tok_str, nested_list, s, can_read_stream);
4492 ptr = (int *)macro_ptr;
4493 macro_ptr = ml.p;
4494 if (can_read_stream && *can_read_stream == &ml)
4495 *can_read_stream = ml.prev;
4496 if (ret != 0)
4497 goto no_subst;
4498 } else {
4499 no_subst:
4500 tok_str_add2(tok_str, t, &cval);
4503 if (macro_str1)
4504 tok_str_free(macro_str1);
4507 /* return next token with macro substitution */
4508 static void next(void)
4510 Sym *nested_list, *s;
4511 TokenString str;
4512 struct macro_level *ml;
4514 redo:
4515 next_nomacro();
4516 if (!macro_ptr) {
4517 /* if not reading from macro substituted string, then try
4518 to substitute macros */
4519 if (tok >= TOK_IDENT &&
4520 (parse_flags & PARSE_FLAG_PREPROCESS)) {
4521 s = define_find(tok);
4522 if (s) {
4523 /* we have a macro: we try to substitute */
4524 tok_str_new(&str);
4525 nested_list = NULL;
4526 ml = NULL;
4527 if (macro_subst_tok(&str, &nested_list, s, &ml) == 0) {
4528 /* substitution done, NOTE: maybe empty */
4529 tok_str_add(&str, 0);
4530 macro_ptr = str.str;
4531 macro_ptr_allocated = str.str;
4532 goto redo;
4536 } else {
4537 if (tok == 0) {
4538 /* end of macro or end of unget buffer */
4539 if (unget_buffer_enabled) {
4540 macro_ptr = unget_saved_macro_ptr;
4541 unget_buffer_enabled = 0;
4542 } else {
4543 /* end of macro string: free it */
4544 tok_str_free(macro_ptr_allocated);
4545 macro_ptr = NULL;
4547 goto redo;
4551 /* convert preprocessor tokens into C tokens */
4552 if (tok == TOK_PPNUM &&
4553 (parse_flags & PARSE_FLAG_TOK_NUM)) {
4554 parse_number((char *)tokc.cstr->data);
4558 /* push back current token and set current token to 'last_tok'. Only
4559 identifier case handled for labels. */
4560 static inline void unget_tok(int last_tok)
4562 int i, n;
4563 int *q;
4564 unget_saved_macro_ptr = macro_ptr;
4565 unget_buffer_enabled = 1;
4566 q = unget_saved_buffer;
4567 macro_ptr = q;
4568 *q++ = tok;
4569 n = tok_ext_size(tok) - 1;
4570 for(i=0;i<n;i++)
4571 *q++ = tokc.tab[i];
4572 *q = 0; /* end of token string */
4573 tok = last_tok;
4577 void swap(int *p, int *q)
4579 int t;
4580 t = *p;
4581 *p = *q;
4582 *q = t;
4585 void vsetc(CType *type, int r, CValue *vc)
4587 int v;
4589 if (vtop >= vstack + (VSTACK_SIZE - 1))
4590 error("memory full");
4591 /* cannot let cpu flags if other instruction are generated. Also
4592 avoid leaving VT_JMP anywhere except on the top of the stack
4593 because it would complicate the code generator. */
4594 if (vtop >= vstack) {
4595 v = vtop->r & VT_VALMASK;
4596 if (v == VT_CMP || (v & ~1) == VT_JMP)
4597 gv(RC_INT);
4599 vtop++;
4600 vtop->type = *type;
4601 vtop->r = r;
4602 vtop->r2 = VT_CONST;
4603 vtop->c = *vc;
4606 /* push integer constant */
4607 void vpushi(int v)
4609 CValue cval;
4610 cval.i = v;
4611 vsetc(&int_type, VT_CONST, &cval);
4614 /* Return a static symbol pointing to a section */
4615 static Sym *get_sym_ref(CType *type, Section *sec,
4616 unsigned long offset, unsigned long size)
4618 int v;
4619 Sym *sym;
4621 v = anon_sym++;
4622 sym = global_identifier_push(v, type->t | VT_STATIC, 0);
4623 sym->type.ref = type->ref;
4624 sym->r = VT_CONST | VT_SYM;
4625 put_extern_sym(sym, sec, offset, size);
4626 return sym;
4629 /* push a reference to a section offset by adding a dummy symbol */
4630 static void vpush_ref(CType *type, Section *sec, unsigned long offset, unsigned long size)
4632 CValue cval;
4634 cval.ul = 0;
4635 vsetc(type, VT_CONST | VT_SYM, &cval);
4636 vtop->sym = get_sym_ref(type, sec, offset, size);
4639 /* define a new external reference to a symbol 'v' of type 'u' */
4640 static Sym *external_global_sym(int v, CType *type, int r)
4642 Sym *s;
4644 s = sym_find(v);
4645 if (!s) {
4646 /* push forward reference */
4647 s = global_identifier_push(v, type->t | VT_EXTERN, 0);
4648 s->type.ref = type->ref;
4649 s->r = r | VT_CONST | VT_SYM;
4651 return s;
4654 /* define a new external reference to a symbol 'v' of type 'u' */
4655 static Sym *external_sym(int v, CType *type, int r)
4657 Sym *s;
4659 s = sym_find(v);
4660 if (!s) {
4661 /* push forward reference */
4662 s = sym_push(v, type, r | VT_CONST | VT_SYM, 0);
4663 s->type.t |= VT_EXTERN;
4664 } else {
4665 if (!is_compatible_types(&s->type, type))
4666 error("incompatible types for redefinition of '%s'",
4667 get_tok_str(v, NULL));
4669 return s;
4672 /* push a reference to global symbol v */
4673 static void vpush_global_sym(CType *type, int v)
4675 Sym *sym;
4676 CValue cval;
4678 sym = external_global_sym(v, type, 0);
4679 cval.ul = 0;
4680 vsetc(type, VT_CONST | VT_SYM, &cval);
4681 vtop->sym = sym;
4684 void vset(CType *type, int r, int v)
4686 CValue cval;
4688 cval.i = v;
4689 vsetc(type, r, &cval);
4692 void vseti(int r, int v)
4694 CType type;
4695 type.t = VT_INT;
4696 vset(&type, r, v);
4699 void vswap(void)
4701 SValue tmp;
4703 tmp = vtop[0];
4704 vtop[0] = vtop[-1];
4705 vtop[-1] = tmp;
4708 void vpushv(SValue *v)
4710 if (vtop >= vstack + (VSTACK_SIZE - 1))
4711 error("memory full");
4712 vtop++;
4713 *vtop = *v;
4716 void vdup(void)
4718 vpushv(vtop);
4721 /* save r to the memory stack, and mark it as being free */
4722 void save_reg(int r)
4724 int l, saved, size, align;
4725 SValue *p, sv;
4726 CType *type;
4728 /* modify all stack values */
4729 saved = 0;
4730 l = 0;
4731 for(p=vstack;p<=vtop;p++) {
4732 if ((p->r & VT_VALMASK) == r ||
4733 ((p->type.t & VT_BTYPE) == VT_LLONG && (p->r2 & VT_VALMASK) == r)) {
4734 /* must save value on stack if not already done */
4735 if (!saved) {
4736 /* NOTE: must reload 'r' because r might be equal to r2 */
4737 r = p->r & VT_VALMASK;
4738 /* store register in the stack */
4739 type = &p->type;
4740 if ((p->r & VT_LVAL) ||
4741 (!is_float(type->t) && (type->t & VT_BTYPE) != VT_LLONG))
4742 type = &int_type;
4743 size = type_size(type, &align);
4744 loc = (loc - size) & -align;
4745 sv.type.t = type->t;
4746 sv.r = VT_LOCAL | VT_LVAL;
4747 sv.c.ul = loc;
4748 store(r, &sv);
4749 #ifdef TCC_TARGET_I386
4750 /* x86 specific: need to pop fp register ST0 if saved */
4751 if (r == TREG_ST0) {
4752 o(0xd9dd); /* fstp %st(1) */
4754 #endif
4755 /* special long long case */
4756 if ((type->t & VT_BTYPE) == VT_LLONG) {
4757 sv.c.ul += 4;
4758 store(p->r2, &sv);
4760 l = loc;
4761 saved = 1;
4763 /* mark that stack entry as being saved on the stack */
4764 if (p->r & VT_LVAL) {
4765 /* also clear the bounded flag because the
4766 relocation address of the function was stored in
4767 p->c.ul */
4768 p->r = (p->r & ~(VT_VALMASK | VT_BOUNDED)) | VT_LLOCAL;
4769 } else {
4770 p->r = lvalue_type(p->type.t) | VT_LOCAL;
4772 p->r2 = VT_CONST;
4773 p->c.ul = l;
4778 /* find a register of class 'rc2' with at most one reference on stack.
4779 * If none, call get_reg(rc) */
4780 int get_reg_ex(int rc, int rc2)
4782 int r;
4783 SValue *p;
4785 for(r=0;r<NB_REGS;r++) {
4786 if (reg_classes[r] & rc2) {
4787 int n;
4788 n=0;
4789 for(p = vstack; p <= vtop; p++) {
4790 if ((p->r & VT_VALMASK) == r ||
4791 (p->r2 & VT_VALMASK) == r)
4792 n++;
4794 if (n <= 1)
4795 return r;
4798 return get_reg(rc);
4801 /* find a free register of class 'rc'. If none, save one register */
4802 int get_reg(int rc)
4804 int r;
4805 SValue *p;
4807 /* find a free register */
4808 for(r=0;r<NB_REGS;r++) {
4809 if (reg_classes[r] & rc) {
4810 for(p=vstack;p<=vtop;p++) {
4811 if ((p->r & VT_VALMASK) == r ||
4812 (p->r2 & VT_VALMASK) == r)
4813 goto notfound;
4815 return r;
4817 notfound: ;
4820 /* no register left : free the first one on the stack (VERY
4821 IMPORTANT to start from the bottom to ensure that we don't
4822 spill registers used in gen_opi()) */
4823 for(p=vstack;p<=vtop;p++) {
4824 r = p->r & VT_VALMASK;
4825 if (r < VT_CONST && (reg_classes[r] & rc))
4826 goto save_found;
4827 /* also look at second register (if long long) */
4828 r = p->r2 & VT_VALMASK;
4829 if (r < VT_CONST && (reg_classes[r] & rc)) {
4830 save_found:
4831 save_reg(r);
4832 return r;
4835 /* Should never comes here */
4836 return -1;
4839 /* save registers up to (vtop - n) stack entry */
4840 void save_regs(int n)
4842 int r;
4843 SValue *p, *p1;
4844 p1 = vtop - n;
4845 for(p = vstack;p <= p1; p++) {
4846 r = p->r & VT_VALMASK;
4847 if (r < VT_CONST) {
4848 save_reg(r);
4853 /* move register 's' to 'r', and flush previous value of r to memory
4854 if needed */
4855 void move_reg(int r, int s)
4857 SValue sv;
4859 if (r != s) {
4860 save_reg(r);
4861 sv.type.t = VT_INT;
4862 sv.r = s;
4863 sv.c.ul = 0;
4864 load(r, &sv);
4868 /* get address of vtop (vtop MUST BE an lvalue) */
4869 void gaddrof(void)
4871 vtop->r &= ~VT_LVAL;
4872 /* tricky: if saved lvalue, then we can go back to lvalue */
4873 if ((vtop->r & VT_VALMASK) == VT_LLOCAL)
4874 vtop->r = (vtop->r & ~(VT_VALMASK | VT_LVAL_TYPE)) | VT_LOCAL | VT_LVAL;
4877 #ifdef CONFIG_TCC_BCHECK
4878 /* generate lvalue bound code */
4879 void gbound(void)
4881 int lval_type;
4882 CType type1;
4884 vtop->r &= ~VT_MUSTBOUND;
4885 /* if lvalue, then use checking code before dereferencing */
4886 if (vtop->r & VT_LVAL) {
4887 /* if not VT_BOUNDED value, then make one */
4888 if (!(vtop->r & VT_BOUNDED)) {
4889 lval_type = vtop->r & (VT_LVAL_TYPE | VT_LVAL);
4890 /* must save type because we must set it to int to get pointer */
4891 type1 = vtop->type;
4892 vtop->type.t = VT_INT;
4893 gaddrof();
4894 vpushi(0);
4895 gen_bounded_ptr_add();
4896 vtop->r |= lval_type;
4897 vtop->type = type1;
4899 /* then check for dereferencing */
4900 gen_bounded_ptr_deref();
4903 #endif
4905 /* store vtop a register belonging to class 'rc'. lvalues are
4906 converted to values. Cannot be used if cannot be converted to
4907 register value (such as structures). */
4908 int gv(int rc)
4910 int r, r2, rc2, bit_pos, bit_size, size, align, i;
4911 unsigned long long ll;
4913 /* NOTE: get_reg can modify vstack[] */
4914 if (vtop->type.t & VT_BITFIELD) {
4915 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
4916 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
4917 /* remove bit field info to avoid loops */
4918 vtop->type.t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
4919 /* generate shifts */
4920 vpushi(32 - (bit_pos + bit_size));
4921 gen_op(TOK_SHL);
4922 vpushi(32 - bit_size);
4923 /* NOTE: transformed to SHR if unsigned */
4924 gen_op(TOK_SAR);
4925 r = gv(rc);
4926 } else {
4927 if (is_float(vtop->type.t) &&
4928 (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4929 Sym *sym;
4930 int *ptr;
4931 unsigned long offset;
4932 #if defined(TCC_TARGET_ARM) && !defined(TCC_ARM_VFP)
4933 CValue check;
4934 #endif
4936 /* XXX: unify with initializers handling ? */
4937 /* CPUs usually cannot use float constants, so we store them
4938 generically in data segment */
4939 size = type_size(&vtop->type, &align);
4940 offset = (data_section->data_offset + align - 1) & -align;
4941 data_section->data_offset = offset;
4942 /* XXX: not portable yet */
4943 #ifdef __i386__
4944 /* Zero pad x87 tenbyte long doubles */
4945 if (size == 12)
4946 vtop->c.tab[2] &= 0xffff;
4947 #endif
4948 ptr = section_ptr_add(data_section, size);
4949 size = size >> 2;
4950 #if defined(TCC_TARGET_ARM) && !defined(TCC_ARM_VFP)
4951 check.d = 1;
4952 if(check.tab[0])
4953 for(i=0;i<size;i++)
4954 ptr[i] = vtop->c.tab[size-1-i];
4955 else
4956 #endif
4957 for(i=0;i<size;i++)
4958 ptr[i] = vtop->c.tab[i];
4959 sym = get_sym_ref(&vtop->type, data_section, offset, size << 2);
4960 vtop->r |= VT_LVAL | VT_SYM;
4961 vtop->sym = sym;
4962 vtop->c.ul = 0;
4964 #ifdef CONFIG_TCC_BCHECK
4965 if (vtop->r & VT_MUSTBOUND)
4966 gbound();
4967 #endif
4969 r = vtop->r & VT_VALMASK;
4970 /* need to reload if:
4971 - constant
4972 - lvalue (need to dereference pointer)
4973 - already a register, but not in the right class */
4974 if (r >= VT_CONST ||
4975 (vtop->r & VT_LVAL) ||
4976 !(reg_classes[r] & rc) ||
4977 ((vtop->type.t & VT_BTYPE) == VT_LLONG &&
4978 !(reg_classes[vtop->r2] & rc))) {
4979 r = get_reg(rc);
4980 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
4981 /* two register type load : expand to two words
4982 temporarily */
4983 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4984 /* load constant */
4985 ll = vtop->c.ull;
4986 vtop->c.ui = ll; /* first word */
4987 load(r, vtop);
4988 vtop->r = r; /* save register value */
4989 vpushi(ll >> 32); /* second word */
4990 } else if (r >= VT_CONST || /* XXX: test to VT_CONST incorrect ? */
4991 (vtop->r & VT_LVAL)) {
4992 /* We do not want to modifier the long long
4993 pointer here, so the safest (and less
4994 efficient) is to save all the other registers
4995 in the stack. XXX: totally inefficient. */
4996 save_regs(1);
4997 /* load from memory */
4998 load(r, vtop);
4999 vdup();
5000 vtop[-1].r = r; /* save register value */
5001 /* increment pointer to get second word */
5002 vtop->type.t = VT_INT;
5003 gaddrof();
5004 vpushi(4);
5005 gen_op('+');
5006 vtop->r |= VT_LVAL;
5007 } else {
5008 /* move registers */
5009 load(r, vtop);
5010 vdup();
5011 vtop[-1].r = r; /* save register value */
5012 vtop->r = vtop[-1].r2;
5014 /* allocate second register */
5015 rc2 = RC_INT;
5016 if (rc == RC_IRET)
5017 rc2 = RC_LRET;
5018 r2 = get_reg(rc2);
5019 load(r2, vtop);
5020 vpop();
5021 /* write second register */
5022 vtop->r2 = r2;
5023 } else if ((vtop->r & VT_LVAL) && !is_float(vtop->type.t)) {
5024 int t1, t;
5025 /* lvalue of scalar type : need to use lvalue type
5026 because of possible cast */
5027 t = vtop->type.t;
5028 t1 = t;
5029 /* compute memory access type */
5030 if (vtop->r & VT_LVAL_BYTE)
5031 t = VT_BYTE;
5032 else if (vtop->r & VT_LVAL_SHORT)
5033 t = VT_SHORT;
5034 if (vtop->r & VT_LVAL_UNSIGNED)
5035 t |= VT_UNSIGNED;
5036 vtop->type.t = t;
5037 load(r, vtop);
5038 /* restore wanted type */
5039 vtop->type.t = t1;
5040 } else {
5041 /* one register type load */
5042 load(r, vtop);
5045 vtop->r = r;
5046 #ifdef TCC_TARGET_C67
5047 /* uses register pairs for doubles */
5048 if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE)
5049 vtop->r2 = r+1;
5050 #endif
5052 return r;
5055 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
5056 void gv2(int rc1, int rc2)
5058 int v;
5060 /* generate more generic register first. But VT_JMP or VT_CMP
5061 values must be generated first in all cases to avoid possible
5062 reload errors */
5063 v = vtop[0].r & VT_VALMASK;
5064 if (v != VT_CMP && (v & ~1) != VT_JMP && rc1 <= rc2) {
5065 vswap();
5066 gv(rc1);
5067 vswap();
5068 gv(rc2);
5069 /* test if reload is needed for first register */
5070 if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
5071 vswap();
5072 gv(rc1);
5073 vswap();
5075 } else {
5076 gv(rc2);
5077 vswap();
5078 gv(rc1);
5079 vswap();
5080 /* test if reload is needed for first register */
5081 if ((vtop[0].r & VT_VALMASK) >= VT_CONST) {
5082 gv(rc2);
5087 /* expand long long on stack in two int registers */
5088 void lexpand(void)
5090 int u;
5092 u = vtop->type.t & VT_UNSIGNED;
5093 gv(RC_INT);
5094 vdup();
5095 vtop[0].r = vtop[-1].r2;
5096 vtop[0].r2 = VT_CONST;
5097 vtop[-1].r2 = VT_CONST;
5098 vtop[0].type.t = VT_INT | u;
5099 vtop[-1].type.t = VT_INT | u;
5102 #ifdef TCC_TARGET_ARM
5103 /* expand long long on stack */
5104 void lexpand_nr(void)
5106 int u,v;
5108 u = vtop->type.t & VT_UNSIGNED;
5109 vdup();
5110 vtop->r2 = VT_CONST;
5111 vtop->type.t = VT_INT | u;
5112 v=vtop[-1].r & (VT_VALMASK | VT_LVAL);
5113 if (v == VT_CONST) {
5114 vtop[-1].c.ui = vtop->c.ull;
5115 vtop->c.ui = vtop->c.ull >> 32;
5116 vtop->r = VT_CONST;
5117 } else if (v == (VT_LVAL|VT_CONST) || v == (VT_LVAL|VT_LOCAL)) {
5118 vtop->c.ui += 4;
5119 vtop->r = vtop[-1].r;
5120 } else if (v > VT_CONST) {
5121 vtop--;
5122 lexpand();
5123 } else
5124 vtop->r = vtop[-1].r2;
5125 vtop[-1].r2 = VT_CONST;
5126 vtop[-1].type.t = VT_INT | u;
5128 #endif
5130 /* build a long long from two ints */
5131 void lbuild(int t)
5133 gv2(RC_INT, RC_INT);
5134 vtop[-1].r2 = vtop[0].r;
5135 vtop[-1].type.t = t;
5136 vpop();
5139 /* rotate n first stack elements to the bottom
5140 I1 ... In -> I2 ... In I1 [top is right]
5142 void vrotb(int n)
5144 int i;
5145 SValue tmp;
5147 tmp = vtop[-n + 1];
5148 for(i=-n+1;i!=0;i++)
5149 vtop[i] = vtop[i+1];
5150 vtop[0] = tmp;
5153 /* rotate n first stack elements to the top
5154 I1 ... In -> In I1 ... I(n-1) [top is right]
5156 void vrott(int n)
5158 int i;
5159 SValue tmp;
5161 tmp = vtop[0];
5162 for(i = 0;i < n - 1; i++)
5163 vtop[-i] = vtop[-i - 1];
5164 vtop[-n + 1] = tmp;
5167 #ifdef TCC_TARGET_ARM
5168 /* like vrott but in other direction
5169 In ... I1 -> I(n-1) ... I1 In [top is right]
5171 void vnrott(int n)
5173 int i;
5174 SValue tmp;
5176 tmp = vtop[-n + 1];
5177 for(i = n - 1; i > 0; i--)
5178 vtop[-i] = vtop[-i + 1];
5179 vtop[0] = tmp;
5181 #endif
5183 /* pop stack value */
5184 void vpop(void)
5186 int v;
5187 v = vtop->r & VT_VALMASK;
5188 #ifdef TCC_TARGET_I386
5189 /* for x86, we need to pop the FP stack */
5190 if (v == TREG_ST0 && !nocode_wanted) {
5191 o(0xd9dd); /* fstp %st(1) */
5192 } else
5193 #endif
5194 if (v == VT_JMP || v == VT_JMPI) {
5195 /* need to put correct jump if && or || without test */
5196 gsym(vtop->c.ul);
5198 vtop--;
5201 /* convert stack entry to register and duplicate its value in another
5202 register */
5203 void gv_dup(void)
5205 int rc, t, r, r1;
5206 SValue sv;
5208 t = vtop->type.t;
5209 if ((t & VT_BTYPE) == VT_LLONG) {
5210 lexpand();
5211 gv_dup();
5212 vswap();
5213 vrotb(3);
5214 gv_dup();
5215 vrotb(4);
5216 /* stack: H L L1 H1 */
5217 lbuild(t);
5218 vrotb(3);
5219 vrotb(3);
5220 vswap();
5221 lbuild(t);
5222 vswap();
5223 } else {
5224 /* duplicate value */
5225 rc = RC_INT;
5226 sv.type.t = VT_INT;
5227 if (is_float(t)) {
5228 rc = RC_FLOAT;
5229 sv.type.t = t;
5231 r = gv(rc);
5232 r1 = get_reg(rc);
5233 sv.r = r;
5234 sv.c.ul = 0;
5235 load(r1, &sv); /* move r to r1 */
5236 vdup();
5237 /* duplicates value */
5238 vtop->r = r1;
5242 /* generate CPU independent (unsigned) long long operations */
5243 void gen_opl(int op)
5245 int t, a, b, op1, c, i;
5246 int func;
5247 SValue tmp;
5249 switch(op) {
5250 case '/':
5251 case TOK_PDIV:
5252 func = TOK___divdi3;
5253 goto gen_func;
5254 case TOK_UDIV:
5255 func = TOK___udivdi3;
5256 goto gen_func;
5257 case '%':
5258 func = TOK___moddi3;
5259 goto gen_func;
5260 case TOK_UMOD:
5261 func = TOK___umoddi3;
5262 gen_func:
5263 /* call generic long long function */
5264 vpush_global_sym(&func_old_type, func);
5265 vrott(3);
5266 gfunc_call(2);
5267 vpushi(0);
5268 vtop->r = REG_IRET;
5269 vtop->r2 = REG_LRET;
5270 break;
5271 case '^':
5272 case '&':
5273 case '|':
5274 case '*':
5275 case '+':
5276 case '-':
5277 t = vtop->type.t;
5278 vswap();
5279 lexpand();
5280 vrotb(3);
5281 lexpand();
5282 /* stack: L1 H1 L2 H2 */
5283 tmp = vtop[0];
5284 vtop[0] = vtop[-3];
5285 vtop[-3] = tmp;
5286 tmp = vtop[-2];
5287 vtop[-2] = vtop[-3];
5288 vtop[-3] = tmp;
5289 vswap();
5290 /* stack: H1 H2 L1 L2 */
5291 if (op == '*') {
5292 vpushv(vtop - 1);
5293 vpushv(vtop - 1);
5294 gen_op(TOK_UMULL);
5295 lexpand();
5296 /* stack: H1 H2 L1 L2 ML MH */
5297 for(i=0;i<4;i++)
5298 vrotb(6);
5299 /* stack: ML MH H1 H2 L1 L2 */
5300 tmp = vtop[0];
5301 vtop[0] = vtop[-2];
5302 vtop[-2] = tmp;
5303 /* stack: ML MH H1 L2 H2 L1 */
5304 gen_op('*');
5305 vrotb(3);
5306 vrotb(3);
5307 gen_op('*');
5308 /* stack: ML MH M1 M2 */
5309 gen_op('+');
5310 gen_op('+');
5311 } else if (op == '+' || op == '-') {
5312 /* XXX: add non carry method too (for MIPS or alpha) */
5313 if (op == '+')
5314 op1 = TOK_ADDC1;
5315 else
5316 op1 = TOK_SUBC1;
5317 gen_op(op1);
5318 /* stack: H1 H2 (L1 op L2) */
5319 vrotb(3);
5320 vrotb(3);
5321 gen_op(op1 + 1); /* TOK_xxxC2 */
5322 } else {
5323 gen_op(op);
5324 /* stack: H1 H2 (L1 op L2) */
5325 vrotb(3);
5326 vrotb(3);
5327 /* stack: (L1 op L2) H1 H2 */
5328 gen_op(op);
5329 /* stack: (L1 op L2) (H1 op H2) */
5331 /* stack: L H */
5332 lbuild(t);
5333 break;
5334 case TOK_SAR:
5335 case TOK_SHR:
5336 case TOK_SHL:
5337 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
5338 t = vtop[-1].type.t;
5339 vswap();
5340 lexpand();
5341 vrotb(3);
5342 /* stack: L H shift */
5343 c = (int)vtop->c.i;
5344 /* constant: simpler */
5345 /* NOTE: all comments are for SHL. the other cases are
5346 done by swaping words */
5347 vpop();
5348 if (op != TOK_SHL)
5349 vswap();
5350 if (c >= 32) {
5351 /* stack: L H */
5352 vpop();
5353 if (c > 32) {
5354 vpushi(c - 32);
5355 gen_op(op);
5357 if (op != TOK_SAR) {
5358 vpushi(0);
5359 } else {
5360 gv_dup();
5361 vpushi(31);
5362 gen_op(TOK_SAR);
5364 vswap();
5365 } else {
5366 vswap();
5367 gv_dup();
5368 /* stack: H L L */
5369 vpushi(c);
5370 gen_op(op);
5371 vswap();
5372 vpushi(32 - c);
5373 if (op == TOK_SHL)
5374 gen_op(TOK_SHR);
5375 else
5376 gen_op(TOK_SHL);
5377 vrotb(3);
5378 /* stack: L L H */
5379 vpushi(c);
5380 if (op == TOK_SHL)
5381 gen_op(TOK_SHL);
5382 else
5383 gen_op(TOK_SHR);
5384 gen_op('|');
5386 if (op != TOK_SHL)
5387 vswap();
5388 lbuild(t);
5389 } else {
5390 /* XXX: should provide a faster fallback on x86 ? */
5391 switch(op) {
5392 case TOK_SAR:
5393 func = TOK___sardi3;
5394 goto gen_func;
5395 case TOK_SHR:
5396 func = TOK___shrdi3;
5397 goto gen_func;
5398 case TOK_SHL:
5399 func = TOK___shldi3;
5400 goto gen_func;
5403 break;
5404 default:
5405 /* compare operations */
5406 t = vtop->type.t;
5407 vswap();
5408 lexpand();
5409 vrotb(3);
5410 lexpand();
5411 /* stack: L1 H1 L2 H2 */
5412 tmp = vtop[-1];
5413 vtop[-1] = vtop[-2];
5414 vtop[-2] = tmp;
5415 /* stack: L1 L2 H1 H2 */
5416 /* compare high */
5417 op1 = op;
5418 /* when values are equal, we need to compare low words. since
5419 the jump is inverted, we invert the test too. */
5420 if (op1 == TOK_LT)
5421 op1 = TOK_LE;
5422 else if (op1 == TOK_GT)
5423 op1 = TOK_GE;
5424 else if (op1 == TOK_ULT)
5425 op1 = TOK_ULE;
5426 else if (op1 == TOK_UGT)
5427 op1 = TOK_UGE;
5428 a = 0;
5429 b = 0;
5430 gen_op(op1);
5431 if (op1 != TOK_NE) {
5432 a = gtst(1, 0);
5434 if (op != TOK_EQ) {
5435 /* generate non equal test */
5436 /* XXX: NOT PORTABLE yet */
5437 if (a == 0) {
5438 b = gtst(0, 0);
5439 } else {
5440 #if defined(TCC_TARGET_I386)
5441 b = psym(0x850f, 0);
5442 #elif defined(TCC_TARGET_ARM)
5443 b = ind;
5444 o(0x1A000000 | encbranch(ind, 0, 1));
5445 #elif defined(TCC_TARGET_C67)
5446 error("not implemented");
5447 #else
5448 #error not supported
5449 #endif
5452 /* compare low. Always unsigned */
5453 op1 = op;
5454 if (op1 == TOK_LT)
5455 op1 = TOK_ULT;
5456 else if (op1 == TOK_LE)
5457 op1 = TOK_ULE;
5458 else if (op1 == TOK_GT)
5459 op1 = TOK_UGT;
5460 else if (op1 == TOK_GE)
5461 op1 = TOK_UGE;
5462 gen_op(op1);
5463 a = gtst(1, a);
5464 gsym(b);
5465 vseti(VT_JMPI, a);
5466 break;
5470 /* handle integer constant optimizations and various machine
5471 independent opt */
5472 void gen_opic(int op)
5474 int c1, c2, t1, t2, n;
5475 SValue *v1, *v2;
5476 long long l1, l2;
5477 typedef unsigned long long U;
5479 v1 = vtop - 1;
5480 v2 = vtop;
5481 t1 = v1->type.t & VT_BTYPE;
5482 t2 = v2->type.t & VT_BTYPE;
5483 l1 = (t1 == VT_LLONG) ? v1->c.ll : v1->c.i;
5484 l2 = (t2 == VT_LLONG) ? v2->c.ll : v2->c.i;
5486 /* currently, we cannot do computations with forward symbols */
5487 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5488 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5489 if (c1 && c2) {
5490 switch(op) {
5491 case '+': l1 += l2; break;
5492 case '-': l1 -= l2; break;
5493 case '&': l1 &= l2; break;
5494 case '^': l1 ^= l2; break;
5495 case '|': l1 |= l2; break;
5496 case '*': l1 *= l2; break;
5498 case TOK_PDIV:
5499 case '/':
5500 case '%':
5501 case TOK_UDIV:
5502 case TOK_UMOD:
5503 /* if division by zero, generate explicit division */
5504 if (l2 == 0) {
5505 if (const_wanted)
5506 error("division by zero in constant");
5507 goto general_case;
5509 switch(op) {
5510 default: l1 /= l2; break;
5511 case '%': l1 %= l2; break;
5512 case TOK_UDIV: l1 = (U)l1 / l2; break;
5513 case TOK_UMOD: l1 = (U)l1 % l2; break;
5515 break;
5516 case TOK_SHL: l1 <<= l2; break;
5517 case TOK_SHR: l1 = (U)l1 >> l2; break;
5518 case TOK_SAR: l1 >>= l2; break;
5519 /* tests */
5520 case TOK_ULT: l1 = (U)l1 < (U)l2; break;
5521 case TOK_UGE: l1 = (U)l1 >= (U)l2; break;
5522 case TOK_EQ: l1 = l1 == l2; break;
5523 case TOK_NE: l1 = l1 != l2; break;
5524 case TOK_ULE: l1 = (U)l1 <= (U)l2; break;
5525 case TOK_UGT: l1 = (U)l1 > (U)l2; break;
5526 case TOK_LT: l1 = l1 < l2; break;
5527 case TOK_GE: l1 = l1 >= l2; break;
5528 case TOK_LE: l1 = l1 <= l2; break;
5529 case TOK_GT: l1 = l1 > l2; break;
5530 /* logical */
5531 case TOK_LAND: l1 = l1 && l2; break;
5532 case TOK_LOR: l1 = l1 || l2; break;
5533 default:
5534 goto general_case;
5536 v1->c.ll = l1;
5537 vtop--;
5538 } else {
5539 /* if commutative ops, put c2 as constant */
5540 if (c1 && (op == '+' || op == '&' || op == '^' ||
5541 op == '|' || op == '*')) {
5542 vswap();
5543 c2 = c1; //c = c1, c1 = c2, c2 = c;
5544 l2 = l1; //l = l1, l1 = l2, l2 = l;
5546 /* Filter out NOP operations like x*1, x-0, x&-1... */
5547 if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
5548 op == TOK_PDIV) &&
5549 l2 == 1) ||
5550 ((op == '+' || op == '-' || op == '|' || op == '^' ||
5551 op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
5552 l2 == 0) ||
5553 (op == '&' &&
5554 l2 == -1))) {
5555 /* nothing to do */
5556 vtop--;
5557 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
5558 /* try to use shifts instead of muls or divs */
5559 if (l2 > 0 && (l2 & (l2 - 1)) == 0) {
5560 n = -1;
5561 while (l2) {
5562 l2 >>= 1;
5563 n++;
5565 vtop->c.ll = n;
5566 if (op == '*')
5567 op = TOK_SHL;
5568 else if (op == TOK_PDIV)
5569 op = TOK_SAR;
5570 else
5571 op = TOK_SHR;
5573 goto general_case;
5574 } else if (c2 && (op == '+' || op == '-') &&
5575 (vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) ==
5576 (VT_CONST | VT_SYM)) {
5577 /* symbol + constant case */
5578 if (op == '-')
5579 l2 = -l2;
5580 vtop--;
5581 vtop->c.ll += l2;
5582 } else {
5583 general_case:
5584 if (!nocode_wanted) {
5585 /* call low level op generator */
5586 if (t1 == VT_LLONG || t2 == VT_LLONG)
5587 gen_opl(op);
5588 else
5589 gen_opi(op);
5590 } else {
5591 vtop--;
5597 /* generate a floating point operation with constant propagation */
5598 void gen_opif(int op)
5600 int c1, c2;
5601 SValue *v1, *v2;
5602 long double f1, f2;
5604 v1 = vtop - 1;
5605 v2 = vtop;
5606 /* currently, we cannot do computations with forward symbols */
5607 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5608 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5609 if (c1 && c2) {
5610 if (v1->type.t == VT_FLOAT) {
5611 f1 = v1->c.f;
5612 f2 = v2->c.f;
5613 } else if (v1->type.t == VT_DOUBLE) {
5614 f1 = v1->c.d;
5615 f2 = v2->c.d;
5616 } else {
5617 f1 = v1->c.ld;
5618 f2 = v2->c.ld;
5621 /* NOTE: we only do constant propagation if finite number (not
5622 NaN or infinity) (ANSI spec) */
5623 if (!ieee_finite(f1) || !ieee_finite(f2))
5624 goto general_case;
5626 switch(op) {
5627 case '+': f1 += f2; break;
5628 case '-': f1 -= f2; break;
5629 case '*': f1 *= f2; break;
5630 case '/':
5631 if (f2 == 0.0) {
5632 if (const_wanted)
5633 error("division by zero in constant");
5634 goto general_case;
5636 f1 /= f2;
5637 break;
5638 /* XXX: also handles tests ? */
5639 default:
5640 goto general_case;
5642 /* XXX: overflow test ? */
5643 if (v1->type.t == VT_FLOAT) {
5644 v1->c.f = f1;
5645 } else if (v1->type.t == VT_DOUBLE) {
5646 v1->c.d = f1;
5647 } else {
5648 v1->c.ld = f1;
5650 vtop--;
5651 } else {
5652 general_case:
5653 if (!nocode_wanted) {
5654 gen_opf(op);
5655 } else {
5656 vtop--;
5661 static int pointed_size(CType *type)
5663 int align;
5664 return type_size(pointed_type(type), &align);
5667 static inline int is_null_pointer(SValue *p)
5669 if ((p->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
5670 return 0;
5671 return ((p->type.t & VT_BTYPE) == VT_INT && p->c.i == 0) ||
5672 ((p->type.t & VT_BTYPE) == VT_LLONG && p->c.ll == 0);
5675 static inline int is_integer_btype(int bt)
5677 return (bt == VT_BYTE || bt == VT_SHORT ||
5678 bt == VT_INT || bt == VT_LLONG);
5681 /* check types for comparison or substraction of pointers */
5682 static void check_comparison_pointer_types(SValue *p1, SValue *p2, int op)
5684 CType *type1, *type2, tmp_type1, tmp_type2;
5685 int bt1, bt2;
5687 /* null pointers are accepted for all comparisons as gcc */
5688 if (is_null_pointer(p1) || is_null_pointer(p2))
5689 return;
5690 type1 = &p1->type;
5691 type2 = &p2->type;
5692 bt1 = type1->t & VT_BTYPE;
5693 bt2 = type2->t & VT_BTYPE;
5694 /* accept comparison between pointer and integer with a warning */
5695 if ((is_integer_btype(bt1) || is_integer_btype(bt2)) && op != '-') {
5696 if (op != TOK_LOR && op != TOK_LAND )
5697 warning("comparison between pointer and integer");
5698 return;
5701 /* both must be pointers or implicit function pointers */
5702 if (bt1 == VT_PTR) {
5703 type1 = pointed_type(type1);
5704 } else if (bt1 != VT_FUNC)
5705 goto invalid_operands;
5707 if (bt2 == VT_PTR) {
5708 type2 = pointed_type(type2);
5709 } else if (bt2 != VT_FUNC) {
5710 invalid_operands:
5711 error("invalid operands to binary %s", get_tok_str(op, NULL));
5713 if ((type1->t & VT_BTYPE) == VT_VOID ||
5714 (type2->t & VT_BTYPE) == VT_VOID)
5715 return;
5716 tmp_type1 = *type1;
5717 tmp_type2 = *type2;
5718 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5719 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5720 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
5721 /* gcc-like error if '-' is used */
5722 if (op == '-')
5723 goto invalid_operands;
5724 else
5725 warning("comparison of distinct pointer types lacks a cast");
5729 /* generic gen_op: handles types problems */
5730 void gen_op(int op)
5732 int u, t1, t2, bt1, bt2, t;
5733 CType type1;
5735 t1 = vtop[-1].type.t;
5736 t2 = vtop[0].type.t;
5737 bt1 = t1 & VT_BTYPE;
5738 bt2 = t2 & VT_BTYPE;
5740 if (bt1 == VT_PTR || bt2 == VT_PTR) {
5741 /* at least one operand is a pointer */
5742 /* relationnal op: must be both pointers */
5743 if (op >= TOK_ULT && op <= TOK_LOR) {
5744 check_comparison_pointer_types(vtop - 1, vtop, op);
5745 /* pointers are handled are unsigned */
5746 t = VT_INT | VT_UNSIGNED;
5747 goto std_op;
5749 /* if both pointers, then it must be the '-' op */
5750 if (bt1 == VT_PTR && bt2 == VT_PTR) {
5751 if (op != '-')
5752 error("cannot use pointers here");
5753 check_comparison_pointer_types(vtop - 1, vtop, op);
5754 /* XXX: check that types are compatible */
5755 u = pointed_size(&vtop[-1].type);
5756 gen_opic(op);
5757 /* set to integer type */
5758 vtop->type.t = VT_INT;
5759 vpushi(u);
5760 gen_op(TOK_PDIV);
5761 } else {
5762 /* exactly one pointer : must be '+' or '-'. */
5763 if (op != '-' && op != '+')
5764 error("cannot use pointers here");
5765 /* Put pointer as first operand */
5766 if (bt2 == VT_PTR) {
5767 vswap();
5768 swap(&t1, &t2);
5770 type1 = vtop[-1].type;
5771 /* XXX: cast to int ? (long long case) */
5772 vpushi(pointed_size(&vtop[-1].type));
5773 gen_op('*');
5774 #ifdef CONFIG_TCC_BCHECK
5775 /* if evaluating constant expression, no code should be
5776 generated, so no bound check */
5777 if (do_bounds_check && !const_wanted) {
5778 /* if bounded pointers, we generate a special code to
5779 test bounds */
5780 if (op == '-') {
5781 vpushi(0);
5782 vswap();
5783 gen_op('-');
5785 gen_bounded_ptr_add();
5786 } else
5787 #endif
5789 gen_opic(op);
5791 /* put again type if gen_opic() swaped operands */
5792 vtop->type = type1;
5794 } else if (is_float(bt1) || is_float(bt2)) {
5795 /* compute bigger type and do implicit casts */
5796 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
5797 t = VT_LDOUBLE;
5798 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
5799 t = VT_DOUBLE;
5800 } else {
5801 t = VT_FLOAT;
5803 /* floats can only be used for a few operations */
5804 if (op != '+' && op != '-' && op != '*' && op != '/' &&
5805 (op < TOK_ULT || op > TOK_GT))
5806 error("invalid operands for binary operation");
5807 goto std_op;
5808 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
5809 /* cast to biggest op */
5810 t = VT_LLONG;
5811 /* convert to unsigned if it does not fit in a long long */
5812 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
5813 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
5814 t |= VT_UNSIGNED;
5815 goto std_op;
5816 } else {
5817 /* integer operations */
5818 t = VT_INT;
5819 /* convert to unsigned if it does not fit in an integer */
5820 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
5821 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
5822 t |= VT_UNSIGNED;
5823 std_op:
5824 /* XXX: currently, some unsigned operations are explicit, so
5825 we modify them here */
5826 if (t & VT_UNSIGNED) {
5827 if (op == TOK_SAR)
5828 op = TOK_SHR;
5829 else if (op == '/')
5830 op = TOK_UDIV;
5831 else if (op == '%')
5832 op = TOK_UMOD;
5833 else if (op == TOK_LT)
5834 op = TOK_ULT;
5835 else if (op == TOK_GT)
5836 op = TOK_UGT;
5837 else if (op == TOK_LE)
5838 op = TOK_ULE;
5839 else if (op == TOK_GE)
5840 op = TOK_UGE;
5842 vswap();
5843 type1.t = t;
5844 gen_cast(&type1);
5845 vswap();
5846 /* special case for shifts and long long: we keep the shift as
5847 an integer */
5848 if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL)
5849 type1.t = VT_INT;
5850 gen_cast(&type1);
5851 if (is_float(t))
5852 gen_opif(op);
5853 else
5854 gen_opic(op);
5855 if (op >= TOK_ULT && op <= TOK_GT) {
5856 /* relationnal op: the result is an int */
5857 vtop->type.t = VT_INT;
5858 } else {
5859 vtop->type.t = t;
5864 /* generic itof for unsigned long long case */
5865 void gen_cvt_itof1(int t)
5867 if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
5868 (VT_LLONG | VT_UNSIGNED)) {
5870 if (t == VT_FLOAT)
5871 vpush_global_sym(&func_old_type, TOK___ulltof);
5872 else if (t == VT_DOUBLE)
5873 vpush_global_sym(&func_old_type, TOK___ulltod);
5874 else
5875 vpush_global_sym(&func_old_type, TOK___ulltold);
5876 vrott(2);
5877 gfunc_call(1);
5878 vpushi(0);
5879 vtop->r = REG_FRET;
5880 } else {
5881 gen_cvt_itof(t);
5885 /* generic ftoi for unsigned long long case */
5886 void gen_cvt_ftoi1(int t)
5888 int st;
5890 if (t == (VT_LLONG | VT_UNSIGNED)) {
5891 /* not handled natively */
5892 st = vtop->type.t & VT_BTYPE;
5893 if (st == VT_FLOAT)
5894 vpush_global_sym(&func_old_type, TOK___fixunssfdi);
5895 else if (st == VT_DOUBLE)
5896 vpush_global_sym(&func_old_type, TOK___fixunsdfdi);
5897 else
5898 vpush_global_sym(&func_old_type, TOK___fixunsxfdi);
5899 vrott(2);
5900 gfunc_call(1);
5901 vpushi(0);
5902 vtop->r = REG_IRET;
5903 vtop->r2 = REG_LRET;
5904 } else {
5905 gen_cvt_ftoi(t);
5909 /* force char or short cast */
5910 void force_charshort_cast(int t)
5912 int bits, dbt;
5913 dbt = t & VT_BTYPE;
5914 /* XXX: add optimization if lvalue : just change type and offset */
5915 if (dbt == VT_BYTE)
5916 bits = 8;
5917 else
5918 bits = 16;
5919 if (t & VT_UNSIGNED) {
5920 vpushi((1 << bits) - 1);
5921 gen_op('&');
5922 } else {
5923 bits = 32 - bits;
5924 vpushi(bits);
5925 gen_op(TOK_SHL);
5926 /* result must be signed or the SAR is converted to an SHL
5927 This was not the case when "t" was a signed short
5928 and the last value on the stack was an unsigned int */
5929 vtop->type.t &= ~VT_UNSIGNED;
5930 vpushi(bits);
5931 gen_op(TOK_SAR);
5935 /* cast 'vtop' to 'type'. Casting to bitfields is forbidden. */
5936 static void gen_cast(CType *type)
5938 int sbt, dbt, sf, df, c;
5940 /* special delayed cast for char/short */
5941 /* XXX: in some cases (multiple cascaded casts), it may still
5942 be incorrect */
5943 if (vtop->r & VT_MUSTCAST) {
5944 vtop->r &= ~VT_MUSTCAST;
5945 force_charshort_cast(vtop->type.t);
5948 /* bitfields first get cast to ints */
5949 if (vtop->type.t & VT_BITFIELD) {
5950 gv(RC_INT);
5953 dbt = type->t & (VT_BTYPE | VT_UNSIGNED);
5954 sbt = vtop->type.t & (VT_BTYPE | VT_UNSIGNED);
5956 if (sbt != dbt && !nocode_wanted) {
5957 sf = is_float(sbt);
5958 df = is_float(dbt);
5959 c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5960 if (sf && df) {
5961 /* convert from fp to fp */
5962 if (c) {
5963 /* constant case: we can do it now */
5964 /* XXX: in ISOC, cannot do it if error in convert */
5965 if (dbt == VT_FLOAT && sbt == VT_DOUBLE)
5966 vtop->c.f = (float)vtop->c.d;
5967 else if (dbt == VT_FLOAT && sbt == VT_LDOUBLE)
5968 vtop->c.f = (float)vtop->c.ld;
5969 else if (dbt == VT_DOUBLE && sbt == VT_FLOAT)
5970 vtop->c.d = (double)vtop->c.f;
5971 else if (dbt == VT_DOUBLE && sbt == VT_LDOUBLE)
5972 vtop->c.d = (double)vtop->c.ld;
5973 else if (dbt == VT_LDOUBLE && sbt == VT_FLOAT)
5974 vtop->c.ld = (long double)vtop->c.f;
5975 else if (dbt == VT_LDOUBLE && sbt == VT_DOUBLE)
5976 vtop->c.ld = (long double)vtop->c.d;
5977 } else {
5978 /* non constant case: generate code */
5979 gen_cvt_ftof(dbt);
5981 } else if (df) {
5982 /* convert int to fp */
5983 if (c) {
5984 switch(sbt) {
5985 case VT_LLONG | VT_UNSIGNED:
5986 case VT_LLONG:
5987 /* XXX: add const cases for long long */
5988 goto do_itof;
5989 case VT_INT | VT_UNSIGNED:
5990 switch(dbt) {
5991 case VT_FLOAT: vtop->c.f = (float)vtop->c.ui; break;
5992 case VT_DOUBLE: vtop->c.d = (double)vtop->c.ui; break;
5993 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.ui; break;
5995 break;
5996 default:
5997 switch(dbt) {
5998 case VT_FLOAT: vtop->c.f = (float)vtop->c.i; break;
5999 case VT_DOUBLE: vtop->c.d = (double)vtop->c.i; break;
6000 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.i; break;
6002 break;
6004 } else {
6005 do_itof:
6006 #if !defined(TCC_TARGET_ARM)
6007 gen_cvt_itof1(dbt);
6008 #else
6009 gen_cvt_itof(dbt);
6010 #endif
6012 } else if (sf) {
6013 /* convert fp to int */
6014 if (dbt == VT_BOOL) {
6015 vpushi(0);
6016 gen_op(TOK_NE);
6017 } else {
6018 /* we handle char/short/etc... with generic code */
6019 if (dbt != (VT_INT | VT_UNSIGNED) &&
6020 dbt != (VT_LLONG | VT_UNSIGNED) &&
6021 dbt != VT_LLONG)
6022 dbt = VT_INT;
6023 if (c) {
6024 switch(dbt) {
6025 case VT_LLONG | VT_UNSIGNED:
6026 case VT_LLONG:
6027 /* XXX: add const cases for long long */
6028 goto do_ftoi;
6029 case VT_INT | VT_UNSIGNED:
6030 switch(sbt) {
6031 case VT_FLOAT: vtop->c.ui = (unsigned int)vtop->c.d; break;
6032 case VT_DOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
6033 case VT_LDOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
6035 break;
6036 default:
6037 /* int case */
6038 switch(sbt) {
6039 case VT_FLOAT: vtop->c.i = (int)vtop->c.d; break;
6040 case VT_DOUBLE: vtop->c.i = (int)vtop->c.d; break;
6041 case VT_LDOUBLE: vtop->c.i = (int)vtop->c.d; break;
6043 break;
6045 } else {
6046 do_ftoi:
6047 gen_cvt_ftoi1(dbt);
6049 if (dbt == VT_INT && (type->t & (VT_BTYPE | VT_UNSIGNED)) != dbt) {
6050 /* additional cast for char/short... */
6051 vtop->type.t = dbt;
6052 gen_cast(type);
6055 } else if ((dbt & VT_BTYPE) == VT_LLONG) {
6056 if ((sbt & VT_BTYPE) != VT_LLONG) {
6057 /* scalar to long long */
6058 if (c) {
6059 if (sbt == (VT_INT | VT_UNSIGNED))
6060 vtop->c.ll = vtop->c.ui;
6061 else
6062 vtop->c.ll = vtop->c.i;
6063 } else {
6064 /* machine independent conversion */
6065 gv(RC_INT);
6066 /* generate high word */
6067 if (sbt == (VT_INT | VT_UNSIGNED)) {
6068 vpushi(0);
6069 gv(RC_INT);
6070 } else {
6071 gv_dup();
6072 vpushi(31);
6073 gen_op(TOK_SAR);
6075 /* patch second register */
6076 vtop[-1].r2 = vtop->r;
6077 vpop();
6080 } else if (dbt == VT_BOOL) {
6081 /* scalar to bool */
6082 vpushi(0);
6083 gen_op(TOK_NE);
6084 } else if ((dbt & VT_BTYPE) == VT_BYTE ||
6085 (dbt & VT_BTYPE) == VT_SHORT) {
6086 if (sbt == VT_PTR) {
6087 vtop->type.t = VT_INT;
6088 warning("nonportable conversion from pointer to char/short");
6090 force_charshort_cast(dbt);
6091 } else if ((dbt & VT_BTYPE) == VT_INT) {
6092 /* scalar to int */
6093 if (sbt == VT_LLONG) {
6094 /* from long long: just take low order word */
6095 lexpand();
6096 vpop();
6098 /* if lvalue and single word type, nothing to do because
6099 the lvalue already contains the real type size (see
6100 VT_LVAL_xxx constants) */
6102 } else if ((dbt & VT_BTYPE) == VT_PTR && !(vtop->r & VT_LVAL)) {
6103 /* if we are casting between pointer types,
6104 we must update the VT_LVAL_xxx size */
6105 vtop->r = (vtop->r & ~VT_LVAL_TYPE)
6106 | (lvalue_type(type->ref->type.t) & VT_LVAL_TYPE);
6108 vtop->type = *type;
6111 /* return type size. Put alignment at 'a' */
6112 static int type_size(CType *type, int *a)
6114 Sym *s;
6115 int bt;
6117 bt = type->t & VT_BTYPE;
6118 if (bt == VT_STRUCT) {
6119 /* struct/union */
6120 s = type->ref;
6121 *a = s->r;
6122 return s->c;
6123 } else if (bt == VT_PTR) {
6124 if (type->t & VT_ARRAY) {
6125 s = type->ref;
6126 return type_size(&s->type, a) * s->c;
6127 } else {
6128 *a = PTR_SIZE;
6129 return PTR_SIZE;
6131 } else if (bt == VT_LDOUBLE) {
6132 *a = LDOUBLE_ALIGN;
6133 return LDOUBLE_SIZE;
6134 } else if (bt == VT_DOUBLE || bt == VT_LLONG) {
6135 #ifdef TCC_TARGET_I386
6136 *a = 4;
6137 #elif defined(TCC_TARGET_ARM)
6138 #ifdef TCC_ARM_EABI
6139 *a = 8;
6140 #else
6141 *a = 4;
6142 #endif
6143 #else
6144 *a = 8;
6145 #endif
6146 return 8;
6147 } else if (bt == VT_INT || bt == VT_ENUM || bt == VT_FLOAT) {
6148 *a = 4;
6149 return 4;
6150 } else if (bt == VT_SHORT) {
6151 *a = 2;
6152 return 2;
6153 } else {
6154 /* char, void, function, _Bool */
6155 *a = 1;
6156 return 1;
6160 /* return the pointed type of t */
6161 static inline CType *pointed_type(CType *type)
6163 return &type->ref->type;
6166 /* modify type so that its it is a pointer to type. */
6167 static void mk_pointer(CType *type)
6169 Sym *s;
6170 s = sym_push(SYM_FIELD, type, 0, -1);
6171 type->t = VT_PTR | (type->t & ~VT_TYPE);
6172 type->ref = s;
6175 /* compare function types. OLD functions match any new functions */
6176 static int is_compatible_func(CType *type1, CType *type2)
6178 Sym *s1, *s2;
6180 s1 = type1->ref;
6181 s2 = type2->ref;
6182 if (!is_compatible_types(&s1->type, &s2->type))
6183 return 0;
6184 /* check func_call */
6185 if (FUNC_CALL(s1->r) != FUNC_CALL(s2->r))
6186 return 0;
6187 /* XXX: not complete */
6188 if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
6189 return 1;
6190 if (s1->c != s2->c)
6191 return 0;
6192 while (s1 != NULL) {
6193 if (s2 == NULL)
6194 return 0;
6195 if (!is_compatible_parameter_types(&s1->type, &s2->type))
6196 return 0;
6197 s1 = s1->next;
6198 s2 = s2->next;
6200 if (s2)
6201 return 0;
6202 return 1;
6205 /* return true if type1 and type2 are the same. If unqualified is
6206 true, qualifiers on the types are ignored.
6208 - enums are not checked as gcc __builtin_types_compatible_p ()
6210 static int compare_types(CType *type1, CType *type2, int unqualified)
6212 int bt1, t1, t2;
6214 t1 = type1->t & VT_TYPE;
6215 t2 = type2->t & VT_TYPE;
6216 if (unqualified) {
6217 /* strip qualifiers before comparing */
6218 t1 &= ~(VT_CONSTANT | VT_VOLATILE);
6219 t2 &= ~(VT_CONSTANT | VT_VOLATILE);
6221 /* XXX: bitfields ? */
6222 if (t1 != t2)
6223 return 0;
6224 /* test more complicated cases */
6225 bt1 = t1 & VT_BTYPE;
6226 if (bt1 == VT_PTR) {
6227 type1 = pointed_type(type1);
6228 type2 = pointed_type(type2);
6229 return is_compatible_types(type1, type2);
6230 } else if (bt1 == VT_STRUCT) {
6231 return (type1->ref == type2->ref);
6232 } else if (bt1 == VT_FUNC) {
6233 return is_compatible_func(type1, type2);
6234 } else {
6235 return 1;
6239 /* return true if type1 and type2 are exactly the same (including
6240 qualifiers).
6242 static int is_compatible_types(CType *type1, CType *type2)
6244 return compare_types(type1,type2,0);
6247 /* return true if type1 and type2 are the same (ignoring qualifiers).
6249 static int is_compatible_parameter_types(CType *type1, CType *type2)
6251 return compare_types(type1,type2,1);
6254 /* print a type. If 'varstr' is not NULL, then the variable is also
6255 printed in the type */
6256 /* XXX: union */
6257 /* XXX: add array and function pointers */
6258 void type_to_str(char *buf, int buf_size,
6259 CType *type, const char *varstr)
6261 int bt, v, t;
6262 Sym *s, *sa;
6263 char buf1[256];
6264 const char *tstr;
6266 t = type->t & VT_TYPE;
6267 bt = t & VT_BTYPE;
6268 buf[0] = '\0';
6269 if (t & VT_CONSTANT)
6270 pstrcat(buf, buf_size, "const ");
6271 if (t & VT_VOLATILE)
6272 pstrcat(buf, buf_size, "volatile ");
6273 if (t & VT_UNSIGNED)
6274 pstrcat(buf, buf_size, "unsigned ");
6275 switch(bt) {
6276 case VT_VOID:
6277 tstr = "void";
6278 goto add_tstr;
6279 case VT_BOOL:
6280 tstr = "_Bool";
6281 goto add_tstr;
6282 case VT_BYTE:
6283 tstr = "char";
6284 goto add_tstr;
6285 case VT_SHORT:
6286 tstr = "short";
6287 goto add_tstr;
6288 case VT_INT:
6289 tstr = "int";
6290 goto add_tstr;
6291 case VT_LONG:
6292 tstr = "long";
6293 goto add_tstr;
6294 case VT_LLONG:
6295 tstr = "long long";
6296 goto add_tstr;
6297 case VT_FLOAT:
6298 tstr = "float";
6299 goto add_tstr;
6300 case VT_DOUBLE:
6301 tstr = "double";
6302 goto add_tstr;
6303 case VT_LDOUBLE:
6304 tstr = "long double";
6305 add_tstr:
6306 pstrcat(buf, buf_size, tstr);
6307 break;
6308 case VT_ENUM:
6309 case VT_STRUCT:
6310 if (bt == VT_STRUCT)
6311 tstr = "struct ";
6312 else
6313 tstr = "enum ";
6314 pstrcat(buf, buf_size, tstr);
6315 v = type->ref->v & ~SYM_STRUCT;
6316 if (v >= SYM_FIRST_ANOM)
6317 pstrcat(buf, buf_size, "<anonymous>");
6318 else
6319 pstrcat(buf, buf_size, get_tok_str(v, NULL));
6320 break;
6321 case VT_FUNC:
6322 s = type->ref;
6323 type_to_str(buf, buf_size, &s->type, varstr);
6324 pstrcat(buf, buf_size, "(");
6325 sa = s->next;
6326 while (sa != NULL) {
6327 type_to_str(buf1, sizeof(buf1), &sa->type, NULL);
6328 pstrcat(buf, buf_size, buf1);
6329 sa = sa->next;
6330 if (sa)
6331 pstrcat(buf, buf_size, ", ");
6333 pstrcat(buf, buf_size, ")");
6334 goto no_var;
6335 case VT_PTR:
6336 s = type->ref;
6337 pstrcpy(buf1, sizeof(buf1), "*");
6338 if (varstr)
6339 pstrcat(buf1, sizeof(buf1), varstr);
6340 type_to_str(buf, buf_size, &s->type, buf1);
6341 goto no_var;
6343 if (varstr) {
6344 pstrcat(buf, buf_size, " ");
6345 pstrcat(buf, buf_size, varstr);
6347 no_var: ;
6350 /* verify type compatibility to store vtop in 'dt' type, and generate
6351 casts if needed. */
6352 static void gen_assign_cast(CType *dt)
6354 CType *st, *type1, *type2, tmp_type1, tmp_type2;
6355 char buf1[256], buf2[256];
6356 int dbt, sbt;
6358 st = &vtop->type; /* source type */
6359 dbt = dt->t & VT_BTYPE;
6360 sbt = st->t & VT_BTYPE;
6361 if (dt->t & VT_CONSTANT)
6362 warning("assignment of read-only location");
6363 switch(dbt) {
6364 case VT_PTR:
6365 /* special cases for pointers */
6366 /* '0' can also be a pointer */
6367 if (is_null_pointer(vtop))
6368 goto type_ok;
6369 /* accept implicit pointer to integer cast with warning */
6370 if (is_integer_btype(sbt)) {
6371 warning("assignment makes pointer from integer without a cast");
6372 goto type_ok;
6374 type1 = pointed_type(dt);
6375 /* a function is implicitely a function pointer */
6376 if (sbt == VT_FUNC) {
6377 if ((type1->t & VT_BTYPE) != VT_VOID &&
6378 !is_compatible_types(pointed_type(dt), st))
6379 goto error;
6380 else
6381 goto type_ok;
6383 if (sbt != VT_PTR)
6384 goto error;
6385 type2 = pointed_type(st);
6386 if ((type1->t & VT_BTYPE) == VT_VOID ||
6387 (type2->t & VT_BTYPE) == VT_VOID) {
6388 /* void * can match anything */
6389 } else {
6390 /* exact type match, except for unsigned */
6391 tmp_type1 = *type1;
6392 tmp_type2 = *type2;
6393 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
6394 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
6395 if (!is_compatible_types(&tmp_type1, &tmp_type2))
6396 warning("assignment from incompatible pointer type");
6398 /* check const and volatile */
6399 if ((!(type1->t & VT_CONSTANT) && (type2->t & VT_CONSTANT)) ||
6400 (!(type1->t & VT_VOLATILE) && (type2->t & VT_VOLATILE)))
6401 warning("assignment discards qualifiers from pointer target type");
6402 break;
6403 case VT_BYTE:
6404 case VT_SHORT:
6405 case VT_INT:
6406 case VT_LLONG:
6407 if (sbt == VT_PTR || sbt == VT_FUNC) {
6408 warning("assignment makes integer from pointer without a cast");
6410 /* XXX: more tests */
6411 break;
6412 case VT_STRUCT:
6413 tmp_type1 = *dt;
6414 tmp_type2 = *st;
6415 tmp_type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
6416 tmp_type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
6417 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
6418 error:
6419 type_to_str(buf1, sizeof(buf1), st, NULL);
6420 type_to_str(buf2, sizeof(buf2), dt, NULL);
6421 error("cannot cast '%s' to '%s'", buf1, buf2);
6423 break;
6425 type_ok:
6426 gen_cast(dt);
6429 /* store vtop in lvalue pushed on stack */
6430 void vstore(void)
6432 int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
6434 ft = vtop[-1].type.t;
6435 sbt = vtop->type.t & VT_BTYPE;
6436 dbt = ft & VT_BTYPE;
6437 if (((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
6438 (sbt == VT_INT && dbt == VT_SHORT)) {
6439 /* optimize char/short casts */
6440 delayed_cast = VT_MUSTCAST;
6441 vtop->type.t = ft & VT_TYPE;
6442 /* XXX: factorize */
6443 if (ft & VT_CONSTANT)
6444 warning("assignment of read-only location");
6445 } else {
6446 delayed_cast = 0;
6447 if (!(ft & VT_BITFIELD))
6448 gen_assign_cast(&vtop[-1].type);
6451 if (sbt == VT_STRUCT) {
6452 /* if structure, only generate pointer */
6453 /* structure assignment : generate memcpy */
6454 /* XXX: optimize if small size */
6455 if (!nocode_wanted) {
6456 size = type_size(&vtop->type, &align);
6458 #ifdef TCC_ARM_EABI
6459 if(!(align & 7))
6460 vpush_global_sym(&func_old_type, TOK_memcpy8);
6461 else if(!(align & 3))
6462 vpush_global_sym(&func_old_type, TOK_memcpy4);
6463 else
6464 #endif
6465 vpush_global_sym(&func_old_type, TOK_memcpy);
6467 /* destination */
6468 vpushv(vtop - 2);
6469 vtop->type.t = VT_INT;
6470 gaddrof();
6471 /* source */
6472 vpushv(vtop - 2);
6473 vtop->type.t = VT_INT;
6474 gaddrof();
6475 /* type size */
6476 vpushi(size);
6477 gfunc_call(3);
6479 vswap();
6480 vpop();
6481 } else {
6482 vswap();
6483 vpop();
6485 /* leave source on stack */
6486 } else if (ft & VT_BITFIELD) {
6487 /* bitfield store handling */
6488 bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
6489 bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
6490 /* remove bit field info to avoid loops */
6491 vtop[-1].type.t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
6493 /* duplicate source into other register */
6494 gv_dup();
6495 vswap();
6496 vrott(3);
6498 /* duplicate destination */
6499 vdup();
6500 vtop[-1] = vtop[-2];
6502 /* mask and shift source */
6503 vpushi((1 << bit_size) - 1);
6504 gen_op('&');
6505 vpushi(bit_pos);
6506 gen_op(TOK_SHL);
6507 /* load destination, mask and or with source */
6508 vswap();
6509 vpushi(~(((1 << bit_size) - 1) << bit_pos));
6510 gen_op('&');
6511 gen_op('|');
6512 /* store result */
6513 vstore();
6515 /* pop off shifted source from "duplicate source..." above */
6516 vpop();
6518 } else {
6519 #ifdef CONFIG_TCC_BCHECK
6520 /* bound check case */
6521 if (vtop[-1].r & VT_MUSTBOUND) {
6522 vswap();
6523 gbound();
6524 vswap();
6526 #endif
6527 if (!nocode_wanted) {
6528 rc = RC_INT;
6529 if (is_float(ft))
6530 rc = RC_FLOAT;
6531 r = gv(rc); /* generate value */
6532 /* if lvalue was saved on stack, must read it */
6533 if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
6534 SValue sv;
6535 t = get_reg(RC_INT);
6536 sv.type.t = VT_INT;
6537 sv.r = VT_LOCAL | VT_LVAL;
6538 sv.c.ul = vtop[-1].c.ul;
6539 load(t, &sv);
6540 vtop[-1].r = t | VT_LVAL;
6542 store(r, vtop - 1);
6543 /* two word case handling : store second register at word + 4 */
6544 if ((ft & VT_BTYPE) == VT_LLONG) {
6545 vswap();
6546 /* convert to int to increment easily */
6547 vtop->type.t = VT_INT;
6548 gaddrof();
6549 vpushi(4);
6550 gen_op('+');
6551 vtop->r |= VT_LVAL;
6552 vswap();
6553 /* XXX: it works because r2 is spilled last ! */
6554 store(vtop->r2, vtop - 1);
6557 vswap();
6558 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
6559 vtop->r |= delayed_cast;
6563 /* post defines POST/PRE add. c is the token ++ or -- */
6564 void inc(int post, int c)
6566 test_lvalue();
6567 vdup(); /* save lvalue */
6568 if (post) {
6569 gv_dup(); /* duplicate value */
6570 vrotb(3);
6571 vrotb(3);
6573 /* add constant */
6574 vpushi(c - TOK_MID);
6575 gen_op('+');
6576 vstore(); /* store value */
6577 if (post)
6578 vpop(); /* if post op, return saved value */
6581 /* Parse GNUC __attribute__ extension. Currently, the following
6582 extensions are recognized:
6583 - aligned(n) : set data/function alignment.
6584 - packed : force data alignment to 1
6585 - section(x) : generate data/code in this section.
6586 - unused : currently ignored, but may be used someday.
6587 - regparm(n) : pass function parameters in registers (i386 only)
6589 static void parse_attribute(AttributeDef *ad)
6591 int t, n;
6593 while (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) {
6594 next();
6595 skip('(');
6596 skip('(');
6597 while (tok != ')') {
6598 if (tok < TOK_IDENT)
6599 expect("attribute name");
6600 t = tok;
6601 next();
6602 switch(t) {
6603 case TOK_SECTION1:
6604 case TOK_SECTION2:
6605 skip('(');
6606 if (tok != TOK_STR)
6607 expect("section name");
6608 ad->section = find_section(tcc_state, (char *)tokc.cstr->data);
6609 next();
6610 skip(')');
6611 break;
6612 case TOK_ALIGNED1:
6613 case TOK_ALIGNED2:
6614 if (tok == '(') {
6615 next();
6616 n = expr_const();
6617 if (n <= 0 || (n & (n - 1)) != 0)
6618 error("alignment must be a positive power of two");
6619 skip(')');
6620 } else {
6621 n = MAX_ALIGN;
6623 ad->aligned = n;
6624 break;
6625 case TOK_PACKED1:
6626 case TOK_PACKED2:
6627 ad->packed = 1;
6628 break;
6629 case TOK_UNUSED1:
6630 case TOK_UNUSED2:
6631 /* currently, no need to handle it because tcc does not
6632 track unused objects */
6633 break;
6634 case TOK_NORETURN1:
6635 case TOK_NORETURN2:
6636 /* currently, no need to handle it because tcc does not
6637 track unused objects */
6638 break;
6639 case TOK_CDECL1:
6640 case TOK_CDECL2:
6641 case TOK_CDECL3:
6642 FUNC_CALL(ad->func_attr) = FUNC_CDECL;
6643 break;
6644 case TOK_STDCALL1:
6645 case TOK_STDCALL2:
6646 case TOK_STDCALL3:
6647 FUNC_CALL(ad->func_attr) = FUNC_STDCALL;
6648 break;
6649 #ifdef TCC_TARGET_I386
6650 case TOK_REGPARM1:
6651 case TOK_REGPARM2:
6652 skip('(');
6653 n = expr_const();
6654 if (n > 3)
6655 n = 3;
6656 else if (n < 0)
6657 n = 0;
6658 if (n > 0)
6659 FUNC_CALL(ad->func_attr) = FUNC_FASTCALL1 + n - 1;
6660 skip(')');
6661 break;
6662 case TOK_FASTCALL1:
6663 case TOK_FASTCALL2:
6664 case TOK_FASTCALL3:
6665 FUNC_CALL(ad->func_attr) = FUNC_FASTCALLW;
6666 break;
6667 #endif
6668 case TOK_DLLEXPORT:
6669 FUNC_EXPORT(ad->func_attr) = 1;
6670 break;
6671 default:
6672 if (tcc_state->warn_unsupported)
6673 warning("'%s' attribute ignored", get_tok_str(t, NULL));
6674 /* skip parameters */
6675 if (tok == '(') {
6676 int parenthesis = 0;
6677 do {
6678 if (tok == '(')
6679 parenthesis++;
6680 else if (tok == ')')
6681 parenthesis--;
6682 next();
6683 } while (parenthesis && tok != -1);
6685 break;
6687 if (tok != ',')
6688 break;
6689 next();
6691 skip(')');
6692 skip(')');
6696 /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
6697 static void struct_decl(CType *type, int u)
6699 int a, v, size, align, maxalign, c, offset;
6700 int bit_size, bit_pos, bsize, bt, lbit_pos;
6701 Sym *s, *ss, *ass, **ps;
6702 AttributeDef ad;
6703 CType type1, btype;
6705 a = tok; /* save decl type */
6706 next();
6707 if (tok != '{') {
6708 v = tok;
6709 next();
6710 /* struct already defined ? return it */
6711 if (v < TOK_IDENT)
6712 expect("struct/union/enum name");
6713 s = struct_find(v);
6714 if (s) {
6715 if (s->type.t != a)
6716 error("invalid type");
6717 goto do_decl;
6719 } else {
6720 v = anon_sym++;
6722 type1.t = a;
6723 /* we put an undefined size for struct/union */
6724 s = sym_push(v | SYM_STRUCT, &type1, 0, -1);
6725 s->r = 0; /* default alignment is zero as gcc */
6726 /* put struct/union/enum name in type */
6727 do_decl:
6728 type->t = u;
6729 type->ref = s;
6731 if (tok == '{') {
6732 next();
6733 if (s->c != -1)
6734 error("struct/union/enum already defined");
6735 /* cannot be empty */
6736 c = 0;
6737 /* non empty enums are not allowed */
6738 if (a == TOK_ENUM) {
6739 for(;;) {
6740 v = tok;
6741 if (v < TOK_UIDENT)
6742 expect("identifier");
6743 next();
6744 if (tok == '=') {
6745 next();
6746 c = expr_const();
6748 /* enum symbols have static storage */
6749 ss = sym_push(v, &int_type, VT_CONST, c);
6750 ss->type.t |= VT_STATIC;
6751 if (tok != ',')
6752 break;
6753 next();
6754 c++;
6755 /* NOTE: we accept a trailing comma */
6756 if (tok == '}')
6757 break;
6759 skip('}');
6760 } else {
6761 maxalign = 1;
6762 ps = &s->next;
6763 bit_pos = 0;
6764 offset = 0;
6765 while (tok != '}') {
6766 parse_btype(&btype, &ad);
6767 while (1) {
6768 bit_size = -1;
6769 v = 0;
6770 type1 = btype;
6771 if (tok != ':') {
6772 type_decl(&type1, &ad, &v, TYPE_DIRECT | TYPE_ABSTRACT);
6773 if (v == 0 && (type1.t & VT_BTYPE) != VT_STRUCT)
6774 expect("identifier");
6775 if ((type1.t & VT_BTYPE) == VT_FUNC ||
6776 (type1.t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN | VT_INLINE)))
6777 error("invalid type for '%s'",
6778 get_tok_str(v, NULL));
6780 if (tok == ':') {
6781 next();
6782 bit_size = expr_const();
6783 /* XXX: handle v = 0 case for messages */
6784 if (bit_size < 0)
6785 error("negative width in bit-field '%s'",
6786 get_tok_str(v, NULL));
6787 if (v && bit_size == 0)
6788 error("zero width for bit-field '%s'",
6789 get_tok_str(v, NULL));
6791 size = type_size(&type1, &align);
6792 if (ad.aligned) {
6793 if (align < ad.aligned)
6794 align = ad.aligned;
6795 } else if (ad.packed) {
6796 align = 1;
6797 } else if (*tcc_state->pack_stack_ptr) {
6798 if (align > *tcc_state->pack_stack_ptr)
6799 align = *tcc_state->pack_stack_ptr;
6801 lbit_pos = 0;
6802 if (bit_size >= 0) {
6803 bt = type1.t & VT_BTYPE;
6804 if (bt != VT_INT &&
6805 bt != VT_BYTE &&
6806 bt != VT_SHORT &&
6807 bt != VT_BOOL &&
6808 bt != VT_ENUM)
6809 error("bitfields must have scalar type");
6810 bsize = size * 8;
6811 if (bit_size > bsize) {
6812 error("width of '%s' exceeds its type",
6813 get_tok_str(v, NULL));
6814 } else if (bit_size == bsize) {
6815 /* no need for bit fields */
6816 bit_pos = 0;
6817 } else if (bit_size == 0) {
6818 /* XXX: what to do if only padding in a
6819 structure ? */
6820 /* zero size: means to pad */
6821 if (bit_pos > 0)
6822 bit_pos = bsize;
6823 } else {
6824 /* we do not have enough room ? */
6825 if ((bit_pos + bit_size) > bsize)
6826 bit_pos = 0;
6827 lbit_pos = bit_pos;
6828 /* XXX: handle LSB first */
6829 type1.t |= VT_BITFIELD |
6830 (bit_pos << VT_STRUCT_SHIFT) |
6831 (bit_size << (VT_STRUCT_SHIFT + 6));
6832 bit_pos += bit_size;
6834 } else {
6835 bit_pos = 0;
6837 if (v != 0 || (type1.t & VT_BTYPE) == VT_STRUCT) {
6838 /* add new memory data only if starting
6839 bit field */
6840 if (lbit_pos == 0) {
6841 if (a == TOK_STRUCT) {
6842 c = (c + align - 1) & -align;
6843 offset = c;
6844 if (size > 0)
6845 c += size;
6846 } else {
6847 offset = 0;
6848 if (size > c)
6849 c = size;
6851 if (align > maxalign)
6852 maxalign = align;
6854 #if 0
6855 printf("add field %s offset=%d",
6856 get_tok_str(v, NULL), offset);
6857 if (type1.t & VT_BITFIELD) {
6858 printf(" pos=%d size=%d",
6859 (type1.t >> VT_STRUCT_SHIFT) & 0x3f,
6860 (type1.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
6862 printf("\n");
6863 #endif
6865 if (v == 0 && (type1.t & VT_BTYPE) == VT_STRUCT) {
6866 ass = type1.ref;
6867 while ((ass = ass->next) != NULL) {
6868 ss = sym_push(ass->v, &ass->type, 0, offset + ass->c);
6869 *ps = ss;
6870 ps = &ss->next;
6872 } else if (v) {
6873 ss = sym_push(v | SYM_FIELD, &type1, 0, offset);
6874 *ps = ss;
6875 ps = &ss->next;
6877 if (tok == ';' || tok == TOK_EOF)
6878 break;
6879 skip(',');
6881 skip(';');
6883 skip('}');
6884 /* store size and alignment */
6885 s->c = (c + maxalign - 1) & -maxalign;
6886 s->r = maxalign;
6891 /* return 0 if no type declaration. otherwise, return the basic type
6892 and skip it.
6894 static int parse_btype(CType *type, AttributeDef *ad)
6896 int t, u, type_found, typespec_found, typedef_found;
6897 Sym *s;
6898 CType type1;
6900 memset(ad, 0, sizeof(AttributeDef));
6901 type_found = 0;
6902 typespec_found = 0;
6903 typedef_found = 0;
6904 t = 0;
6905 while(1) {
6906 switch(tok) {
6907 case TOK_EXTENSION:
6908 /* currently, we really ignore extension */
6909 next();
6910 continue;
6912 /* basic types */
6913 case TOK_CHAR:
6914 u = VT_BYTE;
6915 basic_type:
6916 next();
6917 basic_type1:
6918 if ((t & VT_BTYPE) != 0)
6919 error("too many basic types");
6920 t |= u;
6921 typespec_found = 1;
6922 break;
6923 case TOK_VOID:
6924 u = VT_VOID;
6925 goto basic_type;
6926 case TOK_SHORT:
6927 u = VT_SHORT;
6928 goto basic_type;
6929 case TOK_INT:
6930 next();
6931 typespec_found = 1;
6932 break;
6933 case TOK_LONG:
6934 next();
6935 if ((t & VT_BTYPE) == VT_DOUBLE) {
6936 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6937 } else if ((t & VT_BTYPE) == VT_LONG) {
6938 t = (t & ~VT_BTYPE) | VT_LLONG;
6939 } else {
6940 u = VT_LONG;
6941 goto basic_type1;
6943 break;
6944 case TOK_BOOL:
6945 u = VT_BOOL;
6946 goto basic_type;
6947 case TOK_FLOAT:
6948 u = VT_FLOAT;
6949 goto basic_type;
6950 case TOK_DOUBLE:
6951 next();
6952 if ((t & VT_BTYPE) == VT_LONG) {
6953 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6954 } else {
6955 u = VT_DOUBLE;
6956 goto basic_type1;
6958 break;
6959 case TOK_ENUM:
6960 struct_decl(&type1, VT_ENUM);
6961 basic_type2:
6962 u = type1.t;
6963 type->ref = type1.ref;
6964 goto basic_type1;
6965 case TOK_STRUCT:
6966 case TOK_UNION:
6967 struct_decl(&type1, VT_STRUCT);
6968 goto basic_type2;
6970 /* type modifiers */
6971 case TOK_CONST1:
6972 case TOK_CONST2:
6973 case TOK_CONST3:
6974 t |= VT_CONSTANT;
6975 next();
6976 break;
6977 case TOK_VOLATILE1:
6978 case TOK_VOLATILE2:
6979 case TOK_VOLATILE3:
6980 t |= VT_VOLATILE;
6981 next();
6982 break;
6983 case TOK_SIGNED1:
6984 case TOK_SIGNED2:
6985 case TOK_SIGNED3:
6986 typespec_found = 1;
6987 t |= VT_SIGNED;
6988 next();
6989 break;
6990 case TOK_REGISTER:
6991 case TOK_AUTO:
6992 case TOK_RESTRICT1:
6993 case TOK_RESTRICT2:
6994 case TOK_RESTRICT3:
6995 next();
6996 break;
6997 case TOK_UNSIGNED:
6998 t |= VT_UNSIGNED;
6999 next();
7000 typespec_found = 1;
7001 break;
7003 /* storage */
7004 case TOK_EXTERN:
7005 t |= VT_EXTERN;
7006 next();
7007 break;
7008 case TOK_STATIC:
7009 t |= VT_STATIC;
7010 next();
7011 break;
7012 case TOK_TYPEDEF:
7013 t |= VT_TYPEDEF;
7014 next();
7015 break;
7016 case TOK_INLINE1:
7017 case TOK_INLINE2:
7018 case TOK_INLINE3:
7019 t |= VT_INLINE;
7020 next();
7021 break;
7023 /* GNUC attribute */
7024 case TOK_ATTRIBUTE1:
7025 case TOK_ATTRIBUTE2:
7026 parse_attribute(ad);
7027 break;
7028 /* GNUC typeof */
7029 case TOK_TYPEOF1:
7030 case TOK_TYPEOF2:
7031 case TOK_TYPEOF3:
7032 next();
7033 parse_expr_type(&type1);
7034 goto basic_type2;
7035 default:
7036 if (typespec_found || typedef_found)
7037 goto the_end;
7038 s = sym_find(tok);
7039 if (!s || !(s->type.t & VT_TYPEDEF))
7040 goto the_end;
7041 typedef_found = 1;
7042 t |= (s->type.t & ~VT_TYPEDEF);
7043 type->ref = s->type.ref;
7044 next();
7045 typespec_found = 1;
7046 break;
7048 type_found = 1;
7050 the_end:
7051 if ((t & (VT_SIGNED|VT_UNSIGNED)) == (VT_SIGNED|VT_UNSIGNED))
7052 error("signed and unsigned modifier");
7053 if (tcc_state->char_is_unsigned) {
7054 if ((t & (VT_SIGNED|VT_UNSIGNED|VT_BTYPE)) == VT_BYTE)
7055 t |= VT_UNSIGNED;
7057 t &= ~VT_SIGNED;
7059 /* long is never used as type */
7060 if ((t & VT_BTYPE) == VT_LONG)
7061 t = (t & ~VT_BTYPE) | VT_INT;
7062 type->t = t;
7063 return type_found;
7066 /* convert a function parameter type (array to pointer and function to
7067 function pointer) */
7068 static inline void convert_parameter_type(CType *pt)
7070 /* remove const and volatile qualifiers (XXX: const could be used
7071 to indicate a const function parameter */
7072 pt->t &= ~(VT_CONSTANT | VT_VOLATILE);
7073 /* array must be transformed to pointer according to ANSI C */
7074 pt->t &= ~VT_ARRAY;
7075 if ((pt->t & VT_BTYPE) == VT_FUNC) {
7076 mk_pointer(pt);
7080 static void post_type(CType *type, AttributeDef *ad)
7082 int n, l, t1, arg_size, align;
7083 Sym **plast, *s, *first;
7084 AttributeDef ad1;
7085 CType pt;
7087 if (tok == '(') {
7088 /* function declaration */
7089 next();
7090 l = 0;
7091 first = NULL;
7092 plast = &first;
7093 arg_size = 0;
7094 if (tok != ')') {
7095 for(;;) {
7096 /* read param name and compute offset */
7097 if (l != FUNC_OLD) {
7098 if (!parse_btype(&pt, &ad1)) {
7099 if (l) {
7100 error("invalid type");
7101 } else {
7102 l = FUNC_OLD;
7103 goto old_proto;
7106 l = FUNC_NEW;
7107 if ((pt.t & VT_BTYPE) == VT_VOID && tok == ')')
7108 break;
7109 type_decl(&pt, &ad1, &n, TYPE_DIRECT | TYPE_ABSTRACT);
7110 if ((pt.t & VT_BTYPE) == VT_VOID)
7111 error("parameter declared as void");
7112 arg_size += (type_size(&pt, &align) + 3) & ~3;
7113 } else {
7114 old_proto:
7115 n = tok;
7116 if (n < TOK_UIDENT)
7117 expect("identifier");
7118 pt.t = VT_INT;
7119 next();
7121 convert_parameter_type(&pt);
7122 s = sym_push(n | SYM_FIELD, &pt, 0, 0);
7123 *plast = s;
7124 plast = &s->next;
7125 if (tok == ')')
7126 break;
7127 skip(',');
7128 if (l == FUNC_NEW && tok == TOK_DOTS) {
7129 l = FUNC_ELLIPSIS;
7130 next();
7131 break;
7135 /* if no parameters, then old type prototype */
7136 if (l == 0)
7137 l = FUNC_OLD;
7138 skip(')');
7139 t1 = type->t & VT_STORAGE;
7140 /* NOTE: const is ignored in returned type as it has a special
7141 meaning in gcc / C++ */
7142 type->t &= ~(VT_STORAGE | VT_CONSTANT);
7143 post_type(type, ad);
7144 /* we push a anonymous symbol which will contain the function prototype */
7145 FUNC_ARGS(ad->func_attr) = arg_size;
7146 s = sym_push(SYM_FIELD, type, ad->func_attr, l);
7147 s->next = first;
7148 type->t = t1 | VT_FUNC;
7149 type->ref = s;
7150 } else if (tok == '[') {
7151 /* array definition */
7152 next();
7153 n = -1;
7154 if (tok != ']') {
7155 n = expr_const();
7156 if (n < 0)
7157 error("invalid array size");
7159 skip(']');
7160 /* parse next post type */
7161 t1 = type->t & VT_STORAGE;
7162 type->t &= ~VT_STORAGE;
7163 post_type(type, ad);
7165 /* we push a anonymous symbol which will contain the array
7166 element type */
7167 s = sym_push(SYM_FIELD, type, 0, n);
7168 type->t = t1 | VT_ARRAY | VT_PTR;
7169 type->ref = s;
7173 /* Parse a type declaration (except basic type), and return the type
7174 in 'type'. 'td' is a bitmask indicating which kind of type decl is
7175 expected. 'type' should contain the basic type. 'ad' is the
7176 attribute definition of the basic type. It can be modified by
7177 type_decl().
7179 static void type_decl(CType *type, AttributeDef *ad, int *v, int td)
7181 Sym *s;
7182 CType type1, *type2;
7183 int qualifiers;
7185 while (tok == '*') {
7186 qualifiers = 0;
7187 redo:
7188 next();
7189 switch(tok) {
7190 case TOK_CONST1:
7191 case TOK_CONST2:
7192 case TOK_CONST3:
7193 qualifiers |= VT_CONSTANT;
7194 goto redo;
7195 case TOK_VOLATILE1:
7196 case TOK_VOLATILE2:
7197 case TOK_VOLATILE3:
7198 qualifiers |= VT_VOLATILE;
7199 goto redo;
7200 case TOK_RESTRICT1:
7201 case TOK_RESTRICT2:
7202 case TOK_RESTRICT3:
7203 goto redo;
7205 mk_pointer(type);
7206 type->t |= qualifiers;
7209 /* XXX: clarify attribute handling */
7210 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
7211 parse_attribute(ad);
7213 /* recursive type */
7214 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
7215 type1.t = 0; /* XXX: same as int */
7216 if (tok == '(') {
7217 next();
7218 /* XXX: this is not correct to modify 'ad' at this point, but
7219 the syntax is not clear */
7220 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
7221 parse_attribute(ad);
7222 type_decl(&type1, ad, v, td);
7223 skip(')');
7224 } else {
7225 /* type identifier */
7226 if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
7227 *v = tok;
7228 next();
7229 } else {
7230 if (!(td & TYPE_ABSTRACT))
7231 expect("identifier");
7232 *v = 0;
7235 post_type(type, ad);
7236 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
7237 parse_attribute(ad);
7238 if (!type1.t)
7239 return;
7240 /* append type at the end of type1 */
7241 type2 = &type1;
7242 for(;;) {
7243 s = type2->ref;
7244 type2 = &s->type;
7245 if (!type2->t) {
7246 *type2 = *type;
7247 break;
7250 *type = type1;
7253 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
7254 static int lvalue_type(int t)
7256 int bt, r;
7257 r = VT_LVAL;
7258 bt = t & VT_BTYPE;
7259 if (bt == VT_BYTE || bt == VT_BOOL)
7260 r |= VT_LVAL_BYTE;
7261 else if (bt == VT_SHORT)
7262 r |= VT_LVAL_SHORT;
7263 else
7264 return r;
7265 if (t & VT_UNSIGNED)
7266 r |= VT_LVAL_UNSIGNED;
7267 return r;
7270 /* indirection with full error checking and bound check */
7271 static void indir(void)
7273 if ((vtop->type.t & VT_BTYPE) != VT_PTR) {
7274 if ((vtop->type.t & VT_BTYPE) == VT_FUNC)
7275 return;
7276 expect("pointer");
7278 if ((vtop->r & VT_LVAL) && !nocode_wanted)
7279 gv(RC_INT);
7280 vtop->type = *pointed_type(&vtop->type);
7281 /* Arrays and functions are never lvalues */
7282 if (!(vtop->type.t & VT_ARRAY)
7283 && (vtop->type.t & VT_BTYPE) != VT_FUNC) {
7284 vtop->r |= lvalue_type(vtop->type.t);
7285 /* if bound checking, the referenced pointer must be checked */
7286 if (do_bounds_check)
7287 vtop->r |= VT_MUSTBOUND;
7291 /* pass a parameter to a function and do type checking and casting */
7292 static void gfunc_param_typed(Sym *func, Sym *arg)
7294 int func_type;
7295 CType type;
7297 func_type = func->c;
7298 if (func_type == FUNC_OLD ||
7299 (func_type == FUNC_ELLIPSIS && arg == NULL)) {
7300 /* default casting : only need to convert float to double */
7301 if ((vtop->type.t & VT_BTYPE) == VT_FLOAT) {
7302 type.t = VT_DOUBLE;
7303 gen_cast(&type);
7305 } else if (arg == NULL) {
7306 error("too many arguments to function");
7307 } else {
7308 type = arg->type;
7309 type.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
7310 gen_assign_cast(&type);
7314 /* parse an expression of the form '(type)' or '(expr)' and return its
7315 type */
7316 static void parse_expr_type(CType *type)
7318 int n;
7319 AttributeDef ad;
7321 skip('(');
7322 if (parse_btype(type, &ad)) {
7323 type_decl(type, &ad, &n, TYPE_ABSTRACT);
7324 } else {
7325 expr_type(type);
7327 skip(')');
7330 static void parse_type(CType *type)
7332 AttributeDef ad;
7333 int n;
7335 if (!parse_btype(type, &ad)) {
7336 expect("type");
7338 type_decl(type, &ad, &n, TYPE_ABSTRACT);
7341 static void vpush_tokc(int t)
7343 CType type;
7344 type.t = t;
7345 vsetc(&type, VT_CONST, &tokc);
7348 static void unary(void)
7350 int n, t, align, size, r;
7351 CType type;
7352 Sym *s;
7353 AttributeDef ad;
7355 /* XXX: GCC 2.95.3 does not generate a table although it should be
7356 better here */
7357 tok_next:
7358 switch(tok) {
7359 case TOK_EXTENSION:
7360 next();
7361 goto tok_next;
7362 case TOK_CINT:
7363 case TOK_CCHAR:
7364 case TOK_LCHAR:
7365 vpushi(tokc.i);
7366 next();
7367 break;
7368 case TOK_CUINT:
7369 vpush_tokc(VT_INT | VT_UNSIGNED);
7370 next();
7371 break;
7372 case TOK_CLLONG:
7373 vpush_tokc(VT_LLONG);
7374 next();
7375 break;
7376 case TOK_CULLONG:
7377 vpush_tokc(VT_LLONG | VT_UNSIGNED);
7378 next();
7379 break;
7380 case TOK_CFLOAT:
7381 vpush_tokc(VT_FLOAT);
7382 next();
7383 break;
7384 case TOK_CDOUBLE:
7385 vpush_tokc(VT_DOUBLE);
7386 next();
7387 break;
7388 case TOK_CLDOUBLE:
7389 vpush_tokc(VT_LDOUBLE);
7390 next();
7391 break;
7392 case TOK___FUNCTION__:
7393 if (!gnu_ext)
7394 goto tok_identifier;
7395 /* fall thru */
7396 case TOK___FUNC__:
7398 void *ptr;
7399 int len;
7400 /* special function name identifier */
7401 len = strlen(funcname) + 1;
7402 /* generate char[len] type */
7403 type.t = VT_BYTE;
7404 mk_pointer(&type);
7405 type.t |= VT_ARRAY;
7406 type.ref->c = len;
7407 vpush_ref(&type, data_section, data_section->data_offset, len);
7408 ptr = section_ptr_add(data_section, len);
7409 memcpy(ptr, funcname, len);
7410 next();
7412 break;
7413 case TOK_LSTR:
7414 #ifdef TCC_TARGET_PE
7415 t = VT_SHORT | VT_UNSIGNED;
7416 #else
7417 t = VT_INT;
7418 #endif
7419 goto str_init;
7420 case TOK_STR:
7421 /* string parsing */
7422 t = VT_BYTE;
7423 str_init:
7424 if (tcc_state->warn_write_strings)
7425 t |= VT_CONSTANT;
7426 type.t = t;
7427 mk_pointer(&type);
7428 type.t |= VT_ARRAY;
7429 memset(&ad, 0, sizeof(AttributeDef));
7430 decl_initializer_alloc(&type, &ad, VT_CONST, 2, 0, 0);
7431 break;
7432 case '(':
7433 next();
7434 /* cast ? */
7435 if (parse_btype(&type, &ad)) {
7436 type_decl(&type, &ad, &n, TYPE_ABSTRACT);
7437 skip(')');
7438 /* check ISOC99 compound literal */
7439 if (tok == '{') {
7440 /* data is allocated locally by default */
7441 if (global_expr)
7442 r = VT_CONST;
7443 else
7444 r = VT_LOCAL;
7445 /* all except arrays are lvalues */
7446 if (!(type.t & VT_ARRAY))
7447 r |= lvalue_type(type.t);
7448 memset(&ad, 0, sizeof(AttributeDef));
7449 decl_initializer_alloc(&type, &ad, r, 1, 0, 0);
7450 } else {
7451 unary();
7452 gen_cast(&type);
7454 } else if (tok == '{') {
7455 /* save all registers */
7456 save_regs(0);
7457 /* statement expression : we do not accept break/continue
7458 inside as GCC does */
7459 block(NULL, NULL, NULL, NULL, 0, 1);
7460 skip(')');
7461 } else {
7462 gexpr();
7463 skip(')');
7465 break;
7466 case '*':
7467 next();
7468 unary();
7469 indir();
7470 break;
7471 case '&':
7472 next();
7473 unary();
7474 /* functions names must be treated as function pointers,
7475 except for unary '&' and sizeof. Since we consider that
7476 functions are not lvalues, we only have to handle it
7477 there and in function calls. */
7478 /* arrays can also be used although they are not lvalues */
7479 if ((vtop->type.t & VT_BTYPE) != VT_FUNC &&
7480 !(vtop->type.t & VT_ARRAY) && !(vtop->type.t & VT_LLOCAL))
7481 test_lvalue();
7482 mk_pointer(&vtop->type);
7483 gaddrof();
7484 break;
7485 case '!':
7486 next();
7487 unary();
7488 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST)
7489 vtop->c.i = !vtop->c.i;
7490 else if ((vtop->r & VT_VALMASK) == VT_CMP)
7491 vtop->c.i = vtop->c.i ^ 1;
7492 else {
7493 save_regs(1);
7494 vseti(VT_JMP, gtst(1, 0));
7496 break;
7497 case '~':
7498 next();
7499 unary();
7500 vpushi(-1);
7501 gen_op('^');
7502 break;
7503 case '+':
7504 next();
7505 /* in order to force cast, we add zero */
7506 unary();
7507 if ((vtop->type.t & VT_BTYPE) == VT_PTR)
7508 error("pointer not accepted for unary plus");
7509 vpushi(0);
7510 gen_op('+');
7511 break;
7512 case TOK_SIZEOF:
7513 case TOK_ALIGNOF1:
7514 case TOK_ALIGNOF2:
7515 t = tok;
7516 next();
7517 if (tok == '(') {
7518 parse_expr_type(&type);
7519 } else {
7520 unary_type(&type);
7522 size = type_size(&type, &align);
7523 if (t == TOK_SIZEOF) {
7524 if (size < 0)
7525 error("sizeof applied to an incomplete type");
7526 vpushi(size);
7527 } else {
7528 vpushi(align);
7530 vtop->type.t |= VT_UNSIGNED;
7531 break;
7533 case TOK_builtin_types_compatible_p:
7535 CType type1, type2;
7536 next();
7537 skip('(');
7538 parse_type(&type1);
7539 skip(',');
7540 parse_type(&type2);
7541 skip(')');
7542 type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
7543 type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
7544 vpushi(is_compatible_types(&type1, &type2));
7546 break;
7547 case TOK_builtin_constant_p:
7549 int saved_nocode_wanted, res;
7550 next();
7551 skip('(');
7552 saved_nocode_wanted = nocode_wanted;
7553 nocode_wanted = 1;
7554 gexpr();
7555 res = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
7556 vpop();
7557 nocode_wanted = saved_nocode_wanted;
7558 skip(')');
7559 vpushi(res);
7561 break;
7562 case TOK_INC:
7563 case TOK_DEC:
7564 t = tok;
7565 next();
7566 unary();
7567 inc(0, t);
7568 break;
7569 case '-':
7570 next();
7571 vpushi(0);
7572 unary();
7573 gen_op('-');
7574 break;
7575 case TOK_LAND:
7576 if (!gnu_ext)
7577 goto tok_identifier;
7578 next();
7579 /* allow to take the address of a label */
7580 if (tok < TOK_UIDENT)
7581 expect("label identifier");
7582 s = label_find(tok);
7583 if (!s) {
7584 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
7585 } else {
7586 if (s->r == LABEL_DECLARED)
7587 s->r = LABEL_FORWARD;
7589 if (!s->type.t) {
7590 s->type.t = VT_VOID;
7591 mk_pointer(&s->type);
7592 s->type.t |= VT_STATIC;
7594 vset(&s->type, VT_CONST | VT_SYM, 0);
7595 vtop->sym = s;
7596 next();
7597 break;
7598 default:
7599 tok_identifier:
7600 t = tok;
7601 next();
7602 if (t < TOK_UIDENT)
7603 expect("identifier");
7604 s = sym_find(t);
7605 if (!s) {
7606 if (tok != '(')
7607 error("'%s' undeclared", get_tok_str(t, NULL));
7608 /* for simple function calls, we tolerate undeclared
7609 external reference to int() function */
7610 if (tcc_state->warn_implicit_function_declaration)
7611 warning("implicit declaration of function '%s'",
7612 get_tok_str(t, NULL));
7613 s = external_global_sym(t, &func_old_type, 0);
7615 if ((s->type.t & (VT_STATIC | VT_INLINE | VT_BTYPE)) ==
7616 (VT_STATIC | VT_INLINE | VT_FUNC)) {
7617 /* if referencing an inline function, then we generate a
7618 symbol to it if not already done. It will have the
7619 effect to generate code for it at the end of the
7620 compilation unit. Inline function as always
7621 generated in the text section. */
7622 if (!s->c)
7623 put_extern_sym(s, text_section, 0, 0);
7624 r = VT_SYM | VT_CONST;
7625 } else {
7626 r = s->r;
7628 vset(&s->type, r, s->c);
7629 /* if forward reference, we must point to s */
7630 if (vtop->r & VT_SYM) {
7631 vtop->sym = s;
7632 vtop->c.ul = 0;
7634 break;
7637 /* post operations */
7638 while (1) {
7639 if (tok == TOK_INC || tok == TOK_DEC) {
7640 inc(1, tok);
7641 next();
7642 } else if (tok == '.' || tok == TOK_ARROW) {
7643 /* field */
7644 if (tok == TOK_ARROW)
7645 indir();
7646 test_lvalue();
7647 gaddrof();
7648 next();
7649 /* expect pointer on structure */
7650 if ((vtop->type.t & VT_BTYPE) != VT_STRUCT)
7651 expect("struct or union");
7652 s = vtop->type.ref;
7653 /* find field */
7654 tok |= SYM_FIELD;
7655 while ((s = s->next) != NULL) {
7656 if (s->v == tok)
7657 break;
7659 if (!s)
7660 error("field not found: %s", get_tok_str(tok & ~SYM_FIELD, NULL));
7661 /* add field offset to pointer */
7662 vtop->type = char_pointer_type; /* change type to 'char *' */
7663 vpushi(s->c);
7664 gen_op('+');
7665 /* change type to field type, and set to lvalue */
7666 vtop->type = s->type;
7667 /* an array is never an lvalue */
7668 if (!(vtop->type.t & VT_ARRAY)) {
7669 vtop->r |= lvalue_type(vtop->type.t);
7670 /* if bound checking, the referenced pointer must be checked */
7671 if (do_bounds_check)
7672 vtop->r |= VT_MUSTBOUND;
7674 next();
7675 } else if (tok == '[') {
7676 next();
7677 gexpr();
7678 gen_op('+');
7679 indir();
7680 skip(']');
7681 } else if (tok == '(') {
7682 SValue ret;
7683 Sym *sa;
7684 int nb_args;
7686 /* function call */
7687 if ((vtop->type.t & VT_BTYPE) != VT_FUNC) {
7688 /* pointer test (no array accepted) */
7689 if ((vtop->type.t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
7690 vtop->type = *pointed_type(&vtop->type);
7691 if ((vtop->type.t & VT_BTYPE) != VT_FUNC)
7692 goto error_func;
7693 } else {
7694 error_func:
7695 expect("function pointer");
7697 } else {
7698 vtop->r &= ~VT_LVAL; /* no lvalue */
7700 /* get return type */
7701 s = vtop->type.ref;
7702 next();
7703 sa = s->next; /* first parameter */
7704 nb_args = 0;
7705 ret.r2 = VT_CONST;
7706 /* compute first implicit argument if a structure is returned */
7707 if ((s->type.t & VT_BTYPE) == VT_STRUCT) {
7708 /* get some space for the returned structure */
7709 size = type_size(&s->type, &align);
7710 loc = (loc - size) & -align;
7711 ret.type = s->type;
7712 ret.r = VT_LOCAL | VT_LVAL;
7713 /* pass it as 'int' to avoid structure arg passing
7714 problems */
7715 vseti(VT_LOCAL, loc);
7716 ret.c = vtop->c;
7717 nb_args++;
7718 } else {
7719 ret.type = s->type;
7720 /* return in register */
7721 if (is_float(ret.type.t)) {
7722 ret.r = REG_FRET;
7723 } else {
7724 if ((ret.type.t & VT_BTYPE) == VT_LLONG)
7725 ret.r2 = REG_LRET;
7726 ret.r = REG_IRET;
7728 ret.c.i = 0;
7730 if (tok != ')') {
7731 for(;;) {
7732 expr_eq();
7733 gfunc_param_typed(s, sa);
7734 nb_args++;
7735 if (sa)
7736 sa = sa->next;
7737 if (tok == ')')
7738 break;
7739 skip(',');
7742 if (sa)
7743 error("too few arguments to function");
7744 skip(')');
7745 if (!nocode_wanted) {
7746 gfunc_call(nb_args);
7747 } else {
7748 vtop -= (nb_args + 1);
7750 /* return value */
7751 vsetc(&ret.type, ret.r, &ret.c);
7752 vtop->r2 = ret.r2;
7753 } else {
7754 break;
7759 static void uneq(void)
7761 int t;
7763 unary();
7764 if (tok == '=' ||
7765 (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
7766 tok == TOK_A_XOR || tok == TOK_A_OR ||
7767 tok == TOK_A_SHL || tok == TOK_A_SAR) {
7768 test_lvalue();
7769 t = tok;
7770 next();
7771 if (t == '=') {
7772 expr_eq();
7773 } else {
7774 vdup();
7775 expr_eq();
7776 gen_op(t & 0x7f);
7778 vstore();
7782 static void expr_prod(void)
7784 int t;
7786 uneq();
7787 while (tok == '*' || tok == '/' || tok == '%') {
7788 t = tok;
7789 next();
7790 uneq();
7791 gen_op(t);
7795 static void expr_sum(void)
7797 int t;
7799 expr_prod();
7800 while (tok == '+' || tok == '-') {
7801 t = tok;
7802 next();
7803 expr_prod();
7804 gen_op(t);
7808 static void expr_shift(void)
7810 int t;
7812 expr_sum();
7813 while (tok == TOK_SHL || tok == TOK_SAR) {
7814 t = tok;
7815 next();
7816 expr_sum();
7817 gen_op(t);
7821 static void expr_cmp(void)
7823 int t;
7825 expr_shift();
7826 while ((tok >= TOK_ULE && tok <= TOK_GT) ||
7827 tok == TOK_ULT || tok == TOK_UGE) {
7828 t = tok;
7829 next();
7830 expr_shift();
7831 gen_op(t);
7835 static void expr_cmpeq(void)
7837 int t;
7839 expr_cmp();
7840 while (tok == TOK_EQ || tok == TOK_NE) {
7841 t = tok;
7842 next();
7843 expr_cmp();
7844 gen_op(t);
7848 static void expr_and(void)
7850 expr_cmpeq();
7851 while (tok == '&') {
7852 next();
7853 expr_cmpeq();
7854 gen_op('&');
7858 static void expr_xor(void)
7860 expr_and();
7861 while (tok == '^') {
7862 next();
7863 expr_and();
7864 gen_op('^');
7868 static void expr_or(void)
7870 expr_xor();
7871 while (tok == '|') {
7872 next();
7873 expr_xor();
7874 gen_op('|');
7878 /* XXX: fix this mess */
7879 static void expr_land_const(void)
7881 expr_or();
7882 while (tok == TOK_LAND) {
7883 next();
7884 expr_or();
7885 gen_op(TOK_LAND);
7889 /* XXX: fix this mess */
7890 static void expr_lor_const(void)
7892 expr_land_const();
7893 while (tok == TOK_LOR) {
7894 next();
7895 expr_land_const();
7896 gen_op(TOK_LOR);
7900 /* only used if non constant */
7901 static void expr_land(void)
7903 int t;
7905 expr_or();
7906 if (tok == TOK_LAND) {
7907 t = 0;
7908 save_regs(1);
7909 for(;;) {
7910 t = gtst(1, t);
7911 if (tok != TOK_LAND) {
7912 vseti(VT_JMPI, t);
7913 break;
7915 next();
7916 expr_or();
7921 static void expr_lor(void)
7923 int t;
7925 expr_land();
7926 if (tok == TOK_LOR) {
7927 t = 0;
7928 save_regs(1);
7929 for(;;) {
7930 t = gtst(0, t);
7931 if (tok != TOK_LOR) {
7932 vseti(VT_JMP, t);
7933 break;
7935 next();
7936 expr_land();
7941 /* XXX: better constant handling */
7942 static void expr_eq(void)
7944 int tt, u, r1, r2, rc, t1, t2, bt1, bt2;
7945 SValue sv;
7946 CType type, type1, type2;
7948 if (const_wanted) {
7949 int c1, c;
7950 expr_lor_const();
7951 if (tok == '?') {
7952 c = vtop->c.i;
7953 vpop();
7954 next();
7955 if (tok == ':' && gnu_ext) {
7956 c1 = c;
7957 } else {
7958 gexpr();
7959 c1 = vtop->c.i;
7960 vpop();
7962 skip(':');
7963 expr_eq();
7964 if (c)
7965 vtop->c.i = c1;
7967 } else {
7968 expr_lor();
7969 if (tok == '?') {
7970 next();
7971 if (vtop != vstack) {
7972 /* needed to avoid having different registers saved in
7973 each branch */
7974 if (is_float(vtop->type.t))
7975 rc = RC_FLOAT;
7976 else
7977 rc = RC_INT;
7978 gv(rc);
7979 save_regs(1);
7981 if (tok == ':' && gnu_ext) {
7982 gv_dup();
7983 tt = gtst(1, 0);
7984 } else {
7985 tt = gtst(1, 0);
7986 gexpr();
7988 type1 = vtop->type;
7989 sv = *vtop; /* save value to handle it later */
7990 vtop--; /* no vpop so that FP stack is not flushed */
7991 skip(':');
7992 u = gjmp(0);
7993 gsym(tt);
7994 expr_eq();
7995 type2 = vtop->type;
7997 t1 = type1.t;
7998 bt1 = t1 & VT_BTYPE;
7999 t2 = type2.t;
8000 bt2 = t2 & VT_BTYPE;
8001 /* cast operands to correct type according to ISOC rules */
8002 if (is_float(bt1) || is_float(bt2)) {
8003 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
8004 type.t = VT_LDOUBLE;
8005 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
8006 type.t = VT_DOUBLE;
8007 } else {
8008 type.t = VT_FLOAT;
8010 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
8011 /* cast to biggest op */
8012 type.t = VT_LLONG;
8013 /* convert to unsigned if it does not fit in a long long */
8014 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
8015 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
8016 type.t |= VT_UNSIGNED;
8017 } else if (bt1 == VT_PTR || bt2 == VT_PTR) {
8018 /* XXX: test pointer compatibility */
8019 type = type1;
8020 } else if (bt1 == VT_FUNC || bt2 == VT_FUNC) {
8021 /* XXX: test function pointer compatibility */
8022 type = type1;
8023 } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
8024 /* XXX: test structure compatibility */
8025 type = type1;
8026 } else if (bt1 == VT_VOID || bt2 == VT_VOID) {
8027 /* NOTE: as an extension, we accept void on only one side */
8028 type.t = VT_VOID;
8029 } else {
8030 /* integer operations */
8031 type.t = VT_INT;
8032 /* convert to unsigned if it does not fit in an integer */
8033 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
8034 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
8035 type.t |= VT_UNSIGNED;
8038 /* now we convert second operand */
8039 gen_cast(&type);
8040 if (VT_STRUCT == (vtop->type.t & VT_BTYPE))
8041 gaddrof();
8042 rc = RC_INT;
8043 if (is_float(type.t)) {
8044 rc = RC_FLOAT;
8045 } else if ((type.t & VT_BTYPE) == VT_LLONG) {
8046 /* for long longs, we use fixed registers to avoid having
8047 to handle a complicated move */
8048 rc = RC_IRET;
8051 r2 = gv(rc);
8052 /* this is horrible, but we must also convert first
8053 operand */
8054 tt = gjmp(0);
8055 gsym(u);
8056 /* put again first value and cast it */
8057 *vtop = sv;
8058 gen_cast(&type);
8059 if (VT_STRUCT == (vtop->type.t & VT_BTYPE))
8060 gaddrof();
8061 r1 = gv(rc);
8062 move_reg(r2, r1);
8063 vtop->r = r2;
8064 gsym(tt);
8069 static void gexpr(void)
8071 while (1) {
8072 expr_eq();
8073 if (tok != ',')
8074 break;
8075 vpop();
8076 next();
8080 /* parse an expression and return its type without any side effect. */
8081 static void expr_type(CType *type)
8083 int saved_nocode_wanted;
8085 saved_nocode_wanted = nocode_wanted;
8086 nocode_wanted = 1;
8087 gexpr();
8088 *type = vtop->type;
8089 vpop();
8090 nocode_wanted = saved_nocode_wanted;
8093 /* parse a unary expression and return its type without any side
8094 effect. */
8095 static void unary_type(CType *type)
8097 int a;
8099 a = nocode_wanted;
8100 nocode_wanted = 1;
8101 unary();
8102 *type = vtop->type;
8103 vpop();
8104 nocode_wanted = a;
8107 /* parse a constant expression and return value in vtop. */
8108 static void expr_const1(void)
8110 int a;
8111 a = const_wanted;
8112 const_wanted = 1;
8113 expr_eq();
8114 const_wanted = a;
8117 /* parse an integer constant and return its value. */
8118 static int expr_const(void)
8120 int c;
8121 expr_const1();
8122 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
8123 expect("constant expression");
8124 c = vtop->c.i;
8125 vpop();
8126 return c;
8129 /* return the label token if current token is a label, otherwise
8130 return zero */
8131 static int is_label(void)
8133 int last_tok;
8135 /* fast test first */
8136 if (tok < TOK_UIDENT)
8137 return 0;
8138 /* no need to save tokc because tok is an identifier */
8139 last_tok = tok;
8140 next();
8141 if (tok == ':') {
8142 next();
8143 return last_tok;
8144 } else {
8145 unget_tok(last_tok);
8146 return 0;
8150 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
8151 int case_reg, int is_expr)
8153 int a, b, c, d;
8154 Sym *s;
8156 /* generate line number info */
8157 if (do_debug &&
8158 (last_line_num != file->line_num || last_ind != ind)) {
8159 put_stabn(N_SLINE, 0, file->line_num, ind - func_ind);
8160 last_ind = ind;
8161 last_line_num = file->line_num;
8164 if (is_expr) {
8165 /* default return value is (void) */
8166 vpushi(0);
8167 vtop->type.t = VT_VOID;
8170 if (tok == TOK_IF) {
8171 /* if test */
8172 next();
8173 skip('(');
8174 gexpr();
8175 skip(')');
8176 a = gtst(1, 0);
8177 block(bsym, csym, case_sym, def_sym, case_reg, 0);
8178 c = tok;
8179 if (c == TOK_ELSE) {
8180 next();
8181 d = gjmp(0);
8182 gsym(a);
8183 block(bsym, csym, case_sym, def_sym, case_reg, 0);
8184 gsym(d); /* patch else jmp */
8185 } else
8186 gsym(a);
8187 } else if (tok == TOK_WHILE) {
8188 next();
8189 d = ind;
8190 skip('(');
8191 gexpr();
8192 skip(')');
8193 a = gtst(1, 0);
8194 b = 0;
8195 block(&a, &b, case_sym, def_sym, case_reg, 0);
8196 gjmp_addr(d);
8197 gsym(a);
8198 gsym_addr(b, d);
8199 } else if (tok == '{') {
8200 Sym *llabel;
8202 next();
8203 /* record local declaration stack position */
8204 s = local_stack;
8205 llabel = local_label_stack;
8206 /* handle local labels declarations */
8207 if (tok == TOK_LABEL) {
8208 next();
8209 for(;;) {
8210 if (tok < TOK_UIDENT)
8211 expect("label identifier");
8212 label_push(&local_label_stack, tok, LABEL_DECLARED);
8213 next();
8214 if (tok == ',') {
8215 next();
8216 } else {
8217 skip(';');
8218 break;
8222 while (tok != '}') {
8223 decl(VT_LOCAL);
8224 if (tok != '}') {
8225 if (is_expr)
8226 vpop();
8227 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
8230 /* pop locally defined labels */
8231 label_pop(&local_label_stack, llabel);
8232 /* pop locally defined symbols */
8233 sym_pop(&local_stack, s);
8234 next();
8235 } else if (tok == TOK_RETURN) {
8236 next();
8237 if (tok != ';') {
8238 gexpr();
8239 gen_assign_cast(&func_vt);
8240 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
8241 CType type;
8242 /* if returning structure, must copy it to implicit
8243 first pointer arg location */
8244 #ifdef TCC_ARM_EABI
8245 int align, size;
8246 size = type_size(&func_vt,&align);
8247 if(size <= 4)
8249 if((vtop->r != (VT_LOCAL | VT_LVAL) || (vtop->c.i & 3))
8250 && (align & 3))
8252 int addr;
8253 loc = (loc - size) & -4;
8254 addr = loc;
8255 type = func_vt;
8256 vset(&type, VT_LOCAL | VT_LVAL, addr);
8257 vswap();
8258 vstore();
8259 vset(&int_type, VT_LOCAL | VT_LVAL, addr);
8261 vtop->type = int_type;
8262 gv(RC_IRET);
8263 } else {
8264 #endif
8265 type = func_vt;
8266 mk_pointer(&type);
8267 vset(&type, VT_LOCAL | VT_LVAL, func_vc);
8268 indir();
8269 vswap();
8270 /* copy structure value to pointer */
8271 vstore();
8272 #ifdef TCC_ARM_EABI
8274 #endif
8275 } else if (is_float(func_vt.t)) {
8276 gv(RC_FRET);
8277 } else {
8278 gv(RC_IRET);
8280 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
8282 skip(';');
8283 rsym = gjmp(rsym); /* jmp */
8284 } else if (tok == TOK_BREAK) {
8285 /* compute jump */
8286 if (!bsym)
8287 error("cannot break");
8288 *bsym = gjmp(*bsym);
8289 next();
8290 skip(';');
8291 } else if (tok == TOK_CONTINUE) {
8292 /* compute jump */
8293 if (!csym)
8294 error("cannot continue");
8295 *csym = gjmp(*csym);
8296 next();
8297 skip(';');
8298 } else if (tok == TOK_FOR) {
8299 int e;
8300 next();
8301 skip('(');
8302 if (tok != ';') {
8303 gexpr();
8304 vpop();
8306 skip(';');
8307 d = ind;
8308 c = ind;
8309 a = 0;
8310 b = 0;
8311 if (tok != ';') {
8312 gexpr();
8313 a = gtst(1, 0);
8315 skip(';');
8316 if (tok != ')') {
8317 e = gjmp(0);
8318 c = ind;
8319 gexpr();
8320 vpop();
8321 gjmp_addr(d);
8322 gsym(e);
8324 skip(')');
8325 block(&a, &b, case_sym, def_sym, case_reg, 0);
8326 gjmp_addr(c);
8327 gsym(a);
8328 gsym_addr(b, c);
8329 } else
8330 if (tok == TOK_DO) {
8331 next();
8332 a = 0;
8333 b = 0;
8334 d = ind;
8335 block(&a, &b, case_sym, def_sym, case_reg, 0);
8336 skip(TOK_WHILE);
8337 skip('(');
8338 gsym(b);
8339 gexpr();
8340 c = gtst(0, 0);
8341 gsym_addr(c, d);
8342 skip(')');
8343 gsym(a);
8344 skip(';');
8345 } else
8346 if (tok == TOK_SWITCH) {
8347 next();
8348 skip('(');
8349 gexpr();
8350 /* XXX: other types than integer */
8351 case_reg = gv(RC_INT);
8352 vpop();
8353 skip(')');
8354 a = 0;
8355 b = gjmp(0); /* jump to first case */
8356 c = 0;
8357 block(&a, csym, &b, &c, case_reg, 0);
8358 /* if no default, jmp after switch */
8359 if (c == 0)
8360 c = ind;
8361 /* default label */
8362 gsym_addr(b, c);
8363 /* break label */
8364 gsym(a);
8365 } else
8366 if (tok == TOK_CASE) {
8367 int v1, v2;
8368 if (!case_sym)
8369 expect("switch");
8370 next();
8371 v1 = expr_const();
8372 v2 = v1;
8373 if (gnu_ext && tok == TOK_DOTS) {
8374 next();
8375 v2 = expr_const();
8376 if (v2 < v1)
8377 warning("empty case range");
8379 /* since a case is like a label, we must skip it with a jmp */
8380 b = gjmp(0);
8381 gsym(*case_sym);
8382 vseti(case_reg, 0);
8383 vpushi(v1);
8384 if (v1 == v2) {
8385 gen_op(TOK_EQ);
8386 *case_sym = gtst(1, 0);
8387 } else {
8388 gen_op(TOK_GE);
8389 *case_sym = gtst(1, 0);
8390 vseti(case_reg, 0);
8391 vpushi(v2);
8392 gen_op(TOK_LE);
8393 *case_sym = gtst(1, *case_sym);
8395 gsym(b);
8396 skip(':');
8397 is_expr = 0;
8398 goto block_after_label;
8399 } else
8400 if (tok == TOK_DEFAULT) {
8401 next();
8402 skip(':');
8403 if (!def_sym)
8404 expect("switch");
8405 if (*def_sym)
8406 error("too many 'default'");
8407 *def_sym = ind;
8408 is_expr = 0;
8409 goto block_after_label;
8410 } else
8411 if (tok == TOK_GOTO) {
8412 next();
8413 if (tok == '*' && gnu_ext) {
8414 /* computed goto */
8415 next();
8416 gexpr();
8417 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
8418 expect("pointer");
8419 ggoto();
8420 } else if (tok >= TOK_UIDENT) {
8421 s = label_find(tok);
8422 /* put forward definition if needed */
8423 if (!s) {
8424 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
8425 } else {
8426 if (s->r == LABEL_DECLARED)
8427 s->r = LABEL_FORWARD;
8429 /* label already defined */
8430 if (s->r & LABEL_FORWARD)
8431 s->next = (void *)gjmp((long)s->next);
8432 else
8433 gjmp_addr((long)s->next);
8434 next();
8435 } else {
8436 expect("label identifier");
8438 skip(';');
8439 } else if (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3) {
8440 asm_instr();
8441 } else {
8442 b = is_label();
8443 if (b) {
8444 /* label case */
8445 s = label_find(b);
8446 if (s) {
8447 if (s->r == LABEL_DEFINED)
8448 error("duplicate label '%s'", get_tok_str(s->v, NULL));
8449 gsym((long)s->next);
8450 s->r = LABEL_DEFINED;
8451 } else {
8452 s = label_push(&global_label_stack, b, LABEL_DEFINED);
8454 s->next = (void *)ind;
8455 /* we accept this, but it is a mistake */
8456 block_after_label:
8457 if (tok == '}') {
8458 warning("deprecated use of label at end of compound statement");
8459 } else {
8460 if (is_expr)
8461 vpop();
8462 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
8464 } else {
8465 /* expression case */
8466 if (tok != ';') {
8467 if (is_expr) {
8468 vpop();
8469 gexpr();
8470 } else {
8471 gexpr();
8472 vpop();
8475 skip(';');
8480 /* t is the array or struct type. c is the array or struct
8481 address. cur_index/cur_field is the pointer to the current
8482 value. 'size_only' is true if only size info is needed (only used
8483 in arrays) */
8484 static void decl_designator(CType *type, Section *sec, unsigned long c,
8485 int *cur_index, Sym **cur_field,
8486 int size_only)
8488 Sym *s, *f;
8489 int notfirst, index, index_last, align, l, nb_elems, elem_size;
8490 CType type1;
8492 notfirst = 0;
8493 elem_size = 0;
8494 nb_elems = 1;
8495 if (gnu_ext && (l = is_label()) != 0)
8496 goto struct_field;
8497 while (tok == '[' || tok == '.') {
8498 if (tok == '[') {
8499 if (!(type->t & VT_ARRAY))
8500 expect("array type");
8501 s = type->ref;
8502 next();
8503 index = expr_const();
8504 if (index < 0 || (s->c >= 0 && index >= s->c))
8505 expect("invalid index");
8506 if (tok == TOK_DOTS && gnu_ext) {
8507 next();
8508 index_last = expr_const();
8509 if (index_last < 0 ||
8510 (s->c >= 0 && index_last >= s->c) ||
8511 index_last < index)
8512 expect("invalid index");
8513 } else {
8514 index_last = index;
8516 skip(']');
8517 if (!notfirst)
8518 *cur_index = index_last;
8519 type = pointed_type(type);
8520 elem_size = type_size(type, &align);
8521 c += index * elem_size;
8522 /* NOTE: we only support ranges for last designator */
8523 nb_elems = index_last - index + 1;
8524 if (nb_elems != 1) {
8525 notfirst = 1;
8526 break;
8528 } else {
8529 next();
8530 l = tok;
8531 next();
8532 struct_field:
8533 if ((type->t & VT_BTYPE) != VT_STRUCT)
8534 expect("struct/union type");
8535 s = type->ref;
8536 l |= SYM_FIELD;
8537 f = s->next;
8538 while (f) {
8539 if (f->v == l)
8540 break;
8541 f = f->next;
8543 if (!f)
8544 expect("field");
8545 if (!notfirst)
8546 *cur_field = f;
8547 /* XXX: fix this mess by using explicit storage field */
8548 type1 = f->type;
8549 type1.t |= (type->t & ~VT_TYPE);
8550 type = &type1;
8551 c += f->c;
8553 notfirst = 1;
8555 if (notfirst) {
8556 if (tok == '=') {
8557 next();
8558 } else {
8559 if (!gnu_ext)
8560 expect("=");
8562 } else {
8563 if (type->t & VT_ARRAY) {
8564 index = *cur_index;
8565 type = pointed_type(type);
8566 c += index * type_size(type, &align);
8567 } else {
8568 f = *cur_field;
8569 if (!f)
8570 error("too many field init");
8571 /* XXX: fix this mess by using explicit storage field */
8572 type1 = f->type;
8573 type1.t |= (type->t & ~VT_TYPE);
8574 type = &type1;
8575 c += f->c;
8578 decl_initializer(type, sec, c, 0, size_only);
8580 /* XXX: make it more general */
8581 if (!size_only && nb_elems > 1) {
8582 unsigned long c_end;
8583 uint8_t *src, *dst;
8584 int i;
8586 if (!sec)
8587 error("range init not supported yet for dynamic storage");
8588 c_end = c + nb_elems * elem_size;
8589 if (c_end > sec->data_allocated)
8590 section_realloc(sec, c_end);
8591 src = sec->data + c;
8592 dst = src;
8593 for(i = 1; i < nb_elems; i++) {
8594 dst += elem_size;
8595 memcpy(dst, src, elem_size);
8600 #define EXPR_VAL 0
8601 #define EXPR_CONST 1
8602 #define EXPR_ANY 2
8604 /* store a value or an expression directly in global data or in local array */
8605 static void init_putv(CType *type, Section *sec, unsigned long c,
8606 int v, int expr_type)
8608 int saved_global_expr, bt, bit_pos, bit_size;
8609 void *ptr;
8610 unsigned long long bit_mask;
8611 CType dtype;
8613 switch(expr_type) {
8614 case EXPR_VAL:
8615 vpushi(v);
8616 break;
8617 case EXPR_CONST:
8618 /* compound literals must be allocated globally in this case */
8619 saved_global_expr = global_expr;
8620 global_expr = 1;
8621 expr_const1();
8622 global_expr = saved_global_expr;
8623 /* NOTE: symbols are accepted */
8624 if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST)
8625 error("initializer element is not constant");
8626 break;
8627 case EXPR_ANY:
8628 expr_eq();
8629 break;
8632 dtype = *type;
8633 dtype.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
8635 if (sec) {
8636 /* XXX: not portable */
8637 /* XXX: generate error if incorrect relocation */
8638 gen_assign_cast(&dtype);
8639 bt = type->t & VT_BTYPE;
8640 ptr = sec->data + c;
8641 /* XXX: make code faster ? */
8642 if (!(type->t & VT_BITFIELD)) {
8643 bit_pos = 0;
8644 bit_size = 32;
8645 bit_mask = -1LL;
8646 } else {
8647 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
8648 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
8649 bit_mask = (1LL << bit_size) - 1;
8651 if ((vtop->r & VT_SYM) &&
8652 (bt == VT_BYTE ||
8653 bt == VT_SHORT ||
8654 bt == VT_DOUBLE ||
8655 bt == VT_LDOUBLE ||
8656 bt == VT_LLONG ||
8657 (bt == VT_INT && bit_size != 32)))
8658 error("initializer element is not computable at load time");
8659 switch(bt) {
8660 case VT_BYTE:
8661 *(char *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8662 break;
8663 case VT_SHORT:
8664 *(short *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8665 break;
8666 case VT_DOUBLE:
8667 *(double *)ptr = vtop->c.d;
8668 break;
8669 case VT_LDOUBLE:
8670 *(long double *)ptr = vtop->c.ld;
8671 break;
8672 case VT_LLONG:
8673 *(long long *)ptr |= (vtop->c.ll & bit_mask) << bit_pos;
8674 break;
8675 default:
8676 if (vtop->r & VT_SYM) {
8677 greloc(sec, vtop->sym, c, R_DATA_32);
8679 *(int *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8680 break;
8682 vtop--;
8683 } else {
8684 vset(&dtype, VT_LOCAL|VT_LVAL, c);
8685 vswap();
8686 vstore();
8687 vpop();
8691 /* put zeros for variable based init */
8692 static void init_putz(CType *t, Section *sec, unsigned long c, int size)
8694 if (sec) {
8695 /* nothing to do because globals are already set to zero */
8696 } else {
8697 vpush_global_sym(&func_old_type, TOK_memset);
8698 vseti(VT_LOCAL, c);
8699 vpushi(0);
8700 vpushi(size);
8701 gfunc_call(3);
8705 /* 't' contains the type and storage info. 'c' is the offset of the
8706 object in section 'sec'. If 'sec' is NULL, it means stack based
8707 allocation. 'first' is true if array '{' must be read (multi
8708 dimension implicit array init handling). 'size_only' is true if
8709 size only evaluation is wanted (only for arrays). */
8710 static void decl_initializer(CType *type, Section *sec, unsigned long c,
8711 int first, int size_only)
8713 int index, array_length, n, no_oblock, nb, parlevel, i;
8714 int size1, align1, expr_type;
8715 Sym *s, *f;
8716 CType *t1;
8718 if (type->t & VT_ARRAY) {
8719 s = type->ref;
8720 n = s->c;
8721 array_length = 0;
8722 t1 = pointed_type(type);
8723 size1 = type_size(t1, &align1);
8725 no_oblock = 1;
8726 if ((first && tok != TOK_LSTR && tok != TOK_STR) ||
8727 tok == '{') {
8728 skip('{');
8729 no_oblock = 0;
8732 /* only parse strings here if correct type (otherwise: handle
8733 them as ((w)char *) expressions */
8734 if ((tok == TOK_LSTR &&
8735 #ifdef TCC_TARGET_PE
8736 (t1->t & VT_BTYPE) == VT_SHORT && (t1->t & VT_UNSIGNED)
8737 #else
8738 (t1->t & VT_BTYPE) == VT_INT
8739 #endif
8740 ) || (tok == TOK_STR && (t1->t & VT_BTYPE) == VT_BYTE)) {
8741 while (tok == TOK_STR || tok == TOK_LSTR) {
8742 int cstr_len, ch;
8743 CString *cstr;
8745 cstr = tokc.cstr;
8746 /* compute maximum number of chars wanted */
8747 if (tok == TOK_STR)
8748 cstr_len = cstr->size;
8749 else
8750 cstr_len = cstr->size / sizeof(nwchar_t);
8751 cstr_len--;
8752 nb = cstr_len;
8753 if (n >= 0 && nb > (n - array_length))
8754 nb = n - array_length;
8755 if (!size_only) {
8756 if (cstr_len > nb)
8757 warning("initializer-string for array is too long");
8758 /* in order to go faster for common case (char
8759 string in global variable, we handle it
8760 specifically */
8761 if (sec && tok == TOK_STR && size1 == 1) {
8762 memcpy(sec->data + c + array_length, cstr->data, nb);
8763 } else {
8764 for(i=0;i<nb;i++) {
8765 if (tok == TOK_STR)
8766 ch = ((unsigned char *)cstr->data)[i];
8767 else
8768 ch = ((nwchar_t *)cstr->data)[i];
8769 init_putv(t1, sec, c + (array_length + i) * size1,
8770 ch, EXPR_VAL);
8774 array_length += nb;
8775 next();
8777 /* only add trailing zero if enough storage (no
8778 warning in this case since it is standard) */
8779 if (n < 0 || array_length < n) {
8780 if (!size_only) {
8781 init_putv(t1, sec, c + (array_length * size1), 0, EXPR_VAL);
8783 array_length++;
8785 } else {
8786 index = 0;
8787 while (tok != '}') {
8788 decl_designator(type, sec, c, &index, NULL, size_only);
8789 if (n >= 0 && index >= n)
8790 error("index too large");
8791 /* must put zero in holes (note that doing it that way
8792 ensures that it even works with designators) */
8793 if (!size_only && array_length < index) {
8794 init_putz(t1, sec, c + array_length * size1,
8795 (index - array_length) * size1);
8797 index++;
8798 if (index > array_length)
8799 array_length = index;
8800 /* special test for multi dimensional arrays (may not
8801 be strictly correct if designators are used at the
8802 same time) */
8803 if (index >= n && no_oblock)
8804 break;
8805 if (tok == '}')
8806 break;
8807 skip(',');
8810 if (!no_oblock)
8811 skip('}');
8812 /* put zeros at the end */
8813 if (!size_only && n >= 0 && array_length < n) {
8814 init_putz(t1, sec, c + array_length * size1,
8815 (n - array_length) * size1);
8817 /* patch type size if needed */
8818 if (n < 0)
8819 s->c = array_length;
8820 } else if ((type->t & VT_BTYPE) == VT_STRUCT &&
8821 (sec || !first || tok == '{')) {
8822 int par_count;
8824 /* NOTE: the previous test is a specific case for automatic
8825 struct/union init */
8826 /* XXX: union needs only one init */
8828 /* XXX: this test is incorrect for local initializers
8829 beginning with ( without {. It would be much more difficult
8830 to do it correctly (ideally, the expression parser should
8831 be used in all cases) */
8832 par_count = 0;
8833 if (tok == '(') {
8834 AttributeDef ad1;
8835 CType type1;
8836 next();
8837 while (tok == '(') {
8838 par_count++;
8839 next();
8841 if (!parse_btype(&type1, &ad1))
8842 expect("cast");
8843 type_decl(&type1, &ad1, &n, TYPE_ABSTRACT);
8844 #if 0
8845 if (!is_assignable_types(type, &type1))
8846 error("invalid type for cast");
8847 #endif
8848 skip(')');
8850 no_oblock = 1;
8851 if (first || tok == '{') {
8852 skip('{');
8853 no_oblock = 0;
8855 s = type->ref;
8856 f = s->next;
8857 array_length = 0;
8858 index = 0;
8859 n = s->c;
8860 while (tok != '}') {
8861 decl_designator(type, sec, c, NULL, &f, size_only);
8862 index = f->c;
8863 if (!size_only && array_length < index) {
8864 init_putz(type, sec, c + array_length,
8865 index - array_length);
8867 index = index + type_size(&f->type, &align1);
8868 if (index > array_length)
8869 array_length = index;
8870 f = f->next;
8871 if (no_oblock && f == NULL)
8872 break;
8873 if (tok == '}')
8874 break;
8875 skip(',');
8877 /* put zeros at the end */
8878 if (!size_only && array_length < n) {
8879 init_putz(type, sec, c + array_length,
8880 n - array_length);
8882 if (!no_oblock)
8883 skip('}');
8884 while (par_count) {
8885 skip(')');
8886 par_count--;
8888 } else if (tok == '{') {
8889 next();
8890 decl_initializer(type, sec, c, first, size_only);
8891 skip('}');
8892 } else if (size_only) {
8893 /* just skip expression */
8894 parlevel = 0;
8895 while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
8896 tok != -1) {
8897 if (tok == '(')
8898 parlevel++;
8899 else if (tok == ')')
8900 parlevel--;
8901 next();
8903 } else {
8904 /* currently, we always use constant expression for globals
8905 (may change for scripting case) */
8906 expr_type = EXPR_CONST;
8907 if (!sec)
8908 expr_type = EXPR_ANY;
8909 init_putv(type, sec, c, 0, expr_type);
8913 /* parse an initializer for type 't' if 'has_init' is non zero, and
8914 allocate space in local or global data space ('r' is either
8915 VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
8916 variable 'v' of scope 'scope' is declared before initializers are
8917 parsed. If 'v' is zero, then a reference to the new object is put
8918 in the value stack. If 'has_init' is 2, a special parsing is done
8919 to handle string constants. */
8920 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
8921 int has_init, int v, int scope)
8923 int size, align, addr, data_offset;
8924 int level;
8925 ParseState saved_parse_state;
8926 TokenString init_str;
8927 Section *sec;
8929 size = type_size(type, &align);
8930 /* If unknown size, we must evaluate it before
8931 evaluating initializers because
8932 initializers can generate global data too
8933 (e.g. string pointers or ISOC99 compound
8934 literals). It also simplifies local
8935 initializers handling */
8936 tok_str_new(&init_str);
8937 if (size < 0) {
8938 if (!has_init)
8939 error("unknown type size");
8940 /* get all init string */
8941 if (has_init == 2) {
8942 /* only get strings */
8943 while (tok == TOK_STR || tok == TOK_LSTR) {
8944 tok_str_add_tok(&init_str);
8945 next();
8947 } else {
8948 level = 0;
8949 while (level > 0 || (tok != ',' && tok != ';')) {
8950 if (tok < 0)
8951 error("unexpected end of file in initializer");
8952 tok_str_add_tok(&init_str);
8953 if (tok == '{')
8954 level++;
8955 else if (tok == '}') {
8956 if (level == 0)
8957 break;
8958 level--;
8960 next();
8963 tok_str_add(&init_str, -1);
8964 tok_str_add(&init_str, 0);
8966 /* compute size */
8967 save_parse_state(&saved_parse_state);
8969 macro_ptr = init_str.str;
8970 next();
8971 decl_initializer(type, NULL, 0, 1, 1);
8972 /* prepare second initializer parsing */
8973 macro_ptr = init_str.str;
8974 next();
8976 /* if still unknown size, error */
8977 size = type_size(type, &align);
8978 if (size < 0)
8979 error("unknown type size");
8981 /* take into account specified alignment if bigger */
8982 if (ad->aligned) {
8983 if (ad->aligned > align)
8984 align = ad->aligned;
8985 } else if (ad->packed) {
8986 align = 1;
8988 if ((r & VT_VALMASK) == VT_LOCAL) {
8989 sec = NULL;
8990 if (do_bounds_check && (type->t & VT_ARRAY))
8991 loc--;
8992 loc = (loc - size) & -align;
8993 addr = loc;
8994 /* handles bounds */
8995 /* XXX: currently, since we do only one pass, we cannot track
8996 '&' operators, so we add only arrays */
8997 if (do_bounds_check && (type->t & VT_ARRAY)) {
8998 unsigned long *bounds_ptr;
8999 /* add padding between regions */
9000 loc--;
9001 /* then add local bound info */
9002 bounds_ptr = section_ptr_add(lbounds_section, 2 * sizeof(unsigned long));
9003 bounds_ptr[0] = addr;
9004 bounds_ptr[1] = size;
9006 if (v) {
9007 /* local variable */
9008 sym_push(v, type, r, addr);
9009 } else {
9010 /* push local reference */
9011 vset(type, r, addr);
9013 } else {
9014 Sym *sym;
9016 sym = NULL;
9017 if (v && scope == VT_CONST) {
9018 /* see if the symbol was already defined */
9019 sym = sym_find(v);
9020 if (sym) {
9021 if (!is_compatible_types(&sym->type, type))
9022 error("incompatible types for redefinition of '%s'",
9023 get_tok_str(v, NULL));
9024 if (sym->type.t & VT_EXTERN) {
9025 /* if the variable is extern, it was not allocated */
9026 sym->type.t &= ~VT_EXTERN;
9027 /* set array size if it was ommited in extern
9028 declaration */
9029 if ((sym->type.t & VT_ARRAY) &&
9030 sym->type.ref->c < 0 &&
9031 type->ref->c >= 0)
9032 sym->type.ref->c = type->ref->c;
9033 } else {
9034 /* we accept several definitions of the same
9035 global variable. this is tricky, because we
9036 must play with the SHN_COMMON type of the symbol */
9037 /* XXX: should check if the variable was already
9038 initialized. It is incorrect to initialized it
9039 twice */
9040 /* no init data, we won't add more to the symbol */
9041 if (!has_init)
9042 goto no_alloc;
9047 /* allocate symbol in corresponding section */
9048 sec = ad->section;
9049 if (!sec) {
9050 if (has_init)
9051 sec = data_section;
9052 else if (tcc_state->nocommon)
9053 sec = bss_section;
9055 if (sec) {
9056 data_offset = sec->data_offset;
9057 data_offset = (data_offset + align - 1) & -align;
9058 addr = data_offset;
9059 /* very important to increment global pointer at this time
9060 because initializers themselves can create new initializers */
9061 data_offset += size;
9062 /* add padding if bound check */
9063 if (do_bounds_check)
9064 data_offset++;
9065 sec->data_offset = data_offset;
9066 /* allocate section space to put the data */
9067 if (sec->sh_type != SHT_NOBITS &&
9068 data_offset > sec->data_allocated)
9069 section_realloc(sec, data_offset);
9070 /* align section if needed */
9071 if (align > sec->sh_addralign)
9072 sec->sh_addralign = align;
9073 } else {
9074 addr = 0; /* avoid warning */
9077 if (v) {
9078 if (scope != VT_CONST || !sym) {
9079 sym = sym_push(v, type, r | VT_SYM, 0);
9081 /* update symbol definition */
9082 if (sec) {
9083 put_extern_sym(sym, sec, addr, size);
9084 } else {
9085 Elf32_Sym *esym;
9086 /* put a common area */
9087 put_extern_sym(sym, NULL, align, size);
9088 /* XXX: find a nicer way */
9089 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
9090 esym->st_shndx = SHN_COMMON;
9092 } else {
9093 CValue cval;
9095 /* push global reference */
9096 sym = get_sym_ref(type, sec, addr, size);
9097 cval.ul = 0;
9098 vsetc(type, VT_CONST | VT_SYM, &cval);
9099 vtop->sym = sym;
9102 /* handles bounds now because the symbol must be defined
9103 before for the relocation */
9104 if (do_bounds_check) {
9105 unsigned long *bounds_ptr;
9107 greloc(bounds_section, sym, bounds_section->data_offset, R_DATA_32);
9108 /* then add global bound info */
9109 bounds_ptr = section_ptr_add(bounds_section, 2 * sizeof(long));
9110 bounds_ptr[0] = 0; /* relocated */
9111 bounds_ptr[1] = size;
9114 if (has_init) {
9115 decl_initializer(type, sec, addr, 1, 0);
9116 /* restore parse state if needed */
9117 if (init_str.str) {
9118 tok_str_free(init_str.str);
9119 restore_parse_state(&saved_parse_state);
9122 no_alloc: ;
9125 void put_func_debug(Sym *sym)
9127 char buf[512];
9129 /* stabs info */
9130 /* XXX: we put here a dummy type */
9131 snprintf(buf, sizeof(buf), "%s:%c1",
9132 funcname, sym->type.t & VT_STATIC ? 'f' : 'F');
9133 put_stabs_r(buf, N_FUN, 0, file->line_num, 0,
9134 cur_text_section, sym->c);
9135 last_ind = 0;
9136 last_line_num = 0;
9139 /* parse an old style function declaration list */
9140 /* XXX: check multiple parameter */
9141 static void func_decl_list(Sym *func_sym)
9143 AttributeDef ad;
9144 int v;
9145 Sym *s;
9146 CType btype, type;
9148 /* parse each declaration */
9149 while (tok != '{' && tok != ';' && tok != ',' && tok != TOK_EOF) {
9150 if (!parse_btype(&btype, &ad))
9151 expect("declaration list");
9152 if (((btype.t & VT_BTYPE) == VT_ENUM ||
9153 (btype.t & VT_BTYPE) == VT_STRUCT) &&
9154 tok == ';') {
9155 /* we accept no variable after */
9156 } else {
9157 for(;;) {
9158 type = btype;
9159 type_decl(&type, &ad, &v, TYPE_DIRECT);
9160 /* find parameter in function parameter list */
9161 s = func_sym->next;
9162 while (s != NULL) {
9163 if ((s->v & ~SYM_FIELD) == v)
9164 goto found;
9165 s = s->next;
9167 error("declaration for parameter '%s' but no such parameter",
9168 get_tok_str(v, NULL));
9169 found:
9170 /* check that no storage specifier except 'register' was given */
9171 if (type.t & VT_STORAGE)
9172 error("storage class specified for '%s'", get_tok_str(v, NULL));
9173 convert_parameter_type(&type);
9174 /* we can add the type (NOTE: it could be local to the function) */
9175 s->type = type;
9176 /* accept other parameters */
9177 if (tok == ',')
9178 next();
9179 else
9180 break;
9183 skip(';');
9187 /* parse a function defined by symbol 'sym' and generate its code in
9188 'cur_text_section' */
9189 static void gen_function(Sym *sym)
9191 int saved_nocode_wanted = nocode_wanted;
9192 nocode_wanted = 0;
9193 ind = cur_text_section->data_offset;
9194 /* NOTE: we patch the symbol size later */
9195 put_extern_sym(sym, cur_text_section, ind, 0);
9196 funcname = get_tok_str(sym->v, NULL);
9197 func_ind = ind;
9198 /* put debug symbol */
9199 if (do_debug)
9200 put_func_debug(sym);
9201 /* push a dummy symbol to enable local sym storage */
9202 sym_push2(&local_stack, SYM_FIELD, 0, 0);
9203 gfunc_prolog(&sym->type);
9204 rsym = 0;
9205 block(NULL, NULL, NULL, NULL, 0, 0);
9206 gsym(rsym);
9207 gfunc_epilog();
9208 cur_text_section->data_offset = ind;
9209 label_pop(&global_label_stack, NULL);
9210 sym_pop(&local_stack, NULL); /* reset local stack */
9211 /* end of function */
9212 /* patch symbol size */
9213 ((Elf32_Sym *)symtab_section->data)[sym->c].st_size =
9214 ind - func_ind;
9215 if (do_debug) {
9216 put_stabn(N_FUN, 0, 0, ind - func_ind);
9218 funcname = ""; /* for safety */
9219 func_vt.t = VT_VOID; /* for safety */
9220 ind = 0; /* for safety */
9221 nocode_wanted = saved_nocode_wanted;
9224 static void gen_inline_functions(void)
9226 Sym *sym;
9227 CType *type;
9228 int *str, inline_generated;
9230 /* iterate while inline function are referenced */
9231 for(;;) {
9232 inline_generated = 0;
9233 for(sym = global_stack; sym != NULL; sym = sym->prev) {
9234 type = &sym->type;
9235 if (((type->t & VT_BTYPE) == VT_FUNC) &&
9236 (type->t & (VT_STATIC | VT_INLINE)) ==
9237 (VT_STATIC | VT_INLINE) &&
9238 sym->c != 0) {
9239 /* the function was used: generate its code and
9240 convert it to a normal function */
9241 str = INLINE_DEF(sym->r);
9242 sym->r = VT_SYM | VT_CONST;
9243 sym->type.t &= ~VT_INLINE;
9245 macro_ptr = str;
9246 next();
9247 cur_text_section = text_section;
9248 gen_function(sym);
9249 macro_ptr = NULL; /* fail safe */
9251 tok_str_free(str);
9252 inline_generated = 1;
9255 if (!inline_generated)
9256 break;
9259 /* free all remaining inline function tokens */
9260 for(sym = global_stack; sym != NULL; sym = sym->prev) {
9261 type = &sym->type;
9262 if (((type->t & VT_BTYPE) == VT_FUNC) &&
9263 (type->t & (VT_STATIC | VT_INLINE)) ==
9264 (VT_STATIC | VT_INLINE)) {
9265 //gr printf("sym %d %s\n", sym->r, get_tok_str(sym->v, NULL));
9266 if (sym->r == (VT_SYM | VT_CONST)) //gr beware!
9267 continue;
9268 str = INLINE_DEF(sym->r);
9269 tok_str_free(str);
9270 sym->r = 0; /* fail safe */
9275 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
9276 static void decl(int l)
9278 int v, has_init, r;
9279 CType type, btype;
9280 Sym *sym;
9281 AttributeDef ad;
9283 while (1) {
9284 if (!parse_btype(&btype, &ad)) {
9285 /* skip redundant ';' */
9286 /* XXX: find more elegant solution */
9287 if (tok == ';') {
9288 next();
9289 continue;
9291 if (l == VT_CONST &&
9292 (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3)) {
9293 /* global asm block */
9294 asm_global_instr();
9295 continue;
9297 /* special test for old K&R protos without explicit int
9298 type. Only accepted when defining global data */
9299 if (l == VT_LOCAL || tok < TOK_DEFINE)
9300 break;
9301 btype.t = VT_INT;
9303 if (((btype.t & VT_BTYPE) == VT_ENUM ||
9304 (btype.t & VT_BTYPE) == VT_STRUCT) &&
9305 tok == ';') {
9306 /* we accept no variable after */
9307 next();
9308 continue;
9310 while (1) { /* iterate thru each declaration */
9311 type = btype;
9312 type_decl(&type, &ad, &v, TYPE_DIRECT);
9313 #if 0
9315 char buf[500];
9316 type_to_str(buf, sizeof(buf), t, get_tok_str(v, NULL));
9317 printf("type = '%s'\n", buf);
9319 #endif
9320 if ((type.t & VT_BTYPE) == VT_FUNC) {
9321 /* if old style function prototype, we accept a
9322 declaration list */
9323 sym = type.ref;
9324 if (sym->c == FUNC_OLD)
9325 func_decl_list(sym);
9328 if (tok == '{') {
9329 if (l == VT_LOCAL)
9330 error("cannot use local functions");
9331 if ((type.t & VT_BTYPE) != VT_FUNC)
9332 expect("function definition");
9334 /* reject abstract declarators in function definition */
9335 sym = type.ref;
9336 while ((sym = sym->next) != NULL)
9337 if (!(sym->v & ~SYM_FIELD))
9338 expect("identifier");
9340 /* XXX: cannot do better now: convert extern line to static inline */
9341 if ((type.t & (VT_EXTERN | VT_INLINE)) == (VT_EXTERN | VT_INLINE))
9342 type.t = (type.t & ~VT_EXTERN) | VT_STATIC;
9344 sym = sym_find(v);
9345 if (sym) {
9346 if ((sym->type.t & VT_BTYPE) != VT_FUNC)
9347 goto func_error1;
9348 /* specific case: if not func_call defined, we put
9349 the one of the prototype */
9350 /* XXX: should have default value */
9351 r = sym->type.ref->r;
9352 if (FUNC_CALL(r) != FUNC_CDECL
9353 && FUNC_CALL(type.ref->r) == FUNC_CDECL)
9354 FUNC_CALL(type.ref->r) = FUNC_CALL(r);
9355 if (FUNC_EXPORT(r))
9356 FUNC_EXPORT(type.ref->r) = 1;
9358 if (!is_compatible_types(&sym->type, &type)) {
9359 func_error1:
9360 error("incompatible types for redefinition of '%s'",
9361 get_tok_str(v, NULL));
9363 /* if symbol is already defined, then put complete type */
9364 sym->type = type;
9365 } else {
9366 /* put function symbol */
9367 sym = global_identifier_push(v, type.t, 0);
9368 sym->type.ref = type.ref;
9371 /* static inline functions are just recorded as a kind
9372 of macro. Their code will be emitted at the end of
9373 the compilation unit only if they are used */
9374 if ((type.t & (VT_INLINE | VT_STATIC)) ==
9375 (VT_INLINE | VT_STATIC)) {
9376 TokenString func_str;
9377 int block_level;
9379 tok_str_new(&func_str);
9381 block_level = 0;
9382 for(;;) {
9383 int t;
9384 if (tok == TOK_EOF)
9385 error("unexpected end of file");
9386 tok_str_add_tok(&func_str);
9387 t = tok;
9388 next();
9389 if (t == '{') {
9390 block_level++;
9391 } else if (t == '}') {
9392 block_level--;
9393 if (block_level == 0)
9394 break;
9397 tok_str_add(&func_str, -1);
9398 tok_str_add(&func_str, 0);
9399 INLINE_DEF(sym->r) = func_str.str;
9400 } else {
9401 /* compute text section */
9402 cur_text_section = ad.section;
9403 if (!cur_text_section)
9404 cur_text_section = text_section;
9405 sym->r = VT_SYM | VT_CONST;
9406 gen_function(sym);
9408 break;
9409 } else {
9410 if (btype.t & VT_TYPEDEF) {
9411 /* save typedefed type */
9412 /* XXX: test storage specifiers ? */
9413 sym = sym_push(v, &type, 0, 0);
9414 sym->type.t |= VT_TYPEDEF;
9415 } else if ((type.t & VT_BTYPE) == VT_FUNC) {
9416 /* external function definition */
9417 /* specific case for func_call attribute */
9418 if (ad.func_attr)
9419 type.ref->r = ad.func_attr;
9420 external_sym(v, &type, 0);
9421 } else {
9422 /* not lvalue if array */
9423 r = 0;
9424 if (!(type.t & VT_ARRAY))
9425 r |= lvalue_type(type.t);
9426 has_init = (tok == '=');
9427 if ((btype.t & VT_EXTERN) ||
9428 ((type.t & VT_ARRAY) && (type.t & VT_STATIC) &&
9429 !has_init && l == VT_CONST && type.ref->c < 0)) {
9430 /* external variable */
9431 /* NOTE: as GCC, uninitialized global static
9432 arrays of null size are considered as
9433 extern */
9434 external_sym(v, &type, r);
9435 } else {
9436 type.t |= (btype.t & VT_STATIC); /* Retain "static". */
9437 if (type.t & VT_STATIC)
9438 r |= VT_CONST;
9439 else
9440 r |= l;
9441 if (has_init)
9442 next();
9443 decl_initializer_alloc(&type, &ad, r,
9444 has_init, v, l);
9447 if (tok != ',') {
9448 skip(';');
9449 break;
9451 next();
9457 /* better than nothing, but needs extension to handle '-E' option
9458 correctly too */
9459 static void preprocess_init(TCCState *s1)
9461 s1->include_stack_ptr = s1->include_stack;
9462 /* XXX: move that before to avoid having to initialize
9463 file->ifdef_stack_ptr ? */
9464 s1->ifdef_stack_ptr = s1->ifdef_stack;
9465 file->ifdef_stack_ptr = s1->ifdef_stack_ptr;
9467 /* XXX: not ANSI compliant: bound checking says error */
9468 vtop = vstack - 1;
9469 s1->pack_stack[0] = 0;
9470 s1->pack_stack_ptr = s1->pack_stack;
9473 /* compile the C file opened in 'file'. Return non zero if errors. */
9474 static int tcc_compile(TCCState *s1)
9476 Sym *define_start;
9477 char buf[512];
9478 volatile int section_sym;
9480 #ifdef INC_DEBUG
9481 printf("%s: **** new file\n", file->filename);
9482 #endif
9483 preprocess_init(s1);
9485 funcname = "";
9486 anon_sym = SYM_FIRST_ANOM;
9488 /* file info: full path + filename */
9489 section_sym = 0; /* avoid warning */
9490 if (do_debug) {
9491 section_sym = put_elf_sym(symtab_section, 0, 0,
9492 ELF32_ST_INFO(STB_LOCAL, STT_SECTION), 0,
9493 text_section->sh_num, NULL);
9494 getcwd(buf, sizeof(buf));
9495 #ifdef _WIN32
9496 normalize_slashes(buf);
9497 #endif
9498 pstrcat(buf, sizeof(buf), "/");
9499 put_stabs_r(buf, N_SO, 0, 0,
9500 text_section->data_offset, text_section, section_sym);
9501 put_stabs_r(file->filename, N_SO, 0, 0,
9502 text_section->data_offset, text_section, section_sym);
9504 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
9505 symbols can be safely used */
9506 put_elf_sym(symtab_section, 0, 0,
9507 ELF32_ST_INFO(STB_LOCAL, STT_FILE), 0,
9508 SHN_ABS, file->filename);
9510 /* define some often used types */
9511 int_type.t = VT_INT;
9513 char_pointer_type.t = VT_BYTE;
9514 mk_pointer(&char_pointer_type);
9516 func_old_type.t = VT_FUNC;
9517 func_old_type.ref = sym_push(SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD);
9519 #if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)
9520 float_type.t = VT_FLOAT;
9521 double_type.t = VT_DOUBLE;
9523 func_float_type.t = VT_FUNC;
9524 func_float_type.ref = sym_push(SYM_FIELD, &float_type, FUNC_CDECL, FUNC_OLD);
9525 func_double_type.t = VT_FUNC;
9526 func_double_type.ref = sym_push(SYM_FIELD, &double_type, FUNC_CDECL, FUNC_OLD);
9527 #endif
9529 #if 0
9530 /* define 'void *alloca(unsigned int)' builtin function */
9532 Sym *s1;
9534 p = anon_sym++;
9535 sym = sym_push(p, mk_pointer(VT_VOID), FUNC_CDECL, FUNC_NEW);
9536 s1 = sym_push(SYM_FIELD, VT_UNSIGNED | VT_INT, 0, 0);
9537 s1->next = NULL;
9538 sym->next = s1;
9539 sym_push(TOK_alloca, VT_FUNC | (p << VT_STRUCT_SHIFT), VT_CONST, 0);
9541 #endif
9543 define_start = define_stack;
9544 nocode_wanted = 1;
9546 if (setjmp(s1->error_jmp_buf) == 0) {
9547 s1->nb_errors = 0;
9548 s1->error_set_jmp_enabled = 1;
9550 ch = file->buf_ptr[0];
9551 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
9552 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM;
9553 next();
9554 decl(VT_CONST);
9555 if (tok != TOK_EOF)
9556 expect("declaration");
9558 /* end of translation unit info */
9559 if (do_debug) {
9560 put_stabs_r(NULL, N_SO, 0, 0,
9561 text_section->data_offset, text_section, section_sym);
9564 s1->error_set_jmp_enabled = 0;
9566 /* reset define stack, but leave -Dsymbols (may be incorrect if
9567 they are undefined) */
9568 free_defines(define_start);
9570 gen_inline_functions();
9572 sym_pop(&global_stack, NULL);
9574 return s1->nb_errors != 0 ? -1 : 0;
9577 /* Preprocess the current file */
9578 /* XXX: add line and file infos, add options to preserve spaces */
9579 static int tcc_preprocess(TCCState *s1)
9581 Sym *define_start;
9582 int last_is_space;
9584 preprocess_init(s1);
9586 define_start = define_stack;
9588 ch = file->buf_ptr[0];
9589 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
9590 parse_flags = PARSE_FLAG_ASM_COMMENTS | PARSE_FLAG_PREPROCESS |
9591 PARSE_FLAG_LINEFEED;
9592 last_is_space = 1;
9593 next();
9594 for(;;) {
9595 if (tok == TOK_EOF) {
9596 break;
9597 } else if (tok == TOK_LINEFEED) {
9598 last_is_space = 1;
9599 } else {
9600 if (!last_is_space)
9601 fputc(' ', s1->outfile);
9602 last_is_space = 0;
9604 fputs(get_tok_str(tok, &tokc), s1->outfile);
9605 next();
9607 free_defines(define_start);
9608 return 0;
9611 #ifdef LIBTCC
9612 int tcc_compile_string(TCCState *s, const char *str)
9614 BufferedFile bf1, *bf = &bf1;
9615 int ret, len;
9616 char *buf;
9618 /* init file structure */
9619 bf->fd = -1;
9620 /* XXX: avoid copying */
9621 len = strlen(str);
9622 buf = tcc_malloc(len + 1);
9623 if (!buf)
9624 return -1;
9625 memcpy(buf, str, len);
9626 buf[len] = CH_EOB;
9627 bf->buf_ptr = buf;
9628 bf->buf_end = buf + len;
9629 pstrcpy(bf->filename, sizeof(bf->filename), "<string>");
9630 bf->line_num = 1;
9631 file = bf;
9633 ret = tcc_compile(s);
9635 tcc_free(buf);
9637 /* currently, no need to close */
9638 return ret;
9640 #endif
9642 /* define a preprocessor symbol. A value can also be provided with the '=' operator */
9643 void tcc_define_symbol(TCCState *s1, const char *sym, const char *value)
9645 BufferedFile bf1, *bf = &bf1;
9647 pstrcpy(bf->buffer, IO_BUF_SIZE, sym);
9648 pstrcat(bf->buffer, IO_BUF_SIZE, " ");
9649 /* default value */
9650 if (!value)
9651 value = "1";
9652 pstrcat(bf->buffer, IO_BUF_SIZE, value);
9654 /* init file structure */
9655 bf->fd = -1;
9656 bf->buf_ptr = bf->buffer;
9657 bf->buf_end = bf->buffer + strlen(bf->buffer);
9658 *bf->buf_end = CH_EOB;
9659 bf->filename[0] = '\0';
9660 bf->line_num = 1;
9661 file = bf;
9663 s1->include_stack_ptr = s1->include_stack;
9665 /* parse with define parser */
9666 ch = file->buf_ptr[0];
9667 next_nomacro();
9668 parse_define();
9669 file = NULL;
9672 /* undefine a preprocessor symbol */
9673 void tcc_undefine_symbol(TCCState *s1, const char *sym)
9675 TokenSym *ts;
9676 Sym *s;
9677 ts = tok_alloc(sym, strlen(sym));
9678 s = define_find(ts->tok);
9679 /* undefine symbol by putting an invalid name */
9680 if (s)
9681 define_undef(s);
9684 #ifdef CONFIG_TCC_ASM
9686 #ifdef TCC_TARGET_I386
9687 #include "i386-asm.c"
9688 #endif
9689 #include "tccasm.c"
9691 #else
9692 static void asm_instr(void)
9694 error("inline asm() not supported");
9696 static void asm_global_instr(void)
9698 error("inline asm() not supported");
9700 #endif
9702 #include "tccelf.c"
9704 #ifdef TCC_TARGET_COFF
9705 #include "tcccoff.c"
9706 #endif
9708 #ifdef TCC_TARGET_PE
9709 #include "tccpe.c"
9710 #endif
9712 /* print the position in the source file of PC value 'pc' by reading
9713 the stabs debug information */
9714 static void rt_printline(unsigned long wanted_pc)
9716 Stab_Sym *sym, *sym_end;
9717 char func_name[128], last_func_name[128];
9718 unsigned long func_addr, last_pc, pc;
9719 const char *incl_files[INCLUDE_STACK_SIZE];
9720 int incl_index, len, last_line_num, i;
9721 const char *str, *p;
9723 fprintf(stderr, "0x%08lx:", wanted_pc);
9725 func_name[0] = '\0';
9726 func_addr = 0;
9727 incl_index = 0;
9728 last_func_name[0] = '\0';
9729 last_pc = 0xffffffff;
9730 last_line_num = 1;
9731 sym = (Stab_Sym *)stab_section->data + 1;
9732 sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset);
9733 while (sym < sym_end) {
9734 switch(sym->n_type) {
9735 /* function start or end */
9736 case N_FUN:
9737 if (sym->n_strx == 0) {
9738 /* we test if between last line and end of function */
9739 pc = sym->n_value + func_addr;
9740 if (wanted_pc >= last_pc && wanted_pc < pc)
9741 goto found;
9742 func_name[0] = '\0';
9743 func_addr = 0;
9744 } else {
9745 str = stabstr_section->data + sym->n_strx;
9746 p = strchr(str, ':');
9747 if (!p) {
9748 pstrcpy(func_name, sizeof(func_name), str);
9749 } else {
9750 len = p - str;
9751 if (len > sizeof(func_name) - 1)
9752 len = sizeof(func_name) - 1;
9753 memcpy(func_name, str, len);
9754 func_name[len] = '\0';
9756 func_addr = sym->n_value;
9758 break;
9759 /* line number info */
9760 case N_SLINE:
9761 pc = sym->n_value + func_addr;
9762 if (wanted_pc >= last_pc && wanted_pc < pc)
9763 goto found;
9764 last_pc = pc;
9765 last_line_num = sym->n_desc;
9766 /* XXX: slow! */
9767 strcpy(last_func_name, func_name);
9768 break;
9769 /* include files */
9770 case N_BINCL:
9771 str = stabstr_section->data + sym->n_strx;
9772 add_incl:
9773 if (incl_index < INCLUDE_STACK_SIZE) {
9774 incl_files[incl_index++] = str;
9776 break;
9777 case N_EINCL:
9778 if (incl_index > 1)
9779 incl_index--;
9780 break;
9781 case N_SO:
9782 if (sym->n_strx == 0) {
9783 incl_index = 0; /* end of translation unit */
9784 } else {
9785 str = stabstr_section->data + sym->n_strx;
9786 /* do not add path */
9787 len = strlen(str);
9788 if (len > 0 && str[len - 1] != '/')
9789 goto add_incl;
9791 break;
9793 sym++;
9796 /* second pass: we try symtab symbols (no line number info) */
9797 incl_index = 0;
9799 Elf32_Sym *sym, *sym_end;
9800 int type;
9802 sym_end = (Elf32_Sym *)(symtab_section->data + symtab_section->data_offset);
9803 for(sym = (Elf32_Sym *)symtab_section->data + 1;
9804 sym < sym_end;
9805 sym++) {
9806 type = ELF32_ST_TYPE(sym->st_info);
9807 if (type == STT_FUNC) {
9808 if (wanted_pc >= sym->st_value &&
9809 wanted_pc < sym->st_value + sym->st_size) {
9810 pstrcpy(last_func_name, sizeof(last_func_name),
9811 strtab_section->data + sym->st_name);
9812 goto found;
9817 /* did not find any info: */
9818 fprintf(stderr, " ???\n");
9819 return;
9820 found:
9821 if (last_func_name[0] != '\0') {
9822 fprintf(stderr, " %s()", last_func_name);
9824 if (incl_index > 0) {
9825 fprintf(stderr, " (%s:%d",
9826 incl_files[incl_index - 1], last_line_num);
9827 for(i = incl_index - 2; i >= 0; i--)
9828 fprintf(stderr, ", included from %s", incl_files[i]);
9829 fprintf(stderr, ")");
9831 fprintf(stderr, "\n");
9834 #if !defined(_WIN32) && !defined(CONFIG_TCCBOOT)
9836 #ifdef __i386__
9838 /* fix for glibc 2.1 */
9839 #ifndef REG_EIP
9840 #define REG_EIP EIP
9841 #define REG_EBP EBP
9842 #endif
9844 /* return the PC at frame level 'level'. Return non zero if not found */
9845 static int rt_get_caller_pc(unsigned long *paddr,
9846 ucontext_t *uc, int level)
9848 unsigned long fp;
9849 int i;
9851 if (level == 0) {
9852 #if defined(__FreeBSD__)
9853 *paddr = uc->uc_mcontext.mc_eip;
9854 #elif defined(__dietlibc__)
9855 *paddr = uc->uc_mcontext.eip;
9856 #else
9857 *paddr = uc->uc_mcontext.gregs[REG_EIP];
9858 #endif
9859 return 0;
9860 } else {
9861 #if defined(__FreeBSD__)
9862 fp = uc->uc_mcontext.mc_ebp;
9863 #elif defined(__dietlibc__)
9864 fp = uc->uc_mcontext.ebp;
9865 #else
9866 fp = uc->uc_mcontext.gregs[REG_EBP];
9867 #endif
9868 for(i=1;i<level;i++) {
9869 /* XXX: check address validity with program info */
9870 if (fp <= 0x1000 || fp >= 0xc0000000)
9871 return -1;
9872 fp = ((unsigned long *)fp)[0];
9874 *paddr = ((unsigned long *)fp)[1];
9875 return 0;
9878 #else
9880 #warning add arch specific rt_get_caller_pc()
9882 static int rt_get_caller_pc(unsigned long *paddr,
9883 ucontext_t *uc, int level)
9885 return -1;
9887 #endif
9889 /* emit a run time error at position 'pc' */
9890 void rt_error(ucontext_t *uc, const char *fmt, ...)
9892 va_list ap;
9893 unsigned long pc;
9894 int i;
9896 va_start(ap, fmt);
9897 fprintf(stderr, "Runtime error: ");
9898 vfprintf(stderr, fmt, ap);
9899 fprintf(stderr, "\n");
9900 for(i=0;i<num_callers;i++) {
9901 if (rt_get_caller_pc(&pc, uc, i) < 0)
9902 break;
9903 if (i == 0)
9904 fprintf(stderr, "at ");
9905 else
9906 fprintf(stderr, "by ");
9907 rt_printline(pc);
9909 exit(255);
9910 va_end(ap);
9913 /* signal handler for fatal errors */
9914 static void sig_error(int signum, siginfo_t *siginf, void *puc)
9916 ucontext_t *uc = puc;
9918 switch(signum) {
9919 case SIGFPE:
9920 switch(siginf->si_code) {
9921 case FPE_INTDIV:
9922 case FPE_FLTDIV:
9923 rt_error(uc, "division by zero");
9924 break;
9925 default:
9926 rt_error(uc, "floating point exception");
9927 break;
9929 break;
9930 case SIGBUS:
9931 case SIGSEGV:
9932 if (rt_bound_error_msg && *rt_bound_error_msg)
9933 rt_error(uc, *rt_bound_error_msg);
9934 else
9935 rt_error(uc, "dereferencing invalid pointer");
9936 break;
9937 case SIGILL:
9938 rt_error(uc, "illegal instruction");
9939 break;
9940 case SIGABRT:
9941 rt_error(uc, "abort() called");
9942 break;
9943 default:
9944 rt_error(uc, "caught signal %d", signum);
9945 break;
9947 exit(255);
9949 #endif
9951 /* do all relocations (needed before using tcc_get_symbol()) */
9952 int tcc_relocate(TCCState *s1)
9954 Section *s;
9955 int i;
9957 s1->nb_errors = 0;
9959 #ifdef TCC_TARGET_PE
9960 pe_add_runtime(s1);
9961 #else
9962 tcc_add_runtime(s1);
9963 #endif
9965 relocate_common_syms();
9967 tcc_add_linker_symbols(s1);
9968 #ifndef TCC_TARGET_PE
9969 build_got_entries(s1);
9970 #endif
9971 /* compute relocation address : section are relocated in place. We
9972 also alloc the bss space */
9973 for(i = 1; i < s1->nb_sections; i++) {
9974 s = s1->sections[i];
9975 if (s->sh_flags & SHF_ALLOC) {
9976 if (s->sh_type == SHT_NOBITS)
9977 s->data = tcc_mallocz(s->data_offset);
9978 s->sh_addr = (unsigned long)s->data;
9982 relocate_syms(s1, 1);
9984 if (s1->nb_errors != 0)
9985 return -1;
9987 /* relocate each section */
9988 for(i = 1; i < s1->nb_sections; i++) {
9989 s = s1->sections[i];
9990 if (s->reloc)
9991 relocate_section(s1, s);
9994 /* mark executable sections as executable in memory */
9995 for(i = 1; i < s1->nb_sections; i++) {
9996 s = s1->sections[i];
9997 if ((s->sh_flags & (SHF_ALLOC | SHF_EXECINSTR)) ==
9998 (SHF_ALLOC | SHF_EXECINSTR))
9999 set_pages_executable(s->data, s->data_offset);
10001 return 0;
10004 /* launch the compiled program with the given arguments */
10005 int tcc_run(TCCState *s1, int argc, char **argv)
10007 int (*prog_main)(int, char **);
10009 if (tcc_relocate(s1) < 0)
10010 return -1;
10012 prog_main = tcc_get_symbol_err(s1, "main");
10014 if (do_debug) {
10015 #if defined(_WIN32) || defined(CONFIG_TCCBOOT)
10016 error("debug mode currently not available for Windows");
10017 #else
10018 struct sigaction sigact;
10019 /* install TCC signal handlers to print debug info on fatal
10020 runtime errors */
10021 sigact.sa_flags = SA_SIGINFO | SA_RESETHAND;
10022 sigact.sa_sigaction = sig_error;
10023 sigemptyset(&sigact.sa_mask);
10024 sigaction(SIGFPE, &sigact, NULL);
10025 sigaction(SIGILL, &sigact, NULL);
10026 sigaction(SIGSEGV, &sigact, NULL);
10027 sigaction(SIGBUS, &sigact, NULL);
10028 sigaction(SIGABRT, &sigact, NULL);
10029 #endif
10032 #ifdef CONFIG_TCC_BCHECK
10033 if (do_bounds_check) {
10034 void (*bound_init)(void);
10036 /* set error function */
10037 rt_bound_error_msg = (void *)tcc_get_symbol_err(s1,
10038 "__bound_error_msg");
10040 /* XXX: use .init section so that it also work in binary ? */
10041 bound_init = (void *)tcc_get_symbol_err(s1, "__bound_init");
10042 bound_init();
10044 #endif
10045 return (*prog_main)(argc, argv);
10048 TCCState *tcc_new(void)
10050 const char *p, *r;
10051 TCCState *s;
10052 TokenSym *ts;
10053 int i, c;
10055 s = tcc_mallocz(sizeof(TCCState));
10056 if (!s)
10057 return NULL;
10058 tcc_state = s;
10059 s->output_type = TCC_OUTPUT_MEMORY;
10061 /* init isid table */
10062 for(i=0;i<256;i++)
10063 isidnum_table[i] = isid(i) || isnum(i);
10065 /* add all tokens */
10066 table_ident = NULL;
10067 memset(hash_ident, 0, TOK_HASH_SIZE * sizeof(TokenSym *));
10069 tok_ident = TOK_IDENT;
10070 p = tcc_keywords;
10071 while (*p) {
10072 r = p;
10073 for(;;) {
10074 c = *r++;
10075 if (c == '\0')
10076 break;
10078 ts = tok_alloc(p, r - p - 1);
10079 p = r;
10082 /* we add dummy defines for some special macros to speed up tests
10083 and to have working defined() */
10084 define_push(TOK___LINE__, MACRO_OBJ, NULL, NULL);
10085 define_push(TOK___FILE__, MACRO_OBJ, NULL, NULL);
10086 define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL);
10087 define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL);
10089 /* standard defines */
10090 tcc_define_symbol(s, "__STDC__", NULL);
10091 tcc_define_symbol(s, "__STDC_VERSION__", "199901L");
10092 #if defined(TCC_TARGET_I386)
10093 tcc_define_symbol(s, "__i386__", NULL);
10094 #endif
10095 #if defined(TCC_TARGET_ARM)
10096 tcc_define_symbol(s, "__ARM_ARCH_4__", NULL);
10097 tcc_define_symbol(s, "__arm_elf__", NULL);
10098 tcc_define_symbol(s, "__arm_elf", NULL);
10099 tcc_define_symbol(s, "arm_elf", NULL);
10100 tcc_define_symbol(s, "__arm__", NULL);
10101 tcc_define_symbol(s, "__arm", NULL);
10102 tcc_define_symbol(s, "arm", NULL);
10103 tcc_define_symbol(s, "__APCS_32__", NULL);
10104 #endif
10105 #ifdef TCC_TARGET_PE
10106 tcc_define_symbol(s, "_WIN32", NULL);
10107 #else
10108 tcc_define_symbol(s, "__unix__", NULL);
10109 tcc_define_symbol(s, "__unix", NULL);
10110 #if defined(__linux)
10111 tcc_define_symbol(s, "__linux__", NULL);
10112 tcc_define_symbol(s, "__linux", NULL);
10113 #endif
10114 #endif
10115 /* tiny C specific defines */
10116 tcc_define_symbol(s, "__TINYC__", NULL);
10118 /* tiny C & gcc defines */
10119 tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned int");
10120 tcc_define_symbol(s, "__PTRDIFF_TYPE__", "int");
10121 #ifdef TCC_TARGET_PE
10122 tcc_define_symbol(s, "__WCHAR_TYPE__", "unsigned short");
10123 #else
10124 tcc_define_symbol(s, "__WCHAR_TYPE__", "int");
10125 #endif
10127 /* default library paths */
10128 #ifdef TCC_TARGET_PE
10130 char buf[1024];
10131 snprintf(buf, sizeof(buf), "%s/lib", tcc_lib_path);
10132 tcc_add_library_path(s, buf);
10134 #else
10135 tcc_add_library_path(s, "/usr/local/lib");
10136 tcc_add_library_path(s, "/usr/lib");
10137 tcc_add_library_path(s, "/lib");
10138 #endif
10140 /* no section zero */
10141 dynarray_add((void ***)&s->sections, &s->nb_sections, NULL);
10143 /* create standard sections */
10144 text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
10145 data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
10146 bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
10148 /* symbols are always generated for linking stage */
10149 symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0,
10150 ".strtab",
10151 ".hashtab", SHF_PRIVATE);
10152 strtab_section = symtab_section->link;
10154 /* private symbol table for dynamic symbols */
10155 s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE,
10156 ".dynstrtab",
10157 ".dynhashtab", SHF_PRIVATE);
10158 s->alacarte_link = 1;
10160 #ifdef CHAR_IS_UNSIGNED
10161 s->char_is_unsigned = 1;
10162 #endif
10163 #if defined(TCC_TARGET_PE) && 0
10164 /* XXX: currently the PE linker is not ready to support that */
10165 s->leading_underscore = 1;
10166 #endif
10167 return s;
10170 void tcc_delete(TCCState *s1)
10172 int i, n;
10174 /* free -D defines */
10175 free_defines(NULL);
10177 /* free tokens */
10178 n = tok_ident - TOK_IDENT;
10179 for(i = 0; i < n; i++)
10180 tcc_free(table_ident[i]);
10181 tcc_free(table_ident);
10183 /* free all sections */
10185 free_section(symtab_section->hash);
10187 free_section(s1->dynsymtab_section->hash);
10188 free_section(s1->dynsymtab_section->link);
10189 free_section(s1->dynsymtab_section);
10191 for(i = 1; i < s1->nb_sections; i++)
10192 free_section(s1->sections[i]);
10193 tcc_free(s1->sections);
10195 /* free loaded dlls array */
10196 dynarray_reset(&s1->loaded_dlls, &s1->nb_loaded_dlls);
10198 /* free library paths */
10199 dynarray_reset(&s1->library_paths, &s1->nb_library_paths);
10201 /* free include paths */
10202 dynarray_reset(&s1->cached_includes, &s1->nb_cached_includes);
10203 dynarray_reset(&s1->include_paths, &s1->nb_include_paths);
10204 dynarray_reset(&s1->sysinclude_paths, &s1->nb_sysinclude_paths);
10206 tcc_free(s1);
10209 int tcc_add_include_path(TCCState *s1, const char *pathname)
10211 char *pathname1;
10213 pathname1 = tcc_strdup(pathname);
10214 dynarray_add((void ***)&s1->include_paths, &s1->nb_include_paths, pathname1);
10215 return 0;
10218 int tcc_add_sysinclude_path(TCCState *s1, const char *pathname)
10220 char *pathname1;
10222 pathname1 = tcc_strdup(pathname);
10223 dynarray_add((void ***)&s1->sysinclude_paths, &s1->nb_sysinclude_paths, pathname1);
10224 return 0;
10227 static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
10229 const char *ext;
10230 Elf32_Ehdr ehdr;
10231 int fd, ret;
10232 BufferedFile *saved_file;
10234 /* find source file type with extension */
10235 ext = tcc_fileextension(filename);
10236 if (ext[0])
10237 ext++;
10239 /* open the file */
10240 saved_file = file;
10241 file = tcc_open(s1, filename);
10242 if (!file) {
10243 if (flags & AFF_PRINT_ERROR) {
10244 error_noabort("file '%s' not found", filename);
10246 ret = -1;
10247 goto fail1;
10250 if (flags & AFF_PREPROCESS) {
10251 ret = tcc_preprocess(s1);
10252 } else if (!ext[0] || !strcmp(ext, "c")) {
10253 /* C file assumed */
10254 ret = tcc_compile(s1);
10255 } else
10256 #ifdef CONFIG_TCC_ASM
10257 if (!strcmp(ext, "S")) {
10258 /* preprocessed assembler */
10259 ret = tcc_assemble(s1, 1);
10260 } else if (!strcmp(ext, "s")) {
10261 /* non preprocessed assembler */
10262 ret = tcc_assemble(s1, 0);
10263 } else
10264 #endif
10265 #ifdef TCC_TARGET_PE
10266 if (!strcmp(ext, "def")) {
10267 ret = pe_load_def_file(s1, file->fd);
10268 } else
10269 #endif
10271 fd = file->fd;
10272 /* assume executable format: auto guess file type */
10273 ret = read(fd, &ehdr, sizeof(ehdr));
10274 lseek(fd, 0, SEEK_SET);
10275 if (ret <= 0) {
10276 error_noabort("could not read header");
10277 goto fail;
10278 } else if (ret != sizeof(ehdr)) {
10279 goto try_load_script;
10282 if (ehdr.e_ident[0] == ELFMAG0 &&
10283 ehdr.e_ident[1] == ELFMAG1 &&
10284 ehdr.e_ident[2] == ELFMAG2 &&
10285 ehdr.e_ident[3] == ELFMAG3) {
10286 file->line_num = 0; /* do not display line number if error */
10287 if (ehdr.e_type == ET_REL) {
10288 ret = tcc_load_object_file(s1, fd, 0);
10289 } else if (ehdr.e_type == ET_DYN) {
10290 if (s1->output_type == TCC_OUTPUT_MEMORY) {
10291 #ifdef TCC_TARGET_PE
10292 ret = -1;
10293 #else
10294 void *h;
10295 h = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY);
10296 if (h)
10297 ret = 0;
10298 else
10299 ret = -1;
10300 #endif
10301 } else {
10302 ret = tcc_load_dll(s1, fd, filename,
10303 (flags & AFF_REFERENCED_DLL) != 0);
10305 } else {
10306 error_noabort("unrecognized ELF file");
10307 goto fail;
10309 } else if (memcmp((char *)&ehdr, ARMAG, 8) == 0) {
10310 file->line_num = 0; /* do not display line number if error */
10311 ret = tcc_load_archive(s1, fd);
10312 } else
10313 #ifdef TCC_TARGET_COFF
10314 if (*(uint16_t *)(&ehdr) == COFF_C67_MAGIC) {
10315 ret = tcc_load_coff(s1, fd);
10316 } else
10317 #endif
10318 #ifdef TCC_TARGET_PE
10319 if (pe_test_res_file(&ehdr, ret)) {
10320 ret = pe_load_res_file(s1, fd);
10321 } else
10322 #endif
10324 /* as GNU ld, consider it is an ld script if not recognized */
10325 try_load_script:
10326 ret = tcc_load_ldscript(s1);
10327 if (ret < 0) {
10328 error_noabort("unrecognized file type");
10329 goto fail;
10333 the_end:
10334 tcc_close(file);
10335 fail1:
10336 file = saved_file;
10337 return ret;
10338 fail:
10339 ret = -1;
10340 goto the_end;
10343 int tcc_add_file(TCCState *s, const char *filename)
10345 return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR);
10348 int tcc_add_library_path(TCCState *s, const char *pathname)
10350 char *pathname1;
10352 pathname1 = tcc_strdup(pathname);
10353 dynarray_add((void ***)&s->library_paths, &s->nb_library_paths, pathname1);
10354 return 0;
10357 /* find and load a dll. Return non zero if not found */
10358 /* XXX: add '-rpath' option support ? */
10359 static int tcc_add_dll(TCCState *s, const char *filename, int flags)
10361 char buf[1024];
10362 int i;
10364 for(i = 0; i < s->nb_library_paths; i++) {
10365 snprintf(buf, sizeof(buf), "%s/%s",
10366 s->library_paths[i], filename);
10367 if (tcc_add_file_internal(s, buf, flags) == 0)
10368 return 0;
10370 return -1;
10373 /* the library name is the same as the argument of the '-l' option */
10374 int tcc_add_library(TCCState *s, const char *libraryname)
10376 char buf[1024];
10377 int i;
10379 /* first we look for the dynamic library if not static linking */
10380 if (!s->static_link) {
10381 #ifdef TCC_TARGET_PE
10382 snprintf(buf, sizeof(buf), "%s.def", libraryname);
10383 #else
10384 snprintf(buf, sizeof(buf), "lib%s.so", libraryname);
10385 #endif
10386 if (tcc_add_dll(s, buf, 0) == 0)
10387 return 0;
10390 /* then we look for the static library */
10391 for(i = 0; i < s->nb_library_paths; i++) {
10392 snprintf(buf, sizeof(buf), "%s/lib%s.a",
10393 s->library_paths[i], libraryname);
10394 if (tcc_add_file_internal(s, buf, 0) == 0)
10395 return 0;
10397 return -1;
10400 int tcc_add_symbol(TCCState *s, const char *name, unsigned long val)
10402 add_elf_sym(symtab_section, val, 0,
10403 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
10404 SHN_ABS, name);
10405 return 0;
10408 int tcc_set_output_type(TCCState *s, int output_type)
10410 s->output_type = output_type;
10412 if (!s->nostdinc) {
10413 char buf[1024];
10415 /* default include paths */
10416 /* XXX: reverse order needed if -isystem support */
10417 #ifndef TCC_TARGET_PE
10418 tcc_add_sysinclude_path(s, "/usr/local/include");
10419 tcc_add_sysinclude_path(s, "/usr/include");
10420 #endif
10421 snprintf(buf, sizeof(buf), "%s/include", tcc_lib_path);
10422 tcc_add_sysinclude_path(s, buf);
10423 #ifdef TCC_TARGET_PE
10424 snprintf(buf, sizeof(buf), "%s/include/winapi", tcc_lib_path);
10425 tcc_add_sysinclude_path(s, buf);
10426 #endif
10429 /* if bound checking, then add corresponding sections */
10430 #ifdef CONFIG_TCC_BCHECK
10431 if (do_bounds_check) {
10432 /* define symbol */
10433 tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL);
10434 /* create bounds sections */
10435 bounds_section = new_section(s, ".bounds",
10436 SHT_PROGBITS, SHF_ALLOC);
10437 lbounds_section = new_section(s, ".lbounds",
10438 SHT_PROGBITS, SHF_ALLOC);
10440 #endif
10442 if (s->char_is_unsigned) {
10443 tcc_define_symbol(s, "__CHAR_UNSIGNED__", NULL);
10446 /* add debug sections */
10447 if (do_debug) {
10448 /* stab symbols */
10449 stab_section = new_section(s, ".stab", SHT_PROGBITS, 0);
10450 stab_section->sh_entsize = sizeof(Stab_Sym);
10451 stabstr_section = new_section(s, ".stabstr", SHT_STRTAB, 0);
10452 put_elf_str(stabstr_section, "");
10453 stab_section->link = stabstr_section;
10454 /* put first entry */
10455 put_stabs("", 0, 0, 0, 0);
10458 /* add libc crt1/crti objects */
10459 #ifndef TCC_TARGET_PE
10460 if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) &&
10461 !s->nostdlib) {
10462 if (output_type != TCC_OUTPUT_DLL)
10463 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crt1.o");
10464 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crti.o");
10466 #endif
10467 return 0;
10470 #define WD_ALL 0x0001 /* warning is activated when using -Wall */
10471 #define FD_INVERT 0x0002 /* invert value before storing */
10473 typedef struct FlagDef {
10474 uint16_t offset;
10475 uint16_t flags;
10476 const char *name;
10477 } FlagDef;
10479 static const FlagDef warning_defs[] = {
10480 { offsetof(TCCState, warn_unsupported), 0, "unsupported" },
10481 { offsetof(TCCState, warn_write_strings), 0, "write-strings" },
10482 { offsetof(TCCState, warn_error), 0, "error" },
10483 { offsetof(TCCState, warn_implicit_function_declaration), WD_ALL,
10484 "implicit-function-declaration" },
10487 static int set_flag(TCCState *s, const FlagDef *flags, int nb_flags,
10488 const char *name, int value)
10490 int i;
10491 const FlagDef *p;
10492 const char *r;
10494 r = name;
10495 if (r[0] == 'n' && r[1] == 'o' && r[2] == '-') {
10496 r += 3;
10497 value = !value;
10499 for(i = 0, p = flags; i < nb_flags; i++, p++) {
10500 if (!strcmp(r, p->name))
10501 goto found;
10503 return -1;
10504 found:
10505 if (p->flags & FD_INVERT)
10506 value = !value;
10507 *(int *)((uint8_t *)s + p->offset) = value;
10508 return 0;
10512 /* set/reset a warning */
10513 int tcc_set_warning(TCCState *s, const char *warning_name, int value)
10515 int i;
10516 const FlagDef *p;
10518 if (!strcmp(warning_name, "all")) {
10519 for(i = 0, p = warning_defs; i < countof(warning_defs); i++, p++) {
10520 if (p->flags & WD_ALL)
10521 *(int *)((uint8_t *)s + p->offset) = 1;
10523 return 0;
10524 } else {
10525 return set_flag(s, warning_defs, countof(warning_defs),
10526 warning_name, value);
10530 static const FlagDef flag_defs[] = {
10531 { offsetof(TCCState, char_is_unsigned), 0, "unsigned-char" },
10532 { offsetof(TCCState, char_is_unsigned), FD_INVERT, "signed-char" },
10533 { offsetof(TCCState, nocommon), FD_INVERT, "common" },
10534 { offsetof(TCCState, leading_underscore), 0, "leading-underscore" },
10537 /* set/reset a flag */
10538 int tcc_set_flag(TCCState *s, const char *flag_name, int value)
10540 return set_flag(s, flag_defs, countof(flag_defs),
10541 flag_name, value);
10544 #if !defined(LIBTCC)
10546 static int64_t getclock_us(void)
10548 #ifdef _WIN32
10549 struct _timeb tb;
10550 _ftime(&tb);
10551 return (tb.time * 1000LL + tb.millitm) * 1000LL;
10552 #else
10553 struct timeval tv;
10554 gettimeofday(&tv, NULL);
10555 return tv.tv_sec * 1000000LL + tv.tv_usec;
10556 #endif
10559 void help(void)
10561 printf("tcc version " TCC_VERSION " - Tiny C Compiler - Copyright (C) 2001-2006 Fabrice Bellard\n"
10562 "usage: tcc [-v] [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
10563 " [-Wwarn] [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-static]\n"
10564 " [infile1 infile2...] [-run infile args...]\n"
10565 "\n"
10566 "General options:\n"
10567 " -v display current version\n"
10568 " -c compile only - generate an object file\n"
10569 " -o outfile set output filename\n"
10570 " -Bdir set tcc internal library path\n"
10571 " -bench output compilation statistics\n"
10572 " -run run compiled source\n"
10573 " -fflag set or reset (with 'no-' prefix) 'flag' (see man page)\n"
10574 " -Wwarning set or reset (with 'no-' prefix) 'warning' (see man page)\n"
10575 " -w disable all warnings\n"
10576 "Preprocessor options:\n"
10577 " -E preprocess only\n"
10578 " -Idir add include path 'dir'\n"
10579 " -Dsym[=val] define 'sym' with value 'val'\n"
10580 " -Usym undefine 'sym'\n"
10581 "Linker options:\n"
10582 " -Ldir add library path 'dir'\n"
10583 " -llib link with dynamic or static library 'lib'\n"
10584 " -shared generate a shared library\n"
10585 " -static static linking\n"
10586 " -rdynamic export all global symbols to dynamic linker\n"
10587 " -r generate (relocatable) object file\n"
10588 "Debugger options:\n"
10589 " -g generate runtime debug info\n"
10590 #ifdef CONFIG_TCC_BCHECK
10591 " -b compile with built-in memory and bounds checker (implies -g)\n"
10592 #endif
10593 " -bt N show N callers in stack traces\n"
10597 #define TCC_OPTION_HAS_ARG 0x0001
10598 #define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
10600 typedef struct TCCOption {
10601 const char *name;
10602 uint16_t index;
10603 uint16_t flags;
10604 } TCCOption;
10606 enum {
10607 TCC_OPTION_HELP,
10608 TCC_OPTION_I,
10609 TCC_OPTION_D,
10610 TCC_OPTION_U,
10611 TCC_OPTION_L,
10612 TCC_OPTION_B,
10613 TCC_OPTION_l,
10614 TCC_OPTION_bench,
10615 TCC_OPTION_bt,
10616 TCC_OPTION_b,
10617 TCC_OPTION_g,
10618 TCC_OPTION_c,
10619 TCC_OPTION_static,
10620 TCC_OPTION_shared,
10621 TCC_OPTION_o,
10622 TCC_OPTION_r,
10623 TCC_OPTION_Wl,
10624 TCC_OPTION_W,
10625 TCC_OPTION_O,
10626 TCC_OPTION_m,
10627 TCC_OPTION_f,
10628 TCC_OPTION_nostdinc,
10629 TCC_OPTION_nostdlib,
10630 TCC_OPTION_print_search_dirs,
10631 TCC_OPTION_rdynamic,
10632 TCC_OPTION_run,
10633 TCC_OPTION_v,
10634 TCC_OPTION_w,
10635 TCC_OPTION_pipe,
10636 TCC_OPTION_E,
10639 static const TCCOption tcc_options[] = {
10640 { "h", TCC_OPTION_HELP, 0 },
10641 { "?", TCC_OPTION_HELP, 0 },
10642 { "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG },
10643 { "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG },
10644 { "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG },
10645 { "L", TCC_OPTION_L, TCC_OPTION_HAS_ARG },
10646 { "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG },
10647 { "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10648 { "bench", TCC_OPTION_bench, 0 },
10649 { "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG },
10650 #ifdef CONFIG_TCC_BCHECK
10651 { "b", TCC_OPTION_b, 0 },
10652 #endif
10653 { "g", TCC_OPTION_g, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10654 { "c", TCC_OPTION_c, 0 },
10655 { "static", TCC_OPTION_static, 0 },
10656 { "shared", TCC_OPTION_shared, 0 },
10657 { "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG },
10658 { "run", TCC_OPTION_run, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10659 { "rdynamic", TCC_OPTION_rdynamic, 0 },
10660 { "r", TCC_OPTION_r, 0 },
10661 { "Wl,", TCC_OPTION_Wl, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10662 { "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10663 { "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10664 { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG },
10665 { "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10666 { "nostdinc", TCC_OPTION_nostdinc, 0 },
10667 { "nostdlib", TCC_OPTION_nostdlib, 0 },
10668 { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 },
10669 { "v", TCC_OPTION_v, 0 },
10670 { "w", TCC_OPTION_w, 0 },
10671 { "pipe", TCC_OPTION_pipe, 0},
10672 { "E", TCC_OPTION_E, 0},
10673 { NULL },
10676 /* convert 'str' into an array of space separated strings */
10677 static int expand_args(char ***pargv, const char *str)
10679 const char *s1;
10680 char **argv, *arg;
10681 int argc, len;
10683 argc = 0;
10684 argv = NULL;
10685 for(;;) {
10686 while (is_space(*str))
10687 str++;
10688 if (*str == '\0')
10689 break;
10690 s1 = str;
10691 while (*str != '\0' && !is_space(*str))
10692 str++;
10693 len = str - s1;
10694 arg = tcc_malloc(len + 1);
10695 memcpy(arg, s1, len);
10696 arg[len] = '\0';
10697 dynarray_add((void ***)&argv, &argc, arg);
10699 *pargv = argv;
10700 return argc;
10703 static char **files;
10704 static int nb_files, nb_libraries;
10705 static int multiple_files;
10706 static int print_search_dirs;
10707 static int output_type;
10708 static int reloc_output;
10709 static const char *outfile;
10711 int parse_args(TCCState *s, int argc, char **argv)
10713 int optind;
10714 const TCCOption *popt;
10715 const char *optarg, *p1, *r1;
10716 char *r;
10718 optind = 0;
10719 while (1) {
10720 if (optind >= argc) {
10721 if (nb_files == 0 && !print_search_dirs)
10722 goto show_help;
10723 else
10724 break;
10726 r = argv[optind++];
10727 if (r[0] != '-') {
10728 /* add a new file */
10729 dynarray_add((void ***)&files, &nb_files, r);
10730 if (!multiple_files) {
10731 optind--;
10732 /* argv[0] will be this file */
10733 break;
10735 } else {
10736 /* find option in table (match only the first chars */
10737 popt = tcc_options;
10738 for(;;) {
10739 p1 = popt->name;
10740 if (p1 == NULL)
10741 error("invalid option -- '%s'", r);
10742 r1 = r + 1;
10743 for(;;) {
10744 if (*p1 == '\0')
10745 goto option_found;
10746 if (*r1 != *p1)
10747 break;
10748 p1++;
10749 r1++;
10751 popt++;
10753 option_found:
10754 if (popt->flags & TCC_OPTION_HAS_ARG) {
10755 if (*r1 != '\0' || (popt->flags & TCC_OPTION_NOSEP)) {
10756 optarg = r1;
10757 } else {
10758 if (optind >= argc)
10759 error("argument to '%s' is missing", r);
10760 optarg = argv[optind++];
10762 } else {
10763 if (*r1 != '\0')
10764 goto show_help;
10765 optarg = NULL;
10768 switch(popt->index) {
10769 case TCC_OPTION_HELP:
10770 show_help:
10771 help();
10772 exit(1);
10773 case TCC_OPTION_I:
10774 if (tcc_add_include_path(s, optarg) < 0)
10775 error("too many include paths");
10776 break;
10777 case TCC_OPTION_D:
10779 char *sym, *value;
10780 sym = (char *)optarg;
10781 value = strchr(sym, '=');
10782 if (value) {
10783 *value = '\0';
10784 value++;
10786 tcc_define_symbol(s, sym, value);
10788 break;
10789 case TCC_OPTION_U:
10790 tcc_undefine_symbol(s, optarg);
10791 break;
10792 case TCC_OPTION_L:
10793 tcc_add_library_path(s, optarg);
10794 break;
10795 case TCC_OPTION_B:
10796 /* set tcc utilities path (mainly for tcc development) */
10797 tcc_lib_path = optarg;
10798 break;
10799 case TCC_OPTION_l:
10800 dynarray_add((void ***)&files, &nb_files, r);
10801 nb_libraries++;
10802 break;
10803 case TCC_OPTION_bench:
10804 do_bench = 1;
10805 break;
10806 case TCC_OPTION_bt:
10807 num_callers = atoi(optarg);
10808 break;
10809 #ifdef CONFIG_TCC_BCHECK
10810 case TCC_OPTION_b:
10811 do_bounds_check = 1;
10812 do_debug = 1;
10813 break;
10814 #endif
10815 case TCC_OPTION_g:
10816 do_debug = 1;
10817 break;
10818 case TCC_OPTION_c:
10819 multiple_files = 1;
10820 output_type = TCC_OUTPUT_OBJ;
10821 break;
10822 case TCC_OPTION_static:
10823 s->static_link = 1;
10824 break;
10825 case TCC_OPTION_shared:
10826 output_type = TCC_OUTPUT_DLL;
10827 break;
10828 case TCC_OPTION_o:
10829 multiple_files = 1;
10830 outfile = optarg;
10831 break;
10832 case TCC_OPTION_r:
10833 /* generate a .o merging several output files */
10834 reloc_output = 1;
10835 output_type = TCC_OUTPUT_OBJ;
10836 break;
10837 case TCC_OPTION_nostdinc:
10838 s->nostdinc = 1;
10839 break;
10840 case TCC_OPTION_nostdlib:
10841 s->nostdlib = 1;
10842 break;
10843 case TCC_OPTION_print_search_dirs:
10844 print_search_dirs = 1;
10845 break;
10846 case TCC_OPTION_run:
10848 int argc1;
10849 char **argv1;
10850 argc1 = expand_args(&argv1, optarg);
10851 if (argc1 > 0) {
10852 parse_args(s, argc1, argv1);
10854 multiple_files = 0;
10855 output_type = TCC_OUTPUT_MEMORY;
10857 break;
10858 case TCC_OPTION_v:
10859 printf("tcc version %s\n", TCC_VERSION);
10860 exit(0);
10861 case TCC_OPTION_f:
10862 if (tcc_set_flag(s, optarg, 1) < 0 && s->warn_unsupported)
10863 goto unsupported_option;
10864 break;
10865 case TCC_OPTION_W:
10866 if (tcc_set_warning(s, optarg, 1) < 0 &&
10867 s->warn_unsupported)
10868 goto unsupported_option;
10869 break;
10870 case TCC_OPTION_w:
10871 s->warn_none = 1;
10872 break;
10873 case TCC_OPTION_rdynamic:
10874 s->rdynamic = 1;
10875 break;
10876 case TCC_OPTION_Wl:
10878 const char *p;
10879 if (strstart(optarg, "-Ttext,", &p)) {
10880 s->text_addr = strtoul(p, NULL, 16);
10881 s->has_text_addr = 1;
10882 } else if (strstart(optarg, "--oformat,", &p)) {
10883 if (strstart(p, "elf32-", NULL)) {
10884 s->output_format = TCC_OUTPUT_FORMAT_ELF;
10885 } else if (!strcmp(p, "binary")) {
10886 s->output_format = TCC_OUTPUT_FORMAT_BINARY;
10887 } else
10888 #ifdef TCC_TARGET_COFF
10889 if (!strcmp(p, "coff")) {
10890 s->output_format = TCC_OUTPUT_FORMAT_COFF;
10891 } else
10892 #endif
10894 error("target %s not found", p);
10896 } else {
10897 error("unsupported linker option '%s'", optarg);
10900 break;
10901 case TCC_OPTION_E:
10902 output_type = TCC_OUTPUT_PREPROCESS;
10903 break;
10904 default:
10905 if (s->warn_unsupported) {
10906 unsupported_option:
10907 warning("unsupported option '%s'", r);
10909 break;
10913 return optind;
10916 int main(int argc, char **argv)
10918 int i;
10919 TCCState *s;
10920 int nb_objfiles, ret, optind;
10921 char objfilename[1024];
10922 int64_t start_time = 0;
10924 #ifdef _WIN32
10925 tcc_lib_path = w32_tcc_lib_path();
10926 #endif
10928 s = tcc_new();
10929 output_type = TCC_OUTPUT_EXE;
10930 outfile = NULL;
10931 multiple_files = 1;
10932 files = NULL;
10933 nb_files = 0;
10934 nb_libraries = 0;
10935 reloc_output = 0;
10936 print_search_dirs = 0;
10937 ret = 0;
10939 optind = parse_args(s, argc - 1, argv + 1) + 1;
10941 if (print_search_dirs) {
10942 /* enough for Linux kernel */
10943 printf("install: %s/\n", tcc_lib_path);
10944 return 0;
10947 nb_objfiles = nb_files - nb_libraries;
10949 /* if outfile provided without other options, we output an
10950 executable */
10951 if (outfile && output_type == TCC_OUTPUT_MEMORY)
10952 output_type = TCC_OUTPUT_EXE;
10954 /* check -c consistency : only single file handled. XXX: checks file type */
10955 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
10956 /* accepts only a single input file */
10957 if (nb_objfiles != 1)
10958 error("cannot specify multiple files with -c");
10959 if (nb_libraries != 0)
10960 error("cannot specify libraries with -c");
10964 if (output_type == TCC_OUTPUT_PREPROCESS) {
10965 if (!outfile) {
10966 s->outfile = stdout;
10967 } else {
10968 s->outfile = fopen(outfile, "w");
10969 if (!s->outfile)
10970 error("could not open '%s", outfile);
10972 } else if (output_type != TCC_OUTPUT_MEMORY) {
10973 if (!outfile) {
10974 /* compute default outfile name */
10975 char *ext;
10976 pstrcpy(objfilename, sizeof(objfilename), tcc_basename(files[0]));
10977 ext = tcc_fileextension(objfilename);
10978 #ifdef TCC_TARGET_PE
10979 if (output_type == TCC_OUTPUT_DLL)
10980 strcpy(ext, ".dll");
10981 else
10982 if (output_type == TCC_OUTPUT_EXE)
10983 strcpy(ext, ".exe");
10984 else
10985 #endif
10986 if (output_type == TCC_OUTPUT_OBJ && !reloc_output && *ext)
10987 strcpy(ext, ".o");
10988 else
10989 pstrcpy(objfilename, sizeof(objfilename), "a.out");
10990 outfile = objfilename;
10994 if (do_bench) {
10995 start_time = getclock_us();
10998 tcc_set_output_type(s, output_type);
11000 /* compile or add each files or library */
11001 for(i = 0; i < nb_files && ret == 0; i++) {
11002 const char *filename;
11004 filename = files[i];
11005 if (output_type == TCC_OUTPUT_PREPROCESS) {
11006 if (tcc_add_file_internal(s, filename,
11007 AFF_PRINT_ERROR | AFF_PREPROCESS) < 0)
11008 ret = 1;
11009 } else if (filename[0] == '-') {
11010 if (tcc_add_library(s, filename + 2) < 0)
11011 error("cannot find %s", filename);
11012 } else {
11013 if (tcc_add_file(s, filename) < 0)
11014 ret = 1;
11018 /* free all files */
11019 tcc_free(files);
11021 if (ret)
11022 goto the_end;
11024 if (do_bench) {
11025 double total_time;
11026 total_time = (double)(getclock_us() - start_time) / 1000000.0;
11027 if (total_time < 0.001)
11028 total_time = 0.001;
11029 if (total_bytes < 1)
11030 total_bytes = 1;
11031 printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
11032 tok_ident - TOK_IDENT, total_lines, total_bytes,
11033 total_time, (int)(total_lines / total_time),
11034 total_bytes / total_time / 1000000.0);
11037 if (s->output_type == TCC_OUTPUT_PREPROCESS) {
11038 if (outfile)
11039 fclose(s->outfile);
11040 } else if (s->output_type == TCC_OUTPUT_MEMORY) {
11041 ret = tcc_run(s, argc - optind, argv + optind);
11042 } else
11043 #ifdef TCC_TARGET_PE
11044 if (s->output_type != TCC_OUTPUT_OBJ) {
11045 ret = pe_output_file(s, outfile);
11046 } else
11047 #endif
11049 ret = tcc_output_file(s, outfile) ? 1 : 0;
11051 the_end:
11052 /* XXX: cannot do it with bound checking because of the malloc hooks */
11053 if (!do_bounds_check)
11054 tcc_delete(s);
11056 #ifdef MEM_DEBUG
11057 if (do_bench) {
11058 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size, mem_max_size);
11060 #endif
11061 return ret;
11064 #endif