Switch to newer tccpe.c (includes support for resources)
[tinycc.git] / tcc.c
bloba8a3f36179500f83b754b73f0cdcef72bcd50c4c
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;
2311 uint8_t *p;
2313 p = file->buf_ptr;
2314 start_of_line = 1;
2315 a = 0;
2316 for(;;) {
2317 redo_no_start:
2318 c = *p;
2319 switch(c) {
2320 case ' ':
2321 case '\t':
2322 case '\f':
2323 case '\v':
2324 case '\r':
2325 p++;
2326 goto redo_no_start;
2327 case '\n':
2328 start_of_line = 1;
2329 file->line_num++;
2330 p++;
2331 goto redo_no_start;
2332 case '\\':
2333 file->buf_ptr = p;
2334 c = handle_eob();
2335 if (c == CH_EOF) {
2336 expect("#endif");
2337 } else if (c == '\\') {
2338 ch = file->buf_ptr[0];
2339 handle_stray_noerror();
2341 p = file->buf_ptr;
2342 goto redo_no_start;
2343 /* skip strings */
2344 case '\"':
2345 case '\'':
2346 p = parse_pp_string(p, c, NULL);
2347 break;
2348 /* skip comments */
2349 case '/':
2350 file->buf_ptr = p;
2351 ch = *p;
2352 minp();
2353 p = file->buf_ptr;
2354 if (ch == '*') {
2355 p = parse_comment(p);
2356 } else if (ch == '/') {
2357 p = parse_line_comment(p);
2359 break;
2361 case '#':
2362 p++;
2363 if (start_of_line) {
2364 file->buf_ptr = p;
2365 next_nomacro();
2366 p = file->buf_ptr;
2367 if (a == 0 &&
2368 (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
2369 goto the_end;
2370 if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
2371 a++;
2372 else if (tok == TOK_ENDIF)
2373 a--;
2375 break;
2376 default:
2377 p++;
2378 break;
2380 start_of_line = 0;
2382 the_end: ;
2383 file->buf_ptr = p;
2386 /* ParseState handling */
2388 /* XXX: currently, no include file info is stored. Thus, we cannot display
2389 accurate messages if the function or data definition spans multiple
2390 files */
2392 /* save current parse state in 's' */
2393 void save_parse_state(ParseState *s)
2395 s->line_num = file->line_num;
2396 s->macro_ptr = macro_ptr;
2397 s->tok = tok;
2398 s->tokc = tokc;
2401 /* restore parse state from 's' */
2402 void restore_parse_state(ParseState *s)
2404 file->line_num = s->line_num;
2405 macro_ptr = s->macro_ptr;
2406 tok = s->tok;
2407 tokc = s->tokc;
2410 /* return the number of additional 'ints' necessary to store the
2411 token */
2412 static inline int tok_ext_size(int t)
2414 switch(t) {
2415 /* 4 bytes */
2416 case TOK_CINT:
2417 case TOK_CUINT:
2418 case TOK_CCHAR:
2419 case TOK_LCHAR:
2420 case TOK_CFLOAT:
2421 case TOK_LINENUM:
2422 return 1;
2423 case TOK_STR:
2424 case TOK_LSTR:
2425 case TOK_PPNUM:
2426 error("unsupported token");
2427 return 1;
2428 case TOK_CDOUBLE:
2429 case TOK_CLLONG:
2430 case TOK_CULLONG:
2431 return 2;
2432 case TOK_CLDOUBLE:
2433 return LDOUBLE_SIZE / 4;
2434 default:
2435 return 0;
2439 /* token string handling */
2441 static inline void tok_str_new(TokenString *s)
2443 s->str = NULL;
2444 s->len = 0;
2445 s->allocated_len = 0;
2446 s->last_line_num = -1;
2449 static void tok_str_free(int *str)
2451 tcc_free(str);
2454 static int *tok_str_realloc(TokenString *s)
2456 int *str, len;
2458 if (s->allocated_len == 0) {
2459 len = 8;
2460 } else {
2461 len = s->allocated_len * 2;
2463 str = tcc_realloc(s->str, len * sizeof(int));
2464 if (!str)
2465 error("memory full");
2466 s->allocated_len = len;
2467 s->str = str;
2468 return str;
2471 static void tok_str_add(TokenString *s, int t)
2473 int len, *str;
2475 len = s->len;
2476 str = s->str;
2477 if (len >= s->allocated_len)
2478 str = tok_str_realloc(s);
2479 str[len++] = t;
2480 s->len = len;
2483 static void tok_str_add2(TokenString *s, int t, CValue *cv)
2485 int len, *str;
2487 len = s->len;
2488 str = s->str;
2490 /* allocate space for worst case */
2491 if (len + TOK_MAX_SIZE > s->allocated_len)
2492 str = tok_str_realloc(s);
2493 str[len++] = t;
2494 switch(t) {
2495 case TOK_CINT:
2496 case TOK_CUINT:
2497 case TOK_CCHAR:
2498 case TOK_LCHAR:
2499 case TOK_CFLOAT:
2500 case TOK_LINENUM:
2501 str[len++] = cv->tab[0];
2502 break;
2503 case TOK_PPNUM:
2504 case TOK_STR:
2505 case TOK_LSTR:
2507 int nb_words;
2508 CString *cstr;
2510 nb_words = (sizeof(CString) + cv->cstr->size + 3) >> 2;
2511 while ((len + nb_words) > s->allocated_len)
2512 str = tok_str_realloc(s);
2513 cstr = (CString *)(str + len);
2514 cstr->data = NULL;
2515 cstr->size = cv->cstr->size;
2516 cstr->data_allocated = NULL;
2517 cstr->size_allocated = cstr->size;
2518 memcpy((char *)cstr + sizeof(CString),
2519 cv->cstr->data, cstr->size);
2520 len += nb_words;
2522 break;
2523 case TOK_CDOUBLE:
2524 case TOK_CLLONG:
2525 case TOK_CULLONG:
2526 #if LDOUBLE_SIZE == 8
2527 case TOK_CLDOUBLE:
2528 #endif
2529 str[len++] = cv->tab[0];
2530 str[len++] = cv->tab[1];
2531 break;
2532 #if LDOUBLE_SIZE == 12
2533 case TOK_CLDOUBLE:
2534 str[len++] = cv->tab[0];
2535 str[len++] = cv->tab[1];
2536 str[len++] = cv->tab[2];
2537 #elif LDOUBLE_SIZE != 8
2538 #error add long double size support
2539 #endif
2540 break;
2541 default:
2542 break;
2544 s->len = len;
2547 /* add the current parse token in token string 's' */
2548 static void tok_str_add_tok(TokenString *s)
2550 CValue cval;
2552 /* save line number info */
2553 if (file->line_num != s->last_line_num) {
2554 s->last_line_num = file->line_num;
2555 cval.i = s->last_line_num;
2556 tok_str_add2(s, TOK_LINENUM, &cval);
2558 tok_str_add2(s, tok, &tokc);
2561 #if LDOUBLE_SIZE == 12
2562 #define LDOUBLE_GET(p, cv) \
2563 cv.tab[0] = p[0]; \
2564 cv.tab[1] = p[1]; \
2565 cv.tab[2] = p[2];
2566 #elif LDOUBLE_SIZE == 8
2567 #define LDOUBLE_GET(p, cv) \
2568 cv.tab[0] = p[0]; \
2569 cv.tab[1] = p[1];
2570 #else
2571 #error add long double size support
2572 #endif
2575 /* get a token from an integer array and increment pointer
2576 accordingly. we code it as a macro to avoid pointer aliasing. */
2577 #define TOK_GET(t, p, cv) \
2579 t = *p++; \
2580 switch(t) { \
2581 case TOK_CINT: \
2582 case TOK_CUINT: \
2583 case TOK_CCHAR: \
2584 case TOK_LCHAR: \
2585 case TOK_CFLOAT: \
2586 case TOK_LINENUM: \
2587 cv.tab[0] = *p++; \
2588 break; \
2589 case TOK_STR: \
2590 case TOK_LSTR: \
2591 case TOK_PPNUM: \
2592 cv.cstr = (CString *)p; \
2593 cv.cstr->data = (char *)p + sizeof(CString);\
2594 p += (sizeof(CString) + cv.cstr->size + 3) >> 2;\
2595 break; \
2596 case TOK_CDOUBLE: \
2597 case TOK_CLLONG: \
2598 case TOK_CULLONG: \
2599 cv.tab[0] = p[0]; \
2600 cv.tab[1] = p[1]; \
2601 p += 2; \
2602 break; \
2603 case TOK_CLDOUBLE: \
2604 LDOUBLE_GET(p, cv); \
2605 p += LDOUBLE_SIZE / 4; \
2606 break; \
2607 default: \
2608 break; \
2612 /* defines handling */
2613 static inline void define_push(int v, int macro_type, int *str, Sym *first_arg)
2615 Sym *s;
2617 s = sym_push2(&define_stack, v, macro_type, (int)str);
2618 s->next = first_arg;
2619 table_ident[v - TOK_IDENT]->sym_define = s;
2622 /* undefined a define symbol. Its name is just set to zero */
2623 static void define_undef(Sym *s)
2625 int v;
2626 v = s->v;
2627 if (v >= TOK_IDENT && v < tok_ident)
2628 table_ident[v - TOK_IDENT]->sym_define = NULL;
2629 s->v = 0;
2632 static inline Sym *define_find(int v)
2634 v -= TOK_IDENT;
2635 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2636 return NULL;
2637 return table_ident[v]->sym_define;
2640 /* free define stack until top reaches 'b' */
2641 static void free_defines(Sym *b)
2643 Sym *top, *top1;
2644 int v;
2646 top = define_stack;
2647 while (top != b) {
2648 top1 = top->prev;
2649 /* do not free args or predefined defines */
2650 if (top->c)
2651 tok_str_free((int *)top->c);
2652 v = top->v;
2653 if (v >= TOK_IDENT && v < tok_ident)
2654 table_ident[v - TOK_IDENT]->sym_define = NULL;
2655 sym_free(top);
2656 top = top1;
2658 define_stack = b;
2661 /* label lookup */
2662 static Sym *label_find(int v)
2664 v -= TOK_IDENT;
2665 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2666 return NULL;
2667 return table_ident[v]->sym_label;
2670 static Sym *label_push(Sym **ptop, int v, int flags)
2672 Sym *s, **ps;
2673 s = sym_push2(ptop, v, 0, 0);
2674 s->r = flags;
2675 ps = &table_ident[v - TOK_IDENT]->sym_label;
2676 if (ptop == &global_label_stack) {
2677 /* modify the top most local identifier, so that
2678 sym_identifier will point to 's' when popped */
2679 while (*ps != NULL)
2680 ps = &(*ps)->prev_tok;
2682 s->prev_tok = *ps;
2683 *ps = s;
2684 return s;
2687 /* pop labels until element last is reached. Look if any labels are
2688 undefined. Define symbols if '&&label' was used. */
2689 static void label_pop(Sym **ptop, Sym *slast)
2691 Sym *s, *s1;
2692 for(s = *ptop; s != slast; s = s1) {
2693 s1 = s->prev;
2694 if (s->r == LABEL_DECLARED) {
2695 warning("label '%s' declared but not used", get_tok_str(s->v, NULL));
2696 } else if (s->r == LABEL_FORWARD) {
2697 error("label '%s' used but not defined",
2698 get_tok_str(s->v, NULL));
2699 } else {
2700 if (s->c) {
2701 /* define corresponding symbol. A size of
2702 1 is put. */
2703 put_extern_sym(s, cur_text_section, (long)s->next, 1);
2706 /* remove label */
2707 table_ident[s->v - TOK_IDENT]->sym_label = s->prev_tok;
2708 sym_free(s);
2710 *ptop = slast;
2713 /* eval an expression for #if/#elif */
2714 static int expr_preprocess(void)
2716 int c, t;
2717 TokenString str;
2719 tok_str_new(&str);
2720 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2721 next(); /* do macro subst */
2722 if (tok == TOK_DEFINED) {
2723 next_nomacro();
2724 t = tok;
2725 if (t == '(')
2726 next_nomacro();
2727 c = define_find(tok) != 0;
2728 if (t == '(')
2729 next_nomacro();
2730 tok = TOK_CINT;
2731 tokc.i = c;
2732 } else if (tok >= TOK_IDENT) {
2733 /* if undefined macro */
2734 tok = TOK_CINT;
2735 tokc.i = 0;
2737 tok_str_add_tok(&str);
2739 tok_str_add(&str, -1); /* simulate end of file */
2740 tok_str_add(&str, 0);
2741 /* now evaluate C constant expression */
2742 macro_ptr = str.str;
2743 next();
2744 c = expr_const();
2745 macro_ptr = NULL;
2746 tok_str_free(str.str);
2747 return c != 0;
2750 #if defined(PARSE_DEBUG) || defined(PP_DEBUG)
2751 static void tok_print(int *str)
2753 int t;
2754 CValue cval;
2756 while (1) {
2757 TOK_GET(t, str, cval);
2758 if (!t)
2759 break;
2760 printf(" %s", get_tok_str(t, &cval));
2762 printf("\n");
2764 #endif
2766 /* parse after #define */
2767 static void parse_define(void)
2769 Sym *s, *first, **ps;
2770 int v, t, varg, is_vaargs, c;
2771 TokenString str;
2773 v = tok;
2774 if (v < TOK_IDENT)
2775 error("invalid macro name '%s'", get_tok_str(tok, &tokc));
2776 /* XXX: should check if same macro (ANSI) */
2777 first = NULL;
2778 t = MACRO_OBJ;
2779 /* '(' must be just after macro definition for MACRO_FUNC */
2780 c = file->buf_ptr[0];
2781 if (c == '\\')
2782 c = handle_stray1(file->buf_ptr);
2783 if (c == '(') {
2784 next_nomacro();
2785 next_nomacro();
2786 ps = &first;
2787 while (tok != ')') {
2788 varg = tok;
2789 next_nomacro();
2790 is_vaargs = 0;
2791 if (varg == TOK_DOTS) {
2792 varg = TOK___VA_ARGS__;
2793 is_vaargs = 1;
2794 } else if (tok == TOK_DOTS && gnu_ext) {
2795 is_vaargs = 1;
2796 next_nomacro();
2798 if (varg < TOK_IDENT)
2799 error("badly punctuated parameter list");
2800 s = sym_push2(&define_stack, varg | SYM_FIELD, is_vaargs, 0);
2801 *ps = s;
2802 ps = &s->next;
2803 if (tok != ',')
2804 break;
2805 next_nomacro();
2807 t = MACRO_FUNC;
2809 tok_str_new(&str);
2810 next_nomacro();
2811 /* EOF testing necessary for '-D' handling */
2812 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2813 tok_str_add2(&str, tok, &tokc);
2814 next_nomacro();
2816 tok_str_add(&str, 0);
2817 #ifdef PP_DEBUG
2818 printf("define %s %d: ", get_tok_str(v, NULL), t);
2819 tok_print(str.str);
2820 #endif
2821 define_push(v, t, str.str, first);
2824 static inline int hash_cached_include(int type, const char *filename)
2826 const unsigned char *s;
2827 unsigned int h;
2829 h = TOK_HASH_INIT;
2830 h = TOK_HASH_FUNC(h, type);
2831 s = filename;
2832 while (*s) {
2833 h = TOK_HASH_FUNC(h, *s);
2834 s++;
2836 h &= (CACHED_INCLUDES_HASH_SIZE - 1);
2837 return h;
2840 /* XXX: use a token or a hash table to accelerate matching ? */
2841 static CachedInclude *search_cached_include(TCCState *s1,
2842 int type, const char *filename)
2844 CachedInclude *e;
2845 int i, h;
2846 h = hash_cached_include(type, filename);
2847 i = s1->cached_includes_hash[h];
2848 for(;;) {
2849 if (i == 0)
2850 break;
2851 e = s1->cached_includes[i - 1];
2852 if (e->type == type && !strcmp(e->filename, filename))
2853 return e;
2854 i = e->hash_next;
2856 return NULL;
2859 static inline void add_cached_include(TCCState *s1, int type,
2860 const char *filename, int ifndef_macro)
2862 CachedInclude *e;
2863 int h;
2865 if (search_cached_include(s1, type, filename))
2866 return;
2867 #ifdef INC_DEBUG
2868 printf("adding cached '%s' %s\n", filename, get_tok_str(ifndef_macro, NULL));
2869 #endif
2870 e = tcc_malloc(sizeof(CachedInclude) + strlen(filename));
2871 if (!e)
2872 return;
2873 e->type = type;
2874 strcpy(e->filename, filename);
2875 e->ifndef_macro = ifndef_macro;
2876 dynarray_add((void ***)&s1->cached_includes, &s1->nb_cached_includes, e);
2877 /* add in hash table */
2878 h = hash_cached_include(type, filename);
2879 e->hash_next = s1->cached_includes_hash[h];
2880 s1->cached_includes_hash[h] = s1->nb_cached_includes;
2883 static void pragma_parse(TCCState *s1)
2885 int val;
2887 next();
2888 if (tok == TOK_pack) {
2890 This may be:
2891 #pragma pack(1) // set
2892 #pragma pack() // reset to default
2893 #pragma pack(push,1) // push & set
2894 #pragma pack(pop) // restore previous
2896 next();
2897 skip('(');
2898 if (tok == TOK_ASM_pop) {
2899 next();
2900 if (s1->pack_stack_ptr <= s1->pack_stack) {
2901 stk_error:
2902 error("out of pack stack");
2904 s1->pack_stack_ptr--;
2905 } else {
2906 val = 0;
2907 if (tok != ')') {
2908 if (tok == TOK_ASM_push) {
2909 next();
2910 if (s1->pack_stack_ptr >= s1->pack_stack + PACK_STACK_SIZE - 1)
2911 goto stk_error;
2912 s1->pack_stack_ptr++;
2913 skip(',');
2915 if (tok != TOK_CINT) {
2916 pack_error:
2917 error("invalid pack pragma");
2919 val = tokc.i;
2920 if (val < 1 || val > 16 || (val & (val - 1)) != 0)
2921 goto pack_error;
2922 next();
2924 *s1->pack_stack_ptr = val;
2925 skip(')');
2930 /* is_bof is true if first non space token at beginning of file */
2931 static void preprocess(int is_bof)
2933 TCCState *s1 = tcc_state;
2934 int size, i, c, n, saved_parse_flags;
2935 char buf[1024], *q;
2936 char buf1[1024];
2937 BufferedFile *f;
2938 Sym *s;
2939 CachedInclude *e;
2941 saved_parse_flags = parse_flags;
2942 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM |
2943 PARSE_FLAG_LINEFEED;
2944 next_nomacro();
2945 redo:
2946 switch(tok) {
2947 case TOK_DEFINE:
2948 next_nomacro();
2949 parse_define();
2950 break;
2951 case TOK_UNDEF:
2952 next_nomacro();
2953 s = define_find(tok);
2954 /* undefine symbol by putting an invalid name */
2955 if (s)
2956 define_undef(s);
2957 break;
2958 case TOK_INCLUDE:
2959 case TOK_INCLUDE_NEXT:
2960 ch = file->buf_ptr[0];
2961 /* XXX: incorrect if comments : use next_nomacro with a special mode */
2962 skip_spaces();
2963 if (ch == '<') {
2964 c = '>';
2965 goto read_name;
2966 } else if (ch == '\"') {
2967 c = ch;
2968 read_name:
2969 inp();
2970 q = buf;
2971 while (ch != c && ch != '\n' && ch != CH_EOF) {
2972 if ((q - buf) < sizeof(buf) - 1)
2973 *q++ = ch;
2974 if (ch == '\\') {
2975 if (handle_stray_noerror() == 0)
2976 --q;
2977 } else
2978 inp();
2980 *q = '\0';
2981 minp();
2982 #if 0
2983 /* eat all spaces and comments after include */
2984 /* XXX: slightly incorrect */
2985 while (ch1 != '\n' && ch1 != CH_EOF)
2986 inp();
2987 #endif
2988 } else {
2989 /* computed #include : either we have only strings or
2990 we have anything enclosed in '<>' */
2991 next();
2992 buf[0] = '\0';
2993 if (tok == TOK_STR) {
2994 while (tok != TOK_LINEFEED) {
2995 if (tok != TOK_STR) {
2996 include_syntax:
2997 error("'#include' expects \"FILENAME\" or <FILENAME>");
2999 pstrcat(buf, sizeof(buf), (char *)tokc.cstr->data);
3000 next();
3002 c = '\"';
3003 } else {
3004 int len;
3005 while (tok != TOK_LINEFEED) {
3006 pstrcat(buf, sizeof(buf), get_tok_str(tok, &tokc));
3007 next();
3009 len = strlen(buf);
3010 /* check syntax and remove '<>' */
3011 if (len < 2 || buf[0] != '<' || buf[len - 1] != '>')
3012 goto include_syntax;
3013 memmove(buf, buf + 1, len - 2);
3014 buf[len - 2] = '\0';
3015 c = '>';
3019 e = search_cached_include(s1, c, buf);
3020 if (e && define_find(e->ifndef_macro)) {
3021 /* no need to parse the include because the 'ifndef macro'
3022 is defined */
3023 #ifdef INC_DEBUG
3024 printf("%s: skipping %s\n", file->filename, buf);
3025 #endif
3026 } else {
3027 if (c == '\"') {
3028 /* first search in current dir if "header.h" */
3029 size = tcc_basename(file->filename) - file->filename;
3030 if (size > sizeof(buf1) - 1)
3031 size = sizeof(buf1) - 1;
3032 memcpy(buf1, file->filename, size);
3033 buf1[size] = '\0';
3034 pstrcat(buf1, sizeof(buf1), buf);
3035 f = tcc_open(s1, buf1);
3036 if (f) {
3037 if (tok == TOK_INCLUDE_NEXT)
3038 tok = TOK_INCLUDE;
3039 else
3040 goto found;
3043 if (s1->include_stack_ptr >= s1->include_stack + INCLUDE_STACK_SIZE)
3044 error("#include recursion too deep");
3045 /* now search in all the include paths */
3046 n = s1->nb_include_paths + s1->nb_sysinclude_paths;
3047 for(i = 0; i < n; i++) {
3048 const char *path;
3049 if (i < s1->nb_include_paths)
3050 path = s1->include_paths[i];
3051 else
3052 path = s1->sysinclude_paths[i - s1->nb_include_paths];
3053 pstrcpy(buf1, sizeof(buf1), path);
3054 pstrcat(buf1, sizeof(buf1), "/");
3055 pstrcat(buf1, sizeof(buf1), buf);
3056 f = tcc_open(s1, buf1);
3057 if (f) {
3058 if (tok == TOK_INCLUDE_NEXT)
3059 tok = TOK_INCLUDE;
3060 else
3061 goto found;
3064 error("include file '%s' not found", buf);
3065 f = NULL;
3066 found:
3067 #ifdef INC_DEBUG
3068 printf("%s: including %s\n", file->filename, buf1);
3069 #endif
3070 f->inc_type = c;
3071 pstrcpy(f->inc_filename, sizeof(f->inc_filename), buf);
3072 /* push current file in stack */
3073 /* XXX: fix current line init */
3074 *s1->include_stack_ptr++ = file;
3075 file = f;
3076 /* add include file debug info */
3077 if (do_debug) {
3078 put_stabs(file->filename, N_BINCL, 0, 0, 0);
3080 tok_flags |= TOK_FLAG_BOF | TOK_FLAG_BOL;
3081 ch = file->buf_ptr[0];
3082 goto the_end;
3084 break;
3085 case TOK_IFNDEF:
3086 c = 1;
3087 goto do_ifdef;
3088 case TOK_IF:
3089 c = expr_preprocess();
3090 goto do_if;
3091 case TOK_IFDEF:
3092 c = 0;
3093 do_ifdef:
3094 next_nomacro();
3095 if (tok < TOK_IDENT)
3096 error("invalid argument for '#if%sdef'", c ? "n" : "");
3097 if (is_bof) {
3098 if (c) {
3099 #ifdef INC_DEBUG
3100 printf("#ifndef %s\n", get_tok_str(tok, NULL));
3101 #endif
3102 file->ifndef_macro = tok;
3105 c = (define_find(tok) != 0) ^ c;
3106 do_if:
3107 if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE)
3108 error("memory full");
3109 *s1->ifdef_stack_ptr++ = c;
3110 goto test_skip;
3111 case TOK_ELSE:
3112 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
3113 error("#else without matching #if");
3114 if (s1->ifdef_stack_ptr[-1] & 2)
3115 error("#else after #else");
3116 c = (s1->ifdef_stack_ptr[-1] ^= 3);
3117 goto test_skip;
3118 case TOK_ELIF:
3119 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
3120 error("#elif without matching #if");
3121 c = s1->ifdef_stack_ptr[-1];
3122 if (c > 1)
3123 error("#elif after #else");
3124 /* last #if/#elif expression was true: we skip */
3125 if (c == 1)
3126 goto skip;
3127 c = expr_preprocess();
3128 s1->ifdef_stack_ptr[-1] = c;
3129 test_skip:
3130 if (!(c & 1)) {
3131 skip:
3132 preprocess_skip();
3133 is_bof = 0;
3134 goto redo;
3136 break;
3137 case TOK_ENDIF:
3138 if (s1->ifdef_stack_ptr <= file->ifdef_stack_ptr)
3139 error("#endif without matching #if");
3140 s1->ifdef_stack_ptr--;
3141 /* '#ifndef macro' was at the start of file. Now we check if
3142 an '#endif' is exactly at the end of file */
3143 if (file->ifndef_macro &&
3144 s1->ifdef_stack_ptr == file->ifdef_stack_ptr) {
3145 file->ifndef_macro_saved = file->ifndef_macro;
3146 /* need to set to zero to avoid false matches if another
3147 #ifndef at middle of file */
3148 file->ifndef_macro = 0;
3149 while (tok != TOK_LINEFEED)
3150 next_nomacro();
3151 tok_flags |= TOK_FLAG_ENDIF;
3152 goto the_end;
3154 break;
3155 case TOK_LINE:
3156 next();
3157 if (tok != TOK_CINT)
3158 error("#line");
3159 file->line_num = tokc.i - 1; /* the line number will be incremented after */
3160 next();
3161 if (tok != TOK_LINEFEED) {
3162 if (tok != TOK_STR)
3163 error("#line");
3164 pstrcpy(file->filename, sizeof(file->filename),
3165 (char *)tokc.cstr->data);
3167 break;
3168 case TOK_ERROR:
3169 case TOK_WARNING:
3170 c = tok;
3171 ch = file->buf_ptr[0];
3172 skip_spaces();
3173 q = buf;
3174 while (ch != '\n' && ch != CH_EOF) {
3175 if ((q - buf) < sizeof(buf) - 1)
3176 *q++ = ch;
3177 if (ch == '\\') {
3178 if (handle_stray_noerror() == 0)
3179 --q;
3180 } else
3181 inp();
3183 *q = '\0';
3184 if (c == TOK_ERROR)
3185 error("#error %s", buf);
3186 else
3187 warning("#warning %s", buf);
3188 break;
3189 case TOK_PRAGMA:
3190 pragma_parse(s1);
3191 break;
3192 default:
3193 if (tok == TOK_LINEFEED || tok == '!' || tok == TOK_CINT) {
3194 /* '!' is ignored to allow C scripts. numbers are ignored
3195 to emulate cpp behaviour */
3196 } else {
3197 if (!(saved_parse_flags & PARSE_FLAG_ASM_COMMENTS))
3198 error("invalid preprocessing directive #%s", get_tok_str(tok, &tokc));
3200 break;
3202 /* ignore other preprocess commands or #! for C scripts */
3203 while (tok != TOK_LINEFEED)
3204 next_nomacro();
3205 the_end:
3206 parse_flags = saved_parse_flags;
3209 /* evaluate escape codes in a string. */
3210 static void parse_escape_string(CString *outstr, const uint8_t *buf, int is_long)
3212 int c, n;
3213 const uint8_t *p;
3215 p = buf;
3216 for(;;) {
3217 c = *p;
3218 if (c == '\0')
3219 break;
3220 if (c == '\\') {
3221 p++;
3222 /* escape */
3223 c = *p;
3224 switch(c) {
3225 case '0': case '1': case '2': case '3':
3226 case '4': case '5': case '6': case '7':
3227 /* at most three octal digits */
3228 n = c - '0';
3229 p++;
3230 c = *p;
3231 if (isoct(c)) {
3232 n = n * 8 + c - '0';
3233 p++;
3234 c = *p;
3235 if (isoct(c)) {
3236 n = n * 8 + c - '0';
3237 p++;
3240 c = n;
3241 goto add_char_nonext;
3242 case 'x':
3243 case 'u':
3244 case 'U':
3245 p++;
3246 n = 0;
3247 for(;;) {
3248 c = *p;
3249 if (c >= 'a' && c <= 'f')
3250 c = c - 'a' + 10;
3251 else if (c >= 'A' && c <= 'F')
3252 c = c - 'A' + 10;
3253 else if (isnum(c))
3254 c = c - '0';
3255 else
3256 break;
3257 n = n * 16 + c;
3258 p++;
3260 c = n;
3261 goto add_char_nonext;
3262 case 'a':
3263 c = '\a';
3264 break;
3265 case 'b':
3266 c = '\b';
3267 break;
3268 case 'f':
3269 c = '\f';
3270 break;
3271 case 'n':
3272 c = '\n';
3273 break;
3274 case 'r':
3275 c = '\r';
3276 break;
3277 case 't':
3278 c = '\t';
3279 break;
3280 case 'v':
3281 c = '\v';
3282 break;
3283 case 'e':
3284 if (!gnu_ext)
3285 goto invalid_escape;
3286 c = 27;
3287 break;
3288 case '\'':
3289 case '\"':
3290 case '\\':
3291 case '?':
3292 break;
3293 default:
3294 invalid_escape:
3295 if (c >= '!' && c <= '~')
3296 warning("unknown escape sequence: \'\\%c\'", c);
3297 else
3298 warning("unknown escape sequence: \'\\x%x\'", c);
3299 break;
3302 p++;
3303 add_char_nonext:
3304 if (!is_long)
3305 cstr_ccat(outstr, c);
3306 else
3307 cstr_wccat(outstr, c);
3309 /* add a trailing '\0' */
3310 if (!is_long)
3311 cstr_ccat(outstr, '\0');
3312 else
3313 cstr_wccat(outstr, '\0');
3316 /* we use 64 bit numbers */
3317 #define BN_SIZE 2
3319 /* bn = (bn << shift) | or_val */
3320 void bn_lshift(unsigned int *bn, int shift, int or_val)
3322 int i;
3323 unsigned int v;
3324 for(i=0;i<BN_SIZE;i++) {
3325 v = bn[i];
3326 bn[i] = (v << shift) | or_val;
3327 or_val = v >> (32 - shift);
3331 void bn_zero(unsigned int *bn)
3333 int i;
3334 for(i=0;i<BN_SIZE;i++) {
3335 bn[i] = 0;
3339 /* parse number in null terminated string 'p' and return it in the
3340 current token */
3341 void parse_number(const char *p)
3343 int b, t, shift, frac_bits, s, exp_val, ch;
3344 char *q;
3345 unsigned int bn[BN_SIZE];
3346 double d;
3348 /* number */
3349 q = token_buf;
3350 ch = *p++;
3351 t = ch;
3352 ch = *p++;
3353 *q++ = t;
3354 b = 10;
3355 if (t == '.') {
3356 goto float_frac_parse;
3357 } else if (t == '0') {
3358 if (ch == 'x' || ch == 'X') {
3359 q--;
3360 ch = *p++;
3361 b = 16;
3362 } else if (tcc_ext && (ch == 'b' || ch == 'B')) {
3363 q--;
3364 ch = *p++;
3365 b = 2;
3368 /* parse all digits. cannot check octal numbers at this stage
3369 because of floating point constants */
3370 while (1) {
3371 if (ch >= 'a' && ch <= 'f')
3372 t = ch - 'a' + 10;
3373 else if (ch >= 'A' && ch <= 'F')
3374 t = ch - 'A' + 10;
3375 else if (isnum(ch))
3376 t = ch - '0';
3377 else
3378 break;
3379 if (t >= b)
3380 break;
3381 if (q >= token_buf + STRING_MAX_SIZE) {
3382 num_too_long:
3383 error("number too long");
3385 *q++ = ch;
3386 ch = *p++;
3388 if (ch == '.' ||
3389 ((ch == 'e' || ch == 'E') && b == 10) ||
3390 ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
3391 if (b != 10) {
3392 /* NOTE: strtox should support that for hexa numbers, but
3393 non ISOC99 libcs do not support it, so we prefer to do
3394 it by hand */
3395 /* hexadecimal or binary floats */
3396 /* XXX: handle overflows */
3397 *q = '\0';
3398 if (b == 16)
3399 shift = 4;
3400 else
3401 shift = 2;
3402 bn_zero(bn);
3403 q = token_buf;
3404 while (1) {
3405 t = *q++;
3406 if (t == '\0') {
3407 break;
3408 } else if (t >= 'a') {
3409 t = t - 'a' + 10;
3410 } else if (t >= 'A') {
3411 t = t - 'A' + 10;
3412 } else {
3413 t = t - '0';
3415 bn_lshift(bn, shift, t);
3417 frac_bits = 0;
3418 if (ch == '.') {
3419 ch = *p++;
3420 while (1) {
3421 t = ch;
3422 if (t >= 'a' && t <= 'f') {
3423 t = t - 'a' + 10;
3424 } else if (t >= 'A' && t <= 'F') {
3425 t = t - 'A' + 10;
3426 } else if (t >= '0' && t <= '9') {
3427 t = t - '0';
3428 } else {
3429 break;
3431 if (t >= b)
3432 error("invalid digit");
3433 bn_lshift(bn, shift, t);
3434 frac_bits += shift;
3435 ch = *p++;
3438 if (ch != 'p' && ch != 'P')
3439 expect("exponent");
3440 ch = *p++;
3441 s = 1;
3442 exp_val = 0;
3443 if (ch == '+') {
3444 ch = *p++;
3445 } else if (ch == '-') {
3446 s = -1;
3447 ch = *p++;
3449 if (ch < '0' || ch > '9')
3450 expect("exponent digits");
3451 while (ch >= '0' && ch <= '9') {
3452 exp_val = exp_val * 10 + ch - '0';
3453 ch = *p++;
3455 exp_val = exp_val * s;
3457 /* now we can generate the number */
3458 /* XXX: should patch directly float number */
3459 d = (double)bn[1] * 4294967296.0 + (double)bn[0];
3460 d = ldexp(d, exp_val - frac_bits);
3461 t = toup(ch);
3462 if (t == 'F') {
3463 ch = *p++;
3464 tok = TOK_CFLOAT;
3465 /* float : should handle overflow */
3466 tokc.f = (float)d;
3467 } else if (t == 'L') {
3468 ch = *p++;
3469 tok = TOK_CLDOUBLE;
3470 /* XXX: not large enough */
3471 tokc.ld = (long double)d;
3472 } else {
3473 tok = TOK_CDOUBLE;
3474 tokc.d = d;
3476 } else {
3477 /* decimal floats */
3478 if (ch == '.') {
3479 if (q >= token_buf + STRING_MAX_SIZE)
3480 goto num_too_long;
3481 *q++ = ch;
3482 ch = *p++;
3483 float_frac_parse:
3484 while (ch >= '0' && ch <= '9') {
3485 if (q >= token_buf + STRING_MAX_SIZE)
3486 goto num_too_long;
3487 *q++ = ch;
3488 ch = *p++;
3491 if (ch == 'e' || ch == 'E') {
3492 if (q >= token_buf + STRING_MAX_SIZE)
3493 goto num_too_long;
3494 *q++ = ch;
3495 ch = *p++;
3496 if (ch == '-' || ch == '+') {
3497 if (q >= token_buf + STRING_MAX_SIZE)
3498 goto num_too_long;
3499 *q++ = ch;
3500 ch = *p++;
3502 if (ch < '0' || ch > '9')
3503 expect("exponent digits");
3504 while (ch >= '0' && ch <= '9') {
3505 if (q >= token_buf + STRING_MAX_SIZE)
3506 goto num_too_long;
3507 *q++ = ch;
3508 ch = *p++;
3511 *q = '\0';
3512 t = toup(ch);
3513 errno = 0;
3514 if (t == 'F') {
3515 ch = *p++;
3516 tok = TOK_CFLOAT;
3517 tokc.f = strtof(token_buf, NULL);
3518 } else if (t == 'L') {
3519 ch = *p++;
3520 tok = TOK_CLDOUBLE;
3521 tokc.ld = strtold(token_buf, NULL);
3522 } else {
3523 tok = TOK_CDOUBLE;
3524 tokc.d = strtod(token_buf, NULL);
3527 } else {
3528 unsigned long long n, n1;
3529 int lcount, ucount;
3531 /* integer number */
3532 *q = '\0';
3533 q = token_buf;
3534 if (b == 10 && *q == '0') {
3535 b = 8;
3536 q++;
3538 n = 0;
3539 while(1) {
3540 t = *q++;
3541 /* no need for checks except for base 10 / 8 errors */
3542 if (t == '\0') {
3543 break;
3544 } else if (t >= 'a') {
3545 t = t - 'a' + 10;
3546 } else if (t >= 'A') {
3547 t = t - 'A' + 10;
3548 } else {
3549 t = t - '0';
3550 if (t >= b)
3551 error("invalid digit");
3553 n1 = n;
3554 n = n * b + t;
3555 /* detect overflow */
3556 /* XXX: this test is not reliable */
3557 if (n < n1)
3558 error("integer constant overflow");
3561 /* XXX: not exactly ANSI compliant */
3562 if ((n & 0xffffffff00000000LL) != 0) {
3563 if ((n >> 63) != 0)
3564 tok = TOK_CULLONG;
3565 else
3566 tok = TOK_CLLONG;
3567 } else if (n > 0x7fffffff) {
3568 tok = TOK_CUINT;
3569 } else {
3570 tok = TOK_CINT;
3572 lcount = 0;
3573 ucount = 0;
3574 for(;;) {
3575 t = toup(ch);
3576 if (t == 'L') {
3577 if (lcount >= 2)
3578 error("three 'l's in integer constant");
3579 lcount++;
3580 if (lcount == 2) {
3581 if (tok == TOK_CINT)
3582 tok = TOK_CLLONG;
3583 else if (tok == TOK_CUINT)
3584 tok = TOK_CULLONG;
3586 ch = *p++;
3587 } else if (t == 'U') {
3588 if (ucount >= 1)
3589 error("two 'u's in integer constant");
3590 ucount++;
3591 if (tok == TOK_CINT)
3592 tok = TOK_CUINT;
3593 else if (tok == TOK_CLLONG)
3594 tok = TOK_CULLONG;
3595 ch = *p++;
3596 } else {
3597 break;
3600 if (tok == TOK_CINT || tok == TOK_CUINT)
3601 tokc.ui = n;
3602 else
3603 tokc.ull = n;
3608 #define PARSE2(c1, tok1, c2, tok2) \
3609 case c1: \
3610 PEEKC(c, p); \
3611 if (c == c2) { \
3612 p++; \
3613 tok = tok2; \
3614 } else { \
3615 tok = tok1; \
3617 break;
3619 /* return next token without macro substitution */
3620 static inline void next_nomacro1(void)
3622 int t, c, is_long;
3623 TokenSym *ts;
3624 uint8_t *p, *p1;
3625 unsigned int h;
3627 p = file->buf_ptr;
3628 redo_no_start:
3629 c = *p;
3630 switch(c) {
3631 case ' ':
3632 case '\t':
3633 case '\f':
3634 case '\v':
3635 case '\r':
3636 p++;
3637 goto redo_no_start;
3639 case '\\':
3640 /* first look if it is in fact an end of buffer */
3641 if (p >= file->buf_end) {
3642 file->buf_ptr = p;
3643 handle_eob();
3644 p = file->buf_ptr;
3645 if (p >= file->buf_end)
3646 goto parse_eof;
3647 else
3648 goto redo_no_start;
3649 } else {
3650 file->buf_ptr = p;
3651 ch = *p;
3652 handle_stray();
3653 p = file->buf_ptr;
3654 goto redo_no_start;
3656 parse_eof:
3658 TCCState *s1 = tcc_state;
3659 if ((parse_flags & PARSE_FLAG_LINEFEED)
3660 && !(tok_flags & TOK_FLAG_EOF)) {
3661 tok_flags |= TOK_FLAG_EOF;
3662 tok = TOK_LINEFEED;
3663 goto keep_tok_flags;
3664 } else if (s1->include_stack_ptr == s1->include_stack ||
3665 !(parse_flags & PARSE_FLAG_PREPROCESS)) {
3666 /* no include left : end of file. */
3667 tok = TOK_EOF;
3668 } else {
3669 tok_flags &= ~TOK_FLAG_EOF;
3670 /* pop include file */
3672 /* test if previous '#endif' was after a #ifdef at
3673 start of file */
3674 if (tok_flags & TOK_FLAG_ENDIF) {
3675 #ifdef INC_DEBUG
3676 printf("#endif %s\n", get_tok_str(file->ifndef_macro_saved, NULL));
3677 #endif
3678 add_cached_include(s1, file->inc_type, file->inc_filename,
3679 file->ifndef_macro_saved);
3682 /* add end of include file debug info */
3683 if (do_debug) {
3684 put_stabd(N_EINCL, 0, 0);
3686 /* pop include stack */
3687 tcc_close(file);
3688 s1->include_stack_ptr--;
3689 file = *s1->include_stack_ptr;
3690 p = file->buf_ptr;
3691 goto redo_no_start;
3694 break;
3696 case '\n':
3697 file->line_num++;
3698 tok_flags |= TOK_FLAG_BOL;
3699 p++;
3700 if (0 == (parse_flags & PARSE_FLAG_LINEFEED))
3701 goto redo_no_start;
3702 tok = TOK_LINEFEED;
3703 goto keep_tok_flags;
3705 case '#':
3706 /* XXX: simplify */
3707 PEEKC(c, p);
3708 if ((tok_flags & TOK_FLAG_BOL) &&
3709 (parse_flags & PARSE_FLAG_PREPROCESS)) {
3710 file->buf_ptr = p;
3711 preprocess(tok_flags & TOK_FLAG_BOF);
3712 p = file->buf_ptr;
3713 goto redo_no_start;
3714 } else {
3715 if (c == '#') {
3716 p++;
3717 tok = TOK_TWOSHARPS;
3718 } else {
3719 if (parse_flags & PARSE_FLAG_ASM_COMMENTS) {
3720 p = parse_line_comment(p - 1);
3721 goto redo_no_start;
3722 } else {
3723 tok = '#';
3727 break;
3729 case 'a': case 'b': case 'c': case 'd':
3730 case 'e': case 'f': case 'g': case 'h':
3731 case 'i': case 'j': case 'k': case 'l':
3732 case 'm': case 'n': case 'o': case 'p':
3733 case 'q': case 'r': case 's': case 't':
3734 case 'u': case 'v': case 'w': case 'x':
3735 case 'y': case 'z':
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':
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 '_':
3744 parse_ident_fast:
3745 p1 = p;
3746 h = TOK_HASH_INIT;
3747 h = TOK_HASH_FUNC(h, c);
3748 p++;
3749 for(;;) {
3750 c = *p;
3751 if (!isidnum_table[c])
3752 break;
3753 h = TOK_HASH_FUNC(h, c);
3754 p++;
3756 if (c != '\\') {
3757 TokenSym **pts;
3758 int len;
3760 /* fast case : no stray found, so we have the full token
3761 and we have already hashed it */
3762 len = p - p1;
3763 h &= (TOK_HASH_SIZE - 1);
3764 pts = &hash_ident[h];
3765 for(;;) {
3766 ts = *pts;
3767 if (!ts)
3768 break;
3769 if (ts->len == len && !memcmp(ts->str, p1, len))
3770 goto token_found;
3771 pts = &(ts->hash_next);
3773 ts = tok_alloc_new(pts, p1, len);
3774 token_found: ;
3775 } else {
3776 /* slower case */
3777 cstr_reset(&tokcstr);
3779 while (p1 < p) {
3780 cstr_ccat(&tokcstr, *p1);
3781 p1++;
3783 p--;
3784 PEEKC(c, p);
3785 parse_ident_slow:
3786 while (isidnum_table[c]) {
3787 cstr_ccat(&tokcstr, c);
3788 PEEKC(c, p);
3790 ts = tok_alloc(tokcstr.data, tokcstr.size);
3792 tok = ts->tok;
3793 break;
3794 case 'L':
3795 t = p[1];
3796 if (t != '\\' && t != '\'' && t != '\"') {
3797 /* fast case */
3798 goto parse_ident_fast;
3799 } else {
3800 PEEKC(c, p);
3801 if (c == '\'' || c == '\"') {
3802 is_long = 1;
3803 goto str_const;
3804 } else {
3805 cstr_reset(&tokcstr);
3806 cstr_ccat(&tokcstr, 'L');
3807 goto parse_ident_slow;
3810 break;
3811 case '0': case '1': case '2': case '3':
3812 case '4': case '5': case '6': case '7':
3813 case '8': case '9':
3815 cstr_reset(&tokcstr);
3816 /* after the first digit, accept digits, alpha, '.' or sign if
3817 prefixed by 'eEpP' */
3818 parse_num:
3819 for(;;) {
3820 t = c;
3821 cstr_ccat(&tokcstr, c);
3822 PEEKC(c, p);
3823 if (!(isnum(c) || isid(c) || c == '.' ||
3824 ((c == '+' || c == '-') &&
3825 (t == 'e' || t == 'E' || t == 'p' || t == 'P'))))
3826 break;
3828 /* We add a trailing '\0' to ease parsing */
3829 cstr_ccat(&tokcstr, '\0');
3830 tokc.cstr = &tokcstr;
3831 tok = TOK_PPNUM;
3832 break;
3833 case '.':
3834 /* special dot handling because it can also start a number */
3835 PEEKC(c, p);
3836 if (isnum(c)) {
3837 cstr_reset(&tokcstr);
3838 cstr_ccat(&tokcstr, '.');
3839 goto parse_num;
3840 } else if (c == '.') {
3841 PEEKC(c, p);
3842 if (c != '.')
3843 expect("'.'");
3844 PEEKC(c, p);
3845 tok = TOK_DOTS;
3846 } else {
3847 tok = '.';
3849 break;
3850 case '\'':
3851 case '\"':
3852 is_long = 0;
3853 str_const:
3855 CString str;
3856 int sep;
3858 sep = c;
3860 /* parse the string */
3861 cstr_new(&str);
3862 p = parse_pp_string(p, sep, &str);
3863 cstr_ccat(&str, '\0');
3865 /* eval the escape (should be done as TOK_PPNUM) */
3866 cstr_reset(&tokcstr);
3867 parse_escape_string(&tokcstr, str.data, is_long);
3868 cstr_free(&str);
3870 if (sep == '\'') {
3871 int char_size;
3872 /* XXX: make it portable */
3873 if (!is_long)
3874 char_size = 1;
3875 else
3876 char_size = sizeof(nwchar_t);
3877 if (tokcstr.size <= char_size)
3878 error("empty character constant");
3879 if (tokcstr.size > 2 * char_size)
3880 warning("multi-character character constant");
3881 if (!is_long) {
3882 tokc.i = *(int8_t *)tokcstr.data;
3883 tok = TOK_CCHAR;
3884 } else {
3885 tokc.i = *(nwchar_t *)tokcstr.data;
3886 tok = TOK_LCHAR;
3888 } else {
3889 tokc.cstr = &tokcstr;
3890 if (!is_long)
3891 tok = TOK_STR;
3892 else
3893 tok = TOK_LSTR;
3896 break;
3898 case '<':
3899 PEEKC(c, p);
3900 if (c == '=') {
3901 p++;
3902 tok = TOK_LE;
3903 } else if (c == '<') {
3904 PEEKC(c, p);
3905 if (c == '=') {
3906 p++;
3907 tok = TOK_A_SHL;
3908 } else {
3909 tok = TOK_SHL;
3911 } else {
3912 tok = TOK_LT;
3914 break;
3916 case '>':
3917 PEEKC(c, p);
3918 if (c == '=') {
3919 p++;
3920 tok = TOK_GE;
3921 } else if (c == '>') {
3922 PEEKC(c, p);
3923 if (c == '=') {
3924 p++;
3925 tok = TOK_A_SAR;
3926 } else {
3927 tok = TOK_SAR;
3929 } else {
3930 tok = TOK_GT;
3932 break;
3934 case '&':
3935 PEEKC(c, p);
3936 if (c == '&') {
3937 p++;
3938 tok = TOK_LAND;
3939 } else if (c == '=') {
3940 p++;
3941 tok = TOK_A_AND;
3942 } else {
3943 tok = '&';
3945 break;
3947 case '|':
3948 PEEKC(c, p);
3949 if (c == '|') {
3950 p++;
3951 tok = TOK_LOR;
3952 } else if (c == '=') {
3953 p++;
3954 tok = TOK_A_OR;
3955 } else {
3956 tok = '|';
3958 break;
3960 case '+':
3961 PEEKC(c, p);
3962 if (c == '+') {
3963 p++;
3964 tok = TOK_INC;
3965 } else if (c == '=') {
3966 p++;
3967 tok = TOK_A_ADD;
3968 } else {
3969 tok = '+';
3971 break;
3973 case '-':
3974 PEEKC(c, p);
3975 if (c == '-') {
3976 p++;
3977 tok = TOK_DEC;
3978 } else if (c == '=') {
3979 p++;
3980 tok = TOK_A_SUB;
3981 } else if (c == '>') {
3982 p++;
3983 tok = TOK_ARROW;
3984 } else {
3985 tok = '-';
3987 break;
3989 PARSE2('!', '!', '=', TOK_NE)
3990 PARSE2('=', '=', '=', TOK_EQ)
3991 PARSE2('*', '*', '=', TOK_A_MUL)
3992 PARSE2('%', '%', '=', TOK_A_MOD)
3993 PARSE2('^', '^', '=', TOK_A_XOR)
3995 /* comments or operator */
3996 case '/':
3997 PEEKC(c, p);
3998 if (c == '*') {
3999 p = parse_comment(p);
4000 goto redo_no_start;
4001 } else if (c == '/') {
4002 p = parse_line_comment(p);
4003 goto redo_no_start;
4004 } else if (c == '=') {
4005 p++;
4006 tok = TOK_A_DIV;
4007 } else {
4008 tok = '/';
4010 break;
4012 /* simple tokens */
4013 case '(':
4014 case ')':
4015 case '[':
4016 case ']':
4017 case '{':
4018 case '}':
4019 case ',':
4020 case ';':
4021 case ':':
4022 case '?':
4023 case '~':
4024 case '$': /* only used in assembler */
4025 case '@': /* dito */
4026 tok = c;
4027 p++;
4028 break;
4029 default:
4030 error("unrecognized character \\x%02x", c);
4031 break;
4033 tok_flags = 0;
4034 keep_tok_flags:
4035 file->buf_ptr = p;
4036 #if defined(PARSE_DEBUG)
4037 printf("token = %s\n", get_tok_str(tok, &tokc));
4038 #endif
4041 /* return next token without macro substitution. Can read input from
4042 macro_ptr buffer */
4043 static void next_nomacro(void)
4045 if (macro_ptr) {
4046 redo:
4047 tok = *macro_ptr;
4048 if (tok) {
4049 TOK_GET(tok, macro_ptr, tokc);
4050 if (tok == TOK_LINENUM) {
4051 file->line_num = tokc.i;
4052 goto redo;
4055 } else {
4056 next_nomacro1();
4060 /* substitute args in macro_str and return allocated string */
4061 static int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
4063 int *st, last_tok, t, notfirst;
4064 Sym *s;
4065 CValue cval;
4066 TokenString str;
4067 CString cstr;
4069 tok_str_new(&str);
4070 last_tok = 0;
4071 while(1) {
4072 TOK_GET(t, macro_str, cval);
4073 if (!t)
4074 break;
4075 if (t == '#') {
4076 /* stringize */
4077 TOK_GET(t, macro_str, cval);
4078 if (!t)
4079 break;
4080 s = sym_find2(args, t);
4081 if (s) {
4082 cstr_new(&cstr);
4083 st = (int *)s->c;
4084 notfirst = 0;
4085 while (*st) {
4086 if (notfirst)
4087 cstr_ccat(&cstr, ' ');
4088 TOK_GET(t, st, cval);
4089 cstr_cat(&cstr, get_tok_str(t, &cval));
4090 #ifndef PP_NOSPACES
4091 notfirst = 1;
4092 #endif
4094 cstr_ccat(&cstr, '\0');
4095 #ifdef PP_DEBUG
4096 printf("stringize: %s\n", (char *)cstr.data);
4097 #endif
4098 /* add string */
4099 cval.cstr = &cstr;
4100 tok_str_add2(&str, TOK_STR, &cval);
4101 cstr_free(&cstr);
4102 } else {
4103 tok_str_add2(&str, t, &cval);
4105 } else if (t >= TOK_IDENT) {
4106 s = sym_find2(args, t);
4107 if (s) {
4108 st = (int *)s->c;
4109 /* if '##' is present before or after, no arg substitution */
4110 if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) {
4111 /* special case for var arg macros : ## eats the
4112 ',' if empty VA_ARGS variable. */
4113 /* XXX: test of the ',' is not 100%
4114 reliable. should fix it to avoid security
4115 problems */
4116 if (gnu_ext && s->type.t &&
4117 last_tok == TOK_TWOSHARPS &&
4118 str.len >= 2 && str.str[str.len - 2] == ',') {
4119 if (*st == 0) {
4120 /* suppress ',' '##' */
4121 str.len -= 2;
4122 } else {
4123 /* suppress '##' and add variable */
4124 str.len--;
4125 goto add_var;
4127 } else {
4128 int t1;
4129 add_var:
4130 for(;;) {
4131 TOK_GET(t1, st, cval);
4132 if (!t1)
4133 break;
4134 tok_str_add2(&str, t1, &cval);
4137 } else {
4138 /* NOTE: the stream cannot be read when macro
4139 substituing an argument */
4140 macro_subst(&str, nested_list, st, NULL);
4142 } else {
4143 tok_str_add(&str, t);
4145 } else {
4146 tok_str_add2(&str, t, &cval);
4148 last_tok = t;
4150 tok_str_add(&str, 0);
4151 return str.str;
4154 static char const ab_month_name[12][4] =
4156 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
4157 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
4160 /* do macro substitution of current token with macro 's' and add
4161 result to (tok_str,tok_len). 'nested_list' is the list of all
4162 macros we got inside to avoid recursing. Return non zero if no
4163 substitution needs to be done */
4164 static int macro_subst_tok(TokenString *tok_str,
4165 Sym **nested_list, Sym *s, struct macro_level **can_read_stream)
4167 Sym *args, *sa, *sa1;
4168 int mstr_allocated, parlevel, *mstr, t, t1;
4169 TokenString str;
4170 char *cstrval;
4171 CValue cval;
4172 CString cstr;
4173 char buf[32];
4175 /* if symbol is a macro, prepare substitution */
4176 /* special macros */
4177 if (tok == TOK___LINE__) {
4178 snprintf(buf, sizeof(buf), "%d", file->line_num);
4179 cstrval = buf;
4180 t1 = TOK_PPNUM;
4181 goto add_cstr1;
4182 } else if (tok == TOK___FILE__) {
4183 cstrval = file->filename;
4184 goto add_cstr;
4185 } else if (tok == TOK___DATE__ || tok == TOK___TIME__) {
4186 time_t ti;
4187 struct tm *tm;
4189 time(&ti);
4190 tm = localtime(&ti);
4191 if (tok == TOK___DATE__) {
4192 snprintf(buf, sizeof(buf), "%s %2d %d",
4193 ab_month_name[tm->tm_mon], tm->tm_mday, tm->tm_year + 1900);
4194 } else {
4195 snprintf(buf, sizeof(buf), "%02d:%02d:%02d",
4196 tm->tm_hour, tm->tm_min, tm->tm_sec);
4198 cstrval = buf;
4199 add_cstr:
4200 t1 = TOK_STR;
4201 add_cstr1:
4202 cstr_new(&cstr);
4203 cstr_cat(&cstr, cstrval);
4204 cstr_ccat(&cstr, '\0');
4205 cval.cstr = &cstr;
4206 tok_str_add2(tok_str, t1, &cval);
4207 cstr_free(&cstr);
4208 } else {
4209 mstr = (int *)s->c;
4210 mstr_allocated = 0;
4211 if (s->type.t == MACRO_FUNC) {
4212 /* NOTE: we do not use next_nomacro to avoid eating the
4213 next token. XXX: find better solution */
4214 redo:
4215 if (macro_ptr) {
4216 t = *macro_ptr;
4217 if (t == 0 && can_read_stream) {
4218 /* end of macro stream: we must look at the token
4219 after in the file */
4220 struct macro_level *ml = *can_read_stream;
4221 macro_ptr = NULL;
4222 if (ml)
4224 macro_ptr = ml->p;
4225 ml->p = NULL;
4226 *can_read_stream = ml -> prev;
4228 goto redo;
4230 } else {
4231 /* XXX: incorrect with comments */
4232 ch = file->buf_ptr[0];
4233 while (is_space(ch) || ch == '\n')
4234 cinp();
4235 t = ch;
4237 if (t != '(') /* no macro subst */
4238 return -1;
4240 /* argument macro */
4241 next_nomacro();
4242 next_nomacro();
4243 args = NULL;
4244 sa = s->next;
4245 /* NOTE: empty args are allowed, except if no args */
4246 for(;;) {
4247 /* handle '()' case */
4248 if (!args && !sa && tok == ')')
4249 break;
4250 if (!sa)
4251 error("macro '%s' used with too many args",
4252 get_tok_str(s->v, 0));
4253 tok_str_new(&str);
4254 parlevel = 0;
4255 /* NOTE: non zero sa->t indicates VA_ARGS */
4256 while ((parlevel > 0 ||
4257 (tok != ')' &&
4258 (tok != ',' || sa->type.t))) &&
4259 tok != -1) {
4260 if (tok == '(')
4261 parlevel++;
4262 else if (tok == ')')
4263 parlevel--;
4264 if (tok != TOK_LINEFEED)
4265 tok_str_add2(&str, tok, &tokc);
4266 next_nomacro();
4268 tok_str_add(&str, 0);
4269 sym_push2(&args, sa->v & ~SYM_FIELD, sa->type.t, (int)str.str);
4270 sa = sa->next;
4271 if (tok == ')') {
4272 /* special case for gcc var args: add an empty
4273 var arg argument if it is omitted */
4274 if (sa && sa->type.t && gnu_ext)
4275 continue;
4276 else
4277 break;
4279 if (tok != ',')
4280 expect(",");
4281 next_nomacro();
4283 if (sa) {
4284 error("macro '%s' used with too few args",
4285 get_tok_str(s->v, 0));
4288 /* now subst each arg */
4289 mstr = macro_arg_subst(nested_list, mstr, args);
4290 /* free memory */
4291 sa = args;
4292 while (sa) {
4293 sa1 = sa->prev;
4294 tok_str_free((int *)sa->c);
4295 sym_free(sa);
4296 sa = sa1;
4298 mstr_allocated = 1;
4300 sym_push2(nested_list, s->v, 0, 0);
4301 macro_subst(tok_str, nested_list, mstr, can_read_stream);
4302 /* pop nested defined symbol */
4303 sa1 = *nested_list;
4304 *nested_list = sa1->prev;
4305 sym_free(sa1);
4306 if (mstr_allocated)
4307 tok_str_free(mstr);
4309 return 0;
4312 /* handle the '##' operator. Return NULL if no '##' seen. Otherwise
4313 return the resulting string (which must be freed). */
4314 static inline int *macro_twosharps(const int *macro_str)
4316 TokenSym *ts;
4317 const int *macro_ptr1, *start_macro_ptr, *ptr, *saved_macro_ptr;
4318 int t;
4319 const char *p1, *p2;
4320 CValue cval;
4321 TokenString macro_str1;
4322 CString cstr;
4324 start_macro_ptr = macro_str;
4325 /* we search the first '##' */
4326 for(;;) {
4327 macro_ptr1 = macro_str;
4328 TOK_GET(t, macro_str, cval);
4329 /* nothing more to do if end of string */
4330 if (t == 0)
4331 return NULL;
4332 if (*macro_str == TOK_TWOSHARPS)
4333 break;
4336 /* we saw '##', so we need more processing to handle it */
4337 cstr_new(&cstr);
4338 tok_str_new(&macro_str1);
4339 tok = t;
4340 tokc = cval;
4342 /* add all tokens seen so far */
4343 for(ptr = start_macro_ptr; ptr < macro_ptr1;) {
4344 TOK_GET(t, ptr, cval);
4345 tok_str_add2(&macro_str1, t, &cval);
4347 saved_macro_ptr = macro_ptr;
4348 /* XXX: get rid of the use of macro_ptr here */
4349 macro_ptr = (int *)macro_str;
4350 for(;;) {
4351 while (*macro_ptr == TOK_TWOSHARPS) {
4352 macro_ptr++;
4353 macro_ptr1 = macro_ptr;
4354 t = *macro_ptr;
4355 if (t) {
4356 TOK_GET(t, macro_ptr, cval);
4357 /* We concatenate the two tokens if we have an
4358 identifier or a preprocessing number */
4359 cstr_reset(&cstr);
4360 p1 = get_tok_str(tok, &tokc);
4361 cstr_cat(&cstr, p1);
4362 p2 = get_tok_str(t, &cval);
4363 cstr_cat(&cstr, p2);
4364 cstr_ccat(&cstr, '\0');
4366 if ((tok >= TOK_IDENT || tok == TOK_PPNUM) &&
4367 (t >= TOK_IDENT || t == TOK_PPNUM)) {
4368 if (tok == TOK_PPNUM) {
4369 /* if number, then create a number token */
4370 /* NOTE: no need to allocate because
4371 tok_str_add2() does it */
4372 cstr_reset(&tokcstr);
4373 tokcstr = cstr;
4374 cstr_new(&cstr);
4375 tokc.cstr = &tokcstr;
4376 } else {
4377 /* if identifier, we must do a test to
4378 validate we have a correct identifier */
4379 if (t == TOK_PPNUM) {
4380 const char *p;
4381 int c;
4383 p = p2;
4384 for(;;) {
4385 c = *p;
4386 if (c == '\0')
4387 break;
4388 p++;
4389 if (!isnum(c) && !isid(c))
4390 goto error_pasting;
4393 ts = tok_alloc(cstr.data, strlen(cstr.data));
4394 tok = ts->tok; /* modify current token */
4396 } else {
4397 const char *str = cstr.data;
4398 const unsigned char *q;
4400 /* we look for a valid token */
4401 /* XXX: do more extensive checks */
4402 if (!strcmp(str, ">>=")) {
4403 tok = TOK_A_SAR;
4404 } else if (!strcmp(str, "<<=")) {
4405 tok = TOK_A_SHL;
4406 } else if (strlen(str) == 2) {
4407 /* search in two bytes table */
4408 q = tok_two_chars;
4409 for(;;) {
4410 if (!*q)
4411 goto error_pasting;
4412 if (q[0] == str[0] && q[1] == str[1])
4413 break;
4414 q += 3;
4416 tok = q[2];
4417 } else {
4418 error_pasting:
4419 /* NOTE: because get_tok_str use a static buffer,
4420 we must save it */
4421 cstr_reset(&cstr);
4422 p1 = get_tok_str(tok, &tokc);
4423 cstr_cat(&cstr, p1);
4424 cstr_ccat(&cstr, '\0');
4425 p2 = get_tok_str(t, &cval);
4426 warning("pasting \"%s\" and \"%s\" does not give a valid preprocessing token", cstr.data, p2);
4427 /* cannot merge tokens: just add them separately */
4428 tok_str_add2(&macro_str1, tok, &tokc);
4429 /* XXX: free associated memory ? */
4430 tok = t;
4431 tokc = cval;
4436 tok_str_add2(&macro_str1, tok, &tokc);
4437 next_nomacro();
4438 if (tok == 0)
4439 break;
4441 macro_ptr = (int *)saved_macro_ptr;
4442 cstr_free(&cstr);
4443 tok_str_add(&macro_str1, 0);
4444 return macro_str1.str;
4448 /* do macro substitution of macro_str and add result to
4449 (tok_str,tok_len). 'nested_list' is the list of all macros we got
4450 inside to avoid recursing. */
4451 static void macro_subst(TokenString *tok_str, Sym **nested_list,
4452 const int *macro_str, struct macro_level ** can_read_stream)
4454 Sym *s;
4455 int *macro_str1;
4456 const int *ptr;
4457 int t, ret;
4458 CValue cval;
4459 struct macro_level ml;
4461 /* first scan for '##' operator handling */
4462 ptr = macro_str;
4463 macro_str1 = macro_twosharps(ptr);
4464 if (macro_str1)
4465 ptr = macro_str1;
4466 while (1) {
4467 /* NOTE: ptr == NULL can only happen if tokens are read from
4468 file stream due to a macro function call */
4469 if (ptr == NULL)
4470 break;
4471 TOK_GET(t, ptr, cval);
4472 if (t == 0)
4473 break;
4474 s = define_find(t);
4475 if (s != NULL) {
4476 /* if nested substitution, do nothing */
4477 if (sym_find2(*nested_list, t))
4478 goto no_subst;
4479 ml.p = macro_ptr;
4480 if (can_read_stream)
4481 ml.prev = *can_read_stream, *can_read_stream = &ml;
4482 macro_ptr = (int *)ptr;
4483 tok = t;
4484 ret = macro_subst_tok(tok_str, nested_list, s, can_read_stream);
4485 ptr = (int *)macro_ptr;
4486 macro_ptr = ml.p;
4487 if (can_read_stream && *can_read_stream == &ml)
4488 *can_read_stream = ml.prev;
4489 if (ret != 0)
4490 goto no_subst;
4491 } else {
4492 no_subst:
4493 tok_str_add2(tok_str, t, &cval);
4496 if (macro_str1)
4497 tok_str_free(macro_str1);
4500 /* return next token with macro substitution */
4501 static void next(void)
4503 Sym *nested_list, *s;
4504 TokenString str;
4505 struct macro_level *ml;
4507 redo:
4508 next_nomacro();
4509 if (!macro_ptr) {
4510 /* if not reading from macro substituted string, then try
4511 to substitute macros */
4512 if (tok >= TOK_IDENT &&
4513 (parse_flags & PARSE_FLAG_PREPROCESS)) {
4514 s = define_find(tok);
4515 if (s) {
4516 /* we have a macro: we try to substitute */
4517 tok_str_new(&str);
4518 nested_list = NULL;
4519 ml = NULL;
4520 if (macro_subst_tok(&str, &nested_list, s, &ml) == 0) {
4521 /* substitution done, NOTE: maybe empty */
4522 tok_str_add(&str, 0);
4523 macro_ptr = str.str;
4524 macro_ptr_allocated = str.str;
4525 goto redo;
4529 } else {
4530 if (tok == 0) {
4531 /* end of macro or end of unget buffer */
4532 if (unget_buffer_enabled) {
4533 macro_ptr = unget_saved_macro_ptr;
4534 unget_buffer_enabled = 0;
4535 } else {
4536 /* end of macro string: free it */
4537 tok_str_free(macro_ptr_allocated);
4538 macro_ptr = NULL;
4540 goto redo;
4544 /* convert preprocessor tokens into C tokens */
4545 if (tok == TOK_PPNUM &&
4546 (parse_flags & PARSE_FLAG_TOK_NUM)) {
4547 parse_number((char *)tokc.cstr->data);
4551 /* push back current token and set current token to 'last_tok'. Only
4552 identifier case handled for labels. */
4553 static inline void unget_tok(int last_tok)
4555 int i, n;
4556 int *q;
4557 unget_saved_macro_ptr = macro_ptr;
4558 unget_buffer_enabled = 1;
4559 q = unget_saved_buffer;
4560 macro_ptr = q;
4561 *q++ = tok;
4562 n = tok_ext_size(tok) - 1;
4563 for(i=0;i<n;i++)
4564 *q++ = tokc.tab[i];
4565 *q = 0; /* end of token string */
4566 tok = last_tok;
4570 void swap(int *p, int *q)
4572 int t;
4573 t = *p;
4574 *p = *q;
4575 *q = t;
4578 void vsetc(CType *type, int r, CValue *vc)
4580 int v;
4582 if (vtop >= vstack + (VSTACK_SIZE - 1))
4583 error("memory full");
4584 /* cannot let cpu flags if other instruction are generated. Also
4585 avoid leaving VT_JMP anywhere except on the top of the stack
4586 because it would complicate the code generator. */
4587 if (vtop >= vstack) {
4588 v = vtop->r & VT_VALMASK;
4589 if (v == VT_CMP || (v & ~1) == VT_JMP)
4590 gv(RC_INT);
4592 vtop++;
4593 vtop->type = *type;
4594 vtop->r = r;
4595 vtop->r2 = VT_CONST;
4596 vtop->c = *vc;
4599 /* push integer constant */
4600 void vpushi(int v)
4602 CValue cval;
4603 cval.i = v;
4604 vsetc(&int_type, VT_CONST, &cval);
4607 /* Return a static symbol pointing to a section */
4608 static Sym *get_sym_ref(CType *type, Section *sec,
4609 unsigned long offset, unsigned long size)
4611 int v;
4612 Sym *sym;
4614 v = anon_sym++;
4615 sym = global_identifier_push(v, type->t | VT_STATIC, 0);
4616 sym->type.ref = type->ref;
4617 sym->r = VT_CONST | VT_SYM;
4618 put_extern_sym(sym, sec, offset, size);
4619 return sym;
4622 /* push a reference to a section offset by adding a dummy symbol */
4623 static void vpush_ref(CType *type, Section *sec, unsigned long offset, unsigned long size)
4625 CValue cval;
4627 cval.ul = 0;
4628 vsetc(type, VT_CONST | VT_SYM, &cval);
4629 vtop->sym = get_sym_ref(type, sec, offset, size);
4632 /* define a new external reference to a symbol 'v' of type 'u' */
4633 static Sym *external_global_sym(int v, CType *type, int r)
4635 Sym *s;
4637 s = sym_find(v);
4638 if (!s) {
4639 /* push forward reference */
4640 s = global_identifier_push(v, type->t | VT_EXTERN, 0);
4641 s->type.ref = type->ref;
4642 s->r = r | VT_CONST | VT_SYM;
4644 return s;
4647 /* define a new external reference to a symbol 'v' of type 'u' */
4648 static Sym *external_sym(int v, CType *type, int r)
4650 Sym *s;
4652 s = sym_find(v);
4653 if (!s) {
4654 /* push forward reference */
4655 s = sym_push(v, type, r | VT_CONST | VT_SYM, 0);
4656 s->type.t |= VT_EXTERN;
4657 } else {
4658 if (!is_compatible_types(&s->type, type))
4659 error("incompatible types for redefinition of '%s'",
4660 get_tok_str(v, NULL));
4662 return s;
4665 /* push a reference to global symbol v */
4666 static void vpush_global_sym(CType *type, int v)
4668 Sym *sym;
4669 CValue cval;
4671 sym = external_global_sym(v, type, 0);
4672 cval.ul = 0;
4673 vsetc(type, VT_CONST | VT_SYM, &cval);
4674 vtop->sym = sym;
4677 void vset(CType *type, int r, int v)
4679 CValue cval;
4681 cval.i = v;
4682 vsetc(type, r, &cval);
4685 void vseti(int r, int v)
4687 CType type;
4688 type.t = VT_INT;
4689 vset(&type, r, v);
4692 void vswap(void)
4694 SValue tmp;
4696 tmp = vtop[0];
4697 vtop[0] = vtop[-1];
4698 vtop[-1] = tmp;
4701 void vpushv(SValue *v)
4703 if (vtop >= vstack + (VSTACK_SIZE - 1))
4704 error("memory full");
4705 vtop++;
4706 *vtop = *v;
4709 void vdup(void)
4711 vpushv(vtop);
4714 /* save r to the memory stack, and mark it as being free */
4715 void save_reg(int r)
4717 int l, saved, size, align;
4718 SValue *p, sv;
4719 CType *type;
4721 /* modify all stack values */
4722 saved = 0;
4723 l = 0;
4724 for(p=vstack;p<=vtop;p++) {
4725 if ((p->r & VT_VALMASK) == r ||
4726 ((p->type.t & VT_BTYPE) == VT_LLONG && (p->r2 & VT_VALMASK) == r)) {
4727 /* must save value on stack if not already done */
4728 if (!saved) {
4729 /* NOTE: must reload 'r' because r might be equal to r2 */
4730 r = p->r & VT_VALMASK;
4731 /* store register in the stack */
4732 type = &p->type;
4733 if ((p->r & VT_LVAL) ||
4734 (!is_float(type->t) && (type->t & VT_BTYPE) != VT_LLONG))
4735 type = &int_type;
4736 size = type_size(type, &align);
4737 loc = (loc - size) & -align;
4738 sv.type.t = type->t;
4739 sv.r = VT_LOCAL | VT_LVAL;
4740 sv.c.ul = loc;
4741 store(r, &sv);
4742 #ifdef TCC_TARGET_I386
4743 /* x86 specific: need to pop fp register ST0 if saved */
4744 if (r == TREG_ST0) {
4745 o(0xd9dd); /* fstp %st(1) */
4747 #endif
4748 /* special long long case */
4749 if ((type->t & VT_BTYPE) == VT_LLONG) {
4750 sv.c.ul += 4;
4751 store(p->r2, &sv);
4753 l = loc;
4754 saved = 1;
4756 /* mark that stack entry as being saved on the stack */
4757 if (p->r & VT_LVAL) {
4758 /* also clear the bounded flag because the
4759 relocation address of the function was stored in
4760 p->c.ul */
4761 p->r = (p->r & ~(VT_VALMASK | VT_BOUNDED)) | VT_LLOCAL;
4762 } else {
4763 p->r = lvalue_type(p->type.t) | VT_LOCAL;
4765 p->r2 = VT_CONST;
4766 p->c.ul = l;
4771 /* find a register of class 'rc2' with at most one reference on stack.
4772 * If none, call get_reg(rc) */
4773 int get_reg_ex(int rc, int rc2)
4775 int r;
4776 SValue *p;
4778 for(r=0;r<NB_REGS;r++) {
4779 if (reg_classes[r] & rc2) {
4780 int n;
4781 n=0;
4782 for(p = vstack; p <= vtop; p++) {
4783 if ((p->r & VT_VALMASK) == r ||
4784 (p->r2 & VT_VALMASK) == r)
4785 n++;
4787 if (n <= 1)
4788 return r;
4791 return get_reg(rc);
4794 /* find a free register of class 'rc'. If none, save one register */
4795 int get_reg(int rc)
4797 int r;
4798 SValue *p;
4800 /* find a free register */
4801 for(r=0;r<NB_REGS;r++) {
4802 if (reg_classes[r] & rc) {
4803 for(p=vstack;p<=vtop;p++) {
4804 if ((p->r & VT_VALMASK) == r ||
4805 (p->r2 & VT_VALMASK) == r)
4806 goto notfound;
4808 return r;
4810 notfound: ;
4813 /* no register left : free the first one on the stack (VERY
4814 IMPORTANT to start from the bottom to ensure that we don't
4815 spill registers used in gen_opi()) */
4816 for(p=vstack;p<=vtop;p++) {
4817 r = p->r & VT_VALMASK;
4818 if (r < VT_CONST && (reg_classes[r] & rc))
4819 goto save_found;
4820 /* also look at second register (if long long) */
4821 r = p->r2 & VT_VALMASK;
4822 if (r < VT_CONST && (reg_classes[r] & rc)) {
4823 save_found:
4824 save_reg(r);
4825 return r;
4828 /* Should never comes here */
4829 return -1;
4832 /* save registers up to (vtop - n) stack entry */
4833 void save_regs(int n)
4835 int r;
4836 SValue *p, *p1;
4837 p1 = vtop - n;
4838 for(p = vstack;p <= p1; p++) {
4839 r = p->r & VT_VALMASK;
4840 if (r < VT_CONST) {
4841 save_reg(r);
4846 /* move register 's' to 'r', and flush previous value of r to memory
4847 if needed */
4848 void move_reg(int r, int s)
4850 SValue sv;
4852 if (r != s) {
4853 save_reg(r);
4854 sv.type.t = VT_INT;
4855 sv.r = s;
4856 sv.c.ul = 0;
4857 load(r, &sv);
4861 /* get address of vtop (vtop MUST BE an lvalue) */
4862 void gaddrof(void)
4864 vtop->r &= ~VT_LVAL;
4865 /* tricky: if saved lvalue, then we can go back to lvalue */
4866 if ((vtop->r & VT_VALMASK) == VT_LLOCAL)
4867 vtop->r = (vtop->r & ~(VT_VALMASK | VT_LVAL_TYPE)) | VT_LOCAL | VT_LVAL;
4870 #ifdef CONFIG_TCC_BCHECK
4871 /* generate lvalue bound code */
4872 void gbound(void)
4874 int lval_type;
4875 CType type1;
4877 vtop->r &= ~VT_MUSTBOUND;
4878 /* if lvalue, then use checking code before dereferencing */
4879 if (vtop->r & VT_LVAL) {
4880 /* if not VT_BOUNDED value, then make one */
4881 if (!(vtop->r & VT_BOUNDED)) {
4882 lval_type = vtop->r & (VT_LVAL_TYPE | VT_LVAL);
4883 /* must save type because we must set it to int to get pointer */
4884 type1 = vtop->type;
4885 vtop->type.t = VT_INT;
4886 gaddrof();
4887 vpushi(0);
4888 gen_bounded_ptr_add();
4889 vtop->r |= lval_type;
4890 vtop->type = type1;
4892 /* then check for dereferencing */
4893 gen_bounded_ptr_deref();
4896 #endif
4898 /* store vtop a register belonging to class 'rc'. lvalues are
4899 converted to values. Cannot be used if cannot be converted to
4900 register value (such as structures). */
4901 int gv(int rc)
4903 int r, r2, rc2, bit_pos, bit_size, size, align, i;
4904 unsigned long long ll;
4906 /* NOTE: get_reg can modify vstack[] */
4907 if (vtop->type.t & VT_BITFIELD) {
4908 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
4909 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
4910 /* remove bit field info to avoid loops */
4911 vtop->type.t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
4912 /* generate shifts */
4913 vpushi(32 - (bit_pos + bit_size));
4914 gen_op(TOK_SHL);
4915 vpushi(32 - bit_size);
4916 /* NOTE: transformed to SHR if unsigned */
4917 gen_op(TOK_SAR);
4918 r = gv(rc);
4919 } else {
4920 if (is_float(vtop->type.t) &&
4921 (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4922 Sym *sym;
4923 int *ptr;
4924 unsigned long offset;
4925 #if defined(TCC_TARGET_ARM) && !defined(TCC_ARM_VFP)
4926 CValue check;
4927 #endif
4929 /* XXX: unify with initializers handling ? */
4930 /* CPUs usually cannot use float constants, so we store them
4931 generically in data segment */
4932 size = type_size(&vtop->type, &align);
4933 offset = (data_section->data_offset + align - 1) & -align;
4934 data_section->data_offset = offset;
4935 /* XXX: not portable yet */
4936 #ifdef __i386__
4937 /* Zero pad x87 tenbyte long doubles */
4938 if (size == 12)
4939 vtop->c.tab[2] &= 0xffff;
4940 #endif
4941 ptr = section_ptr_add(data_section, size);
4942 size = size >> 2;
4943 #if defined(TCC_TARGET_ARM) && !defined(TCC_ARM_VFP)
4944 check.d = 1;
4945 if(check.tab[0])
4946 for(i=0;i<size;i++)
4947 ptr[i] = vtop->c.tab[size-1-i];
4948 else
4949 #endif
4950 for(i=0;i<size;i++)
4951 ptr[i] = vtop->c.tab[i];
4952 sym = get_sym_ref(&vtop->type, data_section, offset, size << 2);
4953 vtop->r |= VT_LVAL | VT_SYM;
4954 vtop->sym = sym;
4955 vtop->c.ul = 0;
4957 #ifdef CONFIG_TCC_BCHECK
4958 if (vtop->r & VT_MUSTBOUND)
4959 gbound();
4960 #endif
4962 r = vtop->r & VT_VALMASK;
4963 /* need to reload if:
4964 - constant
4965 - lvalue (need to dereference pointer)
4966 - already a register, but not in the right class */
4967 if (r >= VT_CONST ||
4968 (vtop->r & VT_LVAL) ||
4969 !(reg_classes[r] & rc) ||
4970 ((vtop->type.t & VT_BTYPE) == VT_LLONG &&
4971 !(reg_classes[vtop->r2] & rc))) {
4972 r = get_reg(rc);
4973 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
4974 /* two register type load : expand to two words
4975 temporarily */
4976 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4977 /* load constant */
4978 ll = vtop->c.ull;
4979 vtop->c.ui = ll; /* first word */
4980 load(r, vtop);
4981 vtop->r = r; /* save register value */
4982 vpushi(ll >> 32); /* second word */
4983 } else if (r >= VT_CONST || /* XXX: test to VT_CONST incorrect ? */
4984 (vtop->r & VT_LVAL)) {
4985 /* We do not want to modifier the long long
4986 pointer here, so the safest (and less
4987 efficient) is to save all the other registers
4988 in the stack. XXX: totally inefficient. */
4989 save_regs(1);
4990 /* load from memory */
4991 load(r, vtop);
4992 vdup();
4993 vtop[-1].r = r; /* save register value */
4994 /* increment pointer to get second word */
4995 vtop->type.t = VT_INT;
4996 gaddrof();
4997 vpushi(4);
4998 gen_op('+');
4999 vtop->r |= VT_LVAL;
5000 } else {
5001 /* move registers */
5002 load(r, vtop);
5003 vdup();
5004 vtop[-1].r = r; /* save register value */
5005 vtop->r = vtop[-1].r2;
5007 /* allocate second register */
5008 rc2 = RC_INT;
5009 if (rc == RC_IRET)
5010 rc2 = RC_LRET;
5011 r2 = get_reg(rc2);
5012 load(r2, vtop);
5013 vpop();
5014 /* write second register */
5015 vtop->r2 = r2;
5016 } else if ((vtop->r & VT_LVAL) && !is_float(vtop->type.t)) {
5017 int t1, t;
5018 /* lvalue of scalar type : need to use lvalue type
5019 because of possible cast */
5020 t = vtop->type.t;
5021 t1 = t;
5022 /* compute memory access type */
5023 if (vtop->r & VT_LVAL_BYTE)
5024 t = VT_BYTE;
5025 else if (vtop->r & VT_LVAL_SHORT)
5026 t = VT_SHORT;
5027 if (vtop->r & VT_LVAL_UNSIGNED)
5028 t |= VT_UNSIGNED;
5029 vtop->type.t = t;
5030 load(r, vtop);
5031 /* restore wanted type */
5032 vtop->type.t = t1;
5033 } else {
5034 /* one register type load */
5035 load(r, vtop);
5038 vtop->r = r;
5039 #ifdef TCC_TARGET_C67
5040 /* uses register pairs for doubles */
5041 if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE)
5042 vtop->r2 = r+1;
5043 #endif
5045 return r;
5048 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
5049 void gv2(int rc1, int rc2)
5051 int v;
5053 /* generate more generic register first. But VT_JMP or VT_CMP
5054 values must be generated first in all cases to avoid possible
5055 reload errors */
5056 v = vtop[0].r & VT_VALMASK;
5057 if (v != VT_CMP && (v & ~1) != VT_JMP && rc1 <= rc2) {
5058 vswap();
5059 gv(rc1);
5060 vswap();
5061 gv(rc2);
5062 /* test if reload is needed for first register */
5063 if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
5064 vswap();
5065 gv(rc1);
5066 vswap();
5068 } else {
5069 gv(rc2);
5070 vswap();
5071 gv(rc1);
5072 vswap();
5073 /* test if reload is needed for first register */
5074 if ((vtop[0].r & VT_VALMASK) >= VT_CONST) {
5075 gv(rc2);
5080 /* expand long long on stack in two int registers */
5081 void lexpand(void)
5083 int u;
5085 u = vtop->type.t & VT_UNSIGNED;
5086 gv(RC_INT);
5087 vdup();
5088 vtop[0].r = vtop[-1].r2;
5089 vtop[0].r2 = VT_CONST;
5090 vtop[-1].r2 = VT_CONST;
5091 vtop[0].type.t = VT_INT | u;
5092 vtop[-1].type.t = VT_INT | u;
5095 #ifdef TCC_TARGET_ARM
5096 /* expand long long on stack */
5097 void lexpand_nr(void)
5099 int u,v;
5101 u = vtop->type.t & VT_UNSIGNED;
5102 vdup();
5103 vtop->r2 = VT_CONST;
5104 vtop->type.t = VT_INT | u;
5105 v=vtop[-1].r & (VT_VALMASK | VT_LVAL);
5106 if (v == VT_CONST) {
5107 vtop[-1].c.ui = vtop->c.ull;
5108 vtop->c.ui = vtop->c.ull >> 32;
5109 vtop->r = VT_CONST;
5110 } else if (v == (VT_LVAL|VT_CONST) || v == (VT_LVAL|VT_LOCAL)) {
5111 vtop->c.ui += 4;
5112 vtop->r = vtop[-1].r;
5113 } else if (v > VT_CONST) {
5114 vtop--;
5115 lexpand();
5116 } else
5117 vtop->r = vtop[-1].r2;
5118 vtop[-1].r2 = VT_CONST;
5119 vtop[-1].type.t = VT_INT | u;
5121 #endif
5123 /* build a long long from two ints */
5124 void lbuild(int t)
5126 gv2(RC_INT, RC_INT);
5127 vtop[-1].r2 = vtop[0].r;
5128 vtop[-1].type.t = t;
5129 vpop();
5132 /* rotate n first stack elements to the bottom
5133 I1 ... In -> I2 ... In I1 [top is right]
5135 void vrotb(int n)
5137 int i;
5138 SValue tmp;
5140 tmp = vtop[-n + 1];
5141 for(i=-n+1;i!=0;i++)
5142 vtop[i] = vtop[i+1];
5143 vtop[0] = tmp;
5146 /* rotate n first stack elements to the top
5147 I1 ... In -> In I1 ... I(n-1) [top is right]
5149 void vrott(int n)
5151 int i;
5152 SValue tmp;
5154 tmp = vtop[0];
5155 for(i = 0;i < n - 1; i++)
5156 vtop[-i] = vtop[-i - 1];
5157 vtop[-n + 1] = tmp;
5160 #ifdef TCC_TARGET_ARM
5161 /* like vrott but in other direction
5162 In ... I1 -> I(n-1) ... I1 In [top is right]
5164 void vnrott(int n)
5166 int i;
5167 SValue tmp;
5169 tmp = vtop[-n + 1];
5170 for(i = n - 1; i > 0; i--)
5171 vtop[-i] = vtop[-i + 1];
5172 vtop[0] = tmp;
5174 #endif
5176 /* pop stack value */
5177 void vpop(void)
5179 int v;
5180 v = vtop->r & VT_VALMASK;
5181 #ifdef TCC_TARGET_I386
5182 /* for x86, we need to pop the FP stack */
5183 if (v == TREG_ST0 && !nocode_wanted) {
5184 o(0xd9dd); /* fstp %st(1) */
5185 } else
5186 #endif
5187 if (v == VT_JMP || v == VT_JMPI) {
5188 /* need to put correct jump if && or || without test */
5189 gsym(vtop->c.ul);
5191 vtop--;
5194 /* convert stack entry to register and duplicate its value in another
5195 register */
5196 void gv_dup(void)
5198 int rc, t, r, r1;
5199 SValue sv;
5201 t = vtop->type.t;
5202 if ((t & VT_BTYPE) == VT_LLONG) {
5203 lexpand();
5204 gv_dup();
5205 vswap();
5206 vrotb(3);
5207 gv_dup();
5208 vrotb(4);
5209 /* stack: H L L1 H1 */
5210 lbuild(t);
5211 vrotb(3);
5212 vrotb(3);
5213 vswap();
5214 lbuild(t);
5215 vswap();
5216 } else {
5217 /* duplicate value */
5218 rc = RC_INT;
5219 sv.type.t = VT_INT;
5220 if (is_float(t)) {
5221 rc = RC_FLOAT;
5222 sv.type.t = t;
5224 r = gv(rc);
5225 r1 = get_reg(rc);
5226 sv.r = r;
5227 sv.c.ul = 0;
5228 load(r1, &sv); /* move r to r1 */
5229 vdup();
5230 /* duplicates value */
5231 vtop->r = r1;
5235 /* generate CPU independent (unsigned) long long operations */
5236 void gen_opl(int op)
5238 int t, a, b, op1, c, i;
5239 int func;
5240 SValue tmp;
5242 switch(op) {
5243 case '/':
5244 case TOK_PDIV:
5245 func = TOK___divdi3;
5246 goto gen_func;
5247 case TOK_UDIV:
5248 func = TOK___udivdi3;
5249 goto gen_func;
5250 case '%':
5251 func = TOK___moddi3;
5252 goto gen_func;
5253 case TOK_UMOD:
5254 func = TOK___umoddi3;
5255 gen_func:
5256 /* call generic long long function */
5257 vpush_global_sym(&func_old_type, func);
5258 vrott(3);
5259 gfunc_call(2);
5260 vpushi(0);
5261 vtop->r = REG_IRET;
5262 vtop->r2 = REG_LRET;
5263 break;
5264 case '^':
5265 case '&':
5266 case '|':
5267 case '*':
5268 case '+':
5269 case '-':
5270 t = vtop->type.t;
5271 vswap();
5272 lexpand();
5273 vrotb(3);
5274 lexpand();
5275 /* stack: L1 H1 L2 H2 */
5276 tmp = vtop[0];
5277 vtop[0] = vtop[-3];
5278 vtop[-3] = tmp;
5279 tmp = vtop[-2];
5280 vtop[-2] = vtop[-3];
5281 vtop[-3] = tmp;
5282 vswap();
5283 /* stack: H1 H2 L1 L2 */
5284 if (op == '*') {
5285 vpushv(vtop - 1);
5286 vpushv(vtop - 1);
5287 gen_op(TOK_UMULL);
5288 lexpand();
5289 /* stack: H1 H2 L1 L2 ML MH */
5290 for(i=0;i<4;i++)
5291 vrotb(6);
5292 /* stack: ML MH H1 H2 L1 L2 */
5293 tmp = vtop[0];
5294 vtop[0] = vtop[-2];
5295 vtop[-2] = tmp;
5296 /* stack: ML MH H1 L2 H2 L1 */
5297 gen_op('*');
5298 vrotb(3);
5299 vrotb(3);
5300 gen_op('*');
5301 /* stack: ML MH M1 M2 */
5302 gen_op('+');
5303 gen_op('+');
5304 } else if (op == '+' || op == '-') {
5305 /* XXX: add non carry method too (for MIPS or alpha) */
5306 if (op == '+')
5307 op1 = TOK_ADDC1;
5308 else
5309 op1 = TOK_SUBC1;
5310 gen_op(op1);
5311 /* stack: H1 H2 (L1 op L2) */
5312 vrotb(3);
5313 vrotb(3);
5314 gen_op(op1 + 1); /* TOK_xxxC2 */
5315 } else {
5316 gen_op(op);
5317 /* stack: H1 H2 (L1 op L2) */
5318 vrotb(3);
5319 vrotb(3);
5320 /* stack: (L1 op L2) H1 H2 */
5321 gen_op(op);
5322 /* stack: (L1 op L2) (H1 op H2) */
5324 /* stack: L H */
5325 lbuild(t);
5326 break;
5327 case TOK_SAR:
5328 case TOK_SHR:
5329 case TOK_SHL:
5330 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
5331 t = vtop[-1].type.t;
5332 vswap();
5333 lexpand();
5334 vrotb(3);
5335 /* stack: L H shift */
5336 c = (int)vtop->c.i;
5337 /* constant: simpler */
5338 /* NOTE: all comments are for SHL. the other cases are
5339 done by swaping words */
5340 vpop();
5341 if (op != TOK_SHL)
5342 vswap();
5343 if (c >= 32) {
5344 /* stack: L H */
5345 vpop();
5346 if (c > 32) {
5347 vpushi(c - 32);
5348 gen_op(op);
5350 if (op != TOK_SAR) {
5351 vpushi(0);
5352 } else {
5353 gv_dup();
5354 vpushi(31);
5355 gen_op(TOK_SAR);
5357 vswap();
5358 } else {
5359 vswap();
5360 gv_dup();
5361 /* stack: H L L */
5362 vpushi(c);
5363 gen_op(op);
5364 vswap();
5365 vpushi(32 - c);
5366 if (op == TOK_SHL)
5367 gen_op(TOK_SHR);
5368 else
5369 gen_op(TOK_SHL);
5370 vrotb(3);
5371 /* stack: L L H */
5372 vpushi(c);
5373 if (op == TOK_SHL)
5374 gen_op(TOK_SHL);
5375 else
5376 gen_op(TOK_SHR);
5377 gen_op('|');
5379 if (op != TOK_SHL)
5380 vswap();
5381 lbuild(t);
5382 } else {
5383 /* XXX: should provide a faster fallback on x86 ? */
5384 switch(op) {
5385 case TOK_SAR:
5386 func = TOK___sardi3;
5387 goto gen_func;
5388 case TOK_SHR:
5389 func = TOK___shrdi3;
5390 goto gen_func;
5391 case TOK_SHL:
5392 func = TOK___shldi3;
5393 goto gen_func;
5396 break;
5397 default:
5398 /* compare operations */
5399 t = vtop->type.t;
5400 vswap();
5401 lexpand();
5402 vrotb(3);
5403 lexpand();
5404 /* stack: L1 H1 L2 H2 */
5405 tmp = vtop[-1];
5406 vtop[-1] = vtop[-2];
5407 vtop[-2] = tmp;
5408 /* stack: L1 L2 H1 H2 */
5409 /* compare high */
5410 op1 = op;
5411 /* when values are equal, we need to compare low words. since
5412 the jump is inverted, we invert the test too. */
5413 if (op1 == TOK_LT)
5414 op1 = TOK_LE;
5415 else if (op1 == TOK_GT)
5416 op1 = TOK_GE;
5417 else if (op1 == TOK_ULT)
5418 op1 = TOK_ULE;
5419 else if (op1 == TOK_UGT)
5420 op1 = TOK_UGE;
5421 a = 0;
5422 b = 0;
5423 gen_op(op1);
5424 if (op1 != TOK_NE) {
5425 a = gtst(1, 0);
5427 if (op != TOK_EQ) {
5428 /* generate non equal test */
5429 /* XXX: NOT PORTABLE yet */
5430 if (a == 0) {
5431 b = gtst(0, 0);
5432 } else {
5433 #if defined(TCC_TARGET_I386)
5434 b = psym(0x850f, 0);
5435 #elif defined(TCC_TARGET_ARM)
5436 b = ind;
5437 o(0x1A000000 | encbranch(ind, 0, 1));
5438 #elif defined(TCC_TARGET_C67)
5439 error("not implemented");
5440 #else
5441 #error not supported
5442 #endif
5445 /* compare low. Always unsigned */
5446 op1 = op;
5447 if (op1 == TOK_LT)
5448 op1 = TOK_ULT;
5449 else if (op1 == TOK_LE)
5450 op1 = TOK_ULE;
5451 else if (op1 == TOK_GT)
5452 op1 = TOK_UGT;
5453 else if (op1 == TOK_GE)
5454 op1 = TOK_UGE;
5455 gen_op(op1);
5456 a = gtst(1, a);
5457 gsym(b);
5458 vseti(VT_JMPI, a);
5459 break;
5463 /* handle integer constant optimizations and various machine
5464 independent opt */
5465 void gen_opic(int op)
5467 int c1, c2, t1, t2, n, c;
5468 SValue *v1, *v2;
5469 long long l1, l2, l;
5470 typedef unsigned long long U;
5472 v1 = vtop - 1;
5473 v2 = vtop;
5474 t1 = v1->type.t & VT_BTYPE;
5475 t2 = v2->type.t & VT_BTYPE;
5476 l1 = (t1 == VT_LLONG) ? v1->c.ll : v1->c.i;
5477 l2 = (t2 == VT_LLONG) ? v2->c.ll : v2->c.i;
5479 /* currently, we cannot do computations with forward symbols */
5480 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5481 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5482 if (c1 && c2) {
5483 switch(op) {
5484 case '+': l1 += l2; break;
5485 case '-': l1 -= l2; break;
5486 case '&': l1 &= l2; break;
5487 case '^': l1 ^= l2; break;
5488 case '|': l1 |= l2; break;
5489 case '*': l1 *= l2; break;
5491 case TOK_PDIV:
5492 case '/':
5493 case '%':
5494 case TOK_UDIV:
5495 case TOK_UMOD:
5496 /* if division by zero, generate explicit division */
5497 if (l2 == 0) {
5498 if (const_wanted)
5499 error("division by zero in constant");
5500 goto general_case;
5502 switch(op) {
5503 default: l1 /= l2; break;
5504 case '%': l1 %= l2; break;
5505 case TOK_UDIV: l1 = (U)l1 / l2; break;
5506 case TOK_UMOD: l1 = (U)l1 % l2; break;
5508 break;
5509 case TOK_SHL: l1 <<= l2; break;
5510 case TOK_SHR: l1 = (U)l1 >> l2; break;
5511 case TOK_SAR: l1 >>= l2; break;
5512 /* tests */
5513 case TOK_ULT: l1 = (U)l1 < (U)l2; break;
5514 case TOK_UGE: l1 = (U)l1 >= (U)l2; break;
5515 case TOK_EQ: l1 = l1 == l2; break;
5516 case TOK_NE: l1 = l1 != l2; break;
5517 case TOK_ULE: l1 = (U)l1 <= (U)l2; break;
5518 case TOK_UGT: l1 = (U)l1 > (U)l2; break;
5519 case TOK_LT: l1 = l1 < l2; break;
5520 case TOK_GE: l1 = l1 >= l2; break;
5521 case TOK_LE: l1 = l1 <= l2; break;
5522 case TOK_GT: l1 = l1 > l2; break;
5523 /* logical */
5524 case TOK_LAND: l1 = l1 && l2; break;
5525 case TOK_LOR: l1 = l1 || l2; break;
5526 default:
5527 goto general_case;
5529 v1->c.ll = l1;
5530 vtop--;
5531 } else {
5532 /* if commutative ops, put c2 as constant */
5533 if (c1 && (op == '+' || op == '&' || op == '^' ||
5534 op == '|' || op == '*')) {
5535 vswap();
5536 c = c1, c1 = c2, c2 = c;
5537 l = l1, l1 = l2, l2 = l;
5539 /* Filter out NOP operations like x*1, x-0, x&-1... */
5540 if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
5541 op == TOK_PDIV) &&
5542 l2 == 1) ||
5543 ((op == '+' || op == '-' || op == '|' || op == '^' ||
5544 op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
5545 l2 == 0) ||
5546 (op == '&' &&
5547 l2 == -1))) {
5548 /* nothing to do */
5549 vtop--;
5550 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
5551 /* try to use shifts instead of muls or divs */
5552 if (l2 > 0 && (l2 & (l2 - 1)) == 0) {
5553 n = -1;
5554 while (l2) {
5555 l2 >>= 1;
5556 n++;
5558 vtop->c.ll = n;
5559 if (op == '*')
5560 op = TOK_SHL;
5561 else if (op == TOK_PDIV)
5562 op = TOK_SAR;
5563 else
5564 op = TOK_SHR;
5566 goto general_case;
5567 } else if (c2 && (op == '+' || op == '-') &&
5568 (vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) ==
5569 (VT_CONST | VT_SYM)) {
5570 /* symbol + constant case */
5571 if (op == '-')
5572 l2 = -l2;
5573 vtop--;
5574 vtop->c.ll += l2;
5575 } else {
5576 general_case:
5577 if (!nocode_wanted) {
5578 /* call low level op generator */
5579 if (t1 == VT_LLONG || t2 == VT_LLONG)
5580 gen_opl(op);
5581 else
5582 gen_opi(op);
5583 } else {
5584 vtop--;
5590 /* generate a floating point operation with constant propagation */
5591 void gen_opif(int op)
5593 int c1, c2;
5594 SValue *v1, *v2;
5595 long double f1, f2;
5597 v1 = vtop - 1;
5598 v2 = vtop;
5599 /* currently, we cannot do computations with forward symbols */
5600 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5601 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5602 if (c1 && c2) {
5603 if (v1->type.t == VT_FLOAT) {
5604 f1 = v1->c.f;
5605 f2 = v2->c.f;
5606 } else if (v1->type.t == VT_DOUBLE) {
5607 f1 = v1->c.d;
5608 f2 = v2->c.d;
5609 } else {
5610 f1 = v1->c.ld;
5611 f2 = v2->c.ld;
5614 /* NOTE: we only do constant propagation if finite number (not
5615 NaN or infinity) (ANSI spec) */
5616 if (!ieee_finite(f1) || !ieee_finite(f2))
5617 goto general_case;
5619 switch(op) {
5620 case '+': f1 += f2; break;
5621 case '-': f1 -= f2; break;
5622 case '*': f1 *= f2; break;
5623 case '/':
5624 if (f2 == 0.0) {
5625 if (const_wanted)
5626 error("division by zero in constant");
5627 goto general_case;
5629 f1 /= f2;
5630 break;
5631 /* XXX: also handles tests ? */
5632 default:
5633 goto general_case;
5635 /* XXX: overflow test ? */
5636 if (v1->type.t == VT_FLOAT) {
5637 v1->c.f = f1;
5638 } else if (v1->type.t == VT_DOUBLE) {
5639 v1->c.d = f1;
5640 } else {
5641 v1->c.ld = f1;
5643 vtop--;
5644 } else {
5645 general_case:
5646 if (!nocode_wanted) {
5647 gen_opf(op);
5648 } else {
5649 vtop--;
5654 static int pointed_size(CType *type)
5656 int align;
5657 return type_size(pointed_type(type), &align);
5660 static inline int is_null_pointer(SValue *p)
5662 if ((p->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
5663 return 0;
5664 return ((p->type.t & VT_BTYPE) == VT_INT && p->c.i == 0) ||
5665 ((p->type.t & VT_BTYPE) == VT_LLONG && p->c.ll == 0);
5668 static inline int is_integer_btype(int bt)
5670 return (bt == VT_BYTE || bt == VT_SHORT ||
5671 bt == VT_INT || bt == VT_LLONG);
5674 /* check types for comparison or substraction of pointers */
5675 static void check_comparison_pointer_types(SValue *p1, SValue *p2, int op)
5677 CType *type1, *type2, tmp_type1, tmp_type2;
5678 int bt1, bt2;
5680 /* null pointers are accepted for all comparisons as gcc */
5681 if (is_null_pointer(p1) || is_null_pointer(p2))
5682 return;
5683 type1 = &p1->type;
5684 type2 = &p2->type;
5685 bt1 = type1->t & VT_BTYPE;
5686 bt2 = type2->t & VT_BTYPE;
5687 /* accept comparison between pointer and integer with a warning */
5688 if ((is_integer_btype(bt1) || is_integer_btype(bt2)) && op != '-') {
5689 if (op != TOK_LOR && op != TOK_LAND )
5690 warning("comparison between pointer and integer");
5691 return;
5694 /* both must be pointers or implicit function pointers */
5695 if (bt1 == VT_PTR) {
5696 type1 = pointed_type(type1);
5697 } else if (bt1 != VT_FUNC)
5698 goto invalid_operands;
5700 if (bt2 == VT_PTR) {
5701 type2 = pointed_type(type2);
5702 } else if (bt2 != VT_FUNC) {
5703 invalid_operands:
5704 error("invalid operands to binary %s", get_tok_str(op, NULL));
5706 if ((type1->t & VT_BTYPE) == VT_VOID ||
5707 (type2->t & VT_BTYPE) == VT_VOID)
5708 return;
5709 tmp_type1 = *type1;
5710 tmp_type2 = *type2;
5711 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5712 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5713 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
5714 /* gcc-like error if '-' is used */
5715 if (op == '-')
5716 goto invalid_operands;
5717 else
5718 warning("comparison of distinct pointer types lacks a cast");
5722 /* generic gen_op: handles types problems */
5723 void gen_op(int op)
5725 int u, t1, t2, bt1, bt2, t;
5726 CType type1;
5728 t1 = vtop[-1].type.t;
5729 t2 = vtop[0].type.t;
5730 bt1 = t1 & VT_BTYPE;
5731 bt2 = t2 & VT_BTYPE;
5733 if (bt1 == VT_PTR || bt2 == VT_PTR) {
5734 /* at least one operand is a pointer */
5735 /* relationnal op: must be both pointers */
5736 if (op >= TOK_ULT && op <= TOK_LOR) {
5737 check_comparison_pointer_types(vtop - 1, vtop, op);
5738 /* pointers are handled are unsigned */
5739 t = VT_INT | VT_UNSIGNED;
5740 goto std_op;
5742 /* if both pointers, then it must be the '-' op */
5743 if (bt1 == VT_PTR && bt2 == VT_PTR) {
5744 if (op != '-')
5745 error("cannot use pointers here");
5746 check_comparison_pointer_types(vtop - 1, vtop, op);
5747 /* XXX: check that types are compatible */
5748 u = pointed_size(&vtop[-1].type);
5749 gen_opic(op);
5750 /* set to integer type */
5751 vtop->type.t = VT_INT;
5752 vpushi(u);
5753 gen_op(TOK_PDIV);
5754 } else {
5755 /* exactly one pointer : must be '+' or '-'. */
5756 if (op != '-' && op != '+')
5757 error("cannot use pointers here");
5758 /* Put pointer as first operand */
5759 if (bt2 == VT_PTR) {
5760 vswap();
5761 swap(&t1, &t2);
5763 type1 = vtop[-1].type;
5764 /* XXX: cast to int ? (long long case) */
5765 vpushi(pointed_size(&vtop[-1].type));
5766 gen_op('*');
5767 #ifdef CONFIG_TCC_BCHECK
5768 /* if evaluating constant expression, no code should be
5769 generated, so no bound check */
5770 if (do_bounds_check && !const_wanted) {
5771 /* if bounded pointers, we generate a special code to
5772 test bounds */
5773 if (op == '-') {
5774 vpushi(0);
5775 vswap();
5776 gen_op('-');
5778 gen_bounded_ptr_add();
5779 } else
5780 #endif
5782 gen_opic(op);
5784 /* put again type if gen_opic() swaped operands */
5785 vtop->type = type1;
5787 } else if (is_float(bt1) || is_float(bt2)) {
5788 /* compute bigger type and do implicit casts */
5789 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
5790 t = VT_LDOUBLE;
5791 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
5792 t = VT_DOUBLE;
5793 } else {
5794 t = VT_FLOAT;
5796 /* floats can only be used for a few operations */
5797 if (op != '+' && op != '-' && op != '*' && op != '/' &&
5798 (op < TOK_ULT || op > TOK_GT))
5799 error("invalid operands for binary operation");
5800 goto std_op;
5801 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
5802 /* cast to biggest op */
5803 t = VT_LLONG;
5804 /* convert to unsigned if it does not fit in a long long */
5805 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
5806 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
5807 t |= VT_UNSIGNED;
5808 goto std_op;
5809 } else {
5810 /* integer operations */
5811 t = VT_INT;
5812 /* convert to unsigned if it does not fit in an integer */
5813 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
5814 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
5815 t |= VT_UNSIGNED;
5816 std_op:
5817 /* XXX: currently, some unsigned operations are explicit, so
5818 we modify them here */
5819 if (t & VT_UNSIGNED) {
5820 if (op == TOK_SAR)
5821 op = TOK_SHR;
5822 else if (op == '/')
5823 op = TOK_UDIV;
5824 else if (op == '%')
5825 op = TOK_UMOD;
5826 else if (op == TOK_LT)
5827 op = TOK_ULT;
5828 else if (op == TOK_GT)
5829 op = TOK_UGT;
5830 else if (op == TOK_LE)
5831 op = TOK_ULE;
5832 else if (op == TOK_GE)
5833 op = TOK_UGE;
5835 vswap();
5836 type1.t = t;
5837 gen_cast(&type1);
5838 vswap();
5839 /* special case for shifts and long long: we keep the shift as
5840 an integer */
5841 if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL)
5842 type1.t = VT_INT;
5843 gen_cast(&type1);
5844 if (is_float(t))
5845 gen_opif(op);
5846 else
5847 gen_opic(op);
5848 if (op >= TOK_ULT && op <= TOK_GT) {
5849 /* relationnal op: the result is an int */
5850 vtop->type.t = VT_INT;
5851 } else {
5852 vtop->type.t = t;
5857 /* generic itof for unsigned long long case */
5858 void gen_cvt_itof1(int t)
5860 if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
5861 (VT_LLONG | VT_UNSIGNED)) {
5863 if (t == VT_FLOAT)
5864 vpush_global_sym(&func_old_type, TOK___ulltof);
5865 else if (t == VT_DOUBLE)
5866 vpush_global_sym(&func_old_type, TOK___ulltod);
5867 else
5868 vpush_global_sym(&func_old_type, TOK___ulltold);
5869 vrott(2);
5870 gfunc_call(1);
5871 vpushi(0);
5872 vtop->r = REG_FRET;
5873 } else {
5874 gen_cvt_itof(t);
5878 /* generic ftoi for unsigned long long case */
5879 void gen_cvt_ftoi1(int t)
5881 int st;
5883 if (t == (VT_LLONG | VT_UNSIGNED)) {
5884 /* not handled natively */
5885 st = vtop->type.t & VT_BTYPE;
5886 if (st == VT_FLOAT)
5887 vpush_global_sym(&func_old_type, TOK___fixunssfdi);
5888 else if (st == VT_DOUBLE)
5889 vpush_global_sym(&func_old_type, TOK___fixunsdfdi);
5890 else
5891 vpush_global_sym(&func_old_type, TOK___fixunsxfdi);
5892 vrott(2);
5893 gfunc_call(1);
5894 vpushi(0);
5895 vtop->r = REG_IRET;
5896 vtop->r2 = REG_LRET;
5897 } else {
5898 gen_cvt_ftoi(t);
5902 /* force char or short cast */
5903 void force_charshort_cast(int t)
5905 int bits, dbt;
5906 dbt = t & VT_BTYPE;
5907 /* XXX: add optimization if lvalue : just change type and offset */
5908 if (dbt == VT_BYTE)
5909 bits = 8;
5910 else
5911 bits = 16;
5912 if (t & VT_UNSIGNED) {
5913 vpushi((1 << bits) - 1);
5914 gen_op('&');
5915 } else {
5916 bits = 32 - bits;
5917 vpushi(bits);
5918 gen_op(TOK_SHL);
5919 /* result must be signed or the SAR is converted to an SHL
5920 This was not the case when "t" was a signed short
5921 and the last value on the stack was an unsigned int */
5922 vtop->type.t &= ~VT_UNSIGNED;
5923 vpushi(bits);
5924 gen_op(TOK_SAR);
5928 /* cast 'vtop' to 'type'. Casting to bitfields is forbidden. */
5929 static void gen_cast(CType *type)
5931 int sbt, dbt, sf, df, c;
5933 /* special delayed cast for char/short */
5934 /* XXX: in some cases (multiple cascaded casts), it may still
5935 be incorrect */
5936 if (vtop->r & VT_MUSTCAST) {
5937 vtop->r &= ~VT_MUSTCAST;
5938 force_charshort_cast(vtop->type.t);
5941 /* bitfields first get cast to ints */
5942 if (vtop->type.t & VT_BITFIELD) {
5943 gv(RC_INT);
5946 dbt = type->t & (VT_BTYPE | VT_UNSIGNED);
5947 sbt = vtop->type.t & (VT_BTYPE | VT_UNSIGNED);
5949 if (sbt != dbt && !nocode_wanted) {
5950 sf = is_float(sbt);
5951 df = is_float(dbt);
5952 c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5953 if (sf && df) {
5954 /* convert from fp to fp */
5955 if (c) {
5956 /* constant case: we can do it now */
5957 /* XXX: in ISOC, cannot do it if error in convert */
5958 if (dbt == VT_FLOAT && sbt == VT_DOUBLE)
5959 vtop->c.f = (float)vtop->c.d;
5960 else if (dbt == VT_FLOAT && sbt == VT_LDOUBLE)
5961 vtop->c.f = (float)vtop->c.ld;
5962 else if (dbt == VT_DOUBLE && sbt == VT_FLOAT)
5963 vtop->c.d = (double)vtop->c.f;
5964 else if (dbt == VT_DOUBLE && sbt == VT_LDOUBLE)
5965 vtop->c.d = (double)vtop->c.ld;
5966 else if (dbt == VT_LDOUBLE && sbt == VT_FLOAT)
5967 vtop->c.ld = (long double)vtop->c.f;
5968 else if (dbt == VT_LDOUBLE && sbt == VT_DOUBLE)
5969 vtop->c.ld = (long double)vtop->c.d;
5970 } else {
5971 /* non constant case: generate code */
5972 gen_cvt_ftof(dbt);
5974 } else if (df) {
5975 /* convert int to fp */
5976 if (c) {
5977 switch(sbt) {
5978 case VT_LLONG | VT_UNSIGNED:
5979 case VT_LLONG:
5980 /* XXX: add const cases for long long */
5981 goto do_itof;
5982 case VT_INT | VT_UNSIGNED:
5983 switch(dbt) {
5984 case VT_FLOAT: vtop->c.f = (float)vtop->c.ui; break;
5985 case VT_DOUBLE: vtop->c.d = (double)vtop->c.ui; break;
5986 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.ui; break;
5988 break;
5989 default:
5990 switch(dbt) {
5991 case VT_FLOAT: vtop->c.f = (float)vtop->c.i; break;
5992 case VT_DOUBLE: vtop->c.d = (double)vtop->c.i; break;
5993 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.i; break;
5995 break;
5997 } else {
5998 do_itof:
5999 #if !defined(TCC_TARGET_ARM)
6000 gen_cvt_itof1(dbt);
6001 #else
6002 gen_cvt_itof(dbt);
6003 #endif
6005 } else if (sf) {
6006 /* convert fp to int */
6007 if (dbt == VT_BOOL) {
6008 vpushi(0);
6009 gen_op(TOK_NE);
6010 } else {
6011 /* we handle char/short/etc... with generic code */
6012 if (dbt != (VT_INT | VT_UNSIGNED) &&
6013 dbt != (VT_LLONG | VT_UNSIGNED) &&
6014 dbt != VT_LLONG)
6015 dbt = VT_INT;
6016 if (c) {
6017 switch(dbt) {
6018 case VT_LLONG | VT_UNSIGNED:
6019 case VT_LLONG:
6020 /* XXX: add const cases for long long */
6021 goto do_ftoi;
6022 case VT_INT | VT_UNSIGNED:
6023 switch(sbt) {
6024 case VT_FLOAT: vtop->c.ui = (unsigned int)vtop->c.d; break;
6025 case VT_DOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
6026 case VT_LDOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
6028 break;
6029 default:
6030 /* int case */
6031 switch(sbt) {
6032 case VT_FLOAT: vtop->c.i = (int)vtop->c.d; break;
6033 case VT_DOUBLE: vtop->c.i = (int)vtop->c.d; break;
6034 case VT_LDOUBLE: vtop->c.i = (int)vtop->c.d; break;
6036 break;
6038 } else {
6039 do_ftoi:
6040 gen_cvt_ftoi1(dbt);
6042 if (dbt == VT_INT && (type->t & (VT_BTYPE | VT_UNSIGNED)) != dbt) {
6043 /* additional cast for char/short... */
6044 vtop->type.t = dbt;
6045 gen_cast(type);
6048 } else if ((dbt & VT_BTYPE) == VT_LLONG) {
6049 if ((sbt & VT_BTYPE) != VT_LLONG) {
6050 /* scalar to long long */
6051 if (c) {
6052 if (sbt == (VT_INT | VT_UNSIGNED))
6053 vtop->c.ll = vtop->c.ui;
6054 else
6055 vtop->c.ll = vtop->c.i;
6056 } else {
6057 /* machine independent conversion */
6058 gv(RC_INT);
6059 /* generate high word */
6060 if (sbt == (VT_INT | VT_UNSIGNED)) {
6061 vpushi(0);
6062 gv(RC_INT);
6063 } else {
6064 gv_dup();
6065 vpushi(31);
6066 gen_op(TOK_SAR);
6068 /* patch second register */
6069 vtop[-1].r2 = vtop->r;
6070 vpop();
6073 } else if (dbt == VT_BOOL) {
6074 /* scalar to bool */
6075 vpushi(0);
6076 gen_op(TOK_NE);
6077 } else if ((dbt & VT_BTYPE) == VT_BYTE ||
6078 (dbt & VT_BTYPE) == VT_SHORT) {
6079 if (sbt == VT_PTR) {
6080 vtop->type.t = VT_INT;
6081 warning("nonportable conversion from pointer to char/short");
6083 force_charshort_cast(dbt);
6084 } else if ((dbt & VT_BTYPE) == VT_INT) {
6085 /* scalar to int */
6086 if (sbt == VT_LLONG) {
6087 /* from long long: just take low order word */
6088 lexpand();
6089 vpop();
6091 /* if lvalue and single word type, nothing to do because
6092 the lvalue already contains the real type size (see
6093 VT_LVAL_xxx constants) */
6095 } else if ((dbt & VT_BTYPE) == VT_PTR && !(vtop->r & VT_LVAL)) {
6096 /* if we are casting between pointer types,
6097 we must update the VT_LVAL_xxx size */
6098 vtop->r = (vtop->r & ~VT_LVAL_TYPE)
6099 | (lvalue_type(type->ref->type.t) & VT_LVAL_TYPE);
6101 vtop->type = *type;
6104 /* return type size. Put alignment at 'a' */
6105 static int type_size(CType *type, int *a)
6107 Sym *s;
6108 int bt;
6110 bt = type->t & VT_BTYPE;
6111 if (bt == VT_STRUCT) {
6112 /* struct/union */
6113 s = type->ref;
6114 *a = s->r;
6115 return s->c;
6116 } else if (bt == VT_PTR) {
6117 if (type->t & VT_ARRAY) {
6118 s = type->ref;
6119 return type_size(&s->type, a) * s->c;
6120 } else {
6121 *a = PTR_SIZE;
6122 return PTR_SIZE;
6124 } else if (bt == VT_LDOUBLE) {
6125 *a = LDOUBLE_ALIGN;
6126 return LDOUBLE_SIZE;
6127 } else if (bt == VT_DOUBLE || bt == VT_LLONG) {
6128 #ifdef TCC_TARGET_I386
6129 *a = 4;
6130 #elif defined(TCC_TARGET_ARM)
6131 #ifdef TCC_ARM_EABI
6132 *a = 8;
6133 #else
6134 *a = 4;
6135 #endif
6136 #else
6137 *a = 8;
6138 #endif
6139 return 8;
6140 } else if (bt == VT_INT || bt == VT_ENUM || bt == VT_FLOAT) {
6141 *a = 4;
6142 return 4;
6143 } else if (bt == VT_SHORT) {
6144 *a = 2;
6145 return 2;
6146 } else {
6147 /* char, void, function, _Bool */
6148 *a = 1;
6149 return 1;
6153 /* return the pointed type of t */
6154 static inline CType *pointed_type(CType *type)
6156 return &type->ref->type;
6159 /* modify type so that its it is a pointer to type. */
6160 static void mk_pointer(CType *type)
6162 Sym *s;
6163 s = sym_push(SYM_FIELD, type, 0, -1);
6164 type->t = VT_PTR | (type->t & ~VT_TYPE);
6165 type->ref = s;
6168 /* compare function types. OLD functions match any new functions */
6169 static int is_compatible_func(CType *type1, CType *type2)
6171 Sym *s1, *s2;
6173 s1 = type1->ref;
6174 s2 = type2->ref;
6175 if (!is_compatible_types(&s1->type, &s2->type))
6176 return 0;
6177 /* check func_call */
6178 if (FUNC_CALL(s1->r) != FUNC_CALL(s2->r))
6179 return 0;
6180 /* XXX: not complete */
6181 if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
6182 return 1;
6183 if (s1->c != s2->c)
6184 return 0;
6185 while (s1 != NULL) {
6186 if (s2 == NULL)
6187 return 0;
6188 if (!is_compatible_parameter_types(&s1->type, &s2->type))
6189 return 0;
6190 s1 = s1->next;
6191 s2 = s2->next;
6193 if (s2)
6194 return 0;
6195 return 1;
6198 /* return true if type1 and type2 are the same. If unqualified is
6199 true, qualifiers on the types are ignored.
6201 - enums are not checked as gcc __builtin_types_compatible_p ()
6203 static int compare_types(CType *type1, CType *type2, int unqualified)
6205 int bt1, t1, t2;
6207 t1 = type1->t & VT_TYPE;
6208 t2 = type2->t & VT_TYPE;
6209 if (unqualified) {
6210 /* strip qualifiers before comparing */
6211 t1 &= ~(VT_CONSTANT | VT_VOLATILE);
6212 t2 &= ~(VT_CONSTANT | VT_VOLATILE);
6214 /* XXX: bitfields ? */
6215 if (t1 != t2)
6216 return 0;
6217 /* test more complicated cases */
6218 bt1 = t1 & VT_BTYPE;
6219 if (bt1 == VT_PTR) {
6220 type1 = pointed_type(type1);
6221 type2 = pointed_type(type2);
6222 return is_compatible_types(type1, type2);
6223 } else if (bt1 == VT_STRUCT) {
6224 return (type1->ref == type2->ref);
6225 } else if (bt1 == VT_FUNC) {
6226 return is_compatible_func(type1, type2);
6227 } else {
6228 return 1;
6232 /* return true if type1 and type2 are exactly the same (including
6233 qualifiers).
6235 static int is_compatible_types(CType *type1, CType *type2)
6237 return compare_types(type1,type2,0);
6240 /* return true if type1 and type2 are the same (ignoring qualifiers).
6242 static int is_compatible_parameter_types(CType *type1, CType *type2)
6244 return compare_types(type1,type2,1);
6247 /* print a type. If 'varstr' is not NULL, then the variable is also
6248 printed in the type */
6249 /* XXX: union */
6250 /* XXX: add array and function pointers */
6251 void type_to_str(char *buf, int buf_size,
6252 CType *type, const char *varstr)
6254 int bt, v, t;
6255 Sym *s, *sa;
6256 char buf1[256];
6257 const char *tstr;
6259 t = type->t & VT_TYPE;
6260 bt = t & VT_BTYPE;
6261 buf[0] = '\0';
6262 if (t & VT_CONSTANT)
6263 pstrcat(buf, buf_size, "const ");
6264 if (t & VT_VOLATILE)
6265 pstrcat(buf, buf_size, "volatile ");
6266 if (t & VT_UNSIGNED)
6267 pstrcat(buf, buf_size, "unsigned ");
6268 switch(bt) {
6269 case VT_VOID:
6270 tstr = "void";
6271 goto add_tstr;
6272 case VT_BOOL:
6273 tstr = "_Bool";
6274 goto add_tstr;
6275 case VT_BYTE:
6276 tstr = "char";
6277 goto add_tstr;
6278 case VT_SHORT:
6279 tstr = "short";
6280 goto add_tstr;
6281 case VT_INT:
6282 tstr = "int";
6283 goto add_tstr;
6284 case VT_LONG:
6285 tstr = "long";
6286 goto add_tstr;
6287 case VT_LLONG:
6288 tstr = "long long";
6289 goto add_tstr;
6290 case VT_FLOAT:
6291 tstr = "float";
6292 goto add_tstr;
6293 case VT_DOUBLE:
6294 tstr = "double";
6295 goto add_tstr;
6296 case VT_LDOUBLE:
6297 tstr = "long double";
6298 add_tstr:
6299 pstrcat(buf, buf_size, tstr);
6300 break;
6301 case VT_ENUM:
6302 case VT_STRUCT:
6303 if (bt == VT_STRUCT)
6304 tstr = "struct ";
6305 else
6306 tstr = "enum ";
6307 pstrcat(buf, buf_size, tstr);
6308 v = type->ref->v & ~SYM_STRUCT;
6309 if (v >= SYM_FIRST_ANOM)
6310 pstrcat(buf, buf_size, "<anonymous>");
6311 else
6312 pstrcat(buf, buf_size, get_tok_str(v, NULL));
6313 break;
6314 case VT_FUNC:
6315 s = type->ref;
6316 type_to_str(buf, buf_size, &s->type, varstr);
6317 pstrcat(buf, buf_size, "(");
6318 sa = s->next;
6319 while (sa != NULL) {
6320 type_to_str(buf1, sizeof(buf1), &sa->type, NULL);
6321 pstrcat(buf, buf_size, buf1);
6322 sa = sa->next;
6323 if (sa)
6324 pstrcat(buf, buf_size, ", ");
6326 pstrcat(buf, buf_size, ")");
6327 goto no_var;
6328 case VT_PTR:
6329 s = type->ref;
6330 pstrcpy(buf1, sizeof(buf1), "*");
6331 if (varstr)
6332 pstrcat(buf1, sizeof(buf1), varstr);
6333 type_to_str(buf, buf_size, &s->type, buf1);
6334 goto no_var;
6336 if (varstr) {
6337 pstrcat(buf, buf_size, " ");
6338 pstrcat(buf, buf_size, varstr);
6340 no_var: ;
6343 /* verify type compatibility to store vtop in 'dt' type, and generate
6344 casts if needed. */
6345 static void gen_assign_cast(CType *dt)
6347 CType *st, *type1, *type2, tmp_type1, tmp_type2;
6348 char buf1[256], buf2[256];
6349 int dbt, sbt;
6351 st = &vtop->type; /* source type */
6352 dbt = dt->t & VT_BTYPE;
6353 sbt = st->t & VT_BTYPE;
6354 if (dt->t & VT_CONSTANT)
6355 warning("assignment of read-only location");
6356 switch(dbt) {
6357 case VT_PTR:
6358 /* special cases for pointers */
6359 /* '0' can also be a pointer */
6360 if (is_null_pointer(vtop))
6361 goto type_ok;
6362 /* accept implicit pointer to integer cast with warning */
6363 if (is_integer_btype(sbt)) {
6364 warning("assignment makes pointer from integer without a cast");
6365 goto type_ok;
6367 type1 = pointed_type(dt);
6368 /* a function is implicitely a function pointer */
6369 if (sbt == VT_FUNC) {
6370 if ((type1->t & VT_BTYPE) != VT_VOID &&
6371 !is_compatible_types(pointed_type(dt), st))
6372 goto error;
6373 else
6374 goto type_ok;
6376 if (sbt != VT_PTR)
6377 goto error;
6378 type2 = pointed_type(st);
6379 if ((type1->t & VT_BTYPE) == VT_VOID ||
6380 (type2->t & VT_BTYPE) == VT_VOID) {
6381 /* void * can match anything */
6382 } else {
6383 /* exact type match, except for unsigned */
6384 tmp_type1 = *type1;
6385 tmp_type2 = *type2;
6386 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
6387 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
6388 if (!is_compatible_types(&tmp_type1, &tmp_type2))
6389 warning("assignment from incompatible pointer type");
6391 /* check const and volatile */
6392 if ((!(type1->t & VT_CONSTANT) && (type2->t & VT_CONSTANT)) ||
6393 (!(type1->t & VT_VOLATILE) && (type2->t & VT_VOLATILE)))
6394 warning("assignment discards qualifiers from pointer target type");
6395 break;
6396 case VT_BYTE:
6397 case VT_SHORT:
6398 case VT_INT:
6399 case VT_LLONG:
6400 if (sbt == VT_PTR || sbt == VT_FUNC) {
6401 warning("assignment makes integer from pointer without a cast");
6403 /* XXX: more tests */
6404 break;
6405 case VT_STRUCT:
6406 tmp_type1 = *dt;
6407 tmp_type2 = *st;
6408 tmp_type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
6409 tmp_type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
6410 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
6411 error:
6412 type_to_str(buf1, sizeof(buf1), st, NULL);
6413 type_to_str(buf2, sizeof(buf2), dt, NULL);
6414 error("cannot cast '%s' to '%s'", buf1, buf2);
6416 break;
6418 type_ok:
6419 gen_cast(dt);
6422 /* store vtop in lvalue pushed on stack */
6423 void vstore(void)
6425 int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
6427 ft = vtop[-1].type.t;
6428 sbt = vtop->type.t & VT_BTYPE;
6429 dbt = ft & VT_BTYPE;
6430 if (((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
6431 (sbt == VT_INT && dbt == VT_SHORT)) {
6432 /* optimize char/short casts */
6433 delayed_cast = VT_MUSTCAST;
6434 vtop->type.t = ft & VT_TYPE;
6435 /* XXX: factorize */
6436 if (ft & VT_CONSTANT)
6437 warning("assignment of read-only location");
6438 } else {
6439 delayed_cast = 0;
6440 if (!(ft & VT_BITFIELD))
6441 gen_assign_cast(&vtop[-1].type);
6444 if (sbt == VT_STRUCT) {
6445 /* if structure, only generate pointer */
6446 /* structure assignment : generate memcpy */
6447 /* XXX: optimize if small size */
6448 if (!nocode_wanted) {
6449 size = type_size(&vtop->type, &align);
6451 #ifdef TCC_ARM_EABI
6452 if(!(align & 7))
6453 vpush_global_sym(&func_old_type, TOK_memcpy8);
6454 else if(!(align & 3))
6455 vpush_global_sym(&func_old_type, TOK_memcpy4);
6456 else
6457 #endif
6458 vpush_global_sym(&func_old_type, TOK_memcpy);
6460 /* destination */
6461 vpushv(vtop - 2);
6462 vtop->type.t = VT_INT;
6463 gaddrof();
6464 /* source */
6465 vpushv(vtop - 2);
6466 vtop->type.t = VT_INT;
6467 gaddrof();
6468 /* type size */
6469 vpushi(size);
6470 gfunc_call(3);
6472 vswap();
6473 vpop();
6474 } else {
6475 vswap();
6476 vpop();
6478 /* leave source on stack */
6479 } else if (ft & VT_BITFIELD) {
6480 /* bitfield store handling */
6481 bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
6482 bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
6483 /* remove bit field info to avoid loops */
6484 vtop[-1].type.t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
6486 /* duplicate source into other register */
6487 gv_dup();
6488 vswap();
6489 vrott(3);
6491 /* duplicate destination */
6492 vdup();
6493 vtop[-1] = vtop[-2];
6495 /* mask and shift source */
6496 vpushi((1 << bit_size) - 1);
6497 gen_op('&');
6498 vpushi(bit_pos);
6499 gen_op(TOK_SHL);
6500 /* load destination, mask and or with source */
6501 vswap();
6502 vpushi(~(((1 << bit_size) - 1) << bit_pos));
6503 gen_op('&');
6504 gen_op('|');
6505 /* store result */
6506 vstore();
6508 /* pop off shifted source from "duplicate source..." above */
6509 vpop();
6511 } else {
6512 #ifdef CONFIG_TCC_BCHECK
6513 /* bound check case */
6514 if (vtop[-1].r & VT_MUSTBOUND) {
6515 vswap();
6516 gbound();
6517 vswap();
6519 #endif
6520 if (!nocode_wanted) {
6521 rc = RC_INT;
6522 if (is_float(ft))
6523 rc = RC_FLOAT;
6524 r = gv(rc); /* generate value */
6525 /* if lvalue was saved on stack, must read it */
6526 if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
6527 SValue sv;
6528 t = get_reg(RC_INT);
6529 sv.type.t = VT_INT;
6530 sv.r = VT_LOCAL | VT_LVAL;
6531 sv.c.ul = vtop[-1].c.ul;
6532 load(t, &sv);
6533 vtop[-1].r = t | VT_LVAL;
6535 store(r, vtop - 1);
6536 /* two word case handling : store second register at word + 4 */
6537 if ((ft & VT_BTYPE) == VT_LLONG) {
6538 vswap();
6539 /* convert to int to increment easily */
6540 vtop->type.t = VT_INT;
6541 gaddrof();
6542 vpushi(4);
6543 gen_op('+');
6544 vtop->r |= VT_LVAL;
6545 vswap();
6546 /* XXX: it works because r2 is spilled last ! */
6547 store(vtop->r2, vtop - 1);
6550 vswap();
6551 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
6552 vtop->r |= delayed_cast;
6556 /* post defines POST/PRE add. c is the token ++ or -- */
6557 void inc(int post, int c)
6559 test_lvalue();
6560 vdup(); /* save lvalue */
6561 if (post) {
6562 gv_dup(); /* duplicate value */
6563 vrotb(3);
6564 vrotb(3);
6566 /* add constant */
6567 vpushi(c - TOK_MID);
6568 gen_op('+');
6569 vstore(); /* store value */
6570 if (post)
6571 vpop(); /* if post op, return saved value */
6574 /* Parse GNUC __attribute__ extension. Currently, the following
6575 extensions are recognized:
6576 - aligned(n) : set data/function alignment.
6577 - packed : force data alignment to 1
6578 - section(x) : generate data/code in this section.
6579 - unused : currently ignored, but may be used someday.
6580 - regparm(n) : pass function parameters in registers (i386 only)
6582 static void parse_attribute(AttributeDef *ad)
6584 int t, n;
6586 while (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) {
6587 next();
6588 skip('(');
6589 skip('(');
6590 while (tok != ')') {
6591 if (tok < TOK_IDENT)
6592 expect("attribute name");
6593 t = tok;
6594 next();
6595 switch(t) {
6596 case TOK_SECTION1:
6597 case TOK_SECTION2:
6598 skip('(');
6599 if (tok != TOK_STR)
6600 expect("section name");
6601 ad->section = find_section(tcc_state, (char *)tokc.cstr->data);
6602 next();
6603 skip(')');
6604 break;
6605 case TOK_ALIGNED1:
6606 case TOK_ALIGNED2:
6607 if (tok == '(') {
6608 next();
6609 n = expr_const();
6610 if (n <= 0 || (n & (n - 1)) != 0)
6611 error("alignment must be a positive power of two");
6612 skip(')');
6613 } else {
6614 n = MAX_ALIGN;
6616 ad->aligned = n;
6617 break;
6618 case TOK_PACKED1:
6619 case TOK_PACKED2:
6620 ad->packed = 1;
6621 break;
6622 case TOK_UNUSED1:
6623 case TOK_UNUSED2:
6624 /* currently, no need to handle it because tcc does not
6625 track unused objects */
6626 break;
6627 case TOK_NORETURN1:
6628 case TOK_NORETURN2:
6629 /* currently, no need to handle it because tcc does not
6630 track unused objects */
6631 break;
6632 case TOK_CDECL1:
6633 case TOK_CDECL2:
6634 case TOK_CDECL3:
6635 FUNC_CALL(ad->func_attr) = FUNC_CDECL;
6636 break;
6637 case TOK_STDCALL1:
6638 case TOK_STDCALL2:
6639 case TOK_STDCALL3:
6640 FUNC_CALL(ad->func_attr) = FUNC_STDCALL;
6641 break;
6642 #ifdef TCC_TARGET_I386
6643 case TOK_REGPARM1:
6644 case TOK_REGPARM2:
6645 skip('(');
6646 n = expr_const();
6647 if (n > 3)
6648 n = 3;
6649 else if (n < 0)
6650 n = 0;
6651 if (n > 0)
6652 FUNC_CALL(ad->func_attr) = FUNC_FASTCALL1 + n - 1;
6653 skip(')');
6654 break;
6655 case TOK_FASTCALL1:
6656 case TOK_FASTCALL2:
6657 case TOK_FASTCALL3:
6658 FUNC_CALL(ad->func_attr) = FUNC_FASTCALLW;
6659 break;
6660 #endif
6661 case TOK_DLLEXPORT:
6662 FUNC_EXPORT(ad->func_attr) = 1;
6663 break;
6664 default:
6665 if (tcc_state->warn_unsupported)
6666 warning("'%s' attribute ignored", get_tok_str(t, NULL));
6667 /* skip parameters */
6668 if (tok == '(') {
6669 int parenthesis = 0;
6670 do {
6671 if (tok == '(')
6672 parenthesis++;
6673 else if (tok == ')')
6674 parenthesis--;
6675 next();
6676 } while (parenthesis && tok != -1);
6678 break;
6680 if (tok != ',')
6681 break;
6682 next();
6684 skip(')');
6685 skip(')');
6689 /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
6690 static void struct_decl(CType *type, int u)
6692 int a, v, size, align, maxalign, c, offset;
6693 int bit_size, bit_pos, bsize, bt, lbit_pos;
6694 Sym *s, *ss, *ass, **ps;
6695 AttributeDef ad;
6696 CType type1, btype;
6698 a = tok; /* save decl type */
6699 next();
6700 if (tok != '{') {
6701 v = tok;
6702 next();
6703 /* struct already defined ? return it */
6704 if (v < TOK_IDENT)
6705 expect("struct/union/enum name");
6706 s = struct_find(v);
6707 if (s) {
6708 if (s->type.t != a)
6709 error("invalid type");
6710 goto do_decl;
6712 } else {
6713 v = anon_sym++;
6715 type1.t = a;
6716 /* we put an undefined size for struct/union */
6717 s = sym_push(v | SYM_STRUCT, &type1, 0, -1);
6718 s->r = 0; /* default alignment is zero as gcc */
6719 /* put struct/union/enum name in type */
6720 do_decl:
6721 type->t = u;
6722 type->ref = s;
6724 if (tok == '{') {
6725 next();
6726 if (s->c != -1)
6727 error("struct/union/enum already defined");
6728 /* cannot be empty */
6729 c = 0;
6730 /* non empty enums are not allowed */
6731 if (a == TOK_ENUM) {
6732 for(;;) {
6733 v = tok;
6734 if (v < TOK_UIDENT)
6735 expect("identifier");
6736 next();
6737 if (tok == '=') {
6738 next();
6739 c = expr_const();
6741 /* enum symbols have static storage */
6742 ss = sym_push(v, &int_type, VT_CONST, c);
6743 ss->type.t |= VT_STATIC;
6744 if (tok != ',')
6745 break;
6746 next();
6747 c++;
6748 /* NOTE: we accept a trailing comma */
6749 if (tok == '}')
6750 break;
6752 skip('}');
6753 } else {
6754 maxalign = 1;
6755 ps = &s->next;
6756 bit_pos = 0;
6757 offset = 0;
6758 while (tok != '}') {
6759 parse_btype(&btype, &ad);
6760 while (1) {
6761 bit_size = -1;
6762 v = 0;
6763 type1 = btype;
6764 if (tok != ':') {
6765 type_decl(&type1, &ad, &v, TYPE_DIRECT | TYPE_ABSTRACT);
6766 if (v == 0 && (type1.t & VT_BTYPE) != VT_STRUCT)
6767 expect("identifier");
6768 if ((type1.t & VT_BTYPE) == VT_FUNC ||
6769 (type1.t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN | VT_INLINE)))
6770 error("invalid type for '%s'",
6771 get_tok_str(v, NULL));
6773 if (tok == ':') {
6774 next();
6775 bit_size = expr_const();
6776 /* XXX: handle v = 0 case for messages */
6777 if (bit_size < 0)
6778 error("negative width in bit-field '%s'",
6779 get_tok_str(v, NULL));
6780 if (v && bit_size == 0)
6781 error("zero width for bit-field '%s'",
6782 get_tok_str(v, NULL));
6784 size = type_size(&type1, &align);
6785 if (ad.aligned) {
6786 if (align < ad.aligned)
6787 align = ad.aligned;
6788 } else if (ad.packed) {
6789 align = 1;
6790 } else if (*tcc_state->pack_stack_ptr) {
6791 if (align > *tcc_state->pack_stack_ptr)
6792 align = *tcc_state->pack_stack_ptr;
6794 lbit_pos = 0;
6795 if (bit_size >= 0) {
6796 bt = type1.t & VT_BTYPE;
6797 if (bt != VT_INT &&
6798 bt != VT_BYTE &&
6799 bt != VT_SHORT &&
6800 bt != VT_BOOL &&
6801 bt != VT_ENUM)
6802 error("bitfields must have scalar type");
6803 bsize = size * 8;
6804 if (bit_size > bsize) {
6805 error("width of '%s' exceeds its type",
6806 get_tok_str(v, NULL));
6807 } else if (bit_size == bsize) {
6808 /* no need for bit fields */
6809 bit_pos = 0;
6810 } else if (bit_size == 0) {
6811 /* XXX: what to do if only padding in a
6812 structure ? */
6813 /* zero size: means to pad */
6814 if (bit_pos > 0)
6815 bit_pos = bsize;
6816 } else {
6817 /* we do not have enough room ? */
6818 if ((bit_pos + bit_size) > bsize)
6819 bit_pos = 0;
6820 lbit_pos = bit_pos;
6821 /* XXX: handle LSB first */
6822 type1.t |= VT_BITFIELD |
6823 (bit_pos << VT_STRUCT_SHIFT) |
6824 (bit_size << (VT_STRUCT_SHIFT + 6));
6825 bit_pos += bit_size;
6827 } else {
6828 bit_pos = 0;
6830 if (v != 0 || (type1.t & VT_BTYPE) == VT_STRUCT) {
6831 /* add new memory data only if starting
6832 bit field */
6833 if (lbit_pos == 0) {
6834 if (a == TOK_STRUCT) {
6835 c = (c + align - 1) & -align;
6836 offset = c;
6837 if (size > 0)
6838 c += size;
6839 } else {
6840 offset = 0;
6841 if (size > c)
6842 c = size;
6844 if (align > maxalign)
6845 maxalign = align;
6847 #if 0
6848 printf("add field %s offset=%d",
6849 get_tok_str(v, NULL), offset);
6850 if (type1.t & VT_BITFIELD) {
6851 printf(" pos=%d size=%d",
6852 (type1.t >> VT_STRUCT_SHIFT) & 0x3f,
6853 (type1.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
6855 printf("\n");
6856 #endif
6858 if (v == 0 && (type1.t & VT_BTYPE) == VT_STRUCT) {
6859 ass = type1.ref;
6860 while ((ass = ass->next) != NULL) {
6861 ss = sym_push(ass->v, &ass->type, 0, offset + ass->c);
6862 *ps = ss;
6863 ps = &ss->next;
6865 } else if (v) {
6866 ss = sym_push(v | SYM_FIELD, &type1, 0, offset);
6867 *ps = ss;
6868 ps = &ss->next;
6870 if (tok == ';' || tok == TOK_EOF)
6871 break;
6872 skip(',');
6874 skip(';');
6876 skip('}');
6877 /* store size and alignment */
6878 s->c = (c + maxalign - 1) & -maxalign;
6879 s->r = maxalign;
6884 /* return 0 if no type declaration. otherwise, return the basic type
6885 and skip it.
6887 static int parse_btype(CType *type, AttributeDef *ad)
6889 int t, u, type_found, typespec_found, typedef_found;
6890 Sym *s;
6891 CType type1;
6893 memset(ad, 0, sizeof(AttributeDef));
6894 type_found = 0;
6895 typespec_found = 0;
6896 typedef_found = 0;
6897 t = 0;
6898 while(1) {
6899 switch(tok) {
6900 case TOK_EXTENSION:
6901 /* currently, we really ignore extension */
6902 next();
6903 continue;
6905 /* basic types */
6906 case TOK_CHAR:
6907 u = VT_BYTE;
6908 basic_type:
6909 next();
6910 basic_type1:
6911 if ((t & VT_BTYPE) != 0)
6912 error("too many basic types");
6913 t |= u;
6914 typespec_found = 1;
6915 break;
6916 case TOK_VOID:
6917 u = VT_VOID;
6918 goto basic_type;
6919 case TOK_SHORT:
6920 u = VT_SHORT;
6921 goto basic_type;
6922 case TOK_INT:
6923 next();
6924 typespec_found = 1;
6925 break;
6926 case TOK_LONG:
6927 next();
6928 if ((t & VT_BTYPE) == VT_DOUBLE) {
6929 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6930 } else if ((t & VT_BTYPE) == VT_LONG) {
6931 t = (t & ~VT_BTYPE) | VT_LLONG;
6932 } else {
6933 u = VT_LONG;
6934 goto basic_type1;
6936 break;
6937 case TOK_BOOL:
6938 u = VT_BOOL;
6939 goto basic_type;
6940 case TOK_FLOAT:
6941 u = VT_FLOAT;
6942 goto basic_type;
6943 case TOK_DOUBLE:
6944 next();
6945 if ((t & VT_BTYPE) == VT_LONG) {
6946 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6947 } else {
6948 u = VT_DOUBLE;
6949 goto basic_type1;
6951 break;
6952 case TOK_ENUM:
6953 struct_decl(&type1, VT_ENUM);
6954 basic_type2:
6955 u = type1.t;
6956 type->ref = type1.ref;
6957 goto basic_type1;
6958 case TOK_STRUCT:
6959 case TOK_UNION:
6960 struct_decl(&type1, VT_STRUCT);
6961 goto basic_type2;
6963 /* type modifiers */
6964 case TOK_CONST1:
6965 case TOK_CONST2:
6966 case TOK_CONST3:
6967 t |= VT_CONSTANT;
6968 next();
6969 break;
6970 case TOK_VOLATILE1:
6971 case TOK_VOLATILE2:
6972 case TOK_VOLATILE3:
6973 t |= VT_VOLATILE;
6974 next();
6975 break;
6976 case TOK_SIGNED1:
6977 case TOK_SIGNED2:
6978 case TOK_SIGNED3:
6979 typespec_found = 1;
6980 t |= VT_SIGNED;
6981 next();
6982 break;
6983 case TOK_REGISTER:
6984 case TOK_AUTO:
6985 case TOK_RESTRICT1:
6986 case TOK_RESTRICT2:
6987 case TOK_RESTRICT3:
6988 next();
6989 break;
6990 case TOK_UNSIGNED:
6991 t |= VT_UNSIGNED;
6992 next();
6993 typespec_found = 1;
6994 break;
6996 /* storage */
6997 case TOK_EXTERN:
6998 t |= VT_EXTERN;
6999 next();
7000 break;
7001 case TOK_STATIC:
7002 t |= VT_STATIC;
7003 next();
7004 break;
7005 case TOK_TYPEDEF:
7006 t |= VT_TYPEDEF;
7007 next();
7008 break;
7009 case TOK_INLINE1:
7010 case TOK_INLINE2:
7011 case TOK_INLINE3:
7012 t |= VT_INLINE;
7013 next();
7014 break;
7016 /* GNUC attribute */
7017 case TOK_ATTRIBUTE1:
7018 case TOK_ATTRIBUTE2:
7019 parse_attribute(ad);
7020 break;
7021 /* GNUC typeof */
7022 case TOK_TYPEOF1:
7023 case TOK_TYPEOF2:
7024 case TOK_TYPEOF3:
7025 next();
7026 parse_expr_type(&type1);
7027 goto basic_type2;
7028 default:
7029 if (typespec_found || typedef_found)
7030 goto the_end;
7031 s = sym_find(tok);
7032 if (!s || !(s->type.t & VT_TYPEDEF))
7033 goto the_end;
7034 typedef_found = 1;
7035 t |= (s->type.t & ~VT_TYPEDEF);
7036 type->ref = s->type.ref;
7037 next();
7038 typespec_found = 1;
7039 break;
7041 type_found = 1;
7043 the_end:
7044 if ((t & (VT_SIGNED|VT_UNSIGNED)) == (VT_SIGNED|VT_UNSIGNED))
7045 error("signed and unsigned modifier");
7046 if (tcc_state->char_is_unsigned) {
7047 if ((t & (VT_SIGNED|VT_UNSIGNED|VT_BTYPE)) == VT_BYTE)
7048 t |= VT_UNSIGNED;
7050 t &= ~VT_SIGNED;
7052 /* long is never used as type */
7053 if ((t & VT_BTYPE) == VT_LONG)
7054 t = (t & ~VT_BTYPE) | VT_INT;
7055 type->t = t;
7056 return type_found;
7059 /* convert a function parameter type (array to pointer and function to
7060 function pointer) */
7061 static inline void convert_parameter_type(CType *pt)
7063 /* remove const and volatile qualifiers (XXX: const could be used
7064 to indicate a const function parameter */
7065 pt->t &= ~(VT_CONSTANT | VT_VOLATILE);
7066 /* array must be transformed to pointer according to ANSI C */
7067 pt->t &= ~VT_ARRAY;
7068 if ((pt->t & VT_BTYPE) == VT_FUNC) {
7069 mk_pointer(pt);
7073 static void post_type(CType *type, AttributeDef *ad)
7075 int n, l, t1, arg_size, align;
7076 Sym **plast, *s, *first;
7077 AttributeDef ad1;
7078 CType pt;
7080 if (tok == '(') {
7081 /* function declaration */
7082 next();
7083 l = 0;
7084 first = NULL;
7085 plast = &first;
7086 arg_size = 0;
7087 if (tok != ')') {
7088 for(;;) {
7089 /* read param name and compute offset */
7090 if (l != FUNC_OLD) {
7091 if (!parse_btype(&pt, &ad1)) {
7092 if (l) {
7093 error("invalid type");
7094 } else {
7095 l = FUNC_OLD;
7096 goto old_proto;
7099 l = FUNC_NEW;
7100 if ((pt.t & VT_BTYPE) == VT_VOID && tok == ')')
7101 break;
7102 type_decl(&pt, &ad1, &n, TYPE_DIRECT | TYPE_ABSTRACT);
7103 if ((pt.t & VT_BTYPE) == VT_VOID)
7104 error("parameter declared as void");
7105 arg_size += (type_size(&pt, &align) + 3) & ~3;
7106 } else {
7107 old_proto:
7108 n = tok;
7109 if (n < TOK_UIDENT)
7110 expect("identifier");
7111 pt.t = VT_INT;
7112 next();
7114 convert_parameter_type(&pt);
7115 s = sym_push(n | SYM_FIELD, &pt, 0, 0);
7116 *plast = s;
7117 plast = &s->next;
7118 if (tok == ')')
7119 break;
7120 skip(',');
7121 if (l == FUNC_NEW && tok == TOK_DOTS) {
7122 l = FUNC_ELLIPSIS;
7123 next();
7124 break;
7128 /* if no parameters, then old type prototype */
7129 if (l == 0)
7130 l = FUNC_OLD;
7131 skip(')');
7132 t1 = type->t & VT_STORAGE;
7133 /* NOTE: const is ignored in returned type as it has a special
7134 meaning in gcc / C++ */
7135 type->t &= ~(VT_STORAGE | VT_CONSTANT);
7136 post_type(type, ad);
7137 /* we push a anonymous symbol which will contain the function prototype */
7138 FUNC_ARGS(ad->func_attr) = arg_size;
7139 s = sym_push(SYM_FIELD, type, ad->func_attr, l);
7140 s->next = first;
7141 type->t = t1 | VT_FUNC;
7142 type->ref = s;
7143 } else if (tok == '[') {
7144 /* array definition */
7145 next();
7146 n = -1;
7147 if (tok != ']') {
7148 n = expr_const();
7149 if (n < 0)
7150 error("invalid array size");
7152 skip(']');
7153 /* parse next post type */
7154 t1 = type->t & VT_STORAGE;
7155 type->t &= ~VT_STORAGE;
7156 post_type(type, ad);
7158 /* we push a anonymous symbol which will contain the array
7159 element type */
7160 s = sym_push(SYM_FIELD, type, 0, n);
7161 type->t = t1 | VT_ARRAY | VT_PTR;
7162 type->ref = s;
7166 /* Parse a type declaration (except basic type), and return the type
7167 in 'type'. 'td' is a bitmask indicating which kind of type decl is
7168 expected. 'type' should contain the basic type. 'ad' is the
7169 attribute definition of the basic type. It can be modified by
7170 type_decl().
7172 static void type_decl(CType *type, AttributeDef *ad, int *v, int td)
7174 Sym *s;
7175 CType type1, *type2;
7176 int qualifiers;
7178 while (tok == '*') {
7179 qualifiers = 0;
7180 redo:
7181 next();
7182 switch(tok) {
7183 case TOK_CONST1:
7184 case TOK_CONST2:
7185 case TOK_CONST3:
7186 qualifiers |= VT_CONSTANT;
7187 goto redo;
7188 case TOK_VOLATILE1:
7189 case TOK_VOLATILE2:
7190 case TOK_VOLATILE3:
7191 qualifiers |= VT_VOLATILE;
7192 goto redo;
7193 case TOK_RESTRICT1:
7194 case TOK_RESTRICT2:
7195 case TOK_RESTRICT3:
7196 goto redo;
7198 mk_pointer(type);
7199 type->t |= qualifiers;
7202 /* XXX: clarify attribute handling */
7203 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
7204 parse_attribute(ad);
7206 /* recursive type */
7207 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
7208 type1.t = 0; /* XXX: same as int */
7209 if (tok == '(') {
7210 next();
7211 /* XXX: this is not correct to modify 'ad' at this point, but
7212 the syntax is not clear */
7213 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
7214 parse_attribute(ad);
7215 type_decl(&type1, ad, v, td);
7216 skip(')');
7217 } else {
7218 /* type identifier */
7219 if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
7220 *v = tok;
7221 next();
7222 } else {
7223 if (!(td & TYPE_ABSTRACT))
7224 expect("identifier");
7225 *v = 0;
7228 post_type(type, ad);
7229 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
7230 parse_attribute(ad);
7231 if (!type1.t)
7232 return;
7233 /* append type at the end of type1 */
7234 type2 = &type1;
7235 for(;;) {
7236 s = type2->ref;
7237 type2 = &s->type;
7238 if (!type2->t) {
7239 *type2 = *type;
7240 break;
7243 *type = type1;
7246 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
7247 static int lvalue_type(int t)
7249 int bt, r;
7250 r = VT_LVAL;
7251 bt = t & VT_BTYPE;
7252 if (bt == VT_BYTE || bt == VT_BOOL)
7253 r |= VT_LVAL_BYTE;
7254 else if (bt == VT_SHORT)
7255 r |= VT_LVAL_SHORT;
7256 else
7257 return r;
7258 if (t & VT_UNSIGNED)
7259 r |= VT_LVAL_UNSIGNED;
7260 return r;
7263 /* indirection with full error checking and bound check */
7264 static void indir(void)
7266 if ((vtop->type.t & VT_BTYPE) != VT_PTR) {
7267 if ((vtop->type.t & VT_BTYPE) == VT_FUNC)
7268 return;
7269 expect("pointer");
7271 if ((vtop->r & VT_LVAL) && !nocode_wanted)
7272 gv(RC_INT);
7273 vtop->type = *pointed_type(&vtop->type);
7274 /* Arrays and functions are never lvalues */
7275 if (!(vtop->type.t & VT_ARRAY)
7276 && (vtop->type.t & VT_BTYPE) != VT_FUNC) {
7277 vtop->r |= lvalue_type(vtop->type.t);
7278 /* if bound checking, the referenced pointer must be checked */
7279 if (do_bounds_check)
7280 vtop->r |= VT_MUSTBOUND;
7284 /* pass a parameter to a function and do type checking and casting */
7285 static void gfunc_param_typed(Sym *func, Sym *arg)
7287 int func_type;
7288 CType type;
7290 func_type = func->c;
7291 if (func_type == FUNC_OLD ||
7292 (func_type == FUNC_ELLIPSIS && arg == NULL)) {
7293 /* default casting : only need to convert float to double */
7294 if ((vtop->type.t & VT_BTYPE) == VT_FLOAT) {
7295 type.t = VT_DOUBLE;
7296 gen_cast(&type);
7298 } else if (arg == NULL) {
7299 error("too many arguments to function");
7300 } else {
7301 type = arg->type;
7302 type.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
7303 gen_assign_cast(&type);
7307 /* parse an expression of the form '(type)' or '(expr)' and return its
7308 type */
7309 static void parse_expr_type(CType *type)
7311 int n;
7312 AttributeDef ad;
7314 skip('(');
7315 if (parse_btype(type, &ad)) {
7316 type_decl(type, &ad, &n, TYPE_ABSTRACT);
7317 } else {
7318 expr_type(type);
7320 skip(')');
7323 static void parse_type(CType *type)
7325 AttributeDef ad;
7326 int n;
7328 if (!parse_btype(type, &ad)) {
7329 expect("type");
7331 type_decl(type, &ad, &n, TYPE_ABSTRACT);
7334 static void vpush_tokc(int t)
7336 CType type;
7337 type.t = t;
7338 vsetc(&type, VT_CONST, &tokc);
7341 static void unary(void)
7343 int n, t, align, size, r;
7344 CType type;
7345 Sym *s;
7346 AttributeDef ad;
7348 /* XXX: GCC 2.95.3 does not generate a table although it should be
7349 better here */
7350 tok_next:
7351 switch(tok) {
7352 case TOK_EXTENSION:
7353 next();
7354 goto tok_next;
7355 case TOK_CINT:
7356 case TOK_CCHAR:
7357 case TOK_LCHAR:
7358 vpushi(tokc.i);
7359 next();
7360 break;
7361 case TOK_CUINT:
7362 vpush_tokc(VT_INT | VT_UNSIGNED);
7363 next();
7364 break;
7365 case TOK_CLLONG:
7366 vpush_tokc(VT_LLONG);
7367 next();
7368 break;
7369 case TOK_CULLONG:
7370 vpush_tokc(VT_LLONG | VT_UNSIGNED);
7371 next();
7372 break;
7373 case TOK_CFLOAT:
7374 vpush_tokc(VT_FLOAT);
7375 next();
7376 break;
7377 case TOK_CDOUBLE:
7378 vpush_tokc(VT_DOUBLE);
7379 next();
7380 break;
7381 case TOK_CLDOUBLE:
7382 vpush_tokc(VT_LDOUBLE);
7383 next();
7384 break;
7385 case TOK___FUNCTION__:
7386 if (!gnu_ext)
7387 goto tok_identifier;
7388 /* fall thru */
7389 case TOK___FUNC__:
7391 void *ptr;
7392 int len;
7393 /* special function name identifier */
7394 len = strlen(funcname) + 1;
7395 /* generate char[len] type */
7396 type.t = VT_BYTE;
7397 mk_pointer(&type);
7398 type.t |= VT_ARRAY;
7399 type.ref->c = len;
7400 vpush_ref(&type, data_section, data_section->data_offset, len);
7401 ptr = section_ptr_add(data_section, len);
7402 memcpy(ptr, funcname, len);
7403 next();
7405 break;
7406 case TOK_LSTR:
7407 #ifdef TCC_TARGET_PE
7408 t = VT_SHORT | VT_UNSIGNED;
7409 #else
7410 t = VT_INT;
7411 #endif
7412 goto str_init;
7413 case TOK_STR:
7414 /* string parsing */
7415 t = VT_BYTE;
7416 str_init:
7417 if (tcc_state->warn_write_strings)
7418 t |= VT_CONSTANT;
7419 type.t = t;
7420 mk_pointer(&type);
7421 type.t |= VT_ARRAY;
7422 memset(&ad, 0, sizeof(AttributeDef));
7423 decl_initializer_alloc(&type, &ad, VT_CONST, 2, 0, 0);
7424 break;
7425 case '(':
7426 next();
7427 /* cast ? */
7428 if (parse_btype(&type, &ad)) {
7429 type_decl(&type, &ad, &n, TYPE_ABSTRACT);
7430 skip(')');
7431 /* check ISOC99 compound literal */
7432 if (tok == '{') {
7433 /* data is allocated locally by default */
7434 if (global_expr)
7435 r = VT_CONST;
7436 else
7437 r = VT_LOCAL;
7438 /* all except arrays are lvalues */
7439 if (!(type.t & VT_ARRAY))
7440 r |= lvalue_type(type.t);
7441 memset(&ad, 0, sizeof(AttributeDef));
7442 decl_initializer_alloc(&type, &ad, r, 1, 0, 0);
7443 } else {
7444 unary();
7445 gen_cast(&type);
7447 } else if (tok == '{') {
7448 /* save all registers */
7449 save_regs(0);
7450 /* statement expression : we do not accept break/continue
7451 inside as GCC does */
7452 block(NULL, NULL, NULL, NULL, 0, 1);
7453 skip(')');
7454 } else {
7455 gexpr();
7456 skip(')');
7458 break;
7459 case '*':
7460 next();
7461 unary();
7462 indir();
7463 break;
7464 case '&':
7465 next();
7466 unary();
7467 /* functions names must be treated as function pointers,
7468 except for unary '&' and sizeof. Since we consider that
7469 functions are not lvalues, we only have to handle it
7470 there and in function calls. */
7471 /* arrays can also be used although they are not lvalues */
7472 if ((vtop->type.t & VT_BTYPE) != VT_FUNC &&
7473 !(vtop->type.t & VT_ARRAY) && !(vtop->type.t & VT_LLOCAL))
7474 test_lvalue();
7475 mk_pointer(&vtop->type);
7476 gaddrof();
7477 break;
7478 case '!':
7479 next();
7480 unary();
7481 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST)
7482 vtop->c.i = !vtop->c.i;
7483 else if ((vtop->r & VT_VALMASK) == VT_CMP)
7484 vtop->c.i = vtop->c.i ^ 1;
7485 else {
7486 save_regs(1);
7487 vseti(VT_JMP, gtst(1, 0));
7489 break;
7490 case '~':
7491 next();
7492 unary();
7493 vpushi(-1);
7494 gen_op('^');
7495 break;
7496 case '+':
7497 next();
7498 /* in order to force cast, we add zero */
7499 unary();
7500 if ((vtop->type.t & VT_BTYPE) == VT_PTR)
7501 error("pointer not accepted for unary plus");
7502 vpushi(0);
7503 gen_op('+');
7504 break;
7505 case TOK_SIZEOF:
7506 case TOK_ALIGNOF1:
7507 case TOK_ALIGNOF2:
7508 t = tok;
7509 next();
7510 if (tok == '(') {
7511 parse_expr_type(&type);
7512 } else {
7513 unary_type(&type);
7515 size = type_size(&type, &align);
7516 if (t == TOK_SIZEOF) {
7517 if (size < 0)
7518 error("sizeof applied to an incomplete type");
7519 vpushi(size);
7520 } else {
7521 vpushi(align);
7523 vtop->type.t |= VT_UNSIGNED;
7524 break;
7526 case TOK_builtin_types_compatible_p:
7528 CType type1, type2;
7529 next();
7530 skip('(');
7531 parse_type(&type1);
7532 skip(',');
7533 parse_type(&type2);
7534 skip(')');
7535 type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
7536 type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
7537 vpushi(is_compatible_types(&type1, &type2));
7539 break;
7540 case TOK_builtin_constant_p:
7542 int saved_nocode_wanted, res;
7543 next();
7544 skip('(');
7545 saved_nocode_wanted = nocode_wanted;
7546 nocode_wanted = 1;
7547 gexpr();
7548 res = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
7549 vpop();
7550 nocode_wanted = saved_nocode_wanted;
7551 skip(')');
7552 vpushi(res);
7554 break;
7555 case TOK_INC:
7556 case TOK_DEC:
7557 t = tok;
7558 next();
7559 unary();
7560 inc(0, t);
7561 break;
7562 case '-':
7563 next();
7564 vpushi(0);
7565 unary();
7566 gen_op('-');
7567 break;
7568 case TOK_LAND:
7569 if (!gnu_ext)
7570 goto tok_identifier;
7571 next();
7572 /* allow to take the address of a label */
7573 if (tok < TOK_UIDENT)
7574 expect("label identifier");
7575 s = label_find(tok);
7576 if (!s) {
7577 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
7578 } else {
7579 if (s->r == LABEL_DECLARED)
7580 s->r = LABEL_FORWARD;
7582 if (!s->type.t) {
7583 s->type.t = VT_VOID;
7584 mk_pointer(&s->type);
7585 s->type.t |= VT_STATIC;
7587 vset(&s->type, VT_CONST | VT_SYM, 0);
7588 vtop->sym = s;
7589 next();
7590 break;
7591 default:
7592 tok_identifier:
7593 t = tok;
7594 next();
7595 if (t < TOK_UIDENT)
7596 expect("identifier");
7597 s = sym_find(t);
7598 if (!s) {
7599 if (tok != '(')
7600 error("'%s' undeclared", get_tok_str(t, NULL));
7601 /* for simple function calls, we tolerate undeclared
7602 external reference to int() function */
7603 if (tcc_state->warn_implicit_function_declaration)
7604 warning("implicit declaration of function '%s'",
7605 get_tok_str(t, NULL));
7606 s = external_global_sym(t, &func_old_type, 0);
7608 if ((s->type.t & (VT_STATIC | VT_INLINE | VT_BTYPE)) ==
7609 (VT_STATIC | VT_INLINE | VT_FUNC)) {
7610 /* if referencing an inline function, then we generate a
7611 symbol to it if not already done. It will have the
7612 effect to generate code for it at the end of the
7613 compilation unit. Inline function as always
7614 generated in the text section. */
7615 if (!s->c)
7616 put_extern_sym(s, text_section, 0, 0);
7617 r = VT_SYM | VT_CONST;
7618 } else {
7619 r = s->r;
7621 vset(&s->type, r, s->c);
7622 /* if forward reference, we must point to s */
7623 if (vtop->r & VT_SYM) {
7624 vtop->sym = s;
7625 vtop->c.ul = 0;
7627 break;
7630 /* post operations */
7631 while (1) {
7632 if (tok == TOK_INC || tok == TOK_DEC) {
7633 inc(1, tok);
7634 next();
7635 } else if (tok == '.' || tok == TOK_ARROW) {
7636 /* field */
7637 if (tok == TOK_ARROW)
7638 indir();
7639 test_lvalue();
7640 gaddrof();
7641 next();
7642 /* expect pointer on structure */
7643 if ((vtop->type.t & VT_BTYPE) != VT_STRUCT)
7644 expect("struct or union");
7645 s = vtop->type.ref;
7646 /* find field */
7647 tok |= SYM_FIELD;
7648 while ((s = s->next) != NULL) {
7649 if (s->v == tok)
7650 break;
7652 if (!s)
7653 error("field not found");
7654 /* add field offset to pointer */
7655 vtop->type = char_pointer_type; /* change type to 'char *' */
7656 vpushi(s->c);
7657 gen_op('+');
7658 /* change type to field type, and set to lvalue */
7659 vtop->type = s->type;
7660 /* an array is never an lvalue */
7661 if (!(vtop->type.t & VT_ARRAY)) {
7662 vtop->r |= lvalue_type(vtop->type.t);
7663 /* if bound checking, the referenced pointer must be checked */
7664 if (do_bounds_check)
7665 vtop->r |= VT_MUSTBOUND;
7667 next();
7668 } else if (tok == '[') {
7669 next();
7670 gexpr();
7671 gen_op('+');
7672 indir();
7673 skip(']');
7674 } else if (tok == '(') {
7675 SValue ret;
7676 Sym *sa;
7677 int nb_args;
7679 /* function call */
7680 if ((vtop->type.t & VT_BTYPE) != VT_FUNC) {
7681 /* pointer test (no array accepted) */
7682 if ((vtop->type.t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
7683 vtop->type = *pointed_type(&vtop->type);
7684 if ((vtop->type.t & VT_BTYPE) != VT_FUNC)
7685 goto error_func;
7686 } else {
7687 error_func:
7688 expect("function pointer");
7690 } else {
7691 vtop->r &= ~VT_LVAL; /* no lvalue */
7693 /* get return type */
7694 s = vtop->type.ref;
7695 next();
7696 sa = s->next; /* first parameter */
7697 nb_args = 0;
7698 ret.r2 = VT_CONST;
7699 /* compute first implicit argument if a structure is returned */
7700 if ((s->type.t & VT_BTYPE) == VT_STRUCT) {
7701 /* get some space for the returned structure */
7702 size = type_size(&s->type, &align);
7703 loc = (loc - size) & -align;
7704 ret.type = s->type;
7705 ret.r = VT_LOCAL | VT_LVAL;
7706 /* pass it as 'int' to avoid structure arg passing
7707 problems */
7708 vseti(VT_LOCAL, loc);
7709 ret.c = vtop->c;
7710 nb_args++;
7711 } else {
7712 ret.type = s->type;
7713 /* return in register */
7714 if (is_float(ret.type.t)) {
7715 ret.r = REG_FRET;
7716 } else {
7717 if ((ret.type.t & VT_BTYPE) == VT_LLONG)
7718 ret.r2 = REG_LRET;
7719 ret.r = REG_IRET;
7721 ret.c.i = 0;
7723 if (tok != ')') {
7724 for(;;) {
7725 expr_eq();
7726 gfunc_param_typed(s, sa);
7727 nb_args++;
7728 if (sa)
7729 sa = sa->next;
7730 if (tok == ')')
7731 break;
7732 skip(',');
7735 if (sa)
7736 error("too few arguments to function");
7737 skip(')');
7738 if (!nocode_wanted) {
7739 gfunc_call(nb_args);
7740 } else {
7741 vtop -= (nb_args + 1);
7743 /* return value */
7744 vsetc(&ret.type, ret.r, &ret.c);
7745 vtop->r2 = ret.r2;
7746 } else {
7747 break;
7752 static void uneq(void)
7754 int t;
7756 unary();
7757 if (tok == '=' ||
7758 (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
7759 tok == TOK_A_XOR || tok == TOK_A_OR ||
7760 tok == TOK_A_SHL || tok == TOK_A_SAR) {
7761 test_lvalue();
7762 t = tok;
7763 next();
7764 if (t == '=') {
7765 expr_eq();
7766 } else {
7767 vdup();
7768 expr_eq();
7769 gen_op(t & 0x7f);
7771 vstore();
7775 static void expr_prod(void)
7777 int t;
7779 uneq();
7780 while (tok == '*' || tok == '/' || tok == '%') {
7781 t = tok;
7782 next();
7783 uneq();
7784 gen_op(t);
7788 static void expr_sum(void)
7790 int t;
7792 expr_prod();
7793 while (tok == '+' || tok == '-') {
7794 t = tok;
7795 next();
7796 expr_prod();
7797 gen_op(t);
7801 static void expr_shift(void)
7803 int t;
7805 expr_sum();
7806 while (tok == TOK_SHL || tok == TOK_SAR) {
7807 t = tok;
7808 next();
7809 expr_sum();
7810 gen_op(t);
7814 static void expr_cmp(void)
7816 int t;
7818 expr_shift();
7819 while ((tok >= TOK_ULE && tok <= TOK_GT) ||
7820 tok == TOK_ULT || tok == TOK_UGE) {
7821 t = tok;
7822 next();
7823 expr_shift();
7824 gen_op(t);
7828 static void expr_cmpeq(void)
7830 int t;
7832 expr_cmp();
7833 while (tok == TOK_EQ || tok == TOK_NE) {
7834 t = tok;
7835 next();
7836 expr_cmp();
7837 gen_op(t);
7841 static void expr_and(void)
7843 expr_cmpeq();
7844 while (tok == '&') {
7845 next();
7846 expr_cmpeq();
7847 gen_op('&');
7851 static void expr_xor(void)
7853 expr_and();
7854 while (tok == '^') {
7855 next();
7856 expr_and();
7857 gen_op('^');
7861 static void expr_or(void)
7863 expr_xor();
7864 while (tok == '|') {
7865 next();
7866 expr_xor();
7867 gen_op('|');
7871 /* XXX: fix this mess */
7872 static void expr_land_const(void)
7874 expr_or();
7875 while (tok == TOK_LAND) {
7876 next();
7877 expr_or();
7878 gen_op(TOK_LAND);
7882 /* XXX: fix this mess */
7883 static void expr_lor_const(void)
7885 expr_land_const();
7886 while (tok == TOK_LOR) {
7887 next();
7888 expr_land_const();
7889 gen_op(TOK_LOR);
7893 /* only used if non constant */
7894 static void expr_land(void)
7896 int t;
7898 expr_or();
7899 if (tok == TOK_LAND) {
7900 t = 0;
7901 save_regs(1);
7902 for(;;) {
7903 t = gtst(1, t);
7904 if (tok != TOK_LAND) {
7905 vseti(VT_JMPI, t);
7906 break;
7908 next();
7909 expr_or();
7914 static void expr_lor(void)
7916 int t;
7918 expr_land();
7919 if (tok == TOK_LOR) {
7920 t = 0;
7921 save_regs(1);
7922 for(;;) {
7923 t = gtst(0, t);
7924 if (tok != TOK_LOR) {
7925 vseti(VT_JMP, t);
7926 break;
7928 next();
7929 expr_land();
7934 /* XXX: better constant handling */
7935 static void expr_eq(void)
7937 int tt, u, r1, r2, rc, t1, t2, bt1, bt2;
7938 SValue sv;
7939 CType type, type1, type2;
7941 if (const_wanted) {
7942 int c1, c;
7943 expr_lor_const();
7944 if (tok == '?') {
7945 c = vtop->c.i;
7946 vpop();
7947 next();
7948 if (tok == ':' && gnu_ext) {
7949 c1 = c;
7950 } else {
7951 gexpr();
7952 c1 = vtop->c.i;
7953 vpop();
7955 skip(':');
7956 expr_eq();
7957 if (c)
7958 vtop->c.i = c1;
7960 } else {
7961 expr_lor();
7962 if (tok == '?') {
7963 next();
7964 if (vtop != vstack) {
7965 /* needed to avoid having different registers saved in
7966 each branch */
7967 if (is_float(vtop->type.t))
7968 rc = RC_FLOAT;
7969 else
7970 rc = RC_INT;
7971 gv(rc);
7972 save_regs(1);
7974 if (tok == ':' && gnu_ext) {
7975 gv_dup();
7976 tt = gtst(1, 0);
7977 } else {
7978 tt = gtst(1, 0);
7979 gexpr();
7981 type1 = vtop->type;
7982 sv = *vtop; /* save value to handle it later */
7983 vtop--; /* no vpop so that FP stack is not flushed */
7984 skip(':');
7985 u = gjmp(0);
7986 gsym(tt);
7987 expr_eq();
7988 type2 = vtop->type;
7990 t1 = type1.t;
7991 bt1 = t1 & VT_BTYPE;
7992 t2 = type2.t;
7993 bt2 = t2 & VT_BTYPE;
7994 /* cast operands to correct type according to ISOC rules */
7995 if (is_float(bt1) || is_float(bt2)) {
7996 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
7997 type.t = VT_LDOUBLE;
7998 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
7999 type.t = VT_DOUBLE;
8000 } else {
8001 type.t = VT_FLOAT;
8003 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
8004 /* cast to biggest op */
8005 type.t = VT_LLONG;
8006 /* convert to unsigned if it does not fit in a long long */
8007 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
8008 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
8009 type.t |= VT_UNSIGNED;
8010 } else if (bt1 == VT_PTR || bt2 == VT_PTR) {
8011 /* XXX: test pointer compatibility */
8012 type = type1;
8013 } else if (bt1 == VT_FUNC || bt2 == VT_FUNC) {
8014 /* XXX: test function pointer compatibility */
8015 type = type1;
8016 } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
8017 /* XXX: test structure compatibility */
8018 type = type1;
8019 } else if (bt1 == VT_VOID || bt2 == VT_VOID) {
8020 /* NOTE: as an extension, we accept void on only one side */
8021 type.t = VT_VOID;
8022 } else {
8023 /* integer operations */
8024 type.t = VT_INT;
8025 /* convert to unsigned if it does not fit in an integer */
8026 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
8027 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
8028 type.t |= VT_UNSIGNED;
8031 /* now we convert second operand */
8032 gen_cast(&type);
8033 if (VT_STRUCT == (vtop->type.t & VT_BTYPE))
8034 gaddrof();
8035 rc = RC_INT;
8036 if (is_float(type.t)) {
8037 rc = RC_FLOAT;
8038 } else if ((type.t & VT_BTYPE) == VT_LLONG) {
8039 /* for long longs, we use fixed registers to avoid having
8040 to handle a complicated move */
8041 rc = RC_IRET;
8044 r2 = gv(rc);
8045 /* this is horrible, but we must also convert first
8046 operand */
8047 tt = gjmp(0);
8048 gsym(u);
8049 /* put again first value and cast it */
8050 *vtop = sv;
8051 gen_cast(&type);
8052 if (VT_STRUCT == (vtop->type.t & VT_BTYPE))
8053 gaddrof();
8054 r1 = gv(rc);
8055 move_reg(r2, r1);
8056 vtop->r = r2;
8057 gsym(tt);
8062 static void gexpr(void)
8064 while (1) {
8065 expr_eq();
8066 if (tok != ',')
8067 break;
8068 vpop();
8069 next();
8073 /* parse an expression and return its type without any side effect. */
8074 static void expr_type(CType *type)
8076 int saved_nocode_wanted;
8078 saved_nocode_wanted = nocode_wanted;
8079 nocode_wanted = 1;
8080 gexpr();
8081 *type = vtop->type;
8082 vpop();
8083 nocode_wanted = saved_nocode_wanted;
8086 /* parse a unary expression and return its type without any side
8087 effect. */
8088 static void unary_type(CType *type)
8090 int a;
8092 a = nocode_wanted;
8093 nocode_wanted = 1;
8094 unary();
8095 *type = vtop->type;
8096 vpop();
8097 nocode_wanted = a;
8100 /* parse a constant expression and return value in vtop. */
8101 static void expr_const1(void)
8103 int a;
8104 a = const_wanted;
8105 const_wanted = 1;
8106 expr_eq();
8107 const_wanted = a;
8110 /* parse an integer constant and return its value. */
8111 static int expr_const(void)
8113 int c;
8114 expr_const1();
8115 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
8116 expect("constant expression");
8117 c = vtop->c.i;
8118 vpop();
8119 return c;
8122 /* return the label token if current token is a label, otherwise
8123 return zero */
8124 static int is_label(void)
8126 int last_tok;
8128 /* fast test first */
8129 if (tok < TOK_UIDENT)
8130 return 0;
8131 /* no need to save tokc because tok is an identifier */
8132 last_tok = tok;
8133 next();
8134 if (tok == ':') {
8135 next();
8136 return last_tok;
8137 } else {
8138 unget_tok(last_tok);
8139 return 0;
8143 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
8144 int case_reg, int is_expr)
8146 int a, b, c, d;
8147 Sym *s;
8149 /* generate line number info */
8150 if (do_debug &&
8151 (last_line_num != file->line_num || last_ind != ind)) {
8152 put_stabn(N_SLINE, 0, file->line_num, ind - func_ind);
8153 last_ind = ind;
8154 last_line_num = file->line_num;
8157 if (is_expr) {
8158 /* default return value is (void) */
8159 vpushi(0);
8160 vtop->type.t = VT_VOID;
8163 if (tok == TOK_IF) {
8164 /* if test */
8165 next();
8166 skip('(');
8167 gexpr();
8168 skip(')');
8169 a = gtst(1, 0);
8170 block(bsym, csym, case_sym, def_sym, case_reg, 0);
8171 c = tok;
8172 if (c == TOK_ELSE) {
8173 next();
8174 d = gjmp(0);
8175 gsym(a);
8176 block(bsym, csym, case_sym, def_sym, case_reg, 0);
8177 gsym(d); /* patch else jmp */
8178 } else
8179 gsym(a);
8180 } else if (tok == TOK_WHILE) {
8181 next();
8182 d = ind;
8183 skip('(');
8184 gexpr();
8185 skip(')');
8186 a = gtst(1, 0);
8187 b = 0;
8188 block(&a, &b, case_sym, def_sym, case_reg, 0);
8189 gjmp_addr(d);
8190 gsym(a);
8191 gsym_addr(b, d);
8192 } else if (tok == '{') {
8193 Sym *llabel;
8195 next();
8196 /* record local declaration stack position */
8197 s = local_stack;
8198 llabel = local_label_stack;
8199 /* handle local labels declarations */
8200 if (tok == TOK_LABEL) {
8201 next();
8202 for(;;) {
8203 if (tok < TOK_UIDENT)
8204 expect("label identifier");
8205 label_push(&local_label_stack, tok, LABEL_DECLARED);
8206 next();
8207 if (tok == ',') {
8208 next();
8209 } else {
8210 skip(';');
8211 break;
8215 while (tok != '}') {
8216 decl(VT_LOCAL);
8217 if (tok != '}') {
8218 if (is_expr)
8219 vpop();
8220 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
8223 /* pop locally defined labels */
8224 label_pop(&local_label_stack, llabel);
8225 /* pop locally defined symbols */
8226 sym_pop(&local_stack, s);
8227 next();
8228 } else if (tok == TOK_RETURN) {
8229 next();
8230 if (tok != ';') {
8231 gexpr();
8232 gen_assign_cast(&func_vt);
8233 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
8234 CType type;
8235 /* if returning structure, must copy it to implicit
8236 first pointer arg location */
8237 #ifdef TCC_ARM_EABI
8238 int align, size;
8239 size = type_size(&func_vt,&align);
8240 if(size <= 4)
8242 if((vtop->r != (VT_LOCAL | VT_LVAL) || (vtop->c.i & 3))
8243 && (align & 3))
8245 int addr;
8246 loc = (loc - size) & -4;
8247 addr = loc;
8248 type = func_vt;
8249 vset(&type, VT_LOCAL | VT_LVAL, addr);
8250 vswap();
8251 vstore();
8252 vset(&int_type, VT_LOCAL | VT_LVAL, addr);
8254 vtop->type = int_type;
8255 gv(RC_IRET);
8256 } else {
8257 #endif
8258 type = func_vt;
8259 mk_pointer(&type);
8260 vset(&type, VT_LOCAL | VT_LVAL, func_vc);
8261 indir();
8262 vswap();
8263 /* copy structure value to pointer */
8264 vstore();
8265 #ifdef TCC_ARM_EABI
8267 #endif
8268 } else if (is_float(func_vt.t)) {
8269 gv(RC_FRET);
8270 } else {
8271 gv(RC_IRET);
8273 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
8275 skip(';');
8276 rsym = gjmp(rsym); /* jmp */
8277 } else if (tok == TOK_BREAK) {
8278 /* compute jump */
8279 if (!bsym)
8280 error("cannot break");
8281 *bsym = gjmp(*bsym);
8282 next();
8283 skip(';');
8284 } else if (tok == TOK_CONTINUE) {
8285 /* compute jump */
8286 if (!csym)
8287 error("cannot continue");
8288 *csym = gjmp(*csym);
8289 next();
8290 skip(';');
8291 } else if (tok == TOK_FOR) {
8292 int e;
8293 next();
8294 skip('(');
8295 if (tok != ';') {
8296 gexpr();
8297 vpop();
8299 skip(';');
8300 d = ind;
8301 c = ind;
8302 a = 0;
8303 b = 0;
8304 if (tok != ';') {
8305 gexpr();
8306 a = gtst(1, 0);
8308 skip(';');
8309 if (tok != ')') {
8310 e = gjmp(0);
8311 c = ind;
8312 gexpr();
8313 vpop();
8314 gjmp_addr(d);
8315 gsym(e);
8317 skip(')');
8318 block(&a, &b, case_sym, def_sym, case_reg, 0);
8319 gjmp_addr(c);
8320 gsym(a);
8321 gsym_addr(b, c);
8322 } else
8323 if (tok == TOK_DO) {
8324 next();
8325 a = 0;
8326 b = 0;
8327 d = ind;
8328 block(&a, &b, case_sym, def_sym, case_reg, 0);
8329 skip(TOK_WHILE);
8330 skip('(');
8331 gsym(b);
8332 gexpr();
8333 c = gtst(0, 0);
8334 gsym_addr(c, d);
8335 skip(')');
8336 gsym(a);
8337 skip(';');
8338 } else
8339 if (tok == TOK_SWITCH) {
8340 next();
8341 skip('(');
8342 gexpr();
8343 /* XXX: other types than integer */
8344 case_reg = gv(RC_INT);
8345 vpop();
8346 skip(')');
8347 a = 0;
8348 b = gjmp(0); /* jump to first case */
8349 c = 0;
8350 block(&a, csym, &b, &c, case_reg, 0);
8351 /* if no default, jmp after switch */
8352 if (c == 0)
8353 c = ind;
8354 /* default label */
8355 gsym_addr(b, c);
8356 /* break label */
8357 gsym(a);
8358 } else
8359 if (tok == TOK_CASE) {
8360 int v1, v2;
8361 if (!case_sym)
8362 expect("switch");
8363 next();
8364 v1 = expr_const();
8365 v2 = v1;
8366 if (gnu_ext && tok == TOK_DOTS) {
8367 next();
8368 v2 = expr_const();
8369 if (v2 < v1)
8370 warning("empty case range");
8372 /* since a case is like a label, we must skip it with a jmp */
8373 b = gjmp(0);
8374 gsym(*case_sym);
8375 vseti(case_reg, 0);
8376 vpushi(v1);
8377 if (v1 == v2) {
8378 gen_op(TOK_EQ);
8379 *case_sym = gtst(1, 0);
8380 } else {
8381 gen_op(TOK_GE);
8382 *case_sym = gtst(1, 0);
8383 vseti(case_reg, 0);
8384 vpushi(v2);
8385 gen_op(TOK_LE);
8386 *case_sym = gtst(1, *case_sym);
8388 gsym(b);
8389 skip(':');
8390 is_expr = 0;
8391 goto block_after_label;
8392 } else
8393 if (tok == TOK_DEFAULT) {
8394 next();
8395 skip(':');
8396 if (!def_sym)
8397 expect("switch");
8398 if (*def_sym)
8399 error("too many 'default'");
8400 *def_sym = ind;
8401 is_expr = 0;
8402 goto block_after_label;
8403 } else
8404 if (tok == TOK_GOTO) {
8405 next();
8406 if (tok == '*' && gnu_ext) {
8407 /* computed goto */
8408 next();
8409 gexpr();
8410 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
8411 expect("pointer");
8412 ggoto();
8413 } else if (tok >= TOK_UIDENT) {
8414 s = label_find(tok);
8415 /* put forward definition if needed */
8416 if (!s) {
8417 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
8418 } else {
8419 if (s->r == LABEL_DECLARED)
8420 s->r = LABEL_FORWARD;
8422 /* label already defined */
8423 if (s->r & LABEL_FORWARD)
8424 s->next = (void *)gjmp((long)s->next);
8425 else
8426 gjmp_addr((long)s->next);
8427 next();
8428 } else {
8429 expect("label identifier");
8431 skip(';');
8432 } else if (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3) {
8433 asm_instr();
8434 } else {
8435 b = is_label();
8436 if (b) {
8437 /* label case */
8438 s = label_find(b);
8439 if (s) {
8440 if (s->r == LABEL_DEFINED)
8441 error("duplicate label '%s'", get_tok_str(s->v, NULL));
8442 gsym((long)s->next);
8443 s->r = LABEL_DEFINED;
8444 } else {
8445 s = label_push(&global_label_stack, b, LABEL_DEFINED);
8447 s->next = (void *)ind;
8448 /* we accept this, but it is a mistake */
8449 block_after_label:
8450 if (tok == '}') {
8451 warning("deprecated use of label at end of compound statement");
8452 } else {
8453 if (is_expr)
8454 vpop();
8455 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
8457 } else {
8458 /* expression case */
8459 if (tok != ';') {
8460 if (is_expr) {
8461 vpop();
8462 gexpr();
8463 } else {
8464 gexpr();
8465 vpop();
8468 skip(';');
8473 /* t is the array or struct type. c is the array or struct
8474 address. cur_index/cur_field is the pointer to the current
8475 value. 'size_only' is true if only size info is needed (only used
8476 in arrays) */
8477 static void decl_designator(CType *type, Section *sec, unsigned long c,
8478 int *cur_index, Sym **cur_field,
8479 int size_only)
8481 Sym *s, *f;
8482 int notfirst, index, index_last, align, l, nb_elems, elem_size;
8483 CType type1;
8485 notfirst = 0;
8486 elem_size = 0;
8487 nb_elems = 1;
8488 if (gnu_ext && (l = is_label()) != 0)
8489 goto struct_field;
8490 while (tok == '[' || tok == '.') {
8491 if (tok == '[') {
8492 if (!(type->t & VT_ARRAY))
8493 expect("array type");
8494 s = type->ref;
8495 next();
8496 index = expr_const();
8497 if (index < 0 || (s->c >= 0 && index >= s->c))
8498 expect("invalid index");
8499 if (tok == TOK_DOTS && gnu_ext) {
8500 next();
8501 index_last = expr_const();
8502 if (index_last < 0 ||
8503 (s->c >= 0 && index_last >= s->c) ||
8504 index_last < index)
8505 expect("invalid index");
8506 } else {
8507 index_last = index;
8509 skip(']');
8510 if (!notfirst)
8511 *cur_index = index_last;
8512 type = pointed_type(type);
8513 elem_size = type_size(type, &align);
8514 c += index * elem_size;
8515 /* NOTE: we only support ranges for last designator */
8516 nb_elems = index_last - index + 1;
8517 if (nb_elems != 1) {
8518 notfirst = 1;
8519 break;
8521 } else {
8522 next();
8523 l = tok;
8524 next();
8525 struct_field:
8526 if ((type->t & VT_BTYPE) != VT_STRUCT)
8527 expect("struct/union type");
8528 s = type->ref;
8529 l |= SYM_FIELD;
8530 f = s->next;
8531 while (f) {
8532 if (f->v == l)
8533 break;
8534 f = f->next;
8536 if (!f)
8537 expect("field");
8538 if (!notfirst)
8539 *cur_field = f;
8540 /* XXX: fix this mess by using explicit storage field */
8541 type1 = f->type;
8542 type1.t |= (type->t & ~VT_TYPE);
8543 type = &type1;
8544 c += f->c;
8546 notfirst = 1;
8548 if (notfirst) {
8549 if (tok == '=') {
8550 next();
8551 } else {
8552 if (!gnu_ext)
8553 expect("=");
8555 } else {
8556 if (type->t & VT_ARRAY) {
8557 index = *cur_index;
8558 type = pointed_type(type);
8559 c += index * type_size(type, &align);
8560 } else {
8561 f = *cur_field;
8562 if (!f)
8563 error("too many field init");
8564 /* XXX: fix this mess by using explicit storage field */
8565 type1 = f->type;
8566 type1.t |= (type->t & ~VT_TYPE);
8567 type = &type1;
8568 c += f->c;
8571 decl_initializer(type, sec, c, 0, size_only);
8573 /* XXX: make it more general */
8574 if (!size_only && nb_elems > 1) {
8575 unsigned long c_end;
8576 uint8_t *src, *dst;
8577 int i;
8579 if (!sec)
8580 error("range init not supported yet for dynamic storage");
8581 c_end = c + nb_elems * elem_size;
8582 if (c_end > sec->data_allocated)
8583 section_realloc(sec, c_end);
8584 src = sec->data + c;
8585 dst = src;
8586 for(i = 1; i < nb_elems; i++) {
8587 dst += elem_size;
8588 memcpy(dst, src, elem_size);
8593 #define EXPR_VAL 0
8594 #define EXPR_CONST 1
8595 #define EXPR_ANY 2
8597 /* store a value or an expression directly in global data or in local array */
8598 static void init_putv(CType *type, Section *sec, unsigned long c,
8599 int v, int expr_type)
8601 int saved_global_expr, bt, bit_pos, bit_size;
8602 void *ptr;
8603 unsigned long long bit_mask;
8604 CType dtype;
8606 switch(expr_type) {
8607 case EXPR_VAL:
8608 vpushi(v);
8609 break;
8610 case EXPR_CONST:
8611 /* compound literals must be allocated globally in this case */
8612 saved_global_expr = global_expr;
8613 global_expr = 1;
8614 expr_const1();
8615 global_expr = saved_global_expr;
8616 /* NOTE: symbols are accepted */
8617 if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST)
8618 error("initializer element is not constant");
8619 break;
8620 case EXPR_ANY:
8621 expr_eq();
8622 break;
8625 dtype = *type;
8626 dtype.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
8628 if (sec) {
8629 /* XXX: not portable */
8630 /* XXX: generate error if incorrect relocation */
8631 gen_assign_cast(&dtype);
8632 bt = type->t & VT_BTYPE;
8633 ptr = sec->data + c;
8634 /* XXX: make code faster ? */
8635 if (!(type->t & VT_BITFIELD)) {
8636 bit_pos = 0;
8637 bit_size = 32;
8638 bit_mask = -1LL;
8639 } else {
8640 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
8641 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
8642 bit_mask = (1LL << bit_size) - 1;
8644 if ((vtop->r & VT_SYM) &&
8645 (bt == VT_BYTE ||
8646 bt == VT_SHORT ||
8647 bt == VT_DOUBLE ||
8648 bt == VT_LDOUBLE ||
8649 bt == VT_LLONG ||
8650 (bt == VT_INT && bit_size != 32)))
8651 error("initializer element is not computable at load time");
8652 switch(bt) {
8653 case VT_BYTE:
8654 *(char *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8655 break;
8656 case VT_SHORT:
8657 *(short *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8658 break;
8659 case VT_DOUBLE:
8660 *(double *)ptr = vtop->c.d;
8661 break;
8662 case VT_LDOUBLE:
8663 *(long double *)ptr = vtop->c.ld;
8664 break;
8665 case VT_LLONG:
8666 *(long long *)ptr |= (vtop->c.ll & bit_mask) << bit_pos;
8667 break;
8668 default:
8669 if (vtop->r & VT_SYM) {
8670 greloc(sec, vtop->sym, c, R_DATA_32);
8672 *(int *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8673 break;
8675 vtop--;
8676 } else {
8677 vset(&dtype, VT_LOCAL|VT_LVAL, c);
8678 vswap();
8679 vstore();
8680 vpop();
8684 /* put zeros for variable based init */
8685 static void init_putz(CType *t, Section *sec, unsigned long c, int size)
8687 if (sec) {
8688 /* nothing to do because globals are already set to zero */
8689 } else {
8690 vpush_global_sym(&func_old_type, TOK_memset);
8691 vseti(VT_LOCAL, c);
8692 vpushi(0);
8693 vpushi(size);
8694 gfunc_call(3);
8698 /* 't' contains the type and storage info. 'c' is the offset of the
8699 object in section 'sec'. If 'sec' is NULL, it means stack based
8700 allocation. 'first' is true if array '{' must be read (multi
8701 dimension implicit array init handling). 'size_only' is true if
8702 size only evaluation is wanted (only for arrays). */
8703 static void decl_initializer(CType *type, Section *sec, unsigned long c,
8704 int first, int size_only)
8706 int index, array_length, n, no_oblock, nb, parlevel, i;
8707 int size1, align1, expr_type;
8708 Sym *s, *f;
8709 CType *t1;
8711 if (type->t & VT_ARRAY) {
8712 s = type->ref;
8713 n = s->c;
8714 array_length = 0;
8715 t1 = pointed_type(type);
8716 size1 = type_size(t1, &align1);
8718 no_oblock = 1;
8719 if ((first && tok != TOK_LSTR && tok != TOK_STR) ||
8720 tok == '{') {
8721 skip('{');
8722 no_oblock = 0;
8725 /* only parse strings here if correct type (otherwise: handle
8726 them as ((w)char *) expressions */
8727 if ((tok == TOK_LSTR &&
8728 #ifdef TCC_TARGET_PE
8729 (t1->t & VT_BTYPE) == VT_SHORT && (t1->t & VT_UNSIGNED)
8730 #else
8731 (t1->t & VT_BTYPE) == VT_INT
8732 #endif
8733 ) || (tok == TOK_STR && (t1->t & VT_BTYPE) == VT_BYTE)) {
8734 while (tok == TOK_STR || tok == TOK_LSTR) {
8735 int cstr_len, ch;
8736 CString *cstr;
8738 cstr = tokc.cstr;
8739 /* compute maximum number of chars wanted */
8740 if (tok == TOK_STR)
8741 cstr_len = cstr->size;
8742 else
8743 cstr_len = cstr->size / sizeof(nwchar_t);
8744 cstr_len--;
8745 nb = cstr_len;
8746 if (n >= 0 && nb > (n - array_length))
8747 nb = n - array_length;
8748 if (!size_only) {
8749 if (cstr_len > nb)
8750 warning("initializer-string for array is too long");
8751 /* in order to go faster for common case (char
8752 string in global variable, we handle it
8753 specifically */
8754 if (sec && tok == TOK_STR && size1 == 1) {
8755 memcpy(sec->data + c + array_length, cstr->data, nb);
8756 } else {
8757 for(i=0;i<nb;i++) {
8758 if (tok == TOK_STR)
8759 ch = ((unsigned char *)cstr->data)[i];
8760 else
8761 ch = ((nwchar_t *)cstr->data)[i];
8762 init_putv(t1, sec, c + (array_length + i) * size1,
8763 ch, EXPR_VAL);
8767 array_length += nb;
8768 next();
8770 /* only add trailing zero if enough storage (no
8771 warning in this case since it is standard) */
8772 if (n < 0 || array_length < n) {
8773 if (!size_only) {
8774 init_putv(t1, sec, c + (array_length * size1), 0, EXPR_VAL);
8776 array_length++;
8778 } else {
8779 index = 0;
8780 while (tok != '}') {
8781 decl_designator(type, sec, c, &index, NULL, size_only);
8782 if (n >= 0 && index >= n)
8783 error("index too large");
8784 /* must put zero in holes (note that doing it that way
8785 ensures that it even works with designators) */
8786 if (!size_only && array_length < index) {
8787 init_putz(t1, sec, c + array_length * size1,
8788 (index - array_length) * size1);
8790 index++;
8791 if (index > array_length)
8792 array_length = index;
8793 /* special test for multi dimensional arrays (may not
8794 be strictly correct if designators are used at the
8795 same time) */
8796 if (index >= n && no_oblock)
8797 break;
8798 if (tok == '}')
8799 break;
8800 skip(',');
8803 if (!no_oblock)
8804 skip('}');
8805 /* put zeros at the end */
8806 if (!size_only && n >= 0 && array_length < n) {
8807 init_putz(t1, sec, c + array_length * size1,
8808 (n - array_length) * size1);
8810 /* patch type size if needed */
8811 if (n < 0)
8812 s->c = array_length;
8813 } else if ((type->t & VT_BTYPE) == VT_STRUCT &&
8814 (sec || !first || tok == '{')) {
8815 int par_count;
8817 /* NOTE: the previous test is a specific case for automatic
8818 struct/union init */
8819 /* XXX: union needs only one init */
8821 /* XXX: this test is incorrect for local initializers
8822 beginning with ( without {. It would be much more difficult
8823 to do it correctly (ideally, the expression parser should
8824 be used in all cases) */
8825 par_count = 0;
8826 if (tok == '(') {
8827 AttributeDef ad1;
8828 CType type1;
8829 next();
8830 while (tok == '(') {
8831 par_count++;
8832 next();
8834 if (!parse_btype(&type1, &ad1))
8835 expect("cast");
8836 type_decl(&type1, &ad1, &n, TYPE_ABSTRACT);
8837 #if 0
8838 if (!is_assignable_types(type, &type1))
8839 error("invalid type for cast");
8840 #endif
8841 skip(')');
8843 no_oblock = 1;
8844 if (first || tok == '{') {
8845 skip('{');
8846 no_oblock = 0;
8848 s = type->ref;
8849 f = s->next;
8850 array_length = 0;
8851 index = 0;
8852 n = s->c;
8853 while (tok != '}') {
8854 decl_designator(type, sec, c, NULL, &f, size_only);
8855 index = f->c;
8856 if (!size_only && array_length < index) {
8857 init_putz(type, sec, c + array_length,
8858 index - array_length);
8860 index = index + type_size(&f->type, &align1);
8861 if (index > array_length)
8862 array_length = index;
8863 f = f->next;
8864 if (no_oblock && f == NULL)
8865 break;
8866 if (tok == '}')
8867 break;
8868 skip(',');
8870 /* put zeros at the end */
8871 if (!size_only && array_length < n) {
8872 init_putz(type, sec, c + array_length,
8873 n - array_length);
8875 if (!no_oblock)
8876 skip('}');
8877 while (par_count) {
8878 skip(')');
8879 par_count--;
8881 } else if (tok == '{') {
8882 next();
8883 decl_initializer(type, sec, c, first, size_only);
8884 skip('}');
8885 } else if (size_only) {
8886 /* just skip expression */
8887 parlevel = 0;
8888 while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
8889 tok != -1) {
8890 if (tok == '(')
8891 parlevel++;
8892 else if (tok == ')')
8893 parlevel--;
8894 next();
8896 } else {
8897 /* currently, we always use constant expression for globals
8898 (may change for scripting case) */
8899 expr_type = EXPR_CONST;
8900 if (!sec)
8901 expr_type = EXPR_ANY;
8902 init_putv(type, sec, c, 0, expr_type);
8906 /* parse an initializer for type 't' if 'has_init' is non zero, and
8907 allocate space in local or global data space ('r' is either
8908 VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
8909 variable 'v' of scope 'scope' is declared before initializers are
8910 parsed. If 'v' is zero, then a reference to the new object is put
8911 in the value stack. If 'has_init' is 2, a special parsing is done
8912 to handle string constants. */
8913 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
8914 int has_init, int v, int scope)
8916 int size, align, addr, data_offset;
8917 int level;
8918 ParseState saved_parse_state;
8919 TokenString init_str;
8920 Section *sec;
8922 size = type_size(type, &align);
8923 /* If unknown size, we must evaluate it before
8924 evaluating initializers because
8925 initializers can generate global data too
8926 (e.g. string pointers or ISOC99 compound
8927 literals). It also simplifies local
8928 initializers handling */
8929 tok_str_new(&init_str);
8930 if (size < 0) {
8931 if (!has_init)
8932 error("unknown type size");
8933 /* get all init string */
8934 if (has_init == 2) {
8935 /* only get strings */
8936 while (tok == TOK_STR || tok == TOK_LSTR) {
8937 tok_str_add_tok(&init_str);
8938 next();
8940 } else {
8941 level = 0;
8942 while (level > 0 || (tok != ',' && tok != ';')) {
8943 if (tok < 0)
8944 error("unexpected end of file in initializer");
8945 tok_str_add_tok(&init_str);
8946 if (tok == '{')
8947 level++;
8948 else if (tok == '}') {
8949 if (level == 0)
8950 break;
8951 level--;
8953 next();
8956 tok_str_add(&init_str, -1);
8957 tok_str_add(&init_str, 0);
8959 /* compute size */
8960 save_parse_state(&saved_parse_state);
8962 macro_ptr = init_str.str;
8963 next();
8964 decl_initializer(type, NULL, 0, 1, 1);
8965 /* prepare second initializer parsing */
8966 macro_ptr = init_str.str;
8967 next();
8969 /* if still unknown size, error */
8970 size = type_size(type, &align);
8971 if (size < 0)
8972 error("unknown type size");
8974 /* take into account specified alignment if bigger */
8975 if (ad->aligned) {
8976 if (ad->aligned > align)
8977 align = ad->aligned;
8978 } else if (ad->packed) {
8979 align = 1;
8981 if ((r & VT_VALMASK) == VT_LOCAL) {
8982 sec = NULL;
8983 if (do_bounds_check && (type->t & VT_ARRAY))
8984 loc--;
8985 loc = (loc - size) & -align;
8986 addr = loc;
8987 /* handles bounds */
8988 /* XXX: currently, since we do only one pass, we cannot track
8989 '&' operators, so we add only arrays */
8990 if (do_bounds_check && (type->t & VT_ARRAY)) {
8991 unsigned long *bounds_ptr;
8992 /* add padding between regions */
8993 loc--;
8994 /* then add local bound info */
8995 bounds_ptr = section_ptr_add(lbounds_section, 2 * sizeof(unsigned long));
8996 bounds_ptr[0] = addr;
8997 bounds_ptr[1] = size;
8999 if (v) {
9000 /* local variable */
9001 sym_push(v, type, r, addr);
9002 } else {
9003 /* push local reference */
9004 vset(type, r, addr);
9006 } else {
9007 Sym *sym;
9009 sym = NULL;
9010 if (v && scope == VT_CONST) {
9011 /* see if the symbol was already defined */
9012 sym = sym_find(v);
9013 if (sym) {
9014 if (!is_compatible_types(&sym->type, type))
9015 error("incompatible types for redefinition of '%s'",
9016 get_tok_str(v, NULL));
9017 if (sym->type.t & VT_EXTERN) {
9018 /* if the variable is extern, it was not allocated */
9019 sym->type.t &= ~VT_EXTERN;
9020 /* set array size if it was ommited in extern
9021 declaration */
9022 if ((sym->type.t & VT_ARRAY) &&
9023 sym->type.ref->c < 0 &&
9024 type->ref->c >= 0)
9025 sym->type.ref->c = type->ref->c;
9026 } else {
9027 /* we accept several definitions of the same
9028 global variable. this is tricky, because we
9029 must play with the SHN_COMMON type of the symbol */
9030 /* XXX: should check if the variable was already
9031 initialized. It is incorrect to initialized it
9032 twice */
9033 /* no init data, we won't add more to the symbol */
9034 if (!has_init)
9035 goto no_alloc;
9040 /* allocate symbol in corresponding section */
9041 sec = ad->section;
9042 if (!sec) {
9043 if (has_init)
9044 sec = data_section;
9045 else if (tcc_state->nocommon)
9046 sec = bss_section;
9048 if (sec) {
9049 data_offset = sec->data_offset;
9050 data_offset = (data_offset + align - 1) & -align;
9051 addr = data_offset;
9052 /* very important to increment global pointer at this time
9053 because initializers themselves can create new initializers */
9054 data_offset += size;
9055 /* add padding if bound check */
9056 if (do_bounds_check)
9057 data_offset++;
9058 sec->data_offset = data_offset;
9059 /* allocate section space to put the data */
9060 if (sec->sh_type != SHT_NOBITS &&
9061 data_offset > sec->data_allocated)
9062 section_realloc(sec, data_offset);
9063 /* align section if needed */
9064 if (align > sec->sh_addralign)
9065 sec->sh_addralign = align;
9066 } else {
9067 addr = 0; /* avoid warning */
9070 if (v) {
9071 if (scope != VT_CONST || !sym) {
9072 sym = sym_push(v, type, r | VT_SYM, 0);
9074 /* update symbol definition */
9075 if (sec) {
9076 put_extern_sym(sym, sec, addr, size);
9077 } else {
9078 Elf32_Sym *esym;
9079 /* put a common area */
9080 put_extern_sym(sym, NULL, align, size);
9081 /* XXX: find a nicer way */
9082 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
9083 esym->st_shndx = SHN_COMMON;
9085 } else {
9086 CValue cval;
9088 /* push global reference */
9089 sym = get_sym_ref(type, sec, addr, size);
9090 cval.ul = 0;
9091 vsetc(type, VT_CONST | VT_SYM, &cval);
9092 vtop->sym = sym;
9095 /* handles bounds now because the symbol must be defined
9096 before for the relocation */
9097 if (do_bounds_check) {
9098 unsigned long *bounds_ptr;
9100 greloc(bounds_section, sym, bounds_section->data_offset, R_DATA_32);
9101 /* then add global bound info */
9102 bounds_ptr = section_ptr_add(bounds_section, 2 * sizeof(long));
9103 bounds_ptr[0] = 0; /* relocated */
9104 bounds_ptr[1] = size;
9107 if (has_init) {
9108 decl_initializer(type, sec, addr, 1, 0);
9109 /* restore parse state if needed */
9110 if (init_str.str) {
9111 tok_str_free(init_str.str);
9112 restore_parse_state(&saved_parse_state);
9115 no_alloc: ;
9118 void put_func_debug(Sym *sym)
9120 char buf[512];
9122 /* stabs info */
9123 /* XXX: we put here a dummy type */
9124 snprintf(buf, sizeof(buf), "%s:%c1",
9125 funcname, sym->type.t & VT_STATIC ? 'f' : 'F');
9126 put_stabs_r(buf, N_FUN, 0, file->line_num, 0,
9127 cur_text_section, sym->c);
9128 last_ind = 0;
9129 last_line_num = 0;
9132 /* parse an old style function declaration list */
9133 /* XXX: check multiple parameter */
9134 static void func_decl_list(Sym *func_sym)
9136 AttributeDef ad;
9137 int v;
9138 Sym *s;
9139 CType btype, type;
9141 /* parse each declaration */
9142 while (tok != '{' && tok != ';' && tok != ',' && tok != TOK_EOF) {
9143 if (!parse_btype(&btype, &ad))
9144 expect("declaration list");
9145 if (((btype.t & VT_BTYPE) == VT_ENUM ||
9146 (btype.t & VT_BTYPE) == VT_STRUCT) &&
9147 tok == ';') {
9148 /* we accept no variable after */
9149 } else {
9150 for(;;) {
9151 type = btype;
9152 type_decl(&type, &ad, &v, TYPE_DIRECT);
9153 /* find parameter in function parameter list */
9154 s = func_sym->next;
9155 while (s != NULL) {
9156 if ((s->v & ~SYM_FIELD) == v)
9157 goto found;
9158 s = s->next;
9160 error("declaration for parameter '%s' but no such parameter",
9161 get_tok_str(v, NULL));
9162 found:
9163 /* check that no storage specifier except 'register' was given */
9164 if (type.t & VT_STORAGE)
9165 error("storage class specified for '%s'", get_tok_str(v, NULL));
9166 convert_parameter_type(&type);
9167 /* we can add the type (NOTE: it could be local to the function) */
9168 s->type = type;
9169 /* accept other parameters */
9170 if (tok == ',')
9171 next();
9172 else
9173 break;
9176 skip(';');
9180 /* parse a function defined by symbol 'sym' and generate its code in
9181 'cur_text_section' */
9182 static void gen_function(Sym *sym)
9184 int saved_nocode_wanted = nocode_wanted;
9185 nocode_wanted = 0;
9186 ind = cur_text_section->data_offset;
9187 /* NOTE: we patch the symbol size later */
9188 put_extern_sym(sym, cur_text_section, ind, 0);
9189 funcname = get_tok_str(sym->v, NULL);
9190 func_ind = ind;
9191 /* put debug symbol */
9192 if (do_debug)
9193 put_func_debug(sym);
9194 /* push a dummy symbol to enable local sym storage */
9195 sym_push2(&local_stack, SYM_FIELD, 0, 0);
9196 gfunc_prolog(&sym->type);
9197 rsym = 0;
9198 block(NULL, NULL, NULL, NULL, 0, 0);
9199 gsym(rsym);
9200 gfunc_epilog();
9201 cur_text_section->data_offset = ind;
9202 label_pop(&global_label_stack, NULL);
9203 sym_pop(&local_stack, NULL); /* reset local stack */
9204 /* end of function */
9205 /* patch symbol size */
9206 ((Elf32_Sym *)symtab_section->data)[sym->c].st_size =
9207 ind - func_ind;
9208 if (do_debug) {
9209 put_stabn(N_FUN, 0, 0, ind - func_ind);
9211 funcname = ""; /* for safety */
9212 func_vt.t = VT_VOID; /* for safety */
9213 ind = 0; /* for safety */
9214 nocode_wanted = saved_nocode_wanted;
9217 static void gen_inline_functions(void)
9219 Sym *sym;
9220 CType *type;
9221 int *str, inline_generated;
9223 /* iterate while inline function are referenced */
9224 for(;;) {
9225 inline_generated = 0;
9226 for(sym = global_stack; sym != NULL; sym = sym->prev) {
9227 type = &sym->type;
9228 if (((type->t & VT_BTYPE) == VT_FUNC) &&
9229 (type->t & (VT_STATIC | VT_INLINE)) ==
9230 (VT_STATIC | VT_INLINE) &&
9231 sym->c != 0) {
9232 /* the function was used: generate its code and
9233 convert it to a normal function */
9234 str = INLINE_DEF(sym->r);
9235 sym->r = VT_SYM | VT_CONST;
9236 sym->type.t &= ~VT_INLINE;
9238 macro_ptr = str;
9239 next();
9240 cur_text_section = text_section;
9241 gen_function(sym);
9242 macro_ptr = NULL; /* fail safe */
9244 tok_str_free(str);
9245 inline_generated = 1;
9248 if (!inline_generated)
9249 break;
9252 /* free all remaining inline function tokens */
9253 for(sym = global_stack; sym != NULL; sym = sym->prev) {
9254 type = &sym->type;
9255 if (((type->t & VT_BTYPE) == VT_FUNC) &&
9256 (type->t & (VT_STATIC | VT_INLINE)) ==
9257 (VT_STATIC | VT_INLINE)) {
9258 //gr printf("sym %d %s\n", sym->r, get_tok_str(sym->v, NULL));
9259 if (sym->r == (VT_SYM | VT_CONST)) //gr beware!
9260 continue;
9261 str = INLINE_DEF(sym->r);
9262 tok_str_free(str);
9263 sym->r = 0; /* fail safe */
9268 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
9269 static void decl(int l)
9271 int v, has_init, r;
9272 CType type, btype;
9273 Sym *sym;
9274 AttributeDef ad;
9276 while (1) {
9277 if (!parse_btype(&btype, &ad)) {
9278 /* skip redundant ';' */
9279 /* XXX: find more elegant solution */
9280 if (tok == ';') {
9281 next();
9282 continue;
9284 if (l == VT_CONST &&
9285 (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3)) {
9286 /* global asm block */
9287 asm_global_instr();
9288 continue;
9290 /* special test for old K&R protos without explicit int
9291 type. Only accepted when defining global data */
9292 if (l == VT_LOCAL || tok < TOK_DEFINE)
9293 break;
9294 btype.t = VT_INT;
9296 if (((btype.t & VT_BTYPE) == VT_ENUM ||
9297 (btype.t & VT_BTYPE) == VT_STRUCT) &&
9298 tok == ';') {
9299 /* we accept no variable after */
9300 next();
9301 continue;
9303 while (1) { /* iterate thru each declaration */
9304 type = btype;
9305 type_decl(&type, &ad, &v, TYPE_DIRECT);
9306 #if 0
9308 char buf[500];
9309 type_to_str(buf, sizeof(buf), &type, get_tok_str(v, NULL));
9310 printf("type = '%s'\n", buf);
9312 #endif
9313 if ((type.t & VT_BTYPE) == VT_FUNC) {
9314 /* if old style function prototype, we accept a
9315 declaration list */
9316 sym = type.ref;
9317 if (sym->c == FUNC_OLD)
9318 func_decl_list(sym);
9321 if (tok == '{') {
9322 if (l == VT_LOCAL)
9323 error("cannot use local functions");
9324 if ((type.t & VT_BTYPE) != VT_FUNC)
9325 expect("function definition");
9327 /* reject abstract declarators in function definition */
9328 sym = type.ref;
9329 while ((sym = sym->next) != NULL)
9330 if (!(sym->v & ~SYM_FIELD))
9331 expect("identifier");
9333 /* XXX: cannot do better now: convert extern line to static inline */
9334 if ((type.t & (VT_EXTERN | VT_INLINE)) == (VT_EXTERN | VT_INLINE))
9335 type.t = (type.t & ~VT_EXTERN) | VT_STATIC;
9337 sym = sym_find(v);
9338 if (sym) {
9339 if ((sym->type.t & VT_BTYPE) != VT_FUNC)
9340 goto func_error1;
9341 /* specific case: if not func_call defined, we put
9342 the one of the prototype */
9343 /* XXX: should have default value */
9344 r = sym->type.ref->r;
9345 if (FUNC_CALL(r) != FUNC_CDECL
9346 && FUNC_CALL(type.ref->r) == FUNC_CDECL)
9347 FUNC_CALL(type.ref->r) = FUNC_CALL(r);
9348 if (FUNC_EXPORT(r))
9349 FUNC_EXPORT(type.ref->r) = 1;
9351 if (!is_compatible_types(&sym->type, &type)) {
9352 func_error1:
9353 error("incompatible types for redefinition of '%s'",
9354 get_tok_str(v, NULL));
9356 /* if symbol is already defined, then put complete type */
9357 sym->type = type;
9358 } else {
9359 /* put function symbol */
9360 sym = global_identifier_push(v, type.t, 0);
9361 sym->type.ref = type.ref;
9364 /* static inline functions are just recorded as a kind
9365 of macro. Their code will be emitted at the end of
9366 the compilation unit only if they are used */
9367 if ((type.t & (VT_INLINE | VT_STATIC)) ==
9368 (VT_INLINE | VT_STATIC)) {
9369 TokenString func_str;
9370 int block_level;
9372 tok_str_new(&func_str);
9374 block_level = 0;
9375 for(;;) {
9376 int t;
9377 if (tok == TOK_EOF)
9378 error("unexpected end of file");
9379 tok_str_add_tok(&func_str);
9380 t = tok;
9381 next();
9382 if (t == '{') {
9383 block_level++;
9384 } else if (t == '}') {
9385 block_level--;
9386 if (block_level == 0)
9387 break;
9390 tok_str_add(&func_str, -1);
9391 tok_str_add(&func_str, 0);
9392 INLINE_DEF(sym->r) = func_str.str;
9393 } else {
9394 /* compute text section */
9395 cur_text_section = ad.section;
9396 if (!cur_text_section)
9397 cur_text_section = text_section;
9398 sym->r = VT_SYM | VT_CONST;
9399 gen_function(sym);
9401 break;
9402 } else {
9403 if (btype.t & VT_TYPEDEF) {
9404 /* save typedefed type */
9405 /* XXX: test storage specifiers ? */
9406 sym = sym_push(v, &type, 0, 0);
9407 sym->type.t |= VT_TYPEDEF;
9408 } else if ((type.t & VT_BTYPE) == VT_FUNC) {
9409 /* external function definition */
9410 /* specific case for func_call attribute */
9411 if (ad.func_attr)
9412 type.ref->r = ad.func_attr;
9413 external_sym(v, &type, 0);
9414 } else {
9415 /* not lvalue if array */
9416 r = 0;
9417 if (!(type.t & VT_ARRAY))
9418 r |= lvalue_type(type.t);
9419 has_init = (tok == '=');
9420 if ((btype.t & VT_EXTERN) ||
9421 ((type.t & VT_ARRAY) && (type.t & VT_STATIC) &&
9422 !has_init && l == VT_CONST && type.ref->c < 0)) {
9423 /* external variable */
9424 /* NOTE: as GCC, uninitialized global static
9425 arrays of null size are considered as
9426 extern */
9427 external_sym(v, &type, r);
9428 } else {
9429 type.t |= (btype.t & VT_STATIC); /* Retain "static". */
9430 if (type.t & VT_STATIC)
9431 r |= VT_CONST;
9432 else
9433 r |= l;
9434 if (has_init)
9435 next();
9436 decl_initializer_alloc(&type, &ad, r,
9437 has_init, v, l);
9440 if (tok != ',') {
9441 skip(';');
9442 break;
9444 next();
9450 /* better than nothing, but needs extension to handle '-E' option
9451 correctly too */
9452 static void preprocess_init(TCCState *s1)
9454 s1->include_stack_ptr = s1->include_stack;
9455 /* XXX: move that before to avoid having to initialize
9456 file->ifdef_stack_ptr ? */
9457 s1->ifdef_stack_ptr = s1->ifdef_stack;
9458 file->ifdef_stack_ptr = s1->ifdef_stack_ptr;
9460 /* XXX: not ANSI compliant: bound checking says error */
9461 vtop = vstack - 1;
9462 s1->pack_stack[0] = 0;
9463 s1->pack_stack_ptr = s1->pack_stack;
9466 /* compile the C file opened in 'file'. Return non zero if errors. */
9467 static int tcc_compile(TCCState *s1)
9469 Sym *define_start;
9470 char buf[512];
9471 volatile int section_sym;
9473 #ifdef INC_DEBUG
9474 printf("%s: **** new file\n", file->filename);
9475 #endif
9476 preprocess_init(s1);
9478 funcname = "";
9479 anon_sym = SYM_FIRST_ANOM;
9481 /* file info: full path + filename */
9482 section_sym = 0; /* avoid warning */
9483 if (do_debug) {
9484 section_sym = put_elf_sym(symtab_section, 0, 0,
9485 ELF32_ST_INFO(STB_LOCAL, STT_SECTION), 0,
9486 text_section->sh_num, NULL);
9487 getcwd(buf, sizeof(buf));
9488 #ifdef _WIN32
9489 normalize_slashes(buf);
9490 #endif
9491 pstrcat(buf, sizeof(buf), "/");
9492 put_stabs_r(buf, N_SO, 0, 0,
9493 text_section->data_offset, text_section, section_sym);
9494 put_stabs_r(file->filename, N_SO, 0, 0,
9495 text_section->data_offset, text_section, section_sym);
9497 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
9498 symbols can be safely used */
9499 put_elf_sym(symtab_section, 0, 0,
9500 ELF32_ST_INFO(STB_LOCAL, STT_FILE), 0,
9501 SHN_ABS, file->filename);
9503 /* define some often used types */
9504 int_type.t = VT_INT;
9506 char_pointer_type.t = VT_BYTE;
9507 mk_pointer(&char_pointer_type);
9509 func_old_type.t = VT_FUNC;
9510 func_old_type.ref = sym_push(SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD);
9512 #if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)
9513 float_type.t = VT_FLOAT;
9514 double_type.t = VT_DOUBLE;
9516 func_float_type.t = VT_FUNC;
9517 func_float_type.ref = sym_push(SYM_FIELD, &float_type, FUNC_CDECL, FUNC_OLD);
9518 func_double_type.t = VT_FUNC;
9519 func_double_type.ref = sym_push(SYM_FIELD, &double_type, FUNC_CDECL, FUNC_OLD);
9520 #endif
9522 #if 0
9523 /* define 'void *alloca(unsigned int)' builtin function */
9525 Sym *s1;
9527 p = anon_sym++;
9528 sym = sym_push(p, mk_pointer(VT_VOID), FUNC_CDECL, FUNC_NEW);
9529 s1 = sym_push(SYM_FIELD, VT_UNSIGNED | VT_INT, 0, 0);
9530 s1->next = NULL;
9531 sym->next = s1;
9532 sym_push(TOK_alloca, VT_FUNC | (p << VT_STRUCT_SHIFT), VT_CONST, 0);
9534 #endif
9536 define_start = define_stack;
9537 nocode_wanted = 1;
9539 if (setjmp(s1->error_jmp_buf) == 0) {
9540 s1->nb_errors = 0;
9541 s1->error_set_jmp_enabled = 1;
9543 ch = file->buf_ptr[0];
9544 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
9545 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM;
9546 next();
9547 decl(VT_CONST);
9548 if (tok != TOK_EOF)
9549 expect("declaration");
9551 /* end of translation unit info */
9552 if (do_debug) {
9553 put_stabs_r(NULL, N_SO, 0, 0,
9554 text_section->data_offset, text_section, section_sym);
9557 s1->error_set_jmp_enabled = 0;
9559 /* reset define stack, but leave -Dsymbols (may be incorrect if
9560 they are undefined) */
9561 free_defines(define_start);
9563 gen_inline_functions();
9565 sym_pop(&global_stack, NULL);
9567 return s1->nb_errors != 0 ? -1 : 0;
9570 /* Preprocess the current file */
9571 /* XXX: add line and file infos, add options to preserve spaces */
9572 static int tcc_preprocess(TCCState *s1)
9574 Sym *define_start;
9575 int last_is_space;
9577 preprocess_init(s1);
9579 define_start = define_stack;
9581 ch = file->buf_ptr[0];
9582 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
9583 parse_flags = PARSE_FLAG_ASM_COMMENTS | PARSE_FLAG_PREPROCESS |
9584 PARSE_FLAG_LINEFEED;
9585 last_is_space = 1;
9586 next();
9587 for(;;) {
9588 if (tok == TOK_EOF) {
9589 break;
9590 } else if (tok == TOK_LINEFEED) {
9591 last_is_space = 1;
9592 } else {
9593 if (!last_is_space)
9594 fputc(' ', s1->outfile);
9595 last_is_space = 0;
9597 fputs(get_tok_str(tok, &tokc), s1->outfile);
9598 next();
9600 free_defines(define_start);
9601 return 0;
9604 #ifdef LIBTCC
9605 int tcc_compile_string(TCCState *s, const char *str)
9607 BufferedFile bf1, *bf = &bf1;
9608 int ret, len;
9609 char *buf;
9611 /* init file structure */
9612 bf->fd = -1;
9613 /* XXX: avoid copying */
9614 len = strlen(str);
9615 buf = tcc_malloc(len + 1);
9616 if (!buf)
9617 return -1;
9618 memcpy(buf, str, len);
9619 buf[len] = CH_EOB;
9620 bf->buf_ptr = buf;
9621 bf->buf_end = buf + len;
9622 pstrcpy(bf->filename, sizeof(bf->filename), "<string>");
9623 bf->line_num = 1;
9624 file = bf;
9626 ret = tcc_compile(s);
9628 tcc_free(buf);
9630 /* currently, no need to close */
9631 return ret;
9633 #endif
9635 /* define a preprocessor symbol. A value can also be provided with the '=' operator */
9636 void tcc_define_symbol(TCCState *s1, const char *sym, const char *value)
9638 BufferedFile bf1, *bf = &bf1;
9640 pstrcpy(bf->buffer, IO_BUF_SIZE, sym);
9641 pstrcat(bf->buffer, IO_BUF_SIZE, " ");
9642 /* default value */
9643 if (!value)
9644 value = "1";
9645 pstrcat(bf->buffer, IO_BUF_SIZE, value);
9647 /* init file structure */
9648 bf->fd = -1;
9649 bf->buf_ptr = bf->buffer;
9650 bf->buf_end = bf->buffer + strlen(bf->buffer);
9651 *bf->buf_end = CH_EOB;
9652 bf->filename[0] = '\0';
9653 bf->line_num = 1;
9654 file = bf;
9656 s1->include_stack_ptr = s1->include_stack;
9658 /* parse with define parser */
9659 ch = file->buf_ptr[0];
9660 next_nomacro();
9661 parse_define();
9662 file = NULL;
9665 /* undefine a preprocessor symbol */
9666 void tcc_undefine_symbol(TCCState *s1, const char *sym)
9668 TokenSym *ts;
9669 Sym *s;
9670 ts = tok_alloc(sym, strlen(sym));
9671 s = define_find(ts->tok);
9672 /* undefine symbol by putting an invalid name */
9673 if (s)
9674 define_undef(s);
9677 #ifdef CONFIG_TCC_ASM
9679 #ifdef TCC_TARGET_I386
9680 #include "i386-asm.c"
9681 #endif
9682 #include "tccasm.c"
9684 #else
9685 static void asm_instr(void)
9687 error("inline asm() not supported");
9689 static void asm_global_instr(void)
9691 error("inline asm() not supported");
9693 #endif
9695 #include "tccelf.c"
9697 #ifdef TCC_TARGET_COFF
9698 #include "tcccoff.c"
9699 #endif
9701 #ifdef TCC_TARGET_PE
9702 #include "tccpe.c"
9703 #endif
9705 /* print the position in the source file of PC value 'pc' by reading
9706 the stabs debug information */
9707 static void rt_printline(unsigned long wanted_pc)
9709 Stab_Sym *sym, *sym_end;
9710 char func_name[128], last_func_name[128];
9711 unsigned long func_addr, last_pc, pc;
9712 const char *incl_files[INCLUDE_STACK_SIZE];
9713 int incl_index, len, last_line_num, i;
9714 const char *str, *p;
9716 fprintf(stderr, "0x%08lx:", wanted_pc);
9718 func_name[0] = '\0';
9719 func_addr = 0;
9720 incl_index = 0;
9721 last_func_name[0] = '\0';
9722 last_pc = 0xffffffff;
9723 last_line_num = 1;
9724 sym = (Stab_Sym *)stab_section->data + 1;
9725 sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset);
9726 while (sym < sym_end) {
9727 switch(sym->n_type) {
9728 /* function start or end */
9729 case N_FUN:
9730 if (sym->n_strx == 0) {
9731 /* we test if between last line and end of function */
9732 pc = sym->n_value + func_addr;
9733 if (wanted_pc >= last_pc && wanted_pc < pc)
9734 goto found;
9735 func_name[0] = '\0';
9736 func_addr = 0;
9737 } else {
9738 str = stabstr_section->data + sym->n_strx;
9739 p = strchr(str, ':');
9740 if (!p) {
9741 pstrcpy(func_name, sizeof(func_name), str);
9742 } else {
9743 len = p - str;
9744 if (len > sizeof(func_name) - 1)
9745 len = sizeof(func_name) - 1;
9746 memcpy(func_name, str, len);
9747 func_name[len] = '\0';
9749 func_addr = sym->n_value;
9751 break;
9752 /* line number info */
9753 case N_SLINE:
9754 pc = sym->n_value + func_addr;
9755 if (wanted_pc >= last_pc && wanted_pc < pc)
9756 goto found;
9757 last_pc = pc;
9758 last_line_num = sym->n_desc;
9759 /* XXX: slow! */
9760 strcpy(last_func_name, func_name);
9761 break;
9762 /* include files */
9763 case N_BINCL:
9764 str = stabstr_section->data + sym->n_strx;
9765 add_incl:
9766 if (incl_index < INCLUDE_STACK_SIZE) {
9767 incl_files[incl_index++] = str;
9769 break;
9770 case N_EINCL:
9771 if (incl_index > 1)
9772 incl_index--;
9773 break;
9774 case N_SO:
9775 if (sym->n_strx == 0) {
9776 incl_index = 0; /* end of translation unit */
9777 } else {
9778 str = stabstr_section->data + sym->n_strx;
9779 /* do not add path */
9780 len = strlen(str);
9781 if (len > 0 && str[len - 1] != '/')
9782 goto add_incl;
9784 break;
9786 sym++;
9789 /* second pass: we try symtab symbols (no line number info) */
9790 incl_index = 0;
9792 Elf32_Sym *sym, *sym_end;
9793 int type;
9795 sym_end = (Elf32_Sym *)(symtab_section->data + symtab_section->data_offset);
9796 for(sym = (Elf32_Sym *)symtab_section->data + 1;
9797 sym < sym_end;
9798 sym++) {
9799 type = ELF32_ST_TYPE(sym->st_info);
9800 if (type == STT_FUNC) {
9801 if (wanted_pc >= sym->st_value &&
9802 wanted_pc < sym->st_value + sym->st_size) {
9803 pstrcpy(last_func_name, sizeof(last_func_name),
9804 strtab_section->data + sym->st_name);
9805 goto found;
9810 /* did not find any info: */
9811 fprintf(stderr, " ???\n");
9812 return;
9813 found:
9814 if (last_func_name[0] != '\0') {
9815 fprintf(stderr, " %s()", last_func_name);
9817 if (incl_index > 0) {
9818 fprintf(stderr, " (%s:%d",
9819 incl_files[incl_index - 1], last_line_num);
9820 for(i = incl_index - 2; i >= 0; i--)
9821 fprintf(stderr, ", included from %s", incl_files[i]);
9822 fprintf(stderr, ")");
9824 fprintf(stderr, "\n");
9827 #if !defined(_WIN32) && !defined(CONFIG_TCCBOOT)
9829 #ifdef __i386__
9831 /* fix for glibc 2.1 */
9832 #ifndef REG_EIP
9833 #define REG_EIP EIP
9834 #define REG_EBP EBP
9835 #endif
9837 /* return the PC at frame level 'level'. Return non zero if not found */
9838 static int rt_get_caller_pc(unsigned long *paddr,
9839 ucontext_t *uc, int level)
9841 unsigned long fp;
9842 int i;
9844 if (level == 0) {
9845 #if defined(__FreeBSD__)
9846 *paddr = uc->uc_mcontext.mc_eip;
9847 #elif defined(__dietlibc__)
9848 *paddr = uc->uc_mcontext.eip;
9849 #else
9850 *paddr = uc->uc_mcontext.gregs[REG_EIP];
9851 #endif
9852 return 0;
9853 } else {
9854 #if defined(__FreeBSD__)
9855 fp = uc->uc_mcontext.mc_ebp;
9856 #elif defined(__dietlibc__)
9857 fp = uc->uc_mcontext.ebp;
9858 #else
9859 fp = uc->uc_mcontext.gregs[REG_EBP];
9860 #endif
9861 for(i=1;i<level;i++) {
9862 /* XXX: check address validity with program info */
9863 if (fp <= 0x1000 || fp >= 0xc0000000)
9864 return -1;
9865 fp = ((unsigned long *)fp)[0];
9867 *paddr = ((unsigned long *)fp)[1];
9868 return 0;
9871 #else
9873 #warning add arch specific rt_get_caller_pc()
9875 static int rt_get_caller_pc(unsigned long *paddr,
9876 ucontext_t *uc, int level)
9878 return -1;
9880 #endif
9882 /* emit a run time error at position 'pc' */
9883 void rt_error(ucontext_t *uc, const char *fmt, ...)
9885 va_list ap;
9886 unsigned long pc;
9887 int i;
9889 va_start(ap, fmt);
9890 fprintf(stderr, "Runtime error: ");
9891 vfprintf(stderr, fmt, ap);
9892 fprintf(stderr, "\n");
9893 for(i=0;i<num_callers;i++) {
9894 if (rt_get_caller_pc(&pc, uc, i) < 0)
9895 break;
9896 if (i == 0)
9897 fprintf(stderr, "at ");
9898 else
9899 fprintf(stderr, "by ");
9900 rt_printline(pc);
9902 exit(255);
9903 va_end(ap);
9906 /* signal handler for fatal errors */
9907 static void sig_error(int signum, siginfo_t *siginf, void *puc)
9909 ucontext_t *uc = puc;
9911 switch(signum) {
9912 case SIGFPE:
9913 switch(siginf->si_code) {
9914 case FPE_INTDIV:
9915 case FPE_FLTDIV:
9916 rt_error(uc, "division by zero");
9917 break;
9918 default:
9919 rt_error(uc, "floating point exception");
9920 break;
9922 break;
9923 case SIGBUS:
9924 case SIGSEGV:
9925 if (rt_bound_error_msg && *rt_bound_error_msg)
9926 rt_error(uc, *rt_bound_error_msg);
9927 else
9928 rt_error(uc, "dereferencing invalid pointer");
9929 break;
9930 case SIGILL:
9931 rt_error(uc, "illegal instruction");
9932 break;
9933 case SIGABRT:
9934 rt_error(uc, "abort() called");
9935 break;
9936 default:
9937 rt_error(uc, "caught signal %d", signum);
9938 break;
9940 exit(255);
9942 #endif
9944 /* do all relocations (needed before using tcc_get_symbol()) */
9945 int tcc_relocate(TCCState *s1)
9947 Section *s;
9948 int i;
9950 s1->nb_errors = 0;
9952 #ifdef TCC_TARGET_PE
9953 pe_add_runtime(s1);
9954 #else
9955 tcc_add_runtime(s1);
9956 #endif
9958 relocate_common_syms();
9960 tcc_add_linker_symbols(s1);
9961 #ifndef TCC_TARGET_PE
9962 build_got_entries(s1);
9963 #endif
9964 /* compute relocation address : section are relocated in place. We
9965 also alloc the bss space */
9966 for(i = 1; i < s1->nb_sections; i++) {
9967 s = s1->sections[i];
9968 if (s->sh_flags & SHF_ALLOC) {
9969 if (s->sh_type == SHT_NOBITS)
9970 s->data = tcc_mallocz(s->data_offset);
9971 s->sh_addr = (unsigned long)s->data;
9975 relocate_syms(s1, 1);
9977 if (s1->nb_errors != 0)
9978 return -1;
9980 /* relocate each section */
9981 for(i = 1; i < s1->nb_sections; i++) {
9982 s = s1->sections[i];
9983 if (s->reloc)
9984 relocate_section(s1, s);
9987 /* mark executable sections as executable in memory */
9988 for(i = 1; i < s1->nb_sections; i++) {
9989 s = s1->sections[i];
9990 if ((s->sh_flags & (SHF_ALLOC | SHF_EXECINSTR)) ==
9991 (SHF_ALLOC | SHF_EXECINSTR))
9992 set_pages_executable(s->data, s->data_offset);
9994 return 0;
9997 /* launch the compiled program with the given arguments */
9998 int tcc_run(TCCState *s1, int argc, char **argv)
10000 int (*prog_main)(int, char **);
10002 if (tcc_relocate(s1) < 0)
10003 return -1;
10005 prog_main = tcc_get_symbol_err(s1, "main");
10007 if (do_debug) {
10008 #if defined(_WIN32) || defined(CONFIG_TCCBOOT)
10009 error("debug mode currently not available for Windows");
10010 #else
10011 struct sigaction sigact;
10012 /* install TCC signal handlers to print debug info on fatal
10013 runtime errors */
10014 sigact.sa_flags = SA_SIGINFO | SA_RESETHAND;
10015 sigact.sa_sigaction = sig_error;
10016 sigemptyset(&sigact.sa_mask);
10017 sigaction(SIGFPE, &sigact, NULL);
10018 sigaction(SIGILL, &sigact, NULL);
10019 sigaction(SIGSEGV, &sigact, NULL);
10020 sigaction(SIGBUS, &sigact, NULL);
10021 sigaction(SIGABRT, &sigact, NULL);
10022 #endif
10025 #ifdef CONFIG_TCC_BCHECK
10026 if (do_bounds_check) {
10027 void (*bound_init)(void);
10029 /* set error function */
10030 rt_bound_error_msg = (void *)tcc_get_symbol_err(s1,
10031 "__bound_error_msg");
10033 /* XXX: use .init section so that it also work in binary ? */
10034 bound_init = (void *)tcc_get_symbol_err(s1, "__bound_init");
10035 bound_init();
10037 #endif
10038 return (*prog_main)(argc, argv);
10041 TCCState *tcc_new(void)
10043 const char *p, *r;
10044 TCCState *s;
10045 TokenSym *ts;
10046 int i, c;
10048 s = tcc_mallocz(sizeof(TCCState));
10049 if (!s)
10050 return NULL;
10051 tcc_state = s;
10052 s->output_type = TCC_OUTPUT_MEMORY;
10054 /* init isid table */
10055 for(i=0;i<256;i++)
10056 isidnum_table[i] = isid(i) || isnum(i);
10058 /* add all tokens */
10059 table_ident = NULL;
10060 memset(hash_ident, 0, TOK_HASH_SIZE * sizeof(TokenSym *));
10062 tok_ident = TOK_IDENT;
10063 p = tcc_keywords;
10064 while (*p) {
10065 r = p;
10066 for(;;) {
10067 c = *r++;
10068 if (c == '\0')
10069 break;
10071 ts = tok_alloc(p, r - p - 1);
10072 p = r;
10075 /* we add dummy defines for some special macros to speed up tests
10076 and to have working defined() */
10077 define_push(TOK___LINE__, MACRO_OBJ, NULL, NULL);
10078 define_push(TOK___FILE__, MACRO_OBJ, NULL, NULL);
10079 define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL);
10080 define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL);
10082 /* standard defines */
10083 tcc_define_symbol(s, "__STDC__", NULL);
10084 #if defined(TCC_TARGET_I386)
10085 tcc_define_symbol(s, "__i386__", NULL);
10086 #endif
10087 #if defined(TCC_TARGET_ARM)
10088 tcc_define_symbol(s, "__ARM_ARCH_4__", NULL);
10089 tcc_define_symbol(s, "__arm_elf__", NULL);
10090 tcc_define_symbol(s, "__arm_elf", NULL);
10091 tcc_define_symbol(s, "arm_elf", NULL);
10092 tcc_define_symbol(s, "__arm__", NULL);
10093 tcc_define_symbol(s, "__arm", NULL);
10094 tcc_define_symbol(s, "arm", NULL);
10095 tcc_define_symbol(s, "__APCS_32__", NULL);
10096 #endif
10097 #ifdef TCC_TARGET_PE
10098 tcc_define_symbol(s, "_WIN32", NULL);
10099 #else
10100 tcc_define_symbol(s, "__unix__", NULL);
10101 tcc_define_symbol(s, "__unix", NULL);
10102 #if defined(__linux)
10103 tcc_define_symbol(s, "__linux__", NULL);
10104 tcc_define_symbol(s, "__linux", NULL);
10105 #endif
10106 #endif
10107 /* tiny C specific defines */
10108 tcc_define_symbol(s, "__TINYC__", NULL);
10110 /* tiny C & gcc defines */
10111 tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned int");
10112 tcc_define_symbol(s, "__PTRDIFF_TYPE__", "int");
10113 #ifdef TCC_TARGET_PE
10114 tcc_define_symbol(s, "__WCHAR_TYPE__", "unsigned short");
10115 #else
10116 tcc_define_symbol(s, "__WCHAR_TYPE__", "int");
10117 #endif
10119 /* default library paths */
10120 #ifdef TCC_TARGET_PE
10122 char buf[1024];
10123 snprintf(buf, sizeof(buf), "%s/lib", tcc_lib_path);
10124 tcc_add_library_path(s, buf);
10126 #else
10127 tcc_add_library_path(s, "/usr/local/lib");
10128 tcc_add_library_path(s, "/usr/lib");
10129 tcc_add_library_path(s, "/lib");
10130 #endif
10132 /* no section zero */
10133 dynarray_add((void ***)&s->sections, &s->nb_sections, NULL);
10135 /* create standard sections */
10136 text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
10137 data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
10138 bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
10140 /* symbols are always generated for linking stage */
10141 symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0,
10142 ".strtab",
10143 ".hashtab", SHF_PRIVATE);
10144 strtab_section = symtab_section->link;
10146 /* private symbol table for dynamic symbols */
10147 s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE,
10148 ".dynstrtab",
10149 ".dynhashtab", SHF_PRIVATE);
10150 s->alacarte_link = 1;
10152 #ifdef CHAR_IS_UNSIGNED
10153 s->char_is_unsigned = 1;
10154 #endif
10155 #if defined(TCC_TARGET_PE) && 0
10156 /* XXX: currently the PE linker is not ready to support that */
10157 s->leading_underscore = 1;
10158 #endif
10159 return s;
10162 void tcc_delete(TCCState *s1)
10164 int i, n;
10166 /* free -D defines */
10167 free_defines(NULL);
10169 /* free tokens */
10170 n = tok_ident - TOK_IDENT;
10171 for(i = 0; i < n; i++)
10172 tcc_free(table_ident[i]);
10173 tcc_free(table_ident);
10175 /* free all sections */
10177 free_section(symtab_section->hash);
10179 free_section(s1->dynsymtab_section->hash);
10180 free_section(s1->dynsymtab_section->link);
10181 free_section(s1->dynsymtab_section);
10183 for(i = 1; i < s1->nb_sections; i++)
10184 free_section(s1->sections[i]);
10185 tcc_free(s1->sections);
10187 /* free loaded dlls array */
10188 dynarray_reset(&s1->loaded_dlls, &s1->nb_loaded_dlls);
10190 /* free library paths */
10191 dynarray_reset(&s1->library_paths, &s1->nb_library_paths);
10193 /* free include paths */
10194 dynarray_reset(&s1->cached_includes, &s1->nb_cached_includes);
10195 dynarray_reset(&s1->include_paths, &s1->nb_include_paths);
10196 dynarray_reset(&s1->sysinclude_paths, &s1->nb_sysinclude_paths);
10198 tcc_free(s1);
10201 int tcc_add_include_path(TCCState *s1, const char *pathname)
10203 char *pathname1;
10205 pathname1 = tcc_strdup(pathname);
10206 dynarray_add((void ***)&s1->include_paths, &s1->nb_include_paths, pathname1);
10207 return 0;
10210 int tcc_add_sysinclude_path(TCCState *s1, const char *pathname)
10212 char *pathname1;
10214 pathname1 = tcc_strdup(pathname);
10215 dynarray_add((void ***)&s1->sysinclude_paths, &s1->nb_sysinclude_paths, pathname1);
10216 return 0;
10219 static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
10221 const char *ext;
10222 Elf32_Ehdr ehdr;
10223 int fd, ret;
10224 BufferedFile *saved_file;
10226 /* find source file type with extension */
10227 ext = tcc_fileextension(filename);
10228 if (ext[0])
10229 ext++;
10231 /* open the file */
10232 saved_file = file;
10233 file = tcc_open(s1, filename);
10234 if (!file) {
10235 if (flags & AFF_PRINT_ERROR) {
10236 error_noabort("file '%s' not found", filename);
10238 ret = -1;
10239 goto fail1;
10242 if (flags & AFF_PREPROCESS) {
10243 ret = tcc_preprocess(s1);
10244 } else if (!ext[0] || !strcmp(ext, "c")) {
10245 /* C file assumed */
10246 ret = tcc_compile(s1);
10247 } else
10248 #ifdef CONFIG_TCC_ASM
10249 if (!strcmp(ext, "S")) {
10250 /* preprocessed assembler */
10251 ret = tcc_assemble(s1, 1);
10252 } else if (!strcmp(ext, "s")) {
10253 /* non preprocessed assembler */
10254 ret = tcc_assemble(s1, 0);
10255 } else
10256 #endif
10257 #ifdef TCC_TARGET_PE
10258 if (!strcmp(ext, "def")) {
10259 ret = pe_load_def_file(s1, file->fd);
10260 } else
10261 #endif
10263 fd = file->fd;
10264 /* assume executable format: auto guess file type */
10265 ret = read(fd, &ehdr, sizeof(ehdr));
10266 lseek(fd, 0, SEEK_SET);
10267 if (ret <= 0) {
10268 error_noabort("could not read header");
10269 goto fail;
10270 } else if (ret != sizeof(ehdr)) {
10271 goto try_load_script;
10274 if (ehdr.e_ident[0] == ELFMAG0 &&
10275 ehdr.e_ident[1] == ELFMAG1 &&
10276 ehdr.e_ident[2] == ELFMAG2 &&
10277 ehdr.e_ident[3] == ELFMAG3) {
10278 file->line_num = 0; /* do not display line number if error */
10279 if (ehdr.e_type == ET_REL) {
10280 ret = tcc_load_object_file(s1, fd, 0);
10281 } else if (ehdr.e_type == ET_DYN) {
10282 if (s1->output_type == TCC_OUTPUT_MEMORY) {
10283 #ifdef TCC_TARGET_PE
10284 ret = -1;
10285 #else
10286 void *h;
10287 h = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY);
10288 if (h)
10289 ret = 0;
10290 else
10291 ret = -1;
10292 #endif
10293 } else {
10294 ret = tcc_load_dll(s1, fd, filename,
10295 (flags & AFF_REFERENCED_DLL) != 0);
10297 } else {
10298 error_noabort("unrecognized ELF file");
10299 goto fail;
10301 } else if (memcmp((char *)&ehdr, ARMAG, 8) == 0) {
10302 file->line_num = 0; /* do not display line number if error */
10303 ret = tcc_load_archive(s1, fd);
10304 } else
10305 #ifdef TCC_TARGET_COFF
10306 if (*(uint16_t *)(&ehdr) == COFF_C67_MAGIC) {
10307 ret = tcc_load_coff(s1, fd);
10308 } else
10309 #endif
10310 #ifdef TCC_TARGET_PE
10311 if (pe_test_res_file(&ehdr, ret)) {
10312 ret = pe_load_res_file(s1, fd);
10313 } else
10314 #endif
10316 /* as GNU ld, consider it is an ld script if not recognized */
10317 try_load_script:
10318 ret = tcc_load_ldscript(s1);
10319 if (ret < 0) {
10320 error_noabort("unrecognized file type");
10321 goto fail;
10325 the_end:
10326 tcc_close(file);
10327 fail1:
10328 file = saved_file;
10329 return ret;
10330 fail:
10331 ret = -1;
10332 goto the_end;
10335 int tcc_add_file(TCCState *s, const char *filename)
10337 return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR);
10340 int tcc_add_library_path(TCCState *s, const char *pathname)
10342 char *pathname1;
10344 pathname1 = tcc_strdup(pathname);
10345 dynarray_add((void ***)&s->library_paths, &s->nb_library_paths, pathname1);
10346 return 0;
10349 /* find and load a dll. Return non zero if not found */
10350 /* XXX: add '-rpath' option support ? */
10351 static int tcc_add_dll(TCCState *s, const char *filename, int flags)
10353 char buf[1024];
10354 int i;
10356 for(i = 0; i < s->nb_library_paths; i++) {
10357 snprintf(buf, sizeof(buf), "%s/%s",
10358 s->library_paths[i], filename);
10359 if (tcc_add_file_internal(s, buf, flags) == 0)
10360 return 0;
10362 return -1;
10365 /* the library name is the same as the argument of the '-l' option */
10366 int tcc_add_library(TCCState *s, const char *libraryname)
10368 char buf[1024];
10369 int i;
10371 /* first we look for the dynamic library if not static linking */
10372 if (!s->static_link) {
10373 #ifdef TCC_TARGET_PE
10374 snprintf(buf, sizeof(buf), "%s.def", libraryname);
10375 #else
10376 snprintf(buf, sizeof(buf), "lib%s.so", libraryname);
10377 #endif
10378 if (tcc_add_dll(s, buf, 0) == 0)
10379 return 0;
10382 /* then we look for the static library */
10383 for(i = 0; i < s->nb_library_paths; i++) {
10384 snprintf(buf, sizeof(buf), "%s/lib%s.a",
10385 s->library_paths[i], libraryname);
10386 if (tcc_add_file_internal(s, buf, 0) == 0)
10387 return 0;
10389 return -1;
10392 int tcc_add_symbol(TCCState *s, const char *name, unsigned long val)
10394 add_elf_sym(symtab_section, val, 0,
10395 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
10396 SHN_ABS, name);
10397 return 0;
10400 int tcc_set_output_type(TCCState *s, int output_type)
10402 s->output_type = output_type;
10404 if (!s->nostdinc) {
10405 char buf[1024];
10407 /* default include paths */
10408 /* XXX: reverse order needed if -isystem support */
10409 #ifndef TCC_TARGET_PE
10410 tcc_add_sysinclude_path(s, "/usr/local/include");
10411 tcc_add_sysinclude_path(s, "/usr/include");
10412 #endif
10413 snprintf(buf, sizeof(buf), "%s/include", tcc_lib_path);
10414 tcc_add_sysinclude_path(s, buf);
10415 #ifdef TCC_TARGET_PE
10416 snprintf(buf, sizeof(buf), "%s/include/winapi", tcc_lib_path);
10417 tcc_add_sysinclude_path(s, buf);
10418 #endif
10421 /* if bound checking, then add corresponding sections */
10422 #ifdef CONFIG_TCC_BCHECK
10423 if (do_bounds_check) {
10424 /* define symbol */
10425 tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL);
10426 /* create bounds sections */
10427 bounds_section = new_section(s, ".bounds",
10428 SHT_PROGBITS, SHF_ALLOC);
10429 lbounds_section = new_section(s, ".lbounds",
10430 SHT_PROGBITS, SHF_ALLOC);
10432 #endif
10434 if (s->char_is_unsigned) {
10435 tcc_define_symbol(s, "__CHAR_UNSIGNED__", NULL);
10438 /* add debug sections */
10439 if (do_debug) {
10440 /* stab symbols */
10441 stab_section = new_section(s, ".stab", SHT_PROGBITS, 0);
10442 stab_section->sh_entsize = sizeof(Stab_Sym);
10443 stabstr_section = new_section(s, ".stabstr", SHT_STRTAB, 0);
10444 put_elf_str(stabstr_section, "");
10445 stab_section->link = stabstr_section;
10446 /* put first entry */
10447 put_stabs("", 0, 0, 0, 0);
10450 /* add libc crt1/crti objects */
10451 #ifndef TCC_TARGET_PE
10452 if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) &&
10453 !s->nostdlib) {
10454 if (output_type != TCC_OUTPUT_DLL)
10455 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crt1.o");
10456 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crti.o");
10458 #endif
10459 return 0;
10462 #define WD_ALL 0x0001 /* warning is activated when using -Wall */
10463 #define FD_INVERT 0x0002 /* invert value before storing */
10465 typedef struct FlagDef {
10466 uint16_t offset;
10467 uint16_t flags;
10468 const char *name;
10469 } FlagDef;
10471 static const FlagDef warning_defs[] = {
10472 { offsetof(TCCState, warn_unsupported), 0, "unsupported" },
10473 { offsetof(TCCState, warn_write_strings), 0, "write-strings" },
10474 { offsetof(TCCState, warn_error), 0, "error" },
10475 { offsetof(TCCState, warn_implicit_function_declaration), WD_ALL,
10476 "implicit-function-declaration" },
10479 static int set_flag(TCCState *s, const FlagDef *flags, int nb_flags,
10480 const char *name, int value)
10482 int i;
10483 const FlagDef *p;
10484 const char *r;
10486 r = name;
10487 if (r[0] == 'n' && r[1] == 'o' && r[2] == '-') {
10488 r += 3;
10489 value = !value;
10491 for(i = 0, p = flags; i < nb_flags; i++, p++) {
10492 if (!strcmp(r, p->name))
10493 goto found;
10495 return -1;
10496 found:
10497 if (p->flags & FD_INVERT)
10498 value = !value;
10499 *(int *)((uint8_t *)s + p->offset) = value;
10500 return 0;
10504 /* set/reset a warning */
10505 int tcc_set_warning(TCCState *s, const char *warning_name, int value)
10507 int i;
10508 const FlagDef *p;
10510 if (!strcmp(warning_name, "all")) {
10511 for(i = 0, p = warning_defs; i < countof(warning_defs); i++, p++) {
10512 if (p->flags & WD_ALL)
10513 *(int *)((uint8_t *)s + p->offset) = 1;
10515 return 0;
10516 } else {
10517 return set_flag(s, warning_defs, countof(warning_defs),
10518 warning_name, value);
10522 static const FlagDef flag_defs[] = {
10523 { offsetof(TCCState, char_is_unsigned), 0, "unsigned-char" },
10524 { offsetof(TCCState, char_is_unsigned), FD_INVERT, "signed-char" },
10525 { offsetof(TCCState, nocommon), FD_INVERT, "common" },
10526 { offsetof(TCCState, leading_underscore), 0, "leading-underscore" },
10529 /* set/reset a flag */
10530 int tcc_set_flag(TCCState *s, const char *flag_name, int value)
10532 return set_flag(s, flag_defs, countof(flag_defs),
10533 flag_name, value);
10536 #if !defined(LIBTCC)
10538 static int64_t getclock_us(void)
10540 #ifdef _WIN32
10541 struct _timeb tb;
10542 _ftime(&tb);
10543 return (tb.time * 1000LL + tb.millitm) * 1000LL;
10544 #else
10545 struct timeval tv;
10546 gettimeofday(&tv, NULL);
10547 return tv.tv_sec * 1000000LL + tv.tv_usec;
10548 #endif
10551 void help(void)
10553 printf("tcc version " TCC_VERSION " - Tiny C Compiler - Copyright (C) 2001-2006 Fabrice Bellard\n"
10554 "usage: tcc [-v] [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
10555 " [-Wwarn] [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-static]\n"
10556 " [infile1 infile2...] [-run infile args...]\n"
10557 "\n"
10558 "General options:\n"
10559 " -v display current version\n"
10560 " -c compile only - generate an object file\n"
10561 " -o outfile set output filename\n"
10562 " -Bdir set tcc internal library path\n"
10563 " -bench output compilation statistics\n"
10564 " -run run compiled source\n"
10565 " -fflag set or reset (with 'no-' prefix) 'flag' (see man page)\n"
10566 " -Wwarning set or reset (with 'no-' prefix) 'warning' (see man page)\n"
10567 " -w disable all warnings\n"
10568 "Preprocessor options:\n"
10569 " -E preprocess only\n"
10570 " -Idir add include path 'dir'\n"
10571 " -Dsym[=val] define 'sym' with value 'val'\n"
10572 " -Usym undefine 'sym'\n"
10573 "Linker options:\n"
10574 " -Ldir add library path 'dir'\n"
10575 " -llib link with dynamic or static library 'lib'\n"
10576 " -shared generate a shared library\n"
10577 " -static static linking\n"
10578 " -rdynamic export all global symbols to dynamic linker\n"
10579 " -r generate (relocatable) object file\n"
10580 "Debugger options:\n"
10581 " -g generate runtime debug info\n"
10582 #ifdef CONFIG_TCC_BCHECK
10583 " -b compile with built-in memory and bounds checker (implies -g)\n"
10584 #endif
10585 " -bt N show N callers in stack traces\n"
10589 #define TCC_OPTION_HAS_ARG 0x0001
10590 #define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
10592 typedef struct TCCOption {
10593 const char *name;
10594 uint16_t index;
10595 uint16_t flags;
10596 } TCCOption;
10598 enum {
10599 TCC_OPTION_HELP,
10600 TCC_OPTION_I,
10601 TCC_OPTION_D,
10602 TCC_OPTION_U,
10603 TCC_OPTION_L,
10604 TCC_OPTION_B,
10605 TCC_OPTION_l,
10606 TCC_OPTION_bench,
10607 TCC_OPTION_bt,
10608 TCC_OPTION_b,
10609 TCC_OPTION_g,
10610 TCC_OPTION_c,
10611 TCC_OPTION_static,
10612 TCC_OPTION_shared,
10613 TCC_OPTION_o,
10614 TCC_OPTION_r,
10615 TCC_OPTION_Wl,
10616 TCC_OPTION_W,
10617 TCC_OPTION_O,
10618 TCC_OPTION_m,
10619 TCC_OPTION_f,
10620 TCC_OPTION_nostdinc,
10621 TCC_OPTION_nostdlib,
10622 TCC_OPTION_print_search_dirs,
10623 TCC_OPTION_rdynamic,
10624 TCC_OPTION_run,
10625 TCC_OPTION_v,
10626 TCC_OPTION_w,
10627 TCC_OPTION_pipe,
10628 TCC_OPTION_E,
10631 static const TCCOption tcc_options[] = {
10632 { "h", TCC_OPTION_HELP, 0 },
10633 { "?", TCC_OPTION_HELP, 0 },
10634 { "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG },
10635 { "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG },
10636 { "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG },
10637 { "L", TCC_OPTION_L, TCC_OPTION_HAS_ARG },
10638 { "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG },
10639 { "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10640 { "bench", TCC_OPTION_bench, 0 },
10641 { "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG },
10642 #ifdef CONFIG_TCC_BCHECK
10643 { "b", TCC_OPTION_b, 0 },
10644 #endif
10645 { "g", TCC_OPTION_g, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10646 { "c", TCC_OPTION_c, 0 },
10647 { "static", TCC_OPTION_static, 0 },
10648 { "shared", TCC_OPTION_shared, 0 },
10649 { "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG },
10650 { "run", TCC_OPTION_run, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10651 { "rdynamic", TCC_OPTION_rdynamic, 0 },
10652 { "r", TCC_OPTION_r, 0 },
10653 { "Wl,", TCC_OPTION_Wl, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10654 { "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10655 { "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10656 { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG },
10657 { "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10658 { "nostdinc", TCC_OPTION_nostdinc, 0 },
10659 { "nostdlib", TCC_OPTION_nostdlib, 0 },
10660 { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 },
10661 { "v", TCC_OPTION_v, 0 },
10662 { "w", TCC_OPTION_w, 0 },
10663 { "pipe", TCC_OPTION_pipe, 0},
10664 { "E", TCC_OPTION_E, 0},
10665 { NULL },
10668 /* convert 'str' into an array of space separated strings */
10669 static int expand_args(char ***pargv, const char *str)
10671 const char *s1;
10672 char **argv, *arg;
10673 int argc, len;
10675 argc = 0;
10676 argv = NULL;
10677 for(;;) {
10678 while (is_space(*str))
10679 str++;
10680 if (*str == '\0')
10681 break;
10682 s1 = str;
10683 while (*str != '\0' && !is_space(*str))
10684 str++;
10685 len = str - s1;
10686 arg = tcc_malloc(len + 1);
10687 memcpy(arg, s1, len);
10688 arg[len] = '\0';
10689 dynarray_add((void ***)&argv, &argc, arg);
10691 *pargv = argv;
10692 return argc;
10695 static char **files;
10696 static int nb_files, nb_libraries;
10697 static int multiple_files;
10698 static int print_search_dirs;
10699 static int output_type;
10700 static int reloc_output;
10701 static const char *outfile;
10703 int parse_args(TCCState *s, int argc, char **argv)
10705 int optind;
10706 const TCCOption *popt;
10707 const char *optarg, *p1, *r1;
10708 char *r;
10710 optind = 0;
10711 while (1) {
10712 if (optind >= argc) {
10713 if (nb_files == 0 && !print_search_dirs)
10714 goto show_help;
10715 else
10716 break;
10718 r = argv[optind++];
10719 if (r[0] != '-') {
10720 /* add a new file */
10721 dynarray_add((void ***)&files, &nb_files, r);
10722 if (!multiple_files) {
10723 optind--;
10724 /* argv[0] will be this file */
10725 break;
10727 } else {
10728 /* find option in table (match only the first chars */
10729 popt = tcc_options;
10730 for(;;) {
10731 p1 = popt->name;
10732 if (p1 == NULL)
10733 error("invalid option -- '%s'", r);
10734 r1 = r + 1;
10735 for(;;) {
10736 if (*p1 == '\0')
10737 goto option_found;
10738 if (*r1 != *p1)
10739 break;
10740 p1++;
10741 r1++;
10743 popt++;
10745 option_found:
10746 if (popt->flags & TCC_OPTION_HAS_ARG) {
10747 if (*r1 != '\0' || (popt->flags & TCC_OPTION_NOSEP)) {
10748 optarg = r1;
10749 } else {
10750 if (optind >= argc)
10751 error("argument to '%s' is missing", r);
10752 optarg = argv[optind++];
10754 } else {
10755 if (*r1 != '\0')
10756 goto show_help;
10757 optarg = NULL;
10760 switch(popt->index) {
10761 case TCC_OPTION_HELP:
10762 show_help:
10763 help();
10764 exit(1);
10765 case TCC_OPTION_I:
10766 if (tcc_add_include_path(s, optarg) < 0)
10767 error("too many include paths");
10768 break;
10769 case TCC_OPTION_D:
10771 char *sym, *value;
10772 sym = (char *)optarg;
10773 value = strchr(sym, '=');
10774 if (value) {
10775 *value = '\0';
10776 value++;
10778 tcc_define_symbol(s, sym, value);
10780 break;
10781 case TCC_OPTION_U:
10782 tcc_undefine_symbol(s, optarg);
10783 break;
10784 case TCC_OPTION_L:
10785 tcc_add_library_path(s, optarg);
10786 break;
10787 case TCC_OPTION_B:
10788 /* set tcc utilities path (mainly for tcc development) */
10789 tcc_lib_path = optarg;
10790 break;
10791 case TCC_OPTION_l:
10792 dynarray_add((void ***)&files, &nb_files, r);
10793 nb_libraries++;
10794 break;
10795 case TCC_OPTION_bench:
10796 do_bench = 1;
10797 break;
10798 case TCC_OPTION_bt:
10799 num_callers = atoi(optarg);
10800 break;
10801 #ifdef CONFIG_TCC_BCHECK
10802 case TCC_OPTION_b:
10803 do_bounds_check = 1;
10804 do_debug = 1;
10805 break;
10806 #endif
10807 case TCC_OPTION_g:
10808 do_debug = 1;
10809 break;
10810 case TCC_OPTION_c:
10811 multiple_files = 1;
10812 output_type = TCC_OUTPUT_OBJ;
10813 break;
10814 case TCC_OPTION_static:
10815 s->static_link = 1;
10816 break;
10817 case TCC_OPTION_shared:
10818 output_type = TCC_OUTPUT_DLL;
10819 break;
10820 case TCC_OPTION_o:
10821 multiple_files = 1;
10822 outfile = optarg;
10823 break;
10824 case TCC_OPTION_r:
10825 /* generate a .o merging several output files */
10826 reloc_output = 1;
10827 output_type = TCC_OUTPUT_OBJ;
10828 break;
10829 case TCC_OPTION_nostdinc:
10830 s->nostdinc = 1;
10831 break;
10832 case TCC_OPTION_nostdlib:
10833 s->nostdlib = 1;
10834 break;
10835 case TCC_OPTION_print_search_dirs:
10836 print_search_dirs = 1;
10837 break;
10838 case TCC_OPTION_run:
10840 int argc1;
10841 char **argv1;
10842 argc1 = expand_args(&argv1, optarg);
10843 if (argc1 > 0) {
10844 parse_args(s, argc1, argv1);
10846 multiple_files = 0;
10847 output_type = TCC_OUTPUT_MEMORY;
10849 break;
10850 case TCC_OPTION_v:
10851 printf("tcc version %s\n", TCC_VERSION);
10852 exit(0);
10853 case TCC_OPTION_f:
10854 if (tcc_set_flag(s, optarg, 1) < 0 && s->warn_unsupported)
10855 goto unsupported_option;
10856 break;
10857 case TCC_OPTION_W:
10858 if (tcc_set_warning(s, optarg, 1) < 0 &&
10859 s->warn_unsupported)
10860 goto unsupported_option;
10861 break;
10862 case TCC_OPTION_w:
10863 s->warn_none = 1;
10864 break;
10865 case TCC_OPTION_rdynamic:
10866 s->rdynamic = 1;
10867 break;
10868 case TCC_OPTION_Wl:
10870 const char *p;
10871 if (strstart(optarg, "-Ttext,", &p)) {
10872 s->text_addr = strtoul(p, NULL, 16);
10873 s->has_text_addr = 1;
10874 } else if (strstart(optarg, "--oformat,", &p)) {
10875 if (strstart(p, "elf32-", NULL)) {
10876 s->output_format = TCC_OUTPUT_FORMAT_ELF;
10877 } else if (!strcmp(p, "binary")) {
10878 s->output_format = TCC_OUTPUT_FORMAT_BINARY;
10879 } else
10880 #ifdef TCC_TARGET_COFF
10881 if (!strcmp(p, "coff")) {
10882 s->output_format = TCC_OUTPUT_FORMAT_COFF;
10883 } else
10884 #endif
10886 error("target %s not found", p);
10888 } else {
10889 error("unsupported linker option '%s'", optarg);
10892 break;
10893 case TCC_OPTION_E:
10894 output_type = TCC_OUTPUT_PREPROCESS;
10895 break;
10896 default:
10897 if (s->warn_unsupported) {
10898 unsupported_option:
10899 warning("unsupported option '%s'", r);
10901 break;
10905 return optind;
10908 int main(int argc, char **argv)
10910 int i;
10911 TCCState *s;
10912 int nb_objfiles, ret, optind;
10913 char objfilename[1024];
10914 int64_t start_time = 0;
10916 #ifdef _WIN32
10917 tcc_lib_path = w32_tcc_lib_path();
10918 #endif
10920 s = tcc_new();
10921 output_type = TCC_OUTPUT_EXE;
10922 outfile = NULL;
10923 multiple_files = 1;
10924 files = NULL;
10925 nb_files = 0;
10926 nb_libraries = 0;
10927 reloc_output = 0;
10928 print_search_dirs = 0;
10929 ret = 0;
10931 optind = parse_args(s, argc - 1, argv + 1) + 1;
10933 if (print_search_dirs) {
10934 /* enough for Linux kernel */
10935 printf("install: %s/\n", tcc_lib_path);
10936 return 0;
10939 nb_objfiles = nb_files - nb_libraries;
10941 /* if outfile provided without other options, we output an
10942 executable */
10943 if (outfile && output_type == TCC_OUTPUT_MEMORY)
10944 output_type = TCC_OUTPUT_EXE;
10946 /* check -c consistency : only single file handled. XXX: checks file type */
10947 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
10948 /* accepts only a single input file */
10949 if (nb_objfiles != 1)
10950 error("cannot specify multiple files with -c");
10951 if (nb_libraries != 0)
10952 error("cannot specify libraries with -c");
10956 if (output_type == TCC_OUTPUT_PREPROCESS) {
10957 if (!outfile) {
10958 s->outfile = stdout;
10959 } else {
10960 s->outfile = fopen(outfile, "w");
10961 if (!s->outfile)
10962 error("could not open '%s", outfile);
10964 } else if (output_type != TCC_OUTPUT_MEMORY) {
10965 if (!outfile) {
10966 /* compute default outfile name */
10967 char *ext;
10968 pstrcpy(objfilename, sizeof(objfilename), tcc_basename(files[0]));
10969 ext = tcc_fileextension(objfilename);
10970 #ifdef TCC_TARGET_PE
10971 if (output_type == TCC_OUTPUT_DLL)
10972 strcpy(ext, ".dll");
10973 else
10974 if (output_type == TCC_OUTPUT_EXE)
10975 strcpy(ext, ".exe");
10976 else
10977 #endif
10978 if (output_type == TCC_OUTPUT_OBJ && !reloc_output && *ext)
10979 strcpy(ext, ".o");
10980 else
10981 pstrcpy(objfilename, sizeof(objfilename), "a.out");
10982 outfile = objfilename;
10986 if (do_bench) {
10987 start_time = getclock_us();
10990 tcc_set_output_type(s, output_type);
10992 /* compile or add each files or library */
10993 for(i = 0; i < nb_files && ret == 0; i++) {
10994 const char *filename;
10996 filename = files[i];
10997 if (output_type == TCC_OUTPUT_PREPROCESS) {
10998 if (tcc_add_file_internal(s, filename,
10999 AFF_PRINT_ERROR | AFF_PREPROCESS) < 0)
11000 ret = 1;
11001 } else if (filename[0] == '-') {
11002 if (tcc_add_library(s, filename + 2) < 0)
11003 error("cannot find %s", filename);
11004 } else {
11005 if (tcc_add_file(s, filename) < 0)
11006 ret = 1;
11010 /* free all files */
11011 tcc_free(files);
11013 if (ret)
11014 goto the_end;
11016 if (do_bench) {
11017 double total_time;
11018 total_time = (double)(getclock_us() - start_time) / 1000000.0;
11019 if (total_time < 0.001)
11020 total_time = 0.001;
11021 if (total_bytes < 1)
11022 total_bytes = 1;
11023 printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
11024 tok_ident - TOK_IDENT, total_lines, total_bytes,
11025 total_time, (int)(total_lines / total_time),
11026 total_bytes / total_time / 1000000.0);
11029 if (s->output_type == TCC_OUTPUT_PREPROCESS) {
11030 if (outfile)
11031 fclose(s->outfile);
11032 } else if (s->output_type == TCC_OUTPUT_MEMORY) {
11033 ret = tcc_run(s, argc - optind, argv + optind);
11034 } else
11035 #ifdef TCC_TARGET_PE
11036 if (s->output_type != TCC_OUTPUT_OBJ) {
11037 ret = pe_output_file(s, outfile);
11038 } else
11039 #endif
11041 ret = tcc_output_file(s, outfile) ? 1 : 0;
11043 the_end:
11044 /* XXX: cannot do it with bound checking because of the malloc hooks */
11045 if (!do_bounds_check)
11046 tcc_delete(s);
11048 #ifdef MEM_DEBUG
11049 if (do_bench) {
11050 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size, mem_max_size);
11052 #endif
11053 return ret;
11056 #endif