Import changesets (part 4) 428,457,460,467: defines for openbsd etc.
[tinycc/daniel.git] / tcc.c
blobce1a21089966e42e493384fc0a7924e323a23cd7
1 /*
2 * TCC - Tiny C Compiler
3 *
4 * Copyright (c) 2001-2004 Fabrice Bellard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #define _GNU_SOURCE
21 #include "config.h"
23 #ifdef CONFIG_TCCBOOT
25 #include "tccboot.h"
26 #define CONFIG_TCC_STATIC
28 #else
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <stdarg.h>
33 #include <string.h>
34 #include <errno.h>
35 #include <math.h>
36 #include <unistd.h>
37 #include <signal.h>
38 #include <fcntl.h>
39 #include <setjmp.h>
40 #include <time.h>
41 #ifdef _WIN32
42 #include <sys/timeb.h>
43 // #include <windows.h>
44 #endif
45 #ifndef _WIN32
46 #include <sys/time.h>
47 #include <sys/ucontext.h>
48 #include <sys/mman.h>
49 #endif
51 #endif /* !CONFIG_TCCBOOT */
53 #ifndef PAGESIZE
54 #define PAGESIZE 4096
55 #endif
57 #include "elf.h"
58 #include "stab.h"
60 #ifndef O_BINARY
61 #define O_BINARY 0
62 #endif
64 #include "libtcc.h"
66 /* parser debug */
67 //#define PARSE_DEBUG
68 /* preprocessor debug */
69 //#define PP_DEBUG
70 /* include file debug */
71 //#define INC_DEBUG
73 //#define MEM_DEBUG
75 /* assembler debug */
76 //#define ASM_DEBUG
78 /* target selection */
79 //#define TCC_TARGET_I386 /* i386 code generator */
80 //#define TCC_TARGET_ARM /* ARMv4 code generator */
81 //#define TCC_TARGET_C67 /* TMS320C67xx code generator */
83 /* default target is I386 */
84 #if !defined(TCC_TARGET_I386) && !defined(TCC_TARGET_ARM) && \
85 !defined(TCC_TARGET_C67)
86 #define TCC_TARGET_I386
87 #endif
89 #if !defined(_WIN32) && !defined(TCC_UCLIBC) && !defined(TCC_TARGET_ARM) && \
90 !defined(TCC_TARGET_C67)
91 #define CONFIG_TCC_BCHECK /* enable bound checking code */
92 #endif
94 #if defined(_WIN32) && !defined(TCC_TARGET_PE)
95 #define CONFIG_TCC_STATIC
96 #endif
98 /* define it to include assembler support */
99 #if !defined(TCC_TARGET_ARM) && !defined(TCC_TARGET_C67)
100 #define CONFIG_TCC_ASM
101 #endif
103 /* object format selection */
104 #if defined(TCC_TARGET_C67)
105 #define TCC_TARGET_COFF
106 #endif
108 #define FALSE 0
109 #define false 0
110 #define TRUE 1
111 #define true 1
112 typedef int BOOL;
114 /* path to find crt1.o, crti.o and crtn.o. Only needed when generating
115 executables or dlls */
116 #define CONFIG_TCC_CRT_PREFIX "/usr/lib"
118 #define INCLUDE_STACK_SIZE 32
119 #define IFDEF_STACK_SIZE 64
120 #define VSTACK_SIZE 256
121 #define STRING_MAX_SIZE 1024
122 #define PACK_STACK_SIZE 8
124 #define TOK_HASH_SIZE 8192 /* must be a power of two */
125 #define TOK_ALLOC_INCR 512 /* must be a power of two */
126 #define TOK_MAX_SIZE 4 /* token max size in int unit when stored in string */
128 /* token symbol management */
129 typedef struct TokenSym {
130 struct TokenSym *hash_next;
131 struct Sym *sym_define; /* direct pointer to define */
132 struct Sym *sym_label; /* direct pointer to label */
133 struct Sym *sym_struct; /* direct pointer to structure */
134 struct Sym *sym_identifier; /* direct pointer to identifier */
135 int tok; /* token number */
136 int len;
137 char str[1];
138 } TokenSym;
140 #ifdef TCC_TARGET_PE
141 typedef unsigned short nwchar_t;
142 #else
143 typedef int nwchar_t;
144 #endif
146 typedef struct CString {
147 int size; /* size in bytes */
148 void *data; /* either 'char *' or 'nwchar_t *' */
149 int size_allocated;
150 void *data_allocated; /* if non NULL, data has been malloced */
151 } CString;
153 /* type definition */
154 typedef struct CType {
155 int t;
156 struct Sym *ref;
157 } CType;
159 /* constant value */
160 typedef union CValue {
161 long double ld;
162 double d;
163 float f;
164 int i;
165 unsigned int ui;
166 unsigned int ul; /* address (should be unsigned long on 64 bit cpu) */
167 long long ll;
168 unsigned long long ull;
169 struct CString *cstr;
170 void *ptr;
171 int tab[1];
172 } CValue;
174 /* value on stack */
175 typedef struct SValue {
176 CType type; /* type */
177 unsigned short r; /* register + flags */
178 unsigned short r2; /* second register, used for 'long long'
179 type. If not used, set to VT_CONST */
180 CValue c; /* constant, if VT_CONST */
181 struct Sym *sym; /* symbol, if (VT_SYM | VT_CONST) */
182 } SValue;
184 /* symbol management */
185 typedef struct Sym {
186 int v; /* symbol token */
187 int r; /* associated register */
188 int c; /* associated number */
189 CType type; /* associated type */
190 struct Sym *next; /* next related symbol */
191 struct Sym *prev; /* prev symbol in stack */
192 struct Sym *prev_tok; /* previous symbol for this token */
193 } Sym;
195 /* section definition */
196 /* XXX: use directly ELF structure for parameters ? */
197 /* special flag to indicate that the section should not be linked to
198 the other ones */
199 #define SHF_PRIVATE 0x80000000
201 typedef struct Section {
202 unsigned long data_offset; /* current data offset */
203 unsigned char *data; /* section data */
204 unsigned long data_allocated; /* used for realloc() handling */
205 int sh_name; /* elf section name (only used during output) */
206 int sh_num; /* elf section number */
207 int sh_type; /* elf section type */
208 int sh_flags; /* elf section flags */
209 int sh_info; /* elf section info */
210 int sh_addralign; /* elf section alignment */
211 int sh_entsize; /* elf entry size */
212 unsigned long sh_size; /* section size (only used during output) */
213 unsigned long sh_addr; /* address at which the section is relocated */
214 unsigned long sh_offset; /* file offset */
215 int nb_hashed_syms; /* used to resize the hash table */
216 struct Section *link; /* link to another section */
217 struct Section *reloc; /* corresponding section for relocation, if any */
218 struct Section *hash; /* hash table for symbols */
219 struct Section *next;
220 char name[1]; /* section name */
221 } Section;
223 typedef struct DLLReference {
224 int level;
225 char name[1];
226 } DLLReference;
228 /* GNUC attribute definition */
229 typedef struct AttributeDef {
230 int aligned;
231 int packed;
232 Section *section;
233 unsigned char func_call; /* FUNC_CDECL, FUNC_STDCALL, FUNC_FASTCALLx */
234 unsigned char dllexport;
235 } AttributeDef;
237 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
238 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
239 #define SYM_FIRST_ANOM 0x10000000 /* first anonymous sym */
241 /* stored in 'Sym.c' field */
242 #define FUNC_NEW 1 /* ansi function prototype */
243 #define FUNC_OLD 2 /* old function prototype */
244 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
246 /* stored in 'Sym.r' field */
247 #define FUNC_CDECL 0 /* standard c call */
248 #define FUNC_STDCALL 1 /* pascal c call */
249 #define FUNC_FASTCALL1 2 /* first param in %eax */
250 #define FUNC_FASTCALL2 3 /* first parameters in %eax, %edx */
251 #define FUNC_FASTCALL3 4 /* first parameter in %eax, %edx, %ecx */
252 #define FUNC_FASTCALLW 5 /* first parameter in %ecx, %edx */
254 /* field 'Sym.t' for macros */
255 #define MACRO_OBJ 0 /* object like macro */
256 #define MACRO_FUNC 1 /* function like macro */
258 /* field 'Sym.r' for C labels */
259 #define LABEL_DEFINED 0 /* label is defined */
260 #define LABEL_FORWARD 1 /* label is forward defined */
261 #define LABEL_DECLARED 2 /* label is declared but never used */
263 /* type_decl() types */
264 #define TYPE_ABSTRACT 1 /* type without variable */
265 #define TYPE_DIRECT 2 /* type with variable */
267 #define IO_BUF_SIZE 8192
269 typedef struct BufferedFile {
270 uint8_t *buf_ptr;
271 uint8_t *buf_end;
272 int fd;
273 int line_num; /* current line number - here to simplify code */
274 int ifndef_macro; /* #ifndef macro / #endif search */
275 int ifndef_macro_saved; /* saved ifndef_macro */
276 int *ifdef_stack_ptr; /* ifdef_stack value at the start of the file */
277 char inc_type; /* type of include */
278 char inc_filename[512]; /* filename specified by the user */
279 char filename[1024]; /* current filename - here to simplify code */
280 unsigned char buffer[IO_BUF_SIZE + 1]; /* extra size for CH_EOB char */
281 } BufferedFile;
283 #define CH_EOB '\\' /* end of buffer or '\0' char in file */
284 #define CH_EOF (-1) /* end of file */
286 /* parsing state (used to save parser state to reparse part of the
287 source several times) */
288 typedef struct ParseState {
289 int *macro_ptr;
290 int line_num;
291 int tok;
292 CValue tokc;
293 } ParseState;
295 /* used to record tokens */
296 typedef struct TokenString {
297 int *str;
298 int len;
299 int allocated_len;
300 int last_line_num;
301 } TokenString;
303 /* include file cache, used to find files faster and also to eliminate
304 inclusion if the include file is protected by #ifndef ... #endif */
305 typedef struct CachedInclude {
306 int ifndef_macro;
307 int hash_next; /* -1 if none */
308 char type; /* '"' or '>' to give include type */
309 char filename[1]; /* path specified in #include */
310 } CachedInclude;
312 #define CACHED_INCLUDES_HASH_SIZE 512
314 /* parser */
315 static struct BufferedFile *file;
316 static int ch, tok;
317 static CValue tokc;
318 static CString tokcstr; /* current parsed string, if any */
319 /* additional informations about token */
320 static int tok_flags;
321 #define TOK_FLAG_BOL 0x0001 /* beginning of line before */
322 #define TOK_FLAG_BOF 0x0002 /* beginning of file before */
323 #define TOK_FLAG_ENDIF 0x0004 /* a endif was found matching starting #ifdef */
324 #define TOK_FLAG_EOF 0x0008 /* end of file */
326 static int *macro_ptr, *macro_ptr_allocated;
327 static int *unget_saved_macro_ptr;
328 static int unget_saved_buffer[TOK_MAX_SIZE + 1];
329 static int unget_buffer_enabled;
330 static int parse_flags;
331 #define PARSE_FLAG_PREPROCESS 0x0001 /* activate preprocessing */
332 #define PARSE_FLAG_TOK_NUM 0x0002 /* return numbers instead of TOK_PPNUM */
333 #define PARSE_FLAG_LINEFEED 0x0004 /* line feed is returned as a
334 token. line feed is also
335 returned at eof */
336 #define PARSE_FLAG_ASM_COMMENTS 0x0008 /* '#' can be used for line comment */
338 static Section *text_section, *data_section, *bss_section; /* predefined sections */
339 static Section *cur_text_section; /* current section where function code is
340 generated */
341 #ifdef CONFIG_TCC_ASM
342 static Section *last_text_section; /* to handle .previous asm directive */
343 #endif
344 /* bound check related sections */
345 static Section *bounds_section; /* contains global data bound description */
346 static Section *lbounds_section; /* contains local data bound description */
347 /* symbol sections */
348 static Section *symtab_section, *strtab_section;
350 /* debug sections */
351 static Section *stab_section, *stabstr_section;
353 /* loc : local variable index
354 ind : output code index
355 rsym: return symbol
356 anon_sym: anonymous symbol index
358 static int rsym, anon_sym, ind, loc;
359 /* expression generation modifiers */
360 static int const_wanted; /* true if constant wanted */
361 static int nocode_wanted; /* true if no code generation wanted for an expression */
362 static int global_expr; /* true if compound literals must be allocated
363 globally (used during initializers parsing */
364 static CType func_vt; /* current function return type (used by return
365 instruction) */
366 static int func_vc;
367 static int last_line_num, last_ind, func_ind; /* debug last line number and pc */
368 static int tok_ident;
369 static TokenSym **table_ident;
370 static TokenSym *hash_ident[TOK_HASH_SIZE];
371 static char token_buf[STRING_MAX_SIZE + 1];
372 static char *funcname;
373 static Sym *global_stack, *local_stack;
374 static Sym *define_stack;
375 static Sym *global_label_stack, *local_label_stack;
376 /* symbol allocator */
377 #define SYM_POOL_NB (8192 / sizeof(Sym))
378 static Sym *sym_free_first;
380 static SValue vstack[VSTACK_SIZE], *vtop;
381 /* some predefined types */
382 static CType char_pointer_type, func_old_type, int_type;
383 /* true if isid(c) || isnum(c) */
384 static unsigned char isidnum_table[256];
386 /* compile with debug symbol (and use them if error during execution) */
387 static int do_debug = 0;
389 /* compile with built-in memory and bounds checker */
390 static int do_bounds_check = 0;
392 /* display benchmark infos */
393 #if !defined(LIBTCC)
394 static int do_bench = 0;
395 #endif
396 static int total_lines;
397 static int total_bytes;
399 /* use GNU C extensions */
400 static int gnu_ext = 1;
402 /* use Tiny C extensions */
403 static int tcc_ext = 1;
405 /* max number of callers shown if error */
406 static int num_callers = 6;
407 static const char **rt_bound_error_msg;
409 /* XXX: get rid of this ASAP */
410 static struct TCCState *tcc_state;
412 /* give the path of the tcc libraries */
413 static const char *tcc_lib_path = CONFIG_TCCDIR;
415 struct TCCState {
416 int output_type;
418 BufferedFile **include_stack_ptr;
419 int *ifdef_stack_ptr;
421 /* include file handling */
422 char **include_paths;
423 int nb_include_paths;
424 char **sysinclude_paths;
425 int nb_sysinclude_paths;
426 CachedInclude **cached_includes;
427 int nb_cached_includes;
429 char **library_paths;
430 int nb_library_paths;
432 /* array of all loaded dlls (including those referenced by loaded
433 dlls) */
434 DLLReference **loaded_dlls;
435 int nb_loaded_dlls;
437 /* sections */
438 Section **sections;
439 int nb_sections; /* number of sections, including first dummy section */
441 /* got handling */
442 Section *got;
443 Section *plt;
444 unsigned long *got_offsets;
445 int nb_got_offsets;
446 /* give the correspondance from symtab indexes to dynsym indexes */
447 int *symtab_to_dynsym;
449 /* temporary dynamic symbol sections (for dll loading) */
450 Section *dynsymtab_section;
451 /* exported dynamic symbol section */
452 Section *dynsym;
454 int nostdinc; /* if true, no standard headers are added */
455 int nostdlib; /* if true, no standard libraries are added */
457 int nocommon; /* if true, do not use common symbols for .bss data */
459 /* if true, static linking is performed */
460 int static_link;
462 /* if true, all symbols are exported */
463 int rdynamic;
465 /* if true, only link in referenced objects from archive */
466 int alacarte_link;
468 /* address of text section */
469 unsigned long text_addr;
470 int has_text_addr;
472 /* output format, see TCC_OUTPUT_FORMAT_xxx */
473 int output_format;
475 /* C language options */
476 int char_is_unsigned;
477 int leading_underscore;
479 /* warning switches */
480 int warn_write_strings;
481 int warn_unsupported;
482 int warn_error;
483 int warn_none;
484 int warn_implicit_function_declaration;
486 /* error handling */
487 void *error_opaque;
488 void (*error_func)(void *opaque, const char *msg);
489 int error_set_jmp_enabled;
490 jmp_buf error_jmp_buf;
491 int nb_errors;
493 /* tiny assembler state */
494 Sym *asm_labels;
496 /* see include_stack_ptr */
497 BufferedFile *include_stack[INCLUDE_STACK_SIZE];
499 /* see ifdef_stack_ptr */
500 int ifdef_stack[IFDEF_STACK_SIZE];
502 /* see cached_includes */
503 int cached_includes_hash[CACHED_INCLUDES_HASH_SIZE];
505 /* pack stack */
506 int pack_stack[PACK_STACK_SIZE];
507 int *pack_stack_ptr;
509 /* output file for preprocessing */
510 FILE *outfile;
513 /* The current value can be: */
514 #define VT_VALMASK 0x00ff
515 #define VT_CONST 0x00f0 /* constant in vc
516 (must be first non register value) */
517 #define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */
518 #define VT_LOCAL 0x00f2 /* offset on stack */
519 #define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */
520 #define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */
521 #define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */
522 #define VT_LVAL 0x0100 /* var is an lvalue */
523 #define VT_SYM 0x0200 /* a symbol value is added */
524 #define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for
525 char/short stored in integer registers) */
526 #define VT_MUSTBOUND 0x0800 /* bound checking must be done before
527 dereferencing value */
528 #define VT_BOUNDED 0x8000 /* value is bounded. The address of the
529 bounding function call point is in vc */
530 #define VT_LVAL_BYTE 0x1000 /* lvalue is a byte */
531 #define VT_LVAL_SHORT 0x2000 /* lvalue is a short */
532 #define VT_LVAL_UNSIGNED 0x4000 /* lvalue is unsigned */
533 #define VT_LVAL_TYPE (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)
535 /* types */
536 #define VT_INT 0 /* integer type */
537 #define VT_BYTE 1 /* signed byte type */
538 #define VT_SHORT 2 /* short type */
539 #define VT_VOID 3 /* void type */
540 #define VT_PTR 4 /* pointer */
541 #define VT_ENUM 5 /* enum definition */
542 #define VT_FUNC 6 /* function type */
543 #define VT_STRUCT 7 /* struct/union definition */
544 #define VT_FLOAT 8 /* IEEE float */
545 #define VT_DOUBLE 9 /* IEEE double */
546 #define VT_LDOUBLE 10 /* IEEE long double */
547 #define VT_BOOL 11 /* ISOC99 boolean type */
548 #define VT_LLONG 12 /* 64 bit integer */
549 #define VT_LONG 13 /* long integer (NEVER USED as type, only
550 during parsing) */
551 #define VT_BTYPE 0x000f /* mask for basic type */
552 #define VT_UNSIGNED 0x0010 /* unsigned type */
553 #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
554 #define VT_BITFIELD 0x0040 /* bitfield modifier */
555 #define VT_CONSTANT 0x0800 /* const modifier */
556 #define VT_VOLATILE 0x1000 /* volatile modifier */
557 #define VT_SIGNED 0x2000 /* signed type */
559 /* storage */
560 #define VT_EXTERN 0x00000080 /* extern definition */
561 #define VT_STATIC 0x00000100 /* static variable */
562 #define VT_TYPEDEF 0x00000200 /* typedef definition */
563 #define VT_INLINE 0x00000400 /* inline definition */
565 #define VT_STRUCT_SHIFT 16 /* shift for bitfield shift values */
567 /* type mask (except storage) */
568 #define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE)
569 #define VT_TYPE (~(VT_STORAGE))
571 /* token values */
573 /* warning: the following compare tokens depend on i386 asm code */
574 #define TOK_ULT 0x92
575 #define TOK_UGE 0x93
576 #define TOK_EQ 0x94
577 #define TOK_NE 0x95
578 #define TOK_ULE 0x96
579 #define TOK_UGT 0x97
580 #define TOK_Nset 0x98
581 #define TOK_Nclear 0x99
582 #define TOK_LT 0x9c
583 #define TOK_GE 0x9d
584 #define TOK_LE 0x9e
585 #define TOK_GT 0x9f
587 #define TOK_LAND 0xa0
588 #define TOK_LOR 0xa1
590 #define TOK_DEC 0xa2
591 #define TOK_MID 0xa3 /* inc/dec, to void constant */
592 #define TOK_INC 0xa4
593 #define TOK_UDIV 0xb0 /* unsigned division */
594 #define TOK_UMOD 0xb1 /* unsigned modulo */
595 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
596 #define TOK_CINT 0xb3 /* number in tokc */
597 #define TOK_CCHAR 0xb4 /* char constant in tokc */
598 #define TOK_STR 0xb5 /* pointer to string in tokc */
599 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
600 #define TOK_LCHAR 0xb7
601 #define TOK_LSTR 0xb8
602 #define TOK_CFLOAT 0xb9 /* float constant */
603 #define TOK_LINENUM 0xba /* line number info */
604 #define TOK_CDOUBLE 0xc0 /* double constant */
605 #define TOK_CLDOUBLE 0xc1 /* long double constant */
606 #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
607 #define TOK_ADDC1 0xc3 /* add with carry generation */
608 #define TOK_ADDC2 0xc4 /* add with carry use */
609 #define TOK_SUBC1 0xc5 /* add with carry generation */
610 #define TOK_SUBC2 0xc6 /* add with carry use */
611 #define TOK_CUINT 0xc8 /* unsigned int constant */
612 #define TOK_CLLONG 0xc9 /* long long constant */
613 #define TOK_CULLONG 0xca /* unsigned long long constant */
614 #define TOK_ARROW 0xcb
615 #define TOK_DOTS 0xcc /* three dots */
616 #define TOK_SHR 0xcd /* unsigned shift right */
617 #define TOK_PPNUM 0xce /* preprocessor number */
619 #define TOK_SHL 0x01 /* shift left */
620 #define TOK_SAR 0x02 /* signed shift right */
622 /* assignement operators : normal operator or 0x80 */
623 #define TOK_A_MOD 0xa5
624 #define TOK_A_AND 0xa6
625 #define TOK_A_MUL 0xaa
626 #define TOK_A_ADD 0xab
627 #define TOK_A_SUB 0xad
628 #define TOK_A_DIV 0xaf
629 #define TOK_A_XOR 0xde
630 #define TOK_A_OR 0xfc
631 #define TOK_A_SHL 0x81
632 #define TOK_A_SAR 0x82
634 #ifndef offsetof
635 #define offsetof(type, field) ((size_t) &((type *)0)->field)
636 #endif
638 #ifndef countof
639 #define countof(tab) (sizeof(tab) / sizeof((tab)[0]))
640 #endif
642 /* WARNING: the content of this string encodes token numbers */
643 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";
645 #define TOK_EOF (-1) /* end of file */
646 #define TOK_LINEFEED 10 /* line feed */
648 /* all identificators and strings have token above that */
649 #define TOK_IDENT 256
651 /* only used for i386 asm opcodes definitions */
652 #define DEF_ASM(x) DEF(TOK_ASM_ ## x, #x)
654 #define DEF_BWL(x) \
655 DEF(TOK_ASM_ ## x ## b, #x "b") \
656 DEF(TOK_ASM_ ## x ## w, #x "w") \
657 DEF(TOK_ASM_ ## x ## l, #x "l") \
658 DEF(TOK_ASM_ ## x, #x)
660 #define DEF_WL(x) \
661 DEF(TOK_ASM_ ## x ## w, #x "w") \
662 DEF(TOK_ASM_ ## x ## l, #x "l") \
663 DEF(TOK_ASM_ ## x, #x)
665 #define DEF_FP1(x) \
666 DEF(TOK_ASM_ ## f ## x ## s, "f" #x "s") \
667 DEF(TOK_ASM_ ## fi ## x ## l, "fi" #x "l") \
668 DEF(TOK_ASM_ ## f ## x ## l, "f" #x "l") \
669 DEF(TOK_ASM_ ## fi ## x ## s, "fi" #x "s")
671 #define DEF_FP(x) \
672 DEF(TOK_ASM_ ## f ## x, "f" #x ) \
673 DEF(TOK_ASM_ ## f ## x ## p, "f" #x "p") \
674 DEF_FP1(x)
676 #define DEF_ASMTEST(x) \
677 DEF_ASM(x ## o) \
678 DEF_ASM(x ## no) \
679 DEF_ASM(x ## b) \
680 DEF_ASM(x ## c) \
681 DEF_ASM(x ## nae) \
682 DEF_ASM(x ## nb) \
683 DEF_ASM(x ## nc) \
684 DEF_ASM(x ## ae) \
685 DEF_ASM(x ## e) \
686 DEF_ASM(x ## z) \
687 DEF_ASM(x ## ne) \
688 DEF_ASM(x ## nz) \
689 DEF_ASM(x ## be) \
690 DEF_ASM(x ## na) \
691 DEF_ASM(x ## nbe) \
692 DEF_ASM(x ## a) \
693 DEF_ASM(x ## s) \
694 DEF_ASM(x ## ns) \
695 DEF_ASM(x ## p) \
696 DEF_ASM(x ## pe) \
697 DEF_ASM(x ## np) \
698 DEF_ASM(x ## po) \
699 DEF_ASM(x ## l) \
700 DEF_ASM(x ## nge) \
701 DEF_ASM(x ## nl) \
702 DEF_ASM(x ## ge) \
703 DEF_ASM(x ## le) \
704 DEF_ASM(x ## ng) \
705 DEF_ASM(x ## nle) \
706 DEF_ASM(x ## g)
708 #define TOK_ASM_int TOK_INT
710 enum tcc_token {
711 TOK_LAST = TOK_IDENT - 1,
712 #define DEF(id, str) id,
713 #include "tcctok.h"
714 #undef DEF
717 static const char tcc_keywords[] =
718 #define DEF(id, str) str "\0"
719 #include "tcctok.h"
720 #undef DEF
723 #define TOK_UIDENT TOK_DEFINE
725 #ifdef _WIN32
726 int __stdcall GetModuleFileNameA(void *, char *, int);
727 void *__stdcall GetProcAddress(void *, const char *);
728 void *__stdcall GetModuleHandleA(const char *);
729 void *__stdcall LoadLibraryA(const char *);
730 int __stdcall FreeConsole(void);
731 int __stdcall VirtualProtect(void*,unsigned long,unsigned long,unsigned long*);
732 #define PAGE_EXECUTE_READWRITE 0x0040
734 #define snprintf _snprintf
735 #define vsnprintf _vsnprintf
736 #ifndef __GNUC__
737 #define strtold (long double)strtod
738 #define strtof (float)strtod
739 #define strtoll (long long)strtol
740 #endif
741 #elif defined(TCC_UCLIBC) || defined(__FreeBSD__) || defined(__DragonFly__) \
742 || defined(__OpenBSD__)
743 /* currently incorrect */
744 long double strtold(const char *nptr, char **endptr)
746 return (long double)strtod(nptr, endptr);
748 float strtof(const char *nptr, char **endptr)
750 return (float)strtod(nptr, endptr);
752 #else
753 /* XXX: need to define this to use them in non ISOC99 context */
754 extern float strtof (const char *__nptr, char **__endptr);
755 extern long double strtold (const char *__nptr, char **__endptr);
756 #endif
758 static char *pstrcpy(char *buf, int buf_size, const char *s);
759 static char *pstrcat(char *buf, int buf_size, const char *s);
760 static char *tcc_basename(const char *name);
762 static void next(void);
763 static void next_nomacro(void);
764 static void parse_expr_type(CType *type);
765 static void expr_type(CType *type);
766 static void unary_type(CType *type);
767 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
768 int case_reg, int is_expr);
769 static int expr_const(void);
770 static void expr_eq(void);
771 static void gexpr(void);
772 static void gen_inline_functions(void);
773 static void decl(int l);
774 static void decl_initializer(CType *type, Section *sec, unsigned long c,
775 int first, int size_only);
776 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
777 int has_init, int v, int scope);
778 int gv(int rc);
779 void gv2(int rc1, int rc2);
780 void move_reg(int r, int s);
781 void save_regs(int n);
782 void save_reg(int r);
783 void vpop(void);
784 void vswap(void);
785 void vdup(void);
786 int get_reg(int rc);
787 int get_reg_ex(int rc,int rc2);
789 struct macro_level {
790 struct macro_level *prev;
791 int *p;
794 static void macro_subst(TokenString *tok_str, Sym **nested_list,
795 const int *macro_str, struct macro_level **can_read_stream);
796 void gen_op(int op);
797 void force_charshort_cast(int t);
798 static void gen_cast(CType *type);
799 void vstore(void);
800 static Sym *sym_find(int v);
801 static Sym *sym_push(int v, CType *type, int r, int c);
803 /* type handling */
804 static int type_size(CType *type, int *a);
805 static inline CType *pointed_type(CType *type);
806 static int pointed_size(CType *type);
807 static int lvalue_type(int t);
808 static int parse_btype(CType *type, AttributeDef *ad);
809 static void type_decl(CType *type, AttributeDef *ad, int *v, int td);
810 static int compare_types(CType *type1, CType *type2, int unqualified);
811 static int is_compatible_types(CType *type1, CType *type2);
812 static int is_compatible_parameter_types(CType *type1, CType *type2);
814 int ieee_finite(double d);
815 void error(const char *fmt, ...);
816 void vpushi(int v);
817 void vrott(int n);
818 void vnrott(int n);
819 void lexpand_nr(void);
820 static void vpush_global_sym(CType *type, int v);
821 void vset(CType *type, int r, int v);
822 void type_to_str(char *buf, int buf_size,
823 CType *type, const char *varstr);
824 char *get_tok_str(int v, CValue *cv);
825 static Sym *get_sym_ref(CType *type, Section *sec,
826 unsigned long offset, unsigned long size);
827 static Sym *external_global_sym(int v, CType *type, int r);
829 /* section generation */
830 static void section_realloc(Section *sec, unsigned long new_size);
831 static void *section_ptr_add(Section *sec, unsigned long size);
832 static void put_extern_sym(Sym *sym, Section *section,
833 unsigned long value, unsigned long size);
834 static void greloc(Section *s, Sym *sym, unsigned long addr, int type);
835 static int put_elf_str(Section *s, const char *sym);
836 static int put_elf_sym(Section *s,
837 unsigned long value, unsigned long size,
838 int info, int other, int shndx, const char *name);
839 static int add_elf_sym(Section *s, unsigned long value, unsigned long size,
840 int info, int other, int sh_num, const char *name);
841 static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
842 int type, int symbol);
843 static void put_stabs(const char *str, int type, int other, int desc,
844 unsigned long value);
845 static void put_stabs_r(const char *str, int type, int other, int desc,
846 unsigned long value, Section *sec, int sym_index);
847 static void put_stabn(int type, int other, int desc, int value);
848 static void put_stabd(int type, int other, int desc);
849 static int tcc_add_dll(TCCState *s, const char *filename, int flags);
851 #define AFF_PRINT_ERROR 0x0001 /* print error if file not found */
852 #define AFF_REFERENCED_DLL 0x0002 /* load a referenced dll from another dll */
853 #define AFF_PREPROCESS 0x0004 /* preprocess file */
854 static int tcc_add_file_internal(TCCState *s, const char *filename, int flags);
856 /* tcccoff.c */
857 int tcc_output_coff(TCCState *s1, FILE *f);
859 /* tccpe.c */
860 void *resolve_sym(TCCState *s1, const char *sym, int type);
861 int pe_load_def_file(struct TCCState *s1, FILE *fp);
862 void pe_setup_paths(struct TCCState *s1, int *p_output_type, const char **p_outfile, char *first_file);
863 unsigned long pe_add_runtime(struct TCCState *s1);
864 int tcc_output_pe(struct TCCState *s1, const char *filename);
866 /* tccasm.c */
868 #ifdef CONFIG_TCC_ASM
870 typedef struct ExprValue {
871 uint32_t v;
872 Sym *sym;
873 } ExprValue;
875 #define MAX_ASM_OPERANDS 30
877 typedef struct ASMOperand {
878 int id; /* GCC 3 optionnal identifier (0 if number only supported */
879 char *constraint;
880 char asm_str[16]; /* computed asm string for operand */
881 SValue *vt; /* C value of the expression */
882 int ref_index; /* if >= 0, gives reference to a output constraint */
883 int input_index; /* if >= 0, gives reference to an input constraint */
884 int priority; /* priority, used to assign registers */
885 int reg; /* if >= 0, register number used for this operand */
886 int is_llong; /* true if double register value */
887 int is_memory; /* true if memory operand */
888 int is_rw; /* for '+' modifier */
889 } ASMOperand;
891 static void asm_expr(TCCState *s1, ExprValue *pe);
892 static int asm_int_expr(TCCState *s1);
893 static int find_constraint(ASMOperand *operands, int nb_operands,
894 const char *name, const char **pp);
896 static int tcc_assemble(TCCState *s1, int do_preprocess);
898 #endif
900 static void asm_instr(void);
901 static void asm_global_instr(void);
903 /* true if float/double/long double type */
904 static inline int is_float(int t)
906 int bt;
907 bt = t & VT_BTYPE;
908 return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT;
911 #ifdef TCC_TARGET_I386
912 #include "i386-gen.c"
913 #endif
915 #ifdef TCC_TARGET_ARM
916 #include "arm-gen.c"
917 #endif
919 #ifdef TCC_TARGET_C67
920 #include "c67-gen.c"
921 #endif
923 #ifdef CONFIG_TCC_STATIC
925 #define RTLD_LAZY 0x001
926 #define RTLD_NOW 0x002
927 #define RTLD_GLOBAL 0x100
928 #define RTLD_DEFAULT NULL
930 /* dummy function for profiling */
931 void *dlopen(const char *filename, int flag)
933 return NULL;
936 const char *dlerror(void)
938 return "error";
941 typedef struct TCCSyms {
942 char *str;
943 void *ptr;
944 } TCCSyms;
946 #define TCCSYM(a) { #a, &a, },
948 /* add the symbol you want here if no dynamic linking is done */
949 static TCCSyms tcc_syms[] = {
950 #if !defined(CONFIG_TCCBOOT)
951 TCCSYM(printf)
952 TCCSYM(fprintf)
953 TCCSYM(fopen)
954 TCCSYM(fclose)
955 #endif
956 { NULL, NULL },
959 void *resolve_sym(TCCState *s1, const char *symbol, int type)
961 TCCSyms *p;
962 p = tcc_syms;
963 while (p->str != NULL) {
964 if (!strcmp(p->str, symbol))
965 return p->ptr;
966 p++;
968 return NULL;
971 #elif !defined(_WIN32)
973 #include <dlfcn.h>
975 void *resolve_sym(TCCState *s1, const char *sym, int type)
977 return dlsym(RTLD_DEFAULT, sym);
980 #endif
982 /********************************************************/
984 /* we use our own 'finite' function to avoid potential problems with
985 non standard math libs */
986 /* XXX: endianness dependent */
987 int ieee_finite(double d)
989 int *p = (int *)&d;
990 return ((unsigned)((p[1] | 0x800fffff) + 1)) >> 31;
993 /* copy a string and truncate it. */
994 static char *pstrcpy(char *buf, int buf_size, const char *s)
996 char *q, *q_end;
997 int c;
999 if (buf_size > 0) {
1000 q = buf;
1001 q_end = buf + buf_size - 1;
1002 while (q < q_end) {
1003 c = *s++;
1004 if (c == '\0')
1005 break;
1006 *q++ = c;
1008 *q = '\0';
1010 return buf;
1013 /* strcat and truncate. */
1014 static char *pstrcat(char *buf, int buf_size, const char *s)
1016 int len;
1017 len = strlen(buf);
1018 if (len < buf_size)
1019 pstrcpy(buf + len, buf_size - len, s);
1020 return buf;
1023 static int strstart(const char *str, const char *val, const char **ptr)
1025 const char *p, *q;
1026 p = str;
1027 q = val;
1028 while (*q != '\0') {
1029 if (*p != *q)
1030 return 0;
1031 p++;
1032 q++;
1034 if (ptr)
1035 *ptr = p;
1036 return 1;
1039 #ifdef _WIN32
1040 char *normalize_slashes(char *path)
1042 char *p;
1043 for (p = path; *p; ++p)
1044 if (*p == '\\')
1045 *p = '/';
1046 return path;
1049 char *w32_tcc_lib_path(void)
1051 /* on win32, we suppose the lib and includes are at the location
1052 of 'tcc.exe' */
1053 char path[1024], *p;
1054 GetModuleFileNameA(NULL, path, sizeof path);
1055 p = tcc_basename(normalize_slashes(strlwr(path)));
1056 if (p - 5 > path && 0 == strncmp(p - 5, "/bin/", 5))
1057 p -= 5;
1058 else if (p > path)
1059 p--;
1060 *p = 0;
1061 return strdup(path);
1063 #endif
1065 void set_pages_executable(void *ptr, unsigned long length)
1067 #ifdef _WIN32
1068 unsigned long old_protect;
1069 VirtualProtect(ptr, length, PAGE_EXECUTE_READWRITE, &old_protect);
1070 #else
1071 unsigned long start, end;
1072 start = (unsigned long)ptr & ~(PAGESIZE - 1);
1073 end = (unsigned long)ptr + length;
1074 end = (end + PAGESIZE - 1) & ~(PAGESIZE - 1);
1075 mprotect((void *)start, end - start, PROT_READ | PROT_WRITE | PROT_EXEC);
1076 #endif
1079 /* memory management */
1080 #ifdef MEM_DEBUG
1081 int mem_cur_size;
1082 int mem_max_size;
1083 #endif
1085 static inline void tcc_free(void *ptr)
1087 #ifdef MEM_DEBUG
1088 mem_cur_size -= malloc_usable_size(ptr);
1089 #endif
1090 free(ptr);
1093 static void *tcc_malloc(unsigned long size)
1095 void *ptr;
1096 ptr = malloc(size);
1097 if (!ptr && size)
1098 error("memory full");
1099 #ifdef MEM_DEBUG
1100 mem_cur_size += malloc_usable_size(ptr);
1101 if (mem_cur_size > mem_max_size)
1102 mem_max_size = mem_cur_size;
1103 #endif
1104 return ptr;
1107 static void *tcc_mallocz(unsigned long size)
1109 void *ptr;
1110 ptr = tcc_malloc(size);
1111 memset(ptr, 0, size);
1112 return ptr;
1115 static inline void *tcc_realloc(void *ptr, unsigned long size)
1117 void *ptr1;
1118 #ifdef MEM_DEBUG
1119 mem_cur_size -= malloc_usable_size(ptr);
1120 #endif
1121 ptr1 = realloc(ptr, size);
1122 #ifdef MEM_DEBUG
1123 /* NOTE: count not correct if alloc error, but not critical */
1124 mem_cur_size += malloc_usable_size(ptr1);
1125 if (mem_cur_size > mem_max_size)
1126 mem_max_size = mem_cur_size;
1127 #endif
1128 return ptr1;
1131 static char *tcc_strdup(const char *str)
1133 char *ptr;
1134 ptr = tcc_malloc(strlen(str) + 1);
1135 strcpy(ptr, str);
1136 return ptr;
1139 #define free(p) use_tcc_free(p)
1140 #define malloc(s) use_tcc_malloc(s)
1141 #define realloc(p, s) use_tcc_realloc(p, s)
1143 static void dynarray_add(void ***ptab, int *nb_ptr, void *data)
1145 int nb, nb_alloc;
1146 void **pp;
1148 nb = *nb_ptr;
1149 pp = *ptab;
1150 /* every power of two we double array size */
1151 if ((nb & (nb - 1)) == 0) {
1152 if (!nb)
1153 nb_alloc = 1;
1154 else
1155 nb_alloc = nb * 2;
1156 pp = tcc_realloc(pp, nb_alloc * sizeof(void *));
1157 if (!pp)
1158 error("memory full");
1159 *ptab = pp;
1161 pp[nb++] = data;
1162 *nb_ptr = nb;
1165 /* symbol allocator */
1166 static Sym *__sym_malloc(void)
1168 Sym *sym_pool, *sym, *last_sym;
1169 int i;
1171 sym_pool = tcc_malloc(SYM_POOL_NB * sizeof(Sym));
1173 last_sym = sym_free_first;
1174 sym = sym_pool;
1175 for(i = 0; i < SYM_POOL_NB; i++) {
1176 sym->next = last_sym;
1177 last_sym = sym;
1178 sym++;
1180 sym_free_first = last_sym;
1181 return last_sym;
1184 static inline Sym *sym_malloc(void)
1186 Sym *sym;
1187 sym = sym_free_first;
1188 if (!sym)
1189 sym = __sym_malloc();
1190 sym_free_first = sym->next;
1191 return sym;
1194 static inline void sym_free(Sym *sym)
1196 sym->next = sym_free_first;
1197 sym_free_first = sym;
1200 Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags)
1202 Section *sec;
1204 sec = tcc_mallocz(sizeof(Section) + strlen(name));
1205 strcpy(sec->name, name);
1206 sec->sh_type = sh_type;
1207 sec->sh_flags = sh_flags;
1208 switch(sh_type) {
1209 case SHT_HASH:
1210 case SHT_REL:
1211 case SHT_DYNSYM:
1212 case SHT_SYMTAB:
1213 case SHT_DYNAMIC:
1214 sec->sh_addralign = 4;
1215 break;
1216 case SHT_STRTAB:
1217 sec->sh_addralign = 1;
1218 break;
1219 default:
1220 sec->sh_addralign = 32; /* default conservative alignment */
1221 break;
1224 /* only add section if not private */
1225 if (!(sh_flags & SHF_PRIVATE)) {
1226 sec->sh_num = s1->nb_sections;
1227 dynarray_add((void ***)&s1->sections, &s1->nb_sections, sec);
1229 return sec;
1232 static void free_section(Section *s)
1234 tcc_free(s->data);
1235 tcc_free(s);
1238 /* realloc section and set its content to zero */
1239 static void section_realloc(Section *sec, unsigned long new_size)
1241 unsigned long size;
1242 unsigned char *data;
1244 size = sec->data_allocated;
1245 if (size == 0)
1246 size = 1;
1247 while (size < new_size)
1248 size = size * 2;
1249 data = tcc_realloc(sec->data, size);
1250 if (!data)
1251 error("memory full");
1252 memset(data + sec->data_allocated, 0, size - sec->data_allocated);
1253 sec->data = data;
1254 sec->data_allocated = size;
1257 /* reserve at least 'size' bytes in section 'sec' from
1258 sec->data_offset. */
1259 static void *section_ptr_add(Section *sec, unsigned long size)
1261 unsigned long offset, offset1;
1263 offset = sec->data_offset;
1264 offset1 = offset + size;
1265 if (offset1 > sec->data_allocated)
1266 section_realloc(sec, offset1);
1267 sec->data_offset = offset1;
1268 return sec->data + offset;
1271 /* return a reference to a section, and create it if it does not
1272 exists */
1273 Section *find_section(TCCState *s1, const char *name)
1275 Section *sec;
1276 int i;
1277 for(i = 1; i < s1->nb_sections; i++) {
1278 sec = s1->sections[i];
1279 if (!strcmp(name, sec->name))
1280 return sec;
1282 /* sections are created as PROGBITS */
1283 return new_section(s1, name, SHT_PROGBITS, SHF_ALLOC);
1286 #define SECTION_ABS ((void *)1)
1288 /* update sym->c so that it points to an external symbol in section
1289 'section' with value 'value' */
1290 static void put_extern_sym2(Sym *sym, Section *section,
1291 unsigned long value, unsigned long size,
1292 int can_add_underscore)
1294 int sym_type, sym_bind, sh_num, info;
1295 Elf32_Sym *esym;
1296 const char *name;
1297 char buf1[256];
1299 if (section == NULL)
1300 sh_num = SHN_UNDEF;
1301 else if (section == SECTION_ABS)
1302 sh_num = SHN_ABS;
1303 else
1304 sh_num = section->sh_num;
1305 if (!sym->c) {
1306 if ((sym->type.t & VT_BTYPE) == VT_FUNC)
1307 sym_type = STT_FUNC;
1308 else
1309 sym_type = STT_OBJECT;
1310 if (sym->type.t & VT_STATIC)
1311 sym_bind = STB_LOCAL;
1312 else
1313 sym_bind = STB_GLOBAL;
1315 name = get_tok_str(sym->v, NULL);
1316 #ifdef CONFIG_TCC_BCHECK
1317 if (do_bounds_check) {
1318 char buf[32];
1320 /* XXX: avoid doing that for statics ? */
1321 /* if bound checking is activated, we change some function
1322 names by adding the "__bound" prefix */
1323 switch(sym->v) {
1324 #if 0
1325 /* XXX: we rely only on malloc hooks */
1326 case TOK_malloc:
1327 case TOK_free:
1328 case TOK_realloc:
1329 case TOK_memalign:
1330 case TOK_calloc:
1331 #endif
1332 case TOK_memcpy:
1333 case TOK_memmove:
1334 case TOK_memset:
1335 case TOK_strlen:
1336 case TOK_strcpy:
1337 case TOK__alloca:
1338 strcpy(buf, "__bound_");
1339 strcat(buf, name);
1340 name = buf;
1341 break;
1344 #endif
1345 if (tcc_state->leading_underscore && can_add_underscore) {
1346 buf1[0] = '_';
1347 pstrcpy(buf1 + 1, sizeof(buf1) - 1, name);
1348 name = buf1;
1350 info = ELF32_ST_INFO(sym_bind, sym_type);
1351 sym->c = add_elf_sym(symtab_section, value, size, info, 0, sh_num, name);
1352 } else {
1353 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
1354 esym->st_value = value;
1355 esym->st_size = size;
1356 esym->st_shndx = sh_num;
1360 static void put_extern_sym(Sym *sym, Section *section,
1361 unsigned long value, unsigned long size)
1363 put_extern_sym2(sym, section, value, size, 1);
1366 /* add a new relocation entry to symbol 'sym' in section 's' */
1367 static void greloc(Section *s, Sym *sym, unsigned long offset, int type)
1369 if (!sym->c)
1370 put_extern_sym(sym, NULL, 0, 0);
1371 /* now we can add ELF relocation info */
1372 put_elf_reloc(symtab_section, s, offset, type, sym->c);
1375 static inline int isid(int c)
1377 return (c >= 'a' && c <= 'z') ||
1378 (c >= 'A' && c <= 'Z') ||
1379 c == '_';
1382 static inline int isnum(int c)
1384 return c >= '0' && c <= '9';
1387 static inline int isoct(int c)
1389 return c >= '0' && c <= '7';
1392 static inline int toup(int c)
1394 if (c >= 'a' && c <= 'z')
1395 return c - 'a' + 'A';
1396 else
1397 return c;
1400 static void strcat_vprintf(char *buf, int buf_size, const char *fmt, va_list ap)
1402 int len;
1403 len = strlen(buf);
1404 vsnprintf(buf + len, buf_size - len, fmt, ap);
1407 static void strcat_printf(char *buf, int buf_size, const char *fmt, ...)
1409 va_list ap;
1410 va_start(ap, fmt);
1411 strcat_vprintf(buf, buf_size, fmt, ap);
1412 va_end(ap);
1415 void error1(TCCState *s1, int is_warning, const char *fmt, va_list ap)
1417 char buf[2048];
1418 BufferedFile **f;
1420 buf[0] = '\0';
1421 if (file) {
1422 for(f = s1->include_stack; f < s1->include_stack_ptr; f++)
1423 strcat_printf(buf, sizeof(buf), "In file included from %s:%d:\n",
1424 (*f)->filename, (*f)->line_num);
1425 if (file->line_num > 0) {
1426 strcat_printf(buf, sizeof(buf),
1427 "%s:%d: ", file->filename, file->line_num);
1428 } else {
1429 strcat_printf(buf, sizeof(buf),
1430 "%s: ", file->filename);
1432 } else {
1433 strcat_printf(buf, sizeof(buf),
1434 "tcc: ");
1436 if (is_warning)
1437 strcat_printf(buf, sizeof(buf), "warning: ");
1438 strcat_vprintf(buf, sizeof(buf), fmt, ap);
1440 if (!s1->error_func) {
1441 /* default case: stderr */
1442 fprintf(stderr, "%s\n", buf);
1443 } else {
1444 s1->error_func(s1->error_opaque, buf);
1446 if (!is_warning || s1->warn_error)
1447 s1->nb_errors++;
1450 #ifdef LIBTCC
1451 void tcc_set_error_func(TCCState *s, void *error_opaque,
1452 void (*error_func)(void *opaque, const char *msg))
1454 s->error_opaque = error_opaque;
1455 s->error_func = error_func;
1457 #endif
1459 /* error without aborting current compilation */
1460 void error_noabort(const char *fmt, ...)
1462 TCCState *s1 = tcc_state;
1463 va_list ap;
1465 va_start(ap, fmt);
1466 error1(s1, 0, fmt, ap);
1467 va_end(ap);
1470 void error(const char *fmt, ...)
1472 TCCState *s1 = tcc_state;
1473 va_list ap;
1475 va_start(ap, fmt);
1476 error1(s1, 0, fmt, ap);
1477 va_end(ap);
1478 /* better than nothing: in some cases, we accept to handle errors */
1479 if (s1->error_set_jmp_enabled) {
1480 longjmp(s1->error_jmp_buf, 1);
1481 } else {
1482 /* XXX: eliminate this someday */
1483 exit(1);
1487 void expect(const char *msg)
1489 error("%s expected", msg);
1492 void warning(const char *fmt, ...)
1494 TCCState *s1 = tcc_state;
1495 va_list ap;
1497 if (s1->warn_none)
1498 return;
1500 va_start(ap, fmt);
1501 error1(s1, 1, fmt, ap);
1502 va_end(ap);
1505 void skip(int c)
1507 if (tok != c)
1508 error("'%c' expected", c);
1509 next();
1512 static void test_lvalue(void)
1514 if (!(vtop->r & VT_LVAL))
1515 expect("lvalue");
1518 /* allocate a new token */
1519 static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len)
1521 TokenSym *ts, **ptable;
1522 int i;
1524 if (tok_ident >= SYM_FIRST_ANOM)
1525 error("memory full");
1527 /* expand token table if needed */
1528 i = tok_ident - TOK_IDENT;
1529 if ((i % TOK_ALLOC_INCR) == 0) {
1530 ptable = tcc_realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *));
1531 if (!ptable)
1532 error("memory full");
1533 table_ident = ptable;
1536 ts = tcc_malloc(sizeof(TokenSym) + len);
1537 table_ident[i] = ts;
1538 ts->tok = tok_ident++;
1539 ts->sym_define = NULL;
1540 ts->sym_label = NULL;
1541 ts->sym_struct = NULL;
1542 ts->sym_identifier = NULL;
1543 ts->len = len;
1544 ts->hash_next = NULL;
1545 memcpy(ts->str, str, len);
1546 ts->str[len] = '\0';
1547 *pts = ts;
1548 return ts;
1551 #define TOK_HASH_INIT 1
1552 #define TOK_HASH_FUNC(h, c) ((h) * 263 + (c))
1554 /* find a token and add it if not found */
1555 static TokenSym *tok_alloc(const char *str, int len)
1557 TokenSym *ts, **pts;
1558 int i;
1559 unsigned int h;
1561 h = TOK_HASH_INIT;
1562 for(i=0;i<len;i++)
1563 h = TOK_HASH_FUNC(h, ((unsigned char *)str)[i]);
1564 h &= (TOK_HASH_SIZE - 1);
1566 pts = &hash_ident[h];
1567 for(;;) {
1568 ts = *pts;
1569 if (!ts)
1570 break;
1571 if (ts->len == len && !memcmp(ts->str, str, len))
1572 return ts;
1573 pts = &(ts->hash_next);
1575 return tok_alloc_new(pts, str, len);
1578 /* CString handling */
1580 static void cstr_realloc(CString *cstr, int new_size)
1582 int size;
1583 void *data;
1585 size = cstr->size_allocated;
1586 if (size == 0)
1587 size = 8; /* no need to allocate a too small first string */
1588 while (size < new_size)
1589 size = size * 2;
1590 data = tcc_realloc(cstr->data_allocated, size);
1591 if (!data)
1592 error("memory full");
1593 cstr->data_allocated = data;
1594 cstr->size_allocated = size;
1595 cstr->data = data;
1598 /* add a byte */
1599 static inline void cstr_ccat(CString *cstr, int ch)
1601 int size;
1602 size = cstr->size + 1;
1603 if (size > cstr->size_allocated)
1604 cstr_realloc(cstr, size);
1605 ((unsigned char *)cstr->data)[size - 1] = ch;
1606 cstr->size = size;
1609 static void cstr_cat(CString *cstr, const char *str)
1611 int c;
1612 for(;;) {
1613 c = *str;
1614 if (c == '\0')
1615 break;
1616 cstr_ccat(cstr, c);
1617 str++;
1621 /* add a wide char */
1622 static void cstr_wccat(CString *cstr, int ch)
1624 int size;
1625 size = cstr->size + sizeof(nwchar_t);
1626 if (size > cstr->size_allocated)
1627 cstr_realloc(cstr, size);
1628 *(nwchar_t *)(((unsigned char *)cstr->data) + size - sizeof(nwchar_t)) = ch;
1629 cstr->size = size;
1632 static void cstr_new(CString *cstr)
1634 memset(cstr, 0, sizeof(CString));
1637 /* free string and reset it to NULL */
1638 static void cstr_free(CString *cstr)
1640 tcc_free(cstr->data_allocated);
1641 cstr_new(cstr);
1644 #define cstr_reset(cstr) cstr_free(cstr)
1646 /* XXX: unicode ? */
1647 static void add_char(CString *cstr, int c)
1649 if (c == '\'' || c == '\"' || c == '\\') {
1650 /* XXX: could be more precise if char or string */
1651 cstr_ccat(cstr, '\\');
1653 if (c >= 32 && c <= 126) {
1654 cstr_ccat(cstr, c);
1655 } else {
1656 cstr_ccat(cstr, '\\');
1657 if (c == '\n') {
1658 cstr_ccat(cstr, 'n');
1659 } else {
1660 cstr_ccat(cstr, '0' + ((c >> 6) & 7));
1661 cstr_ccat(cstr, '0' + ((c >> 3) & 7));
1662 cstr_ccat(cstr, '0' + (c & 7));
1667 /* XXX: buffer overflow */
1668 /* XXX: float tokens */
1669 char *get_tok_str(int v, CValue *cv)
1671 static char buf[STRING_MAX_SIZE + 1];
1672 static CString cstr_buf;
1673 CString *cstr;
1674 unsigned char *q;
1675 char *p;
1676 int i, len;
1678 /* NOTE: to go faster, we give a fixed buffer for small strings */
1679 cstr_reset(&cstr_buf);
1680 cstr_buf.data = buf;
1681 cstr_buf.size_allocated = sizeof(buf);
1682 p = buf;
1684 switch(v) {
1685 case TOK_CINT:
1686 case TOK_CUINT:
1687 /* XXX: not quite exact, but only useful for testing */
1688 sprintf(p, "%u", cv->ui);
1689 break;
1690 case TOK_CLLONG:
1691 case TOK_CULLONG:
1692 /* XXX: not quite exact, but only useful for testing */
1693 sprintf(p, "%Lu", cv->ull);
1694 break;
1695 case TOK_CCHAR:
1696 case TOK_LCHAR:
1697 cstr_ccat(&cstr_buf, '\'');
1698 add_char(&cstr_buf, cv->i);
1699 cstr_ccat(&cstr_buf, '\'');
1700 cstr_ccat(&cstr_buf, '\0');
1701 break;
1702 case TOK_PPNUM:
1703 cstr = cv->cstr;
1704 len = cstr->size - 1;
1705 for(i=0;i<len;i++)
1706 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1707 cstr_ccat(&cstr_buf, '\0');
1708 break;
1709 case TOK_STR:
1710 case TOK_LSTR:
1711 cstr = cv->cstr;
1712 cstr_ccat(&cstr_buf, '\"');
1713 if (v == TOK_STR) {
1714 len = cstr->size - 1;
1715 for(i=0;i<len;i++)
1716 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1717 } else {
1718 len = (cstr->size / sizeof(nwchar_t)) - 1;
1719 for(i=0;i<len;i++)
1720 add_char(&cstr_buf, ((nwchar_t *)cstr->data)[i]);
1722 cstr_ccat(&cstr_buf, '\"');
1723 cstr_ccat(&cstr_buf, '\0');
1724 break;
1725 case TOK_LT:
1726 v = '<';
1727 goto addv;
1728 case TOK_GT:
1729 v = '>';
1730 goto addv;
1731 case TOK_DOTS:
1732 return strcpy(p, "...");
1733 case TOK_A_SHL:
1734 return strcpy(p, "<<=");
1735 case TOK_A_SAR:
1736 return strcpy(p, ">>=");
1737 default:
1738 if (v < TOK_IDENT) {
1739 /* search in two bytes table */
1740 q = tok_two_chars;
1741 while (*q) {
1742 if (q[2] == v) {
1743 *p++ = q[0];
1744 *p++ = q[1];
1745 *p = '\0';
1746 return buf;
1748 q += 3;
1750 addv:
1751 *p++ = v;
1752 *p = '\0';
1753 } else if (v < tok_ident) {
1754 return table_ident[v - TOK_IDENT]->str;
1755 } else if (v >= SYM_FIRST_ANOM) {
1756 /* special name for anonymous symbol */
1757 sprintf(p, "L.%u", v - SYM_FIRST_ANOM);
1758 } else {
1759 /* should never happen */
1760 return NULL;
1762 break;
1764 return cstr_buf.data;
1767 /* push, without hashing */
1768 static Sym *sym_push2(Sym **ps, int v, int t, int c)
1770 Sym *s;
1771 s = sym_malloc();
1772 s->v = v;
1773 s->type.t = t;
1774 s->c = c;
1775 s->next = NULL;
1776 /* add in stack */
1777 s->prev = *ps;
1778 *ps = s;
1779 return s;
1782 /* find a symbol and return its associated structure. 's' is the top
1783 of the symbol stack */
1784 static Sym *sym_find2(Sym *s, int v)
1786 while (s) {
1787 if (s->v == v)
1788 return s;
1789 s = s->prev;
1791 return NULL;
1794 /* structure lookup */
1795 static inline Sym *struct_find(int v)
1797 v -= TOK_IDENT;
1798 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1799 return NULL;
1800 return table_ident[v]->sym_struct;
1803 /* find an identifier */
1804 static inline Sym *sym_find(int v)
1806 v -= TOK_IDENT;
1807 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1808 return NULL;
1809 return table_ident[v]->sym_identifier;
1812 /* push a given symbol on the symbol stack */
1813 static Sym *sym_push(int v, CType *type, int r, int c)
1815 Sym *s, **ps;
1816 TokenSym *ts;
1818 if (local_stack)
1819 ps = &local_stack;
1820 else
1821 ps = &global_stack;
1822 s = sym_push2(ps, v, type->t, c);
1823 s->type.ref = type->ref;
1824 s->r = r;
1825 /* don't record fields or anonymous symbols */
1826 /* XXX: simplify */
1827 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1828 /* record symbol in token array */
1829 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1830 if (v & SYM_STRUCT)
1831 ps = &ts->sym_struct;
1832 else
1833 ps = &ts->sym_identifier;
1834 s->prev_tok = *ps;
1835 *ps = s;
1837 return s;
1840 /* push a global identifier */
1841 static Sym *global_identifier_push(int v, int t, int c)
1843 Sym *s, **ps;
1844 s = sym_push2(&global_stack, v, t, c);
1845 /* don't record anonymous symbol */
1846 if (v < SYM_FIRST_ANOM) {
1847 ps = &table_ident[v - TOK_IDENT]->sym_identifier;
1848 /* modify the top most local identifier, so that
1849 sym_identifier will point to 's' when popped */
1850 while (*ps != NULL)
1851 ps = &(*ps)->prev_tok;
1852 s->prev_tok = NULL;
1853 *ps = s;
1855 return s;
1858 /* pop symbols until top reaches 'b' */
1859 static void sym_pop(Sym **ptop, Sym *b)
1861 Sym *s, *ss, **ps;
1862 TokenSym *ts;
1863 int v;
1865 s = *ptop;
1866 while(s != b) {
1867 ss = s->prev;
1868 v = s->v;
1869 /* remove symbol in token array */
1870 /* XXX: simplify */
1871 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1872 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1873 if (v & SYM_STRUCT)
1874 ps = &ts->sym_struct;
1875 else
1876 ps = &ts->sym_identifier;
1877 *ps = s->prev_tok;
1879 sym_free(s);
1880 s = ss;
1882 *ptop = b;
1885 /* I/O layer */
1887 BufferedFile *tcc_open(TCCState *s1, const char *filename)
1889 int fd;
1890 BufferedFile *bf;
1892 fd = open(filename, O_RDONLY | O_BINARY);
1893 if (fd < 0)
1894 return NULL;
1895 bf = tcc_malloc(sizeof(BufferedFile));
1896 if (!bf) {
1897 close(fd);
1898 return NULL;
1900 bf->fd = fd;
1901 bf->buf_ptr = bf->buffer;
1902 bf->buf_end = bf->buffer;
1903 bf->buffer[0] = CH_EOB; /* put eob symbol */
1904 pstrcpy(bf->filename, sizeof(bf->filename), filename);
1905 #ifdef _WIN32
1906 normalize_slashes(bf->filename);
1907 #endif
1908 bf->line_num = 1;
1909 bf->ifndef_macro = 0;
1910 bf->ifdef_stack_ptr = s1->ifdef_stack_ptr;
1911 // printf("opening '%s'\n", filename);
1912 return bf;
1915 void tcc_close(BufferedFile *bf)
1917 total_lines += bf->line_num;
1918 close(bf->fd);
1919 tcc_free(bf);
1922 /* fill input buffer and peek next char */
1923 static int tcc_peekc_slow(BufferedFile *bf)
1925 int len;
1926 /* only tries to read if really end of buffer */
1927 if (bf->buf_ptr >= bf->buf_end) {
1928 if (bf->fd != -1) {
1929 #if defined(PARSE_DEBUG)
1930 len = 8;
1931 #else
1932 len = IO_BUF_SIZE;
1933 #endif
1934 len = read(bf->fd, bf->buffer, len);
1935 if (len < 0)
1936 len = 0;
1937 } else {
1938 len = 0;
1940 total_bytes += len;
1941 bf->buf_ptr = bf->buffer;
1942 bf->buf_end = bf->buffer + len;
1943 *bf->buf_end = CH_EOB;
1945 if (bf->buf_ptr < bf->buf_end) {
1946 return bf->buf_ptr[0];
1947 } else {
1948 bf->buf_ptr = bf->buf_end;
1949 return CH_EOF;
1953 /* return the current character, handling end of block if necessary
1954 (but not stray) */
1955 static int handle_eob(void)
1957 return tcc_peekc_slow(file);
1960 /* read next char from current input file and handle end of input buffer */
1961 static inline void inp(void)
1963 ch = *(++(file->buf_ptr));
1964 /* end of buffer/file handling */
1965 if (ch == CH_EOB)
1966 ch = handle_eob();
1969 /* handle '\[\r]\n' */
1970 static void handle_stray(void)
1972 while (ch == '\\') {
1973 inp();
1974 if (ch == '\n') {
1975 file->line_num++;
1976 inp();
1977 } else if (ch == '\r') {
1978 inp();
1979 if (ch != '\n')
1980 goto fail;
1981 file->line_num++;
1982 inp();
1983 } else {
1984 fail:
1985 error("stray '\\' in program");
1990 /* skip the stray and handle the \\n case. Output an error if
1991 incorrect char after the stray */
1992 static int handle_stray1(uint8_t *p)
1994 int c;
1996 if (p >= file->buf_end) {
1997 file->buf_ptr = p;
1998 c = handle_eob();
1999 p = file->buf_ptr;
2000 if (c == '\\')
2001 goto parse_stray;
2002 } else {
2003 parse_stray:
2004 file->buf_ptr = p;
2005 ch = *p;
2006 handle_stray();
2007 p = file->buf_ptr;
2008 c = *p;
2010 return c;
2013 /* handle just the EOB case, but not stray */
2014 #define PEEKC_EOB(c, p)\
2016 p++;\
2017 c = *p;\
2018 if (c == '\\') {\
2019 file->buf_ptr = p;\
2020 c = handle_eob();\
2021 p = file->buf_ptr;\
2025 /* handle the complicated stray case */
2026 #define PEEKC(c, p)\
2028 p++;\
2029 c = *p;\
2030 if (c == '\\') {\
2031 c = handle_stray1(p);\
2032 p = file->buf_ptr;\
2036 /* input with '\[\r]\n' handling. Note that this function cannot
2037 handle other characters after '\', so you cannot call it inside
2038 strings or comments */
2039 static void minp(void)
2041 inp();
2042 if (ch == '\\')
2043 handle_stray();
2047 /* single line C++ comments */
2048 static uint8_t *parse_line_comment(uint8_t *p)
2050 int c;
2052 p++;
2053 for(;;) {
2054 c = *p;
2055 redo:
2056 if (c == '\n' || c == CH_EOF) {
2057 break;
2058 } else if (c == '\\') {
2059 file->buf_ptr = p;
2060 c = handle_eob();
2061 p = file->buf_ptr;
2062 if (c == '\\') {
2063 PEEKC_EOB(c, p);
2064 if (c == '\n') {
2065 file->line_num++;
2066 PEEKC_EOB(c, p);
2067 } else if (c == '\r') {
2068 PEEKC_EOB(c, p);
2069 if (c == '\n') {
2070 file->line_num++;
2071 PEEKC_EOB(c, p);
2074 } else {
2075 goto redo;
2077 } else {
2078 p++;
2081 return p;
2084 /* C comments */
2085 static uint8_t *parse_comment(uint8_t *p)
2087 int c;
2089 p++;
2090 for(;;) {
2091 /* fast skip loop */
2092 for(;;) {
2093 c = *p;
2094 if (c == '\n' || c == '*' || c == '\\')
2095 break;
2096 p++;
2097 c = *p;
2098 if (c == '\n' || c == '*' || c == '\\')
2099 break;
2100 p++;
2102 /* now we can handle all the cases */
2103 if (c == '\n') {
2104 file->line_num++;
2105 p++;
2106 } else if (c == '*') {
2107 p++;
2108 for(;;) {
2109 c = *p;
2110 if (c == '*') {
2111 p++;
2112 } else if (c == '/') {
2113 goto end_of_comment;
2114 } else if (c == '\\') {
2115 file->buf_ptr = p;
2116 c = handle_eob();
2117 p = file->buf_ptr;
2118 if (c == '\\') {
2119 /* skip '\[\r]\n', otherwise just skip the stray */
2120 while (c == '\\') {
2121 PEEKC_EOB(c, p);
2122 if (c == '\n') {
2123 file->line_num++;
2124 PEEKC_EOB(c, p);
2125 } else if (c == '\r') {
2126 PEEKC_EOB(c, p);
2127 if (c == '\n') {
2128 file->line_num++;
2129 PEEKC_EOB(c, p);
2131 } else {
2132 goto after_star;
2136 } else {
2137 break;
2140 after_star: ;
2141 } else {
2142 /* stray, eob or eof */
2143 file->buf_ptr = p;
2144 c = handle_eob();
2145 p = file->buf_ptr;
2146 if (c == CH_EOF) {
2147 error("unexpected end of file in comment");
2148 } else if (c == '\\') {
2149 p++;
2153 end_of_comment:
2154 p++;
2155 return p;
2158 #define cinp minp
2160 /* space exlcuding newline */
2161 static inline int is_space(int ch)
2163 return ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f' || ch == '\r';
2166 static inline void skip_spaces(void)
2168 while (is_space(ch))
2169 cinp();
2172 /* parse a string without interpreting escapes */
2173 static uint8_t *parse_pp_string(uint8_t *p,
2174 int sep, CString *str)
2176 int c;
2177 p++;
2178 for(;;) {
2179 c = *p;
2180 if (c == sep) {
2181 break;
2182 } else if (c == '\\') {
2183 file->buf_ptr = p;
2184 c = handle_eob();
2185 p = file->buf_ptr;
2186 if (c == CH_EOF) {
2187 unterminated_string:
2188 /* XXX: indicate line number of start of string */
2189 error("missing terminating %c character", sep);
2190 } else if (c == '\\') {
2191 /* escape : just skip \[\r]\n */
2192 PEEKC_EOB(c, p);
2193 if (c == '\n') {
2194 file->line_num++;
2195 p++;
2196 } else if (c == '\r') {
2197 PEEKC_EOB(c, p);
2198 if (c != '\n')
2199 expect("'\n' after '\r'");
2200 file->line_num++;
2201 p++;
2202 } else if (c == CH_EOF) {
2203 goto unterminated_string;
2204 } else {
2205 if (str) {
2206 cstr_ccat(str, '\\');
2207 cstr_ccat(str, c);
2209 p++;
2212 } else if (c == '\n') {
2213 file->line_num++;
2214 goto add_char;
2215 } else if (c == '\r') {
2216 PEEKC_EOB(c, p);
2217 if (c != '\n') {
2218 if (str)
2219 cstr_ccat(str, '\r');
2220 } else {
2221 file->line_num++;
2222 goto add_char;
2224 } else {
2225 add_char:
2226 if (str)
2227 cstr_ccat(str, c);
2228 p++;
2231 p++;
2232 return p;
2235 /* skip block of text until #else, #elif or #endif. skip also pairs of
2236 #if/#endif */
2237 void preprocess_skip(void)
2239 int a, start_of_line, c;
2240 uint8_t *p;
2242 p = file->buf_ptr;
2243 start_of_line = 1;
2244 a = 0;
2245 for(;;) {
2246 redo_no_start:
2247 c = *p;
2248 switch(c) {
2249 case ' ':
2250 case '\t':
2251 case '\f':
2252 case '\v':
2253 case '\r':
2254 p++;
2255 goto redo_no_start;
2256 case '\n':
2257 start_of_line = 1;
2258 file->line_num++;
2259 p++;
2260 goto redo_no_start;
2261 case '\\':
2262 file->buf_ptr = p;
2263 c = handle_eob();
2264 if (c == CH_EOF) {
2265 expect("#endif");
2266 } else if (c == '\\') {
2267 /* XXX: incorrect: should not give an error */
2268 ch = file->buf_ptr[0];
2269 handle_stray();
2271 p = file->buf_ptr;
2272 goto redo_no_start;
2273 /* skip strings */
2274 case '\"':
2275 case '\'':
2276 p = parse_pp_string(p, c, NULL);
2277 break;
2278 /* skip comments */
2279 case '/':
2280 file->buf_ptr = p;
2281 ch = *p;
2282 minp();
2283 p = file->buf_ptr;
2284 if (ch == '*') {
2285 p = parse_comment(p);
2286 } else if (ch == '/') {
2287 p = parse_line_comment(p);
2289 break;
2291 case '#':
2292 p++;
2293 if (start_of_line) {
2294 file->buf_ptr = p;
2295 next_nomacro();
2296 p = file->buf_ptr;
2297 if (a == 0 &&
2298 (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
2299 goto the_end;
2300 if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
2301 a++;
2302 else if (tok == TOK_ENDIF)
2303 a--;
2305 break;
2306 default:
2307 p++;
2308 break;
2310 start_of_line = 0;
2312 the_end: ;
2313 file->buf_ptr = p;
2316 /* ParseState handling */
2318 /* XXX: currently, no include file info is stored. Thus, we cannot display
2319 accurate messages if the function or data definition spans multiple
2320 files */
2322 /* save current parse state in 's' */
2323 void save_parse_state(ParseState *s)
2325 s->line_num = file->line_num;
2326 s->macro_ptr = macro_ptr;
2327 s->tok = tok;
2328 s->tokc = tokc;
2331 /* restore parse state from 's' */
2332 void restore_parse_state(ParseState *s)
2334 file->line_num = s->line_num;
2335 macro_ptr = s->macro_ptr;
2336 tok = s->tok;
2337 tokc = s->tokc;
2340 /* return the number of additional 'ints' necessary to store the
2341 token */
2342 static inline int tok_ext_size(int t)
2344 switch(t) {
2345 /* 4 bytes */
2346 case TOK_CINT:
2347 case TOK_CUINT:
2348 case TOK_CCHAR:
2349 case TOK_LCHAR:
2350 case TOK_CFLOAT:
2351 case TOK_LINENUM:
2352 return 1;
2353 case TOK_STR:
2354 case TOK_LSTR:
2355 case TOK_PPNUM:
2356 error("unsupported token");
2357 return 1;
2358 case TOK_CDOUBLE:
2359 case TOK_CLLONG:
2360 case TOK_CULLONG:
2361 return 2;
2362 case TOK_CLDOUBLE:
2363 return LDOUBLE_SIZE / 4;
2364 default:
2365 return 0;
2369 /* token string handling */
2371 static inline void tok_str_new(TokenString *s)
2373 s->str = NULL;
2374 s->len = 0;
2375 s->allocated_len = 0;
2376 s->last_line_num = -1;
2379 static void tok_str_free(int *str)
2381 tcc_free(str);
2384 static int *tok_str_realloc(TokenString *s)
2386 int *str, len;
2388 if (s->allocated_len == 0) {
2389 len = 8;
2390 } else {
2391 len = s->allocated_len * 2;
2393 str = tcc_realloc(s->str, len * sizeof(int));
2394 if (!str)
2395 error("memory full");
2396 s->allocated_len = len;
2397 s->str = str;
2398 return str;
2401 static void tok_str_add(TokenString *s, int t)
2403 int len, *str;
2405 len = s->len;
2406 str = s->str;
2407 if (len >= s->allocated_len)
2408 str = tok_str_realloc(s);
2409 str[len++] = t;
2410 s->len = len;
2413 static void tok_str_add2(TokenString *s, int t, CValue *cv)
2415 int len, *str;
2417 len = s->len;
2418 str = s->str;
2420 /* allocate space for worst case */
2421 if (len + TOK_MAX_SIZE > s->allocated_len)
2422 str = tok_str_realloc(s);
2423 str[len++] = t;
2424 switch(t) {
2425 case TOK_CINT:
2426 case TOK_CUINT:
2427 case TOK_CCHAR:
2428 case TOK_LCHAR:
2429 case TOK_CFLOAT:
2430 case TOK_LINENUM:
2431 str[len++] = cv->tab[0];
2432 break;
2433 case TOK_PPNUM:
2434 case TOK_STR:
2435 case TOK_LSTR:
2437 int nb_words;
2438 CString *cstr;
2440 nb_words = (sizeof(CString) + cv->cstr->size + 3) >> 2;
2441 while ((len + nb_words) > s->allocated_len)
2442 str = tok_str_realloc(s);
2443 cstr = (CString *)(str + len);
2444 cstr->data = NULL;
2445 cstr->size = cv->cstr->size;
2446 cstr->data_allocated = NULL;
2447 cstr->size_allocated = cstr->size;
2448 memcpy((char *)cstr + sizeof(CString),
2449 cv->cstr->data, cstr->size);
2450 len += nb_words;
2452 break;
2453 case TOK_CDOUBLE:
2454 case TOK_CLLONG:
2455 case TOK_CULLONG:
2456 #if LDOUBLE_SIZE == 8
2457 case TOK_CLDOUBLE:
2458 #endif
2459 str[len++] = cv->tab[0];
2460 str[len++] = cv->tab[1];
2461 break;
2462 #if LDOUBLE_SIZE == 12
2463 case TOK_CLDOUBLE:
2464 str[len++] = cv->tab[0];
2465 str[len++] = cv->tab[1];
2466 str[len++] = cv->tab[2];
2467 #elif LDOUBLE_SIZE != 8
2468 #error add long double size support
2469 #endif
2470 break;
2471 default:
2472 break;
2474 s->len = len;
2477 /* add the current parse token in token string 's' */
2478 static void tok_str_add_tok(TokenString *s)
2480 CValue cval;
2482 /* save line number info */
2483 if (file->line_num != s->last_line_num) {
2484 s->last_line_num = file->line_num;
2485 cval.i = s->last_line_num;
2486 tok_str_add2(s, TOK_LINENUM, &cval);
2488 tok_str_add2(s, tok, &tokc);
2491 #if LDOUBLE_SIZE == 12
2492 #define LDOUBLE_GET(p, cv) \
2493 cv.tab[0] = p[0]; \
2494 cv.tab[1] = p[1]; \
2495 cv.tab[2] = p[2];
2496 #elif LDOUBLE_SIZE == 8
2497 #define LDOUBLE_GET(p, cv) \
2498 cv.tab[0] = p[0]; \
2499 cv.tab[1] = p[1];
2500 #else
2501 #error add long double size support
2502 #endif
2505 /* get a token from an integer array and increment pointer
2506 accordingly. we code it as a macro to avoid pointer aliasing. */
2507 #define TOK_GET(t, p, cv) \
2509 t = *p++; \
2510 switch(t) { \
2511 case TOK_CINT: \
2512 case TOK_CUINT: \
2513 case TOK_CCHAR: \
2514 case TOK_LCHAR: \
2515 case TOK_CFLOAT: \
2516 case TOK_LINENUM: \
2517 cv.tab[0] = *p++; \
2518 break; \
2519 case TOK_STR: \
2520 case TOK_LSTR: \
2521 case TOK_PPNUM: \
2522 cv.cstr = (CString *)p; \
2523 cv.cstr->data = (char *)p + sizeof(CString);\
2524 p += (sizeof(CString) + cv.cstr->size + 3) >> 2;\
2525 break; \
2526 case TOK_CDOUBLE: \
2527 case TOK_CLLONG: \
2528 case TOK_CULLONG: \
2529 cv.tab[0] = p[0]; \
2530 cv.tab[1] = p[1]; \
2531 p += 2; \
2532 break; \
2533 case TOK_CLDOUBLE: \
2534 LDOUBLE_GET(p, cv); \
2535 p += LDOUBLE_SIZE / 4; \
2536 break; \
2537 default: \
2538 break; \
2542 /* defines handling */
2543 static inline void define_push(int v, int macro_type, int *str, Sym *first_arg)
2545 Sym *s;
2547 s = sym_push2(&define_stack, v, macro_type, (int)str);
2548 s->next = first_arg;
2549 table_ident[v - TOK_IDENT]->sym_define = s;
2552 /* undefined a define symbol. Its name is just set to zero */
2553 static void define_undef(Sym *s)
2555 int v;
2556 v = s->v;
2557 if (v >= TOK_IDENT && v < tok_ident)
2558 table_ident[v - TOK_IDENT]->sym_define = NULL;
2559 s->v = 0;
2562 static inline Sym *define_find(int v)
2564 v -= TOK_IDENT;
2565 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2566 return NULL;
2567 return table_ident[v]->sym_define;
2570 /* free define stack until top reaches 'b' */
2571 static void free_defines(Sym *b)
2573 Sym *top, *top1;
2574 int v;
2576 top = define_stack;
2577 while (top != b) {
2578 top1 = top->prev;
2579 /* do not free args or predefined defines */
2580 if (top->c)
2581 tok_str_free((int *)top->c);
2582 v = top->v;
2583 if (v >= TOK_IDENT && v < tok_ident)
2584 table_ident[v - TOK_IDENT]->sym_define = NULL;
2585 sym_free(top);
2586 top = top1;
2588 define_stack = b;
2591 /* label lookup */
2592 static Sym *label_find(int v)
2594 v -= TOK_IDENT;
2595 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2596 return NULL;
2597 return table_ident[v]->sym_label;
2600 static Sym *label_push(Sym **ptop, int v, int flags)
2602 Sym *s, **ps;
2603 s = sym_push2(ptop, v, 0, 0);
2604 s->r = flags;
2605 ps = &table_ident[v - TOK_IDENT]->sym_label;
2606 if (ptop == &global_label_stack) {
2607 /* modify the top most local identifier, so that
2608 sym_identifier will point to 's' when popped */
2609 while (*ps != NULL)
2610 ps = &(*ps)->prev_tok;
2612 s->prev_tok = *ps;
2613 *ps = s;
2614 return s;
2617 /* pop labels until element last is reached. Look if any labels are
2618 undefined. Define symbols if '&&label' was used. */
2619 static void label_pop(Sym **ptop, Sym *slast)
2621 Sym *s, *s1;
2622 for(s = *ptop; s != slast; s = s1) {
2623 s1 = s->prev;
2624 if (s->r == LABEL_DECLARED) {
2625 warning("label '%s' declared but not used", get_tok_str(s->v, NULL));
2626 } else if (s->r == LABEL_FORWARD) {
2627 error("label '%s' used but not defined",
2628 get_tok_str(s->v, NULL));
2629 } else {
2630 if (s->c) {
2631 /* define corresponding symbol. A size of
2632 1 is put. */
2633 put_extern_sym(s, cur_text_section, (long)s->next, 1);
2636 /* remove label */
2637 table_ident[s->v - TOK_IDENT]->sym_label = s->prev_tok;
2638 sym_free(s);
2640 *ptop = slast;
2643 /* eval an expression for #if/#elif */
2644 static int expr_preprocess(void)
2646 int c, t;
2647 TokenString str;
2649 tok_str_new(&str);
2650 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2651 next(); /* do macro subst */
2652 if (tok == TOK_DEFINED) {
2653 next_nomacro();
2654 t = tok;
2655 if (t == '(')
2656 next_nomacro();
2657 c = define_find(tok) != 0;
2658 if (t == '(')
2659 next_nomacro();
2660 tok = TOK_CINT;
2661 tokc.i = c;
2662 } else if (tok >= TOK_IDENT) {
2663 /* if undefined macro */
2664 tok = TOK_CINT;
2665 tokc.i = 0;
2667 tok_str_add_tok(&str);
2669 tok_str_add(&str, -1); /* simulate end of file */
2670 tok_str_add(&str, 0);
2671 /* now evaluate C constant expression */
2672 macro_ptr = str.str;
2673 next();
2674 c = expr_const();
2675 macro_ptr = NULL;
2676 tok_str_free(str.str);
2677 return c != 0;
2680 #if defined(PARSE_DEBUG) || defined(PP_DEBUG)
2681 static void tok_print(int *str)
2683 int t;
2684 CValue cval;
2686 while (1) {
2687 TOK_GET(t, str, cval);
2688 if (!t)
2689 break;
2690 printf(" %s", get_tok_str(t, &cval));
2692 printf("\n");
2694 #endif
2696 /* parse after #define */
2697 static void parse_define(void)
2699 Sym *s, *first, **ps;
2700 int v, t, varg, is_vaargs, c;
2701 TokenString str;
2703 v = tok;
2704 if (v < TOK_IDENT)
2705 error("invalid macro name '%s'", get_tok_str(tok, &tokc));
2706 /* XXX: should check if same macro (ANSI) */
2707 first = NULL;
2708 t = MACRO_OBJ;
2709 /* '(' must be just after macro definition for MACRO_FUNC */
2710 c = file->buf_ptr[0];
2711 if (c == '\\')
2712 c = handle_stray1(file->buf_ptr);
2713 if (c == '(') {
2714 next_nomacro();
2715 next_nomacro();
2716 ps = &first;
2717 while (tok != ')') {
2718 varg = tok;
2719 next_nomacro();
2720 is_vaargs = 0;
2721 if (varg == TOK_DOTS) {
2722 varg = TOK___VA_ARGS__;
2723 is_vaargs = 1;
2724 } else if (tok == TOK_DOTS && gnu_ext) {
2725 is_vaargs = 1;
2726 next_nomacro();
2728 if (varg < TOK_IDENT)
2729 error("badly punctuated parameter list");
2730 s = sym_push2(&define_stack, varg | SYM_FIELD, is_vaargs, 0);
2731 *ps = s;
2732 ps = &s->next;
2733 if (tok != ',')
2734 break;
2735 next_nomacro();
2737 t = MACRO_FUNC;
2739 tok_str_new(&str);
2740 next_nomacro();
2741 /* EOF testing necessary for '-D' handling */
2742 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2743 tok_str_add2(&str, tok, &tokc);
2744 next_nomacro();
2746 tok_str_add(&str, 0);
2747 #ifdef PP_DEBUG
2748 printf("define %s %d: ", get_tok_str(v, NULL), t);
2749 tok_print(str.str);
2750 #endif
2751 define_push(v, t, str.str, first);
2754 static inline int hash_cached_include(int type, const char *filename)
2756 const unsigned char *s;
2757 unsigned int h;
2759 h = TOK_HASH_INIT;
2760 h = TOK_HASH_FUNC(h, type);
2761 s = filename;
2762 while (*s) {
2763 h = TOK_HASH_FUNC(h, *s);
2764 s++;
2766 h &= (CACHED_INCLUDES_HASH_SIZE - 1);
2767 return h;
2770 /* XXX: use a token or a hash table to accelerate matching ? */
2771 static CachedInclude *search_cached_include(TCCState *s1,
2772 int type, const char *filename)
2774 CachedInclude *e;
2775 int i, h;
2776 h = hash_cached_include(type, filename);
2777 i = s1->cached_includes_hash[h];
2778 for(;;) {
2779 if (i == 0)
2780 break;
2781 e = s1->cached_includes[i - 1];
2782 if (e->type == type && !strcmp(e->filename, filename))
2783 return e;
2784 i = e->hash_next;
2786 return NULL;
2789 static inline void add_cached_include(TCCState *s1, int type,
2790 const char *filename, int ifndef_macro)
2792 CachedInclude *e;
2793 int h;
2795 if (search_cached_include(s1, type, filename))
2796 return;
2797 #ifdef INC_DEBUG
2798 printf("adding cached '%s' %s\n", filename, get_tok_str(ifndef_macro, NULL));
2799 #endif
2800 e = tcc_malloc(sizeof(CachedInclude) + strlen(filename));
2801 if (!e)
2802 return;
2803 e->type = type;
2804 strcpy(e->filename, filename);
2805 e->ifndef_macro = ifndef_macro;
2806 dynarray_add((void ***)&s1->cached_includes, &s1->nb_cached_includes, e);
2807 /* add in hash table */
2808 h = hash_cached_include(type, filename);
2809 e->hash_next = s1->cached_includes_hash[h];
2810 s1->cached_includes_hash[h] = s1->nb_cached_includes;
2813 static void pragma_parse(TCCState *s1)
2815 int val;
2817 next();
2818 if (tok == TOK_pack) {
2820 This may be:
2821 #pragma pack(1) // set
2822 #pragma pack() // reset to default
2823 #pragma pack(push,1) // push & set
2824 #pragma pack(pop) // restore previous
2826 next();
2827 skip('(');
2828 if (tok == TOK_ASM_pop) {
2829 next();
2830 if (s1->pack_stack_ptr <= s1->pack_stack) {
2831 stk_error:
2832 error("out of pack stack");
2834 s1->pack_stack_ptr--;
2835 } else {
2836 val = 0;
2837 if (tok != ')') {
2838 if (tok == TOK_ASM_push) {
2839 next();
2840 if (s1->pack_stack_ptr >= s1->pack_stack + PACK_STACK_SIZE - 1)
2841 goto stk_error;
2842 s1->pack_stack_ptr++;
2843 skip(',');
2845 if (tok != TOK_CINT) {
2846 pack_error:
2847 error("invalid pack pragma");
2849 val = tokc.i;
2850 if (val < 1 || val > 16 || (val & (val - 1)) != 0)
2851 goto pack_error;
2852 next();
2854 *s1->pack_stack_ptr = val;
2855 skip(')');
2860 /* is_bof is true if first non space token at beginning of file */
2861 static void preprocess(int is_bof)
2863 TCCState *s1 = tcc_state;
2864 int size, i, c, n, saved_parse_flags;
2865 char buf[1024], *q, *p;
2866 char buf1[1024];
2867 BufferedFile *f;
2868 Sym *s;
2869 CachedInclude *e;
2871 saved_parse_flags = parse_flags;
2872 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM |
2873 PARSE_FLAG_LINEFEED;
2874 next_nomacro();
2875 redo:
2876 switch(tok) {
2877 case TOK_DEFINE:
2878 next_nomacro();
2879 parse_define();
2880 break;
2881 case TOK_UNDEF:
2882 next_nomacro();
2883 s = define_find(tok);
2884 /* undefine symbol by putting an invalid name */
2885 if (s)
2886 define_undef(s);
2887 break;
2888 case TOK_INCLUDE:
2889 case TOK_INCLUDE_NEXT:
2890 ch = file->buf_ptr[0];
2891 /* XXX: incorrect if comments : use next_nomacro with a special mode */
2892 skip_spaces();
2893 if (ch == '<') {
2894 c = '>';
2895 goto read_name;
2896 } else if (ch == '\"') {
2897 c = ch;
2898 read_name:
2899 /* XXX: better stray handling */
2900 minp();
2901 q = buf;
2902 while (ch != c && ch != '\n' && ch != CH_EOF) {
2903 if ((q - buf) < sizeof(buf) - 1)
2904 *q++ = ch;
2905 minp();
2907 *q = '\0';
2908 minp();
2909 #if 0
2910 /* eat all spaces and comments after include */
2911 /* XXX: slightly incorrect */
2912 while (ch1 != '\n' && ch1 != CH_EOF)
2913 inp();
2914 #endif
2915 } else {
2916 /* computed #include : either we have only strings or
2917 we have anything enclosed in '<>' */
2918 next();
2919 buf[0] = '\0';
2920 if (tok == TOK_STR) {
2921 while (tok != TOK_LINEFEED) {
2922 if (tok != TOK_STR) {
2923 include_syntax:
2924 error("'#include' expects \"FILENAME\" or <FILENAME>");
2926 pstrcat(buf, sizeof(buf), (char *)tokc.cstr->data);
2927 next();
2929 c = '\"';
2930 } else {
2931 int len;
2932 while (tok != TOK_LINEFEED) {
2933 pstrcat(buf, sizeof(buf), get_tok_str(tok, &tokc));
2934 next();
2936 len = strlen(buf);
2937 /* check syntax and remove '<>' */
2938 if (len < 2 || buf[0] != '<' || buf[len - 1] != '>')
2939 goto include_syntax;
2940 memmove(buf, buf + 1, len - 2);
2941 buf[len - 2] = '\0';
2942 c = '>';
2946 e = search_cached_include(s1, c, buf);
2947 if (e && define_find(e->ifndef_macro)) {
2948 /* no need to parse the include because the 'ifndef macro'
2949 is defined */
2950 #ifdef INC_DEBUG
2951 printf("%s: skipping %s\n", file->filename, buf);
2952 #endif
2953 } else {
2954 if (c == '\"') {
2955 /* first search in current dir if "header.h" */
2956 size = 0;
2957 p = strrchr(file->filename, '/');
2958 if (p)
2959 size = p + 1 - file->filename;
2960 if (size > sizeof(buf1) - 1)
2961 size = sizeof(buf1) - 1;
2962 memcpy(buf1, file->filename, size);
2963 buf1[size] = '\0';
2964 pstrcat(buf1, sizeof(buf1), buf);
2965 f = tcc_open(s1, buf1);
2966 if (f) {
2967 if (tok == TOK_INCLUDE_NEXT)
2968 tok = TOK_INCLUDE;
2969 else
2970 goto found;
2973 if (s1->include_stack_ptr >= s1->include_stack + INCLUDE_STACK_SIZE)
2974 error("#include recursion too deep");
2975 /* now search in all the include paths */
2976 n = s1->nb_include_paths + s1->nb_sysinclude_paths;
2977 for(i = 0; i < n; i++) {
2978 const char *path;
2979 if (i < s1->nb_include_paths)
2980 path = s1->include_paths[i];
2981 else
2982 path = s1->sysinclude_paths[i - s1->nb_include_paths];
2983 pstrcpy(buf1, sizeof(buf1), path);
2984 pstrcat(buf1, sizeof(buf1), "/");
2985 pstrcat(buf1, sizeof(buf1), buf);
2986 f = tcc_open(s1, buf1);
2987 if (f) {
2988 if (tok == TOK_INCLUDE_NEXT)
2989 tok = TOK_INCLUDE;
2990 else
2991 goto found;
2994 error("include file '%s' not found", buf);
2995 f = NULL;
2996 found:
2997 #ifdef INC_DEBUG
2998 printf("%s: including %s\n", file->filename, buf1);
2999 #endif
3000 f->inc_type = c;
3001 pstrcpy(f->inc_filename, sizeof(f->inc_filename), buf);
3002 /* push current file in stack */
3003 /* XXX: fix current line init */
3004 *s1->include_stack_ptr++ = file;
3005 file = f;
3006 /* add include file debug info */
3007 if (do_debug) {
3008 put_stabs(file->filename, N_BINCL, 0, 0, 0);
3010 tok_flags |= TOK_FLAG_BOF | TOK_FLAG_BOL;
3011 ch = file->buf_ptr[0];
3012 goto the_end;
3014 break;
3015 case TOK_IFNDEF:
3016 c = 1;
3017 goto do_ifdef;
3018 case TOK_IF:
3019 c = expr_preprocess();
3020 goto do_if;
3021 case TOK_IFDEF:
3022 c = 0;
3023 do_ifdef:
3024 next_nomacro();
3025 if (tok < TOK_IDENT)
3026 error("invalid argument for '#if%sdef'", c ? "n" : "");
3027 if (is_bof) {
3028 if (c) {
3029 #ifdef INC_DEBUG
3030 printf("#ifndef %s\n", get_tok_str(tok, NULL));
3031 #endif
3032 file->ifndef_macro = tok;
3035 c = (define_find(tok) != 0) ^ c;
3036 do_if:
3037 if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE)
3038 error("memory full");
3039 *s1->ifdef_stack_ptr++ = c;
3040 goto test_skip;
3041 case TOK_ELSE:
3042 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
3043 error("#else without matching #if");
3044 if (s1->ifdef_stack_ptr[-1] & 2)
3045 error("#else after #else");
3046 c = (s1->ifdef_stack_ptr[-1] ^= 3);
3047 goto test_skip;
3048 case TOK_ELIF:
3049 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
3050 error("#elif without matching #if");
3051 c = s1->ifdef_stack_ptr[-1];
3052 if (c > 1)
3053 error("#elif after #else");
3054 /* last #if/#elif expression was true: we skip */
3055 if (c == 1)
3056 goto skip;
3057 c = expr_preprocess();
3058 s1->ifdef_stack_ptr[-1] = c;
3059 test_skip:
3060 if (!(c & 1)) {
3061 skip:
3062 preprocess_skip();
3063 is_bof = 0;
3064 goto redo;
3066 break;
3067 case TOK_ENDIF:
3068 if (s1->ifdef_stack_ptr <= file->ifdef_stack_ptr)
3069 error("#endif without matching #if");
3070 s1->ifdef_stack_ptr--;
3071 /* '#ifndef macro' was at the start of file. Now we check if
3072 an '#endif' is exactly at the end of file */
3073 if (file->ifndef_macro &&
3074 s1->ifdef_stack_ptr == file->ifdef_stack_ptr) {
3075 file->ifndef_macro_saved = file->ifndef_macro;
3076 /* need to set to zero to avoid false matches if another
3077 #ifndef at middle of file */
3078 file->ifndef_macro = 0;
3079 while (tok != TOK_LINEFEED)
3080 next_nomacro();
3081 tok_flags |= TOK_FLAG_ENDIF;
3082 goto the_end;
3084 break;
3085 case TOK_LINE:
3086 next();
3087 if (tok != TOK_CINT)
3088 error("#line");
3089 file->line_num = tokc.i - 1; /* the line number will be incremented after */
3090 next();
3091 if (tok != TOK_LINEFEED) {
3092 if (tok != TOK_STR)
3093 error("#line");
3094 pstrcpy(file->filename, sizeof(file->filename),
3095 (char *)tokc.cstr->data);
3097 break;
3098 case TOK_ERROR:
3099 case TOK_WARNING:
3100 c = tok;
3101 ch = file->buf_ptr[0];
3102 skip_spaces();
3103 q = buf;
3104 while (ch != '\n' && ch != CH_EOF) {
3105 if ((q - buf) < sizeof(buf) - 1)
3106 *q++ = ch;
3107 minp();
3109 *q = '\0';
3110 if (c == TOK_ERROR)
3111 error("#error %s", buf);
3112 else
3113 warning("#warning %s", buf);
3114 break;
3115 case TOK_PRAGMA:
3116 pragma_parse(s1);
3117 break;
3118 default:
3119 if (tok == TOK_LINEFEED || tok == '!' || tok == TOK_CINT) {
3120 /* '!' is ignored to allow C scripts. numbers are ignored
3121 to emulate cpp behaviour */
3122 } else {
3123 if (!(saved_parse_flags & PARSE_FLAG_ASM_COMMENTS))
3124 error("invalid preprocessing directive #%s", get_tok_str(tok, &tokc));
3126 break;
3128 /* ignore other preprocess commands or #! for C scripts */
3129 while (tok != TOK_LINEFEED)
3130 next_nomacro();
3131 the_end:
3132 parse_flags = saved_parse_flags;
3135 /* evaluate escape codes in a string. */
3136 static void parse_escape_string(CString *outstr, const uint8_t *buf, int is_long)
3138 int c, n;
3139 const uint8_t *p;
3141 p = buf;
3142 for(;;) {
3143 c = *p;
3144 if (c == '\0')
3145 break;
3146 if (c == '\\') {
3147 p++;
3148 /* escape */
3149 c = *p;
3150 switch(c) {
3151 case '0': case '1': case '2': case '3':
3152 case '4': case '5': case '6': case '7':
3153 /* at most three octal digits */
3154 n = c - '0';
3155 p++;
3156 c = *p;
3157 if (isoct(c)) {
3158 n = n * 8 + c - '0';
3159 p++;
3160 c = *p;
3161 if (isoct(c)) {
3162 n = n * 8 + c - '0';
3163 p++;
3166 c = n;
3167 goto add_char_nonext;
3168 case 'x':
3169 case 'u':
3170 case 'U':
3171 p++;
3172 n = 0;
3173 for(;;) {
3174 c = *p;
3175 if (c >= 'a' && c <= 'f')
3176 c = c - 'a' + 10;
3177 else if (c >= 'A' && c <= 'F')
3178 c = c - 'A' + 10;
3179 else if (isnum(c))
3180 c = c - '0';
3181 else
3182 break;
3183 n = n * 16 + c;
3184 p++;
3186 c = n;
3187 goto add_char_nonext;
3188 case 'a':
3189 c = '\a';
3190 break;
3191 case 'b':
3192 c = '\b';
3193 break;
3194 case 'f':
3195 c = '\f';
3196 break;
3197 case 'n':
3198 c = '\n';
3199 break;
3200 case 'r':
3201 c = '\r';
3202 break;
3203 case 't':
3204 c = '\t';
3205 break;
3206 case 'v':
3207 c = '\v';
3208 break;
3209 case 'e':
3210 if (!gnu_ext)
3211 goto invalid_escape;
3212 c = 27;
3213 break;
3214 case '\'':
3215 case '\"':
3216 case '\\':
3217 case '?':
3218 break;
3219 default:
3220 invalid_escape:
3221 if (c >= '!' && c <= '~')
3222 warning("unknown escape sequence: \'\\%c\'", c);
3223 else
3224 warning("unknown escape sequence: \'\\x%x\'", c);
3225 break;
3228 p++;
3229 add_char_nonext:
3230 if (!is_long)
3231 cstr_ccat(outstr, c);
3232 else
3233 cstr_wccat(outstr, c);
3235 /* add a trailing '\0' */
3236 if (!is_long)
3237 cstr_ccat(outstr, '\0');
3238 else
3239 cstr_wccat(outstr, '\0');
3242 /* we use 64 bit numbers */
3243 #define BN_SIZE 2
3245 /* bn = (bn << shift) | or_val */
3246 void bn_lshift(unsigned int *bn, int shift, int or_val)
3248 int i;
3249 unsigned int v;
3250 for(i=0;i<BN_SIZE;i++) {
3251 v = bn[i];
3252 bn[i] = (v << shift) | or_val;
3253 or_val = v >> (32 - shift);
3257 void bn_zero(unsigned int *bn)
3259 int i;
3260 for(i=0;i<BN_SIZE;i++) {
3261 bn[i] = 0;
3265 /* parse number in null terminated string 'p' and return it in the
3266 current token */
3267 void parse_number(const char *p)
3269 int b, t, shift, frac_bits, s, exp_val, ch;
3270 char *q;
3271 unsigned int bn[BN_SIZE];
3272 double d;
3274 /* number */
3275 q = token_buf;
3276 ch = *p++;
3277 t = ch;
3278 ch = *p++;
3279 *q++ = t;
3280 b = 10;
3281 if (t == '.') {
3282 goto float_frac_parse;
3283 } else if (t == '0') {
3284 if (ch == 'x' || ch == 'X') {
3285 q--;
3286 ch = *p++;
3287 b = 16;
3288 } else if (tcc_ext && (ch == 'b' || ch == 'B')) {
3289 q--;
3290 ch = *p++;
3291 b = 2;
3294 /* parse all digits. cannot check octal numbers at this stage
3295 because of floating point constants */
3296 while (1) {
3297 if (ch >= 'a' && ch <= 'f')
3298 t = ch - 'a' + 10;
3299 else if (ch >= 'A' && ch <= 'F')
3300 t = ch - 'A' + 10;
3301 else if (isnum(ch))
3302 t = ch - '0';
3303 else
3304 break;
3305 if (t >= b)
3306 break;
3307 if (q >= token_buf + STRING_MAX_SIZE) {
3308 num_too_long:
3309 error("number too long");
3311 *q++ = ch;
3312 ch = *p++;
3314 if (ch == '.' ||
3315 ((ch == 'e' || ch == 'E') && b == 10) ||
3316 ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
3317 if (b != 10) {
3318 /* NOTE: strtox should support that for hexa numbers, but
3319 non ISOC99 libcs do not support it, so we prefer to do
3320 it by hand */
3321 /* hexadecimal or binary floats */
3322 /* XXX: handle overflows */
3323 *q = '\0';
3324 if (b == 16)
3325 shift = 4;
3326 else
3327 shift = 2;
3328 bn_zero(bn);
3329 q = token_buf;
3330 while (1) {
3331 t = *q++;
3332 if (t == '\0') {
3333 break;
3334 } else if (t >= 'a') {
3335 t = t - 'a' + 10;
3336 } else if (t >= 'A') {
3337 t = t - 'A' + 10;
3338 } else {
3339 t = t - '0';
3341 bn_lshift(bn, shift, t);
3343 frac_bits = 0;
3344 if (ch == '.') {
3345 ch = *p++;
3346 while (1) {
3347 t = ch;
3348 if (t >= 'a' && t <= 'f') {
3349 t = t - 'a' + 10;
3350 } else if (t >= 'A' && t <= 'F') {
3351 t = t - 'A' + 10;
3352 } else if (t >= '0' && t <= '9') {
3353 t = t - '0';
3354 } else {
3355 break;
3357 if (t >= b)
3358 error("invalid digit");
3359 bn_lshift(bn, shift, t);
3360 frac_bits += shift;
3361 ch = *p++;
3364 if (ch != 'p' && ch != 'P')
3365 expect("exponent");
3366 ch = *p++;
3367 s = 1;
3368 exp_val = 0;
3369 if (ch == '+') {
3370 ch = *p++;
3371 } else if (ch == '-') {
3372 s = -1;
3373 ch = *p++;
3375 if (ch < '0' || ch > '9')
3376 expect("exponent digits");
3377 while (ch >= '0' && ch <= '9') {
3378 exp_val = exp_val * 10 + ch - '0';
3379 ch = *p++;
3381 exp_val = exp_val * s;
3383 /* now we can generate the number */
3384 /* XXX: should patch directly float number */
3385 d = (double)bn[1] * 4294967296.0 + (double)bn[0];
3386 d = ldexp(d, exp_val - frac_bits);
3387 t = toup(ch);
3388 if (t == 'F') {
3389 ch = *p++;
3390 tok = TOK_CFLOAT;
3391 /* float : should handle overflow */
3392 tokc.f = (float)d;
3393 } else if (t == 'L') {
3394 ch = *p++;
3395 tok = TOK_CLDOUBLE;
3396 /* XXX: not large enough */
3397 tokc.ld = (long double)d;
3398 } else {
3399 tok = TOK_CDOUBLE;
3400 tokc.d = d;
3402 } else {
3403 /* decimal floats */
3404 if (ch == '.') {
3405 if (q >= token_buf + STRING_MAX_SIZE)
3406 goto num_too_long;
3407 *q++ = ch;
3408 ch = *p++;
3409 float_frac_parse:
3410 while (ch >= '0' && ch <= '9') {
3411 if (q >= token_buf + STRING_MAX_SIZE)
3412 goto num_too_long;
3413 *q++ = ch;
3414 ch = *p++;
3417 if (ch == 'e' || ch == 'E') {
3418 if (q >= token_buf + STRING_MAX_SIZE)
3419 goto num_too_long;
3420 *q++ = ch;
3421 ch = *p++;
3422 if (ch == '-' || ch == '+') {
3423 if (q >= token_buf + STRING_MAX_SIZE)
3424 goto num_too_long;
3425 *q++ = ch;
3426 ch = *p++;
3428 if (ch < '0' || ch > '9')
3429 expect("exponent digits");
3430 while (ch >= '0' && ch <= '9') {
3431 if (q >= token_buf + STRING_MAX_SIZE)
3432 goto num_too_long;
3433 *q++ = ch;
3434 ch = *p++;
3437 *q = '\0';
3438 t = toup(ch);
3439 errno = 0;
3440 if (t == 'F') {
3441 ch = *p++;
3442 tok = TOK_CFLOAT;
3443 tokc.f = strtof(token_buf, NULL);
3444 } else if (t == 'L') {
3445 ch = *p++;
3446 tok = TOK_CLDOUBLE;
3447 tokc.ld = strtold(token_buf, NULL);
3448 } else {
3449 tok = TOK_CDOUBLE;
3450 tokc.d = strtod(token_buf, NULL);
3453 } else {
3454 unsigned long long n, n1;
3455 int lcount, ucount;
3457 /* integer number */
3458 *q = '\0';
3459 q = token_buf;
3460 if (b == 10 && *q == '0') {
3461 b = 8;
3462 q++;
3464 n = 0;
3465 while(1) {
3466 t = *q++;
3467 /* no need for checks except for base 10 / 8 errors */
3468 if (t == '\0') {
3469 break;
3470 } else if (t >= 'a') {
3471 t = t - 'a' + 10;
3472 } else if (t >= 'A') {
3473 t = t - 'A' + 10;
3474 } else {
3475 t = t - '0';
3476 if (t >= b)
3477 error("invalid digit");
3479 n1 = n;
3480 n = n * b + t;
3481 /* detect overflow */
3482 /* XXX: this test is not reliable */
3483 if (n < n1)
3484 error("integer constant overflow");
3487 /* XXX: not exactly ANSI compliant */
3488 if ((n & 0xffffffff00000000LL) != 0) {
3489 if ((n >> 63) != 0)
3490 tok = TOK_CULLONG;
3491 else
3492 tok = TOK_CLLONG;
3493 } else if (n > 0x7fffffff) {
3494 tok = TOK_CUINT;
3495 } else {
3496 tok = TOK_CINT;
3498 lcount = 0;
3499 ucount = 0;
3500 for(;;) {
3501 t = toup(ch);
3502 if (t == 'L') {
3503 if (lcount >= 2)
3504 error("three 'l's in integer constant");
3505 lcount++;
3506 if (lcount == 2) {
3507 if (tok == TOK_CINT)
3508 tok = TOK_CLLONG;
3509 else if (tok == TOK_CUINT)
3510 tok = TOK_CULLONG;
3512 ch = *p++;
3513 } else if (t == 'U') {
3514 if (ucount >= 1)
3515 error("two 'u's in integer constant");
3516 ucount++;
3517 if (tok == TOK_CINT)
3518 tok = TOK_CUINT;
3519 else if (tok == TOK_CLLONG)
3520 tok = TOK_CULLONG;
3521 ch = *p++;
3522 } else {
3523 break;
3526 if (tok == TOK_CINT || tok == TOK_CUINT)
3527 tokc.ui = n;
3528 else
3529 tokc.ull = n;
3534 #define PARSE2(c1, tok1, c2, tok2) \
3535 case c1: \
3536 PEEKC(c, p); \
3537 if (c == c2) { \
3538 p++; \
3539 tok = tok2; \
3540 } else { \
3541 tok = tok1; \
3543 break;
3545 /* return next token without macro substitution */
3546 static inline void next_nomacro1(void)
3548 int t, c, is_long;
3549 TokenSym *ts;
3550 uint8_t *p, *p1;
3551 unsigned int h;
3553 p = file->buf_ptr;
3554 redo_no_start:
3555 c = *p;
3556 switch(c) {
3557 case ' ':
3558 case '\t':
3559 case '\f':
3560 case '\v':
3561 case '\r':
3562 p++;
3563 goto redo_no_start;
3565 case '\\':
3566 /* first look if it is in fact an end of buffer */
3567 if (p >= file->buf_end) {
3568 file->buf_ptr = p;
3569 handle_eob();
3570 p = file->buf_ptr;
3571 if (p >= file->buf_end)
3572 goto parse_eof;
3573 else
3574 goto redo_no_start;
3575 } else {
3576 file->buf_ptr = p;
3577 ch = *p;
3578 handle_stray();
3579 p = file->buf_ptr;
3580 goto redo_no_start;
3582 parse_eof:
3584 TCCState *s1 = tcc_state;
3585 if ((parse_flags & PARSE_FLAG_LINEFEED)
3586 && !(tok_flags & TOK_FLAG_EOF)) {
3587 tok_flags |= TOK_FLAG_EOF;
3588 tok = TOK_LINEFEED;
3589 goto keep_tok_flags;
3590 } else if (s1->include_stack_ptr == s1->include_stack ||
3591 !(parse_flags & PARSE_FLAG_PREPROCESS)) {
3592 /* no include left : end of file. */
3593 tok = TOK_EOF;
3594 } else {
3595 tok_flags &= ~TOK_FLAG_EOF;
3596 /* pop include file */
3598 /* test if previous '#endif' was after a #ifdef at
3599 start of file */
3600 if (tok_flags & TOK_FLAG_ENDIF) {
3601 #ifdef INC_DEBUG
3602 printf("#endif %s\n", get_tok_str(file->ifndef_macro_saved, NULL));
3603 #endif
3604 add_cached_include(s1, file->inc_type, file->inc_filename,
3605 file->ifndef_macro_saved);
3608 /* add end of include file debug info */
3609 if (do_debug) {
3610 put_stabd(N_EINCL, 0, 0);
3612 /* pop include stack */
3613 tcc_close(file);
3614 s1->include_stack_ptr--;
3615 file = *s1->include_stack_ptr;
3616 p = file->buf_ptr;
3617 goto redo_no_start;
3620 break;
3622 case '\n':
3623 file->line_num++;
3624 tok_flags |= TOK_FLAG_BOL;
3625 p++;
3626 if (0 == (parse_flags & PARSE_FLAG_LINEFEED))
3627 goto redo_no_start;
3628 tok = TOK_LINEFEED;
3629 goto keep_tok_flags;
3631 case '#':
3632 /* XXX: simplify */
3633 PEEKC(c, p);
3634 if ((tok_flags & TOK_FLAG_BOL) &&
3635 (parse_flags & PARSE_FLAG_PREPROCESS)) {
3636 file->buf_ptr = p;
3637 preprocess(tok_flags & TOK_FLAG_BOF);
3638 p = file->buf_ptr;
3639 goto redo_no_start;
3640 } else {
3641 if (c == '#') {
3642 p++;
3643 tok = TOK_TWOSHARPS;
3644 } else {
3645 if (parse_flags & PARSE_FLAG_ASM_COMMENTS) {
3646 p = parse_line_comment(p - 1);
3647 goto redo_no_start;
3648 } else {
3649 tok = '#';
3653 break;
3655 case 'a': case 'b': case 'c': case 'd':
3656 case 'e': case 'f': case 'g': case 'h':
3657 case 'i': case 'j': case 'k': case 'l':
3658 case 'm': case 'n': case 'o': case 'p':
3659 case 'q': case 'r': case 's': case 't':
3660 case 'u': case 'v': case 'w': case 'x':
3661 case 'y': case 'z':
3662 case 'A': case 'B': case 'C': case 'D':
3663 case 'E': case 'F': case 'G': case 'H':
3664 case 'I': case 'J': case 'K':
3665 case 'M': case 'N': case 'O': case 'P':
3666 case 'Q': case 'R': case 'S': case 'T':
3667 case 'U': case 'V': case 'W': case 'X':
3668 case 'Y': case 'Z':
3669 case '_':
3670 parse_ident_fast:
3671 p1 = p;
3672 h = TOK_HASH_INIT;
3673 h = TOK_HASH_FUNC(h, c);
3674 p++;
3675 for(;;) {
3676 c = *p;
3677 if (!isidnum_table[c])
3678 break;
3679 h = TOK_HASH_FUNC(h, c);
3680 p++;
3682 if (c != '\\') {
3683 TokenSym **pts;
3684 int len;
3686 /* fast case : no stray found, so we have the full token
3687 and we have already hashed it */
3688 len = p - p1;
3689 h &= (TOK_HASH_SIZE - 1);
3690 pts = &hash_ident[h];
3691 for(;;) {
3692 ts = *pts;
3693 if (!ts)
3694 break;
3695 if (ts->len == len && !memcmp(ts->str, p1, len))
3696 goto token_found;
3697 pts = &(ts->hash_next);
3699 ts = tok_alloc_new(pts, p1, len);
3700 token_found: ;
3701 } else {
3702 /* slower case */
3703 cstr_reset(&tokcstr);
3705 while (p1 < p) {
3706 cstr_ccat(&tokcstr, *p1);
3707 p1++;
3709 p--;
3710 PEEKC(c, p);
3711 parse_ident_slow:
3712 while (isidnum_table[c]) {
3713 cstr_ccat(&tokcstr, c);
3714 PEEKC(c, p);
3716 ts = tok_alloc(tokcstr.data, tokcstr.size);
3718 tok = ts->tok;
3719 break;
3720 case 'L':
3721 t = p[1];
3722 if (t != '\\' && t != '\'' && t != '\"') {
3723 /* fast case */
3724 goto parse_ident_fast;
3725 } else {
3726 PEEKC(c, p);
3727 if (c == '\'' || c == '\"') {
3728 is_long = 1;
3729 goto str_const;
3730 } else {
3731 cstr_reset(&tokcstr);
3732 cstr_ccat(&tokcstr, 'L');
3733 goto parse_ident_slow;
3736 break;
3737 case '0': case '1': case '2': case '3':
3738 case '4': case '5': case '6': case '7':
3739 case '8': case '9':
3741 cstr_reset(&tokcstr);
3742 /* after the first digit, accept digits, alpha, '.' or sign if
3743 prefixed by 'eEpP' */
3744 parse_num:
3745 for(;;) {
3746 t = c;
3747 cstr_ccat(&tokcstr, c);
3748 PEEKC(c, p);
3749 if (!(isnum(c) || isid(c) || c == '.' ||
3750 ((c == '+' || c == '-') &&
3751 (t == 'e' || t == 'E' || t == 'p' || t == 'P'))))
3752 break;
3754 /* We add a trailing '\0' to ease parsing */
3755 cstr_ccat(&tokcstr, '\0');
3756 tokc.cstr = &tokcstr;
3757 tok = TOK_PPNUM;
3758 break;
3759 case '.':
3760 /* special dot handling because it can also start a number */
3761 PEEKC(c, p);
3762 if (isnum(c)) {
3763 cstr_reset(&tokcstr);
3764 cstr_ccat(&tokcstr, '.');
3765 goto parse_num;
3766 } else if (c == '.') {
3767 PEEKC(c, p);
3768 if (c != '.')
3769 expect("'.'");
3770 PEEKC(c, p);
3771 tok = TOK_DOTS;
3772 } else {
3773 tok = '.';
3775 break;
3776 case '\'':
3777 case '\"':
3778 is_long = 0;
3779 str_const:
3781 CString str;
3782 int sep;
3784 sep = c;
3786 /* parse the string */
3787 cstr_new(&str);
3788 p = parse_pp_string(p, sep, &str);
3789 cstr_ccat(&str, '\0');
3791 /* eval the escape (should be done as TOK_PPNUM) */
3792 cstr_reset(&tokcstr);
3793 parse_escape_string(&tokcstr, str.data, is_long);
3794 cstr_free(&str);
3796 if (sep == '\'') {
3797 int char_size;
3798 /* XXX: make it portable */
3799 if (!is_long)
3800 char_size = 1;
3801 else
3802 char_size = sizeof(nwchar_t);
3803 if (tokcstr.size <= char_size)
3804 error("empty character constant");
3805 if (tokcstr.size > 2 * char_size)
3806 warning("multi-character character constant");
3807 if (!is_long) {
3808 tokc.i = *(int8_t *)tokcstr.data;
3809 tok = TOK_CCHAR;
3810 } else {
3811 tokc.i = *(nwchar_t *)tokcstr.data;
3812 tok = TOK_LCHAR;
3814 } else {
3815 tokc.cstr = &tokcstr;
3816 if (!is_long)
3817 tok = TOK_STR;
3818 else
3819 tok = TOK_LSTR;
3822 break;
3824 case '<':
3825 PEEKC(c, p);
3826 if (c == '=') {
3827 p++;
3828 tok = TOK_LE;
3829 } else if (c == '<') {
3830 PEEKC(c, p);
3831 if (c == '=') {
3832 p++;
3833 tok = TOK_A_SHL;
3834 } else {
3835 tok = TOK_SHL;
3837 } else {
3838 tok = TOK_LT;
3840 break;
3842 case '>':
3843 PEEKC(c, p);
3844 if (c == '=') {
3845 p++;
3846 tok = TOK_GE;
3847 } else if (c == '>') {
3848 PEEKC(c, p);
3849 if (c == '=') {
3850 p++;
3851 tok = TOK_A_SAR;
3852 } else {
3853 tok = TOK_SAR;
3855 } else {
3856 tok = TOK_GT;
3858 break;
3860 case '&':
3861 PEEKC(c, p);
3862 if (c == '&') {
3863 p++;
3864 tok = TOK_LAND;
3865 } else if (c == '=') {
3866 p++;
3867 tok = TOK_A_AND;
3868 } else {
3869 tok = '&';
3871 break;
3873 case '|':
3874 PEEKC(c, p);
3875 if (c == '|') {
3876 p++;
3877 tok = TOK_LOR;
3878 } else if (c == '=') {
3879 p++;
3880 tok = TOK_A_OR;
3881 } else {
3882 tok = '|';
3884 break;
3886 case '+':
3887 PEEKC(c, p);
3888 if (c == '+') {
3889 p++;
3890 tok = TOK_INC;
3891 } else if (c == '=') {
3892 p++;
3893 tok = TOK_A_ADD;
3894 } else {
3895 tok = '+';
3897 break;
3899 case '-':
3900 PEEKC(c, p);
3901 if (c == '-') {
3902 p++;
3903 tok = TOK_DEC;
3904 } else if (c == '=') {
3905 p++;
3906 tok = TOK_A_SUB;
3907 } else if (c == '>') {
3908 p++;
3909 tok = TOK_ARROW;
3910 } else {
3911 tok = '-';
3913 break;
3915 PARSE2('!', '!', '=', TOK_NE)
3916 PARSE2('=', '=', '=', TOK_EQ)
3917 PARSE2('*', '*', '=', TOK_A_MUL)
3918 PARSE2('%', '%', '=', TOK_A_MOD)
3919 PARSE2('^', '^', '=', TOK_A_XOR)
3921 /* comments or operator */
3922 case '/':
3923 PEEKC(c, p);
3924 if (c == '*') {
3925 p = parse_comment(p);
3926 goto redo_no_start;
3927 } else if (c == '/') {
3928 p = parse_line_comment(p);
3929 goto redo_no_start;
3930 } else if (c == '=') {
3931 p++;
3932 tok = TOK_A_DIV;
3933 } else {
3934 tok = '/';
3936 break;
3938 /* simple tokens */
3939 case '(':
3940 case ')':
3941 case '[':
3942 case ']':
3943 case '{':
3944 case '}':
3945 case ',':
3946 case ';':
3947 case ':':
3948 case '?':
3949 case '~':
3950 case '$': /* only used in assembler */
3951 case '@': /* dito */
3952 tok = c;
3953 p++;
3954 break;
3955 default:
3956 error("unrecognized character \\x%02x", c);
3957 break;
3959 tok_flags = 0;
3960 keep_tok_flags:
3961 file->buf_ptr = p;
3962 #if defined(PARSE_DEBUG)
3963 printf("token = %s\n", get_tok_str(tok, &tokc));
3964 #endif
3967 /* return next token without macro substitution. Can read input from
3968 macro_ptr buffer */
3969 static void next_nomacro(void)
3971 if (macro_ptr) {
3972 redo:
3973 tok = *macro_ptr;
3974 if (tok) {
3975 TOK_GET(tok, macro_ptr, tokc);
3976 if (tok == TOK_LINENUM) {
3977 file->line_num = tokc.i;
3978 goto redo;
3981 } else {
3982 next_nomacro1();
3986 /* substitute args in macro_str and return allocated string */
3987 static int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
3989 int *st, last_tok, t, notfirst;
3990 Sym *s;
3991 CValue cval;
3992 TokenString str;
3993 CString cstr;
3995 tok_str_new(&str);
3996 last_tok = 0;
3997 while(1) {
3998 TOK_GET(t, macro_str, cval);
3999 if (!t)
4000 break;
4001 if (t == '#') {
4002 /* stringize */
4003 TOK_GET(t, macro_str, cval);
4004 if (!t)
4005 break;
4006 s = sym_find2(args, t);
4007 if (s) {
4008 cstr_new(&cstr);
4009 st = (int *)s->c;
4010 notfirst = 0;
4011 while (*st) {
4012 if (notfirst)
4013 cstr_ccat(&cstr, ' ');
4014 TOK_GET(t, st, cval);
4015 cstr_cat(&cstr, get_tok_str(t, &cval));
4016 notfirst = 1;
4018 cstr_ccat(&cstr, '\0');
4019 #ifdef PP_DEBUG
4020 printf("stringize: %s\n", (char *)cstr.data);
4021 #endif
4022 /* add string */
4023 cval.cstr = &cstr;
4024 tok_str_add2(&str, TOK_STR, &cval);
4025 cstr_free(&cstr);
4026 } else {
4027 tok_str_add2(&str, t, &cval);
4029 } else if (t >= TOK_IDENT) {
4030 s = sym_find2(args, t);
4031 if (s) {
4032 st = (int *)s->c;
4033 /* if '##' is present before or after, no arg substitution */
4034 if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) {
4035 /* special case for var arg macros : ## eats the
4036 ',' if empty VA_ARGS variable. */
4037 /* XXX: test of the ',' is not 100%
4038 reliable. should fix it to avoid security
4039 problems */
4040 if (gnu_ext && s->type.t &&
4041 last_tok == TOK_TWOSHARPS &&
4042 str.len >= 2 && str.str[str.len - 2] == ',') {
4043 if (*st == 0) {
4044 /* suppress ',' '##' */
4045 str.len -= 2;
4046 } else {
4047 /* suppress '##' and add variable */
4048 str.len--;
4049 goto add_var;
4051 } else {
4052 int t1;
4053 add_var:
4054 for(;;) {
4055 TOK_GET(t1, st, cval);
4056 if (!t1)
4057 break;
4058 tok_str_add2(&str, t1, &cval);
4061 } else {
4062 /* NOTE: the stream cannot be read when macro
4063 substituing an argument */
4064 macro_subst(&str, nested_list, st, NULL);
4066 } else {
4067 tok_str_add(&str, t);
4069 } else {
4070 tok_str_add2(&str, t, &cval);
4072 last_tok = t;
4074 tok_str_add(&str, 0);
4075 return str.str;
4078 static char const ab_month_name[12][4] =
4080 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
4081 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
4084 /* do macro substitution of current token with macro 's' and add
4085 result to (tok_str,tok_len). 'nested_list' is the list of all
4086 macros we got inside to avoid recursing. Return non zero if no
4087 substitution needs to be done */
4088 static int macro_subst_tok(TokenString *tok_str,
4089 Sym **nested_list, Sym *s, struct macro_level **can_read_stream)
4091 Sym *args, *sa, *sa1;
4092 int mstr_allocated, parlevel, *mstr, t, t1;
4093 TokenString str;
4094 char *cstrval;
4095 CValue cval;
4096 CString cstr;
4097 char buf[32];
4099 /* if symbol is a macro, prepare substitution */
4100 /* special macros */
4101 if (tok == TOK___LINE__) {
4102 snprintf(buf, sizeof(buf), "%d", file->line_num);
4103 cstrval = buf;
4104 t1 = TOK_PPNUM;
4105 goto add_cstr1;
4106 } else if (tok == TOK___FILE__) {
4107 cstrval = file->filename;
4108 goto add_cstr;
4109 } else if (tok == TOK___DATE__ || tok == TOK___TIME__) {
4110 time_t ti;
4111 struct tm *tm;
4113 time(&ti);
4114 tm = localtime(&ti);
4115 if (tok == TOK___DATE__) {
4116 snprintf(buf, sizeof(buf), "%s %2d %d",
4117 ab_month_name[tm->tm_mon], tm->tm_mday, tm->tm_year + 1900);
4118 } else {
4119 snprintf(buf, sizeof(buf), "%02d:%02d:%02d",
4120 tm->tm_hour, tm->tm_min, tm->tm_sec);
4122 cstrval = buf;
4123 add_cstr:
4124 t1 = TOK_STR;
4125 add_cstr1:
4126 cstr_new(&cstr);
4127 cstr_cat(&cstr, cstrval);
4128 cstr_ccat(&cstr, '\0');
4129 cval.cstr = &cstr;
4130 tok_str_add2(tok_str, t1, &cval);
4131 cstr_free(&cstr);
4132 } else {
4133 mstr = (int *)s->c;
4134 mstr_allocated = 0;
4135 if (s->type.t == MACRO_FUNC) {
4136 /* NOTE: we do not use next_nomacro to avoid eating the
4137 next token. XXX: find better solution */
4138 redo:
4139 if (macro_ptr) {
4140 t = *macro_ptr;
4141 if (t == 0 && can_read_stream) {
4142 /* end of macro stream: we must look at the token
4143 after in the file */
4144 struct macro_level *ml = *can_read_stream;
4145 macro_ptr = NULL;
4146 if (ml)
4148 macro_ptr = ml->p;
4149 ml->p = NULL;
4150 *can_read_stream = ml -> prev;
4152 goto redo;
4154 } else {
4155 /* XXX: incorrect with comments */
4156 ch = file->buf_ptr[0];
4157 while (is_space(ch) || ch == '\n')
4158 cinp();
4159 t = ch;
4161 if (t != '(') /* no macro subst */
4162 return -1;
4164 /* argument macro */
4165 next_nomacro();
4166 next_nomacro();
4167 args = NULL;
4168 sa = s->next;
4169 /* NOTE: empty args are allowed, except if no args */
4170 for(;;) {
4171 /* handle '()' case */
4172 if (!args && !sa && tok == ')')
4173 break;
4174 if (!sa)
4175 error("macro '%s' used with too many args",
4176 get_tok_str(s->v, 0));
4177 tok_str_new(&str);
4178 parlevel = 0;
4179 /* NOTE: non zero sa->t indicates VA_ARGS */
4180 while ((parlevel > 0 ||
4181 (tok != ')' &&
4182 (tok != ',' || sa->type.t))) &&
4183 tok != -1) {
4184 if (tok == '(')
4185 parlevel++;
4186 else if (tok == ')')
4187 parlevel--;
4188 if (tok != TOK_LINEFEED)
4189 tok_str_add2(&str, tok, &tokc);
4190 next_nomacro();
4192 tok_str_add(&str, 0);
4193 sym_push2(&args, sa->v & ~SYM_FIELD, sa->type.t, (int)str.str);
4194 sa = sa->next;
4195 if (tok == ')') {
4196 /* special case for gcc var args: add an empty
4197 var arg argument if it is omitted */
4198 if (sa && sa->type.t && gnu_ext)
4199 continue;
4200 else
4201 break;
4203 if (tok != ',')
4204 expect(",");
4205 next_nomacro();
4207 if (sa) {
4208 error("macro '%s' used with too few args",
4209 get_tok_str(s->v, 0));
4212 /* now subst each arg */
4213 mstr = macro_arg_subst(nested_list, mstr, args);
4214 /* free memory */
4215 sa = args;
4216 while (sa) {
4217 sa1 = sa->prev;
4218 tok_str_free((int *)sa->c);
4219 sym_free(sa);
4220 sa = sa1;
4222 mstr_allocated = 1;
4224 sym_push2(nested_list, s->v, 0, 0);
4225 macro_subst(tok_str, nested_list, mstr, can_read_stream);
4226 /* pop nested defined symbol */
4227 sa1 = *nested_list;
4228 *nested_list = sa1->prev;
4229 sym_free(sa1);
4230 if (mstr_allocated)
4231 tok_str_free(mstr);
4233 return 0;
4236 /* handle the '##' operator. Return NULL if no '##' seen. Otherwise
4237 return the resulting string (which must be freed). */
4238 static inline int *macro_twosharps(const int *macro_str)
4240 TokenSym *ts;
4241 const int *macro_ptr1, *start_macro_ptr, *ptr, *saved_macro_ptr;
4242 int t;
4243 const char *p1, *p2;
4244 CValue cval;
4245 TokenString macro_str1;
4246 CString cstr;
4248 start_macro_ptr = macro_str;
4249 /* we search the first '##' */
4250 for(;;) {
4251 macro_ptr1 = macro_str;
4252 TOK_GET(t, macro_str, cval);
4253 /* nothing more to do if end of string */
4254 if (t == 0)
4255 return NULL;
4256 if (*macro_str == TOK_TWOSHARPS)
4257 break;
4260 /* we saw '##', so we need more processing to handle it */
4261 cstr_new(&cstr);
4262 tok_str_new(&macro_str1);
4263 tok = t;
4264 tokc = cval;
4266 /* add all tokens seen so far */
4267 for(ptr = start_macro_ptr; ptr < macro_ptr1;) {
4268 TOK_GET(t, ptr, cval);
4269 tok_str_add2(&macro_str1, t, &cval);
4271 saved_macro_ptr = macro_ptr;
4272 /* XXX: get rid of the use of macro_ptr here */
4273 macro_ptr = (int *)macro_str;
4274 for(;;) {
4275 while (*macro_ptr == TOK_TWOSHARPS) {
4276 macro_ptr++;
4277 macro_ptr1 = macro_ptr;
4278 t = *macro_ptr;
4279 if (t) {
4280 TOK_GET(t, macro_ptr, cval);
4281 /* We concatenate the two tokens if we have an
4282 identifier or a preprocessing number */
4283 cstr_reset(&cstr);
4284 p1 = get_tok_str(tok, &tokc);
4285 cstr_cat(&cstr, p1);
4286 p2 = get_tok_str(t, &cval);
4287 cstr_cat(&cstr, p2);
4288 cstr_ccat(&cstr, '\0');
4290 if ((tok >= TOK_IDENT || tok == TOK_PPNUM) &&
4291 (t >= TOK_IDENT || t == TOK_PPNUM)) {
4292 if (tok == TOK_PPNUM) {
4293 /* if number, then create a number token */
4294 /* NOTE: no need to allocate because
4295 tok_str_add2() does it */
4296 cstr_reset(&tokcstr);
4297 tokcstr = cstr;
4298 cstr_new(&cstr);
4299 tokc.cstr = &tokcstr;
4300 } else {
4301 /* if identifier, we must do a test to
4302 validate we have a correct identifier */
4303 if (t == TOK_PPNUM) {
4304 const char *p;
4305 int c;
4307 p = p2;
4308 for(;;) {
4309 c = *p;
4310 if (c == '\0')
4311 break;
4312 p++;
4313 if (!isnum(c) && !isid(c))
4314 goto error_pasting;
4317 ts = tok_alloc(cstr.data, strlen(cstr.data));
4318 tok = ts->tok; /* modify current token */
4320 } else {
4321 const char *str = cstr.data;
4322 const unsigned char *q;
4324 /* we look for a valid token */
4325 /* XXX: do more extensive checks */
4326 if (!strcmp(str, ">>=")) {
4327 tok = TOK_A_SAR;
4328 } else if (!strcmp(str, "<<=")) {
4329 tok = TOK_A_SHL;
4330 } else if (strlen(str) == 2) {
4331 /* search in two bytes table */
4332 q = tok_two_chars;
4333 for(;;) {
4334 if (!*q)
4335 goto error_pasting;
4336 if (q[0] == str[0] && q[1] == str[1])
4337 break;
4338 q += 3;
4340 tok = q[2];
4341 } else {
4342 error_pasting:
4343 /* NOTE: because get_tok_str use a static buffer,
4344 we must save it */
4345 cstr_reset(&cstr);
4346 p1 = get_tok_str(tok, &tokc);
4347 cstr_cat(&cstr, p1);
4348 cstr_ccat(&cstr, '\0');
4349 p2 = get_tok_str(t, &cval);
4350 warning("pasting \"%s\" and \"%s\" does not give a valid preprocessing token", cstr.data, p2);
4351 /* cannot merge tokens: just add them separately */
4352 tok_str_add2(&macro_str1, tok, &tokc);
4353 /* XXX: free associated memory ? */
4354 tok = t;
4355 tokc = cval;
4360 tok_str_add2(&macro_str1, tok, &tokc);
4361 next_nomacro();
4362 if (tok == 0)
4363 break;
4365 macro_ptr = (int *)saved_macro_ptr;
4366 cstr_free(&cstr);
4367 tok_str_add(&macro_str1, 0);
4368 return macro_str1.str;
4372 /* do macro substitution of macro_str and add result to
4373 (tok_str,tok_len). 'nested_list' is the list of all macros we got
4374 inside to avoid recursing. */
4375 static void macro_subst(TokenString *tok_str, Sym **nested_list,
4376 const int *macro_str, struct macro_level ** can_read_stream)
4378 Sym *s;
4379 int *macro_str1;
4380 const int *ptr;
4381 int t, ret;
4382 CValue cval;
4383 struct macro_level ml;
4385 /* first scan for '##' operator handling */
4386 ptr = macro_str;
4387 macro_str1 = macro_twosharps(ptr);
4388 if (macro_str1)
4389 ptr = macro_str1;
4390 while (1) {
4391 /* NOTE: ptr == NULL can only happen if tokens are read from
4392 file stream due to a macro function call */
4393 if (ptr == NULL)
4394 break;
4395 TOK_GET(t, ptr, cval);
4396 if (t == 0)
4397 break;
4398 s = define_find(t);
4399 if (s != NULL) {
4400 /* if nested substitution, do nothing */
4401 if (sym_find2(*nested_list, t))
4402 goto no_subst;
4403 ml.p = macro_ptr;
4404 if (can_read_stream)
4405 ml.prev = *can_read_stream, *can_read_stream = &ml;
4406 macro_ptr = (int *)ptr;
4407 tok = t;
4408 ret = macro_subst_tok(tok_str, nested_list, s, can_read_stream);
4409 ptr = (int *)macro_ptr;
4410 macro_ptr = ml.p;
4411 if (can_read_stream && *can_read_stream == &ml)
4412 *can_read_stream = ml.prev;
4413 if (ret != 0)
4414 goto no_subst;
4415 } else {
4416 no_subst:
4417 tok_str_add2(tok_str, t, &cval);
4420 if (macro_str1)
4421 tok_str_free(macro_str1);
4424 /* return next token with macro substitution */
4425 static void next(void)
4427 Sym *nested_list, *s;
4428 TokenString str;
4429 struct macro_level *ml;
4431 redo:
4432 next_nomacro();
4433 if (!macro_ptr) {
4434 /* if not reading from macro substituted string, then try
4435 to substitute macros */
4436 if (tok >= TOK_IDENT &&
4437 (parse_flags & PARSE_FLAG_PREPROCESS)) {
4438 s = define_find(tok);
4439 if (s) {
4440 /* we have a macro: we try to substitute */
4441 tok_str_new(&str);
4442 nested_list = NULL;
4443 ml = NULL;
4444 if (macro_subst_tok(&str, &nested_list, s, &ml) == 0) {
4445 /* substitution done, NOTE: maybe empty */
4446 tok_str_add(&str, 0);
4447 macro_ptr = str.str;
4448 macro_ptr_allocated = str.str;
4449 goto redo;
4453 } else {
4454 if (tok == 0) {
4455 /* end of macro or end of unget buffer */
4456 if (unget_buffer_enabled) {
4457 macro_ptr = unget_saved_macro_ptr;
4458 unget_buffer_enabled = 0;
4459 } else {
4460 /* end of macro string: free it */
4461 tok_str_free(macro_ptr_allocated);
4462 macro_ptr = NULL;
4464 goto redo;
4468 /* convert preprocessor tokens into C tokens */
4469 if (tok == TOK_PPNUM &&
4470 (parse_flags & PARSE_FLAG_TOK_NUM)) {
4471 parse_number((char *)tokc.cstr->data);
4475 /* push back current token and set current token to 'last_tok'. Only
4476 identifier case handled for labels. */
4477 static inline void unget_tok(int last_tok)
4479 int i, n;
4480 int *q;
4481 unget_saved_macro_ptr = macro_ptr;
4482 unget_buffer_enabled = 1;
4483 q = unget_saved_buffer;
4484 macro_ptr = q;
4485 *q++ = tok;
4486 n = tok_ext_size(tok) - 1;
4487 for(i=0;i<n;i++)
4488 *q++ = tokc.tab[i];
4489 *q = 0; /* end of token string */
4490 tok = last_tok;
4494 void swap(int *p, int *q)
4496 int t;
4497 t = *p;
4498 *p = *q;
4499 *q = t;
4502 void vsetc(CType *type, int r, CValue *vc)
4504 int v;
4506 if (vtop >= vstack + (VSTACK_SIZE - 1))
4507 error("memory full");
4508 /* cannot let cpu flags if other instruction are generated. Also
4509 avoid leaving VT_JMP anywhere except on the top of the stack
4510 because it would complicate the code generator. */
4511 if (vtop >= vstack) {
4512 v = vtop->r & VT_VALMASK;
4513 if (v == VT_CMP || (v & ~1) == VT_JMP)
4514 gv(RC_INT);
4516 vtop++;
4517 vtop->type = *type;
4518 vtop->r = r;
4519 vtop->r2 = VT_CONST;
4520 vtop->c = *vc;
4523 /* push integer constant */
4524 void vpushi(int v)
4526 CValue cval;
4527 cval.i = v;
4528 vsetc(&int_type, VT_CONST, &cval);
4531 /* Return a static symbol pointing to a section */
4532 static Sym *get_sym_ref(CType *type, Section *sec,
4533 unsigned long offset, unsigned long size)
4535 int v;
4536 Sym *sym;
4538 v = anon_sym++;
4539 sym = global_identifier_push(v, type->t | VT_STATIC, 0);
4540 sym->type.ref = type->ref;
4541 sym->r = VT_CONST | VT_SYM;
4542 put_extern_sym(sym, sec, offset, size);
4543 return sym;
4546 /* push a reference to a section offset by adding a dummy symbol */
4547 static void vpush_ref(CType *type, Section *sec, unsigned long offset, unsigned long size)
4549 CValue cval;
4551 cval.ul = 0;
4552 vsetc(type, VT_CONST | VT_SYM, &cval);
4553 vtop->sym = get_sym_ref(type, sec, offset, size);
4556 /* define a new external reference to a symbol 'v' of type 'u' */
4557 static Sym *external_global_sym(int v, CType *type, int r)
4559 Sym *s;
4561 s = sym_find(v);
4562 if (!s) {
4563 /* push forward reference */
4564 s = global_identifier_push(v, type->t | VT_EXTERN, 0);
4565 s->type.ref = type->ref;
4566 s->r = r | VT_CONST | VT_SYM;
4568 return s;
4571 /* define a new external reference to a symbol 'v' of type 'u' */
4572 static Sym *external_sym(int v, CType *type, int r)
4574 Sym *s;
4576 s = sym_find(v);
4577 if (!s) {
4578 /* push forward reference */
4579 s = sym_push(v, type, r | VT_CONST | VT_SYM, 0);
4580 s->type.t |= VT_EXTERN;
4581 } else {
4582 if (!is_compatible_types(&s->type, type))
4583 error("incompatible types for redefinition of '%s'",
4584 get_tok_str(v, NULL));
4586 return s;
4589 /* push a reference to global symbol v */
4590 static void vpush_global_sym(CType *type, int v)
4592 Sym *sym;
4593 CValue cval;
4595 sym = external_global_sym(v, type, 0);
4596 cval.ul = 0;
4597 vsetc(type, VT_CONST | VT_SYM, &cval);
4598 vtop->sym = sym;
4601 void vset(CType *type, int r, int v)
4603 CValue cval;
4605 cval.i = v;
4606 vsetc(type, r, &cval);
4609 void vseti(int r, int v)
4611 CType type;
4612 type.t = VT_INT;
4613 vset(&type, r, v);
4616 void vswap(void)
4618 SValue tmp;
4620 tmp = vtop[0];
4621 vtop[0] = vtop[-1];
4622 vtop[-1] = tmp;
4625 void vpushv(SValue *v)
4627 if (vtop >= vstack + (VSTACK_SIZE - 1))
4628 error("memory full");
4629 vtop++;
4630 *vtop = *v;
4633 void vdup(void)
4635 vpushv(vtop);
4638 /* save r to the memory stack, and mark it as being free */
4639 void save_reg(int r)
4641 int l, saved, size, align;
4642 SValue *p, sv;
4643 CType *type;
4645 /* modify all stack values */
4646 saved = 0;
4647 l = 0;
4648 for(p=vstack;p<=vtop;p++) {
4649 if ((p->r & VT_VALMASK) == r ||
4650 ((p->type.t & VT_BTYPE) == VT_LLONG && (p->r2 & VT_VALMASK) == r)) {
4651 /* must save value on stack if not already done */
4652 if (!saved) {
4653 /* NOTE: must reload 'r' because r might be equal to r2 */
4654 r = p->r & VT_VALMASK;
4655 /* store register in the stack */
4656 type = &p->type;
4657 if ((p->r & VT_LVAL) ||
4658 (!is_float(type->t) && (type->t & VT_BTYPE) != VT_LLONG))
4659 type = &int_type;
4660 size = type_size(type, &align);
4661 loc = (loc - size) & -align;
4662 sv.type.t = type->t;
4663 sv.r = VT_LOCAL | VT_LVAL;
4664 sv.c.ul = loc;
4665 store(r, &sv);
4666 #ifdef TCC_TARGET_I386
4667 /* x86 specific: need to pop fp register ST0 if saved */
4668 if (r == TREG_ST0) {
4669 o(0xd9dd); /* fstp %st(1) */
4671 #endif
4672 /* special long long case */
4673 if ((type->t & VT_BTYPE) == VT_LLONG) {
4674 sv.c.ul += 4;
4675 store(p->r2, &sv);
4677 l = loc;
4678 saved = 1;
4680 /* mark that stack entry as being saved on the stack */
4681 if (p->r & VT_LVAL) {
4682 /* also clear the bounded flag because the
4683 relocation address of the function was stored in
4684 p->c.ul */
4685 p->r = (p->r & ~(VT_VALMASK | VT_BOUNDED)) | VT_LLOCAL;
4686 } else {
4687 p->r = lvalue_type(p->type.t) | VT_LOCAL;
4689 p->r2 = VT_CONST;
4690 p->c.ul = l;
4695 /* find a register of class 'rc2' with at most one reference on stack.
4696 * If none, call get_reg(rc) */
4697 int get_reg_ex(int rc, int rc2)
4699 int r;
4700 SValue *p;
4702 for(r=0;r<NB_REGS;r++) {
4703 if (reg_classes[r] & rc2) {
4704 int n;
4705 n=0;
4706 for(p = vstack; p <= vtop; p++) {
4707 if ((p->r & VT_VALMASK) == r ||
4708 (p->r2 & VT_VALMASK) == r)
4709 n++;
4711 if (n <= 1)
4712 return r;
4715 return get_reg(rc);
4718 /* find a free register of class 'rc'. If none, save one register */
4719 int get_reg(int rc)
4721 int r;
4722 SValue *p;
4724 /* find a free register */
4725 for(r=0;r<NB_REGS;r++) {
4726 if (reg_classes[r] & rc) {
4727 for(p=vstack;p<=vtop;p++) {
4728 if ((p->r & VT_VALMASK) == r ||
4729 (p->r2 & VT_VALMASK) == r)
4730 goto notfound;
4732 return r;
4734 notfound: ;
4737 /* no register left : free the first one on the stack (VERY
4738 IMPORTANT to start from the bottom to ensure that we don't
4739 spill registers used in gen_opi()) */
4740 for(p=vstack;p<=vtop;p++) {
4741 r = p->r & VT_VALMASK;
4742 if (r < VT_CONST && (reg_classes[r] & rc))
4743 goto save_found;
4744 /* also look at second register (if long long) */
4745 r = p->r2 & VT_VALMASK;
4746 if (r < VT_CONST && (reg_classes[r] & rc)) {
4747 save_found:
4748 save_reg(r);
4749 return r;
4752 /* Should never comes here */
4753 return -1;
4756 /* save registers up to (vtop - n) stack entry */
4757 void save_regs(int n)
4759 int r;
4760 SValue *p, *p1;
4761 p1 = vtop - n;
4762 for(p = vstack;p <= p1; p++) {
4763 r = p->r & VT_VALMASK;
4764 if (r < VT_CONST) {
4765 save_reg(r);
4770 /* move register 's' to 'r', and flush previous value of r to memory
4771 if needed */
4772 void move_reg(int r, int s)
4774 SValue sv;
4776 if (r != s) {
4777 save_reg(r);
4778 sv.type.t = VT_INT;
4779 sv.r = s;
4780 sv.c.ul = 0;
4781 load(r, &sv);
4785 /* get address of vtop (vtop MUST BE an lvalue) */
4786 void gaddrof(void)
4788 vtop->r &= ~VT_LVAL;
4789 /* tricky: if saved lvalue, then we can go back to lvalue */
4790 if ((vtop->r & VT_VALMASK) == VT_LLOCAL)
4791 vtop->r = (vtop->r & ~(VT_VALMASK | VT_LVAL_TYPE)) | VT_LOCAL | VT_LVAL;
4794 #ifdef CONFIG_TCC_BCHECK
4795 /* generate lvalue bound code */
4796 void gbound(void)
4798 int lval_type;
4799 CType type1;
4801 vtop->r &= ~VT_MUSTBOUND;
4802 /* if lvalue, then use checking code before dereferencing */
4803 if (vtop->r & VT_LVAL) {
4804 /* if not VT_BOUNDED value, then make one */
4805 if (!(vtop->r & VT_BOUNDED)) {
4806 lval_type = vtop->r & (VT_LVAL_TYPE | VT_LVAL);
4807 /* must save type because we must set it to int to get pointer */
4808 type1 = vtop->type;
4809 vtop->type.t = VT_INT;
4810 gaddrof();
4811 vpushi(0);
4812 gen_bounded_ptr_add();
4813 vtop->r |= lval_type;
4814 vtop->type = type1;
4816 /* then check for dereferencing */
4817 gen_bounded_ptr_deref();
4820 #endif
4822 /* store vtop a register belonging to class 'rc'. lvalues are
4823 converted to values. Cannot be used if cannot be converted to
4824 register value (such as structures). */
4825 int gv(int rc)
4827 int r, r2, rc2, bit_pos, bit_size, size, align, i;
4828 unsigned long long ll;
4830 /* NOTE: get_reg can modify vstack[] */
4831 if (vtop->type.t & VT_BITFIELD) {
4832 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
4833 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
4834 /* remove bit field info to avoid loops */
4835 vtop->type.t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
4836 /* generate shifts */
4837 vpushi(32 - (bit_pos + bit_size));
4838 gen_op(TOK_SHL);
4839 vpushi(32 - bit_size);
4840 /* NOTE: transformed to SHR if unsigned */
4841 gen_op(TOK_SAR);
4842 r = gv(rc);
4843 } else {
4844 if (is_float(vtop->type.t) &&
4845 (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4846 Sym *sym;
4847 int *ptr;
4848 unsigned long offset;
4849 #if defined(TCC_TARGET_ARM) && !defined(TCC_ARM_VFP)
4850 CValue check;
4851 #endif
4853 /* XXX: unify with initializers handling ? */
4854 /* CPUs usually cannot use float constants, so we store them
4855 generically in data segment */
4856 size = type_size(&vtop->type, &align);
4857 offset = (data_section->data_offset + align - 1) & -align;
4858 data_section->data_offset = offset;
4859 /* XXX: not portable yet */
4860 #ifdef __i386__
4861 /* Zero pad x87 tenbyte long doubles */
4862 if (size == 12)
4863 vtop->c.tab[2] &= 0xffff;
4864 #endif
4865 ptr = section_ptr_add(data_section, size);
4866 size = size >> 2;
4867 #if defined(TCC_TARGET_ARM) && !defined(TCC_ARM_VFP)
4868 check.d = 1;
4869 if(check.tab[0])
4870 for(i=0;i<size;i++)
4871 ptr[i] = vtop->c.tab[size-1-i];
4872 else
4873 #endif
4874 for(i=0;i<size;i++)
4875 ptr[i] = vtop->c.tab[i];
4876 sym = get_sym_ref(&vtop->type, data_section, offset, size << 2);
4877 vtop->r |= VT_LVAL | VT_SYM;
4878 vtop->sym = sym;
4879 vtop->c.ul = 0;
4881 #ifdef CONFIG_TCC_BCHECK
4882 if (vtop->r & VT_MUSTBOUND)
4883 gbound();
4884 #endif
4886 r = vtop->r & VT_VALMASK;
4887 /* need to reload if:
4888 - constant
4889 - lvalue (need to dereference pointer)
4890 - already a register, but not in the right class */
4891 if (r >= VT_CONST ||
4892 (vtop->r & VT_LVAL) ||
4893 !(reg_classes[r] & rc) ||
4894 ((vtop->type.t & VT_BTYPE) == VT_LLONG &&
4895 !(reg_classes[vtop->r2] & rc))) {
4896 r = get_reg(rc);
4897 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
4898 /* two register type load : expand to two words
4899 temporarily */
4900 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4901 /* load constant */
4902 ll = vtop->c.ull;
4903 vtop->c.ui = ll; /* first word */
4904 load(r, vtop);
4905 vtop->r = r; /* save register value */
4906 vpushi(ll >> 32); /* second word */
4907 } else if (r >= VT_CONST || /* XXX: test to VT_CONST incorrect ? */
4908 (vtop->r & VT_LVAL)) {
4909 /* We do not want to modifier the long long
4910 pointer here, so the safest (and less
4911 efficient) is to save all the other registers
4912 in the stack. XXX: totally inefficient. */
4913 save_regs(1);
4914 /* load from memory */
4915 load(r, vtop);
4916 vdup();
4917 vtop[-1].r = r; /* save register value */
4918 /* increment pointer to get second word */
4919 vtop->type.t = VT_INT;
4920 gaddrof();
4921 vpushi(4);
4922 gen_op('+');
4923 vtop->r |= VT_LVAL;
4924 } else {
4925 /* move registers */
4926 load(r, vtop);
4927 vdup();
4928 vtop[-1].r = r; /* save register value */
4929 vtop->r = vtop[-1].r2;
4931 /* allocate second register */
4932 rc2 = RC_INT;
4933 if (rc == RC_IRET)
4934 rc2 = RC_LRET;
4935 r2 = get_reg(rc2);
4936 load(r2, vtop);
4937 vpop();
4938 /* write second register */
4939 vtop->r2 = r2;
4940 } else if ((vtop->r & VT_LVAL) && !is_float(vtop->type.t)) {
4941 int t1, t;
4942 /* lvalue of scalar type : need to use lvalue type
4943 because of possible cast */
4944 t = vtop->type.t;
4945 t1 = t;
4946 /* compute memory access type */
4947 if (vtop->r & VT_LVAL_BYTE)
4948 t = VT_BYTE;
4949 else if (vtop->r & VT_LVAL_SHORT)
4950 t = VT_SHORT;
4951 if (vtop->r & VT_LVAL_UNSIGNED)
4952 t |= VT_UNSIGNED;
4953 vtop->type.t = t;
4954 load(r, vtop);
4955 /* restore wanted type */
4956 vtop->type.t = t1;
4957 } else {
4958 /* one register type load */
4959 load(r, vtop);
4962 vtop->r = r;
4963 #ifdef TCC_TARGET_C67
4964 /* uses register pairs for doubles */
4965 if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE)
4966 vtop->r2 = r+1;
4967 #endif
4969 return r;
4972 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
4973 void gv2(int rc1, int rc2)
4975 int v;
4977 /* generate more generic register first. But VT_JMP or VT_CMP
4978 values must be generated first in all cases to avoid possible
4979 reload errors */
4980 v = vtop[0].r & VT_VALMASK;
4981 if (v != VT_CMP && (v & ~1) != VT_JMP && rc1 <= rc2) {
4982 vswap();
4983 gv(rc1);
4984 vswap();
4985 gv(rc2);
4986 /* test if reload is needed for first register */
4987 if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
4988 vswap();
4989 gv(rc1);
4990 vswap();
4992 } else {
4993 gv(rc2);
4994 vswap();
4995 gv(rc1);
4996 vswap();
4997 /* test if reload is needed for first register */
4998 if ((vtop[0].r & VT_VALMASK) >= VT_CONST) {
4999 gv(rc2);
5004 /* expand long long on stack in two int registers */
5005 void lexpand(void)
5007 int u;
5009 u = vtop->type.t & VT_UNSIGNED;
5010 gv(RC_INT);
5011 vdup();
5012 vtop[0].r = vtop[-1].r2;
5013 vtop[0].r2 = VT_CONST;
5014 vtop[-1].r2 = VT_CONST;
5015 vtop[0].type.t = VT_INT | u;
5016 vtop[-1].type.t = VT_INT | u;
5019 #ifdef TCC_TARGET_ARM
5020 /* expand long long on stack */
5021 void lexpand_nr(void)
5023 int u,v;
5025 u = vtop->type.t & VT_UNSIGNED;
5026 vdup();
5027 vtop->r2 = VT_CONST;
5028 vtop->type.t = VT_INT | u;
5029 v=vtop[-1].r & (VT_VALMASK | VT_LVAL);
5030 if (v == VT_CONST) {
5031 vtop[-1].c.ui = vtop->c.ull;
5032 vtop->c.ui = vtop->c.ull >> 32;
5033 vtop->r = VT_CONST;
5034 } else if (v == (VT_LVAL|VT_CONST) || v == (VT_LVAL|VT_LOCAL)) {
5035 vtop->c.ui += 4;
5036 vtop->r = vtop[-1].r;
5037 } else if (v > VT_CONST) {
5038 vtop--;
5039 lexpand();
5040 } else
5041 vtop->r = vtop[-1].r2;
5042 vtop[-1].r2 = VT_CONST;
5043 vtop[-1].type.t = VT_INT | u;
5045 #endif
5047 /* build a long long from two ints */
5048 void lbuild(int t)
5050 gv2(RC_INT, RC_INT);
5051 vtop[-1].r2 = vtop[0].r;
5052 vtop[-1].type.t = t;
5053 vpop();
5056 /* rotate n first stack elements to the bottom
5057 I1 ... In -> I2 ... In I1 [top is right]
5059 void vrotb(int n)
5061 int i;
5062 SValue tmp;
5064 tmp = vtop[-n + 1];
5065 for(i=-n+1;i!=0;i++)
5066 vtop[i] = vtop[i+1];
5067 vtop[0] = tmp;
5070 /* rotate n first stack elements to the top
5071 I1 ... In -> In I1 ... I(n-1) [top is right]
5073 void vrott(int n)
5075 int i;
5076 SValue tmp;
5078 tmp = vtop[0];
5079 for(i = 0;i < n - 1; i++)
5080 vtop[-i] = vtop[-i - 1];
5081 vtop[-n + 1] = tmp;
5084 #ifdef TCC_TARGET_ARM
5085 /* like vrott but in other direction
5086 In ... I1 -> I(n-1) ... I1 In [top is right]
5088 void vnrott(int n)
5090 int i;
5091 SValue tmp;
5093 tmp = vtop[-n + 1];
5094 for(i = n - 1; i > 0; i--)
5095 vtop[-i] = vtop[-i + 1];
5096 vtop[0] = tmp;
5098 #endif
5100 /* pop stack value */
5101 void vpop(void)
5103 int v;
5104 v = vtop->r & VT_VALMASK;
5105 #ifdef TCC_TARGET_I386
5106 /* for x86, we need to pop the FP stack */
5107 if (v == TREG_ST0 && !nocode_wanted) {
5108 o(0xd9dd); /* fstp %st(1) */
5109 } else
5110 #endif
5111 if (v == VT_JMP || v == VT_JMPI) {
5112 /* need to put correct jump if && or || without test */
5113 gsym(vtop->c.ul);
5115 vtop--;
5118 /* convert stack entry to register and duplicate its value in another
5119 register */
5120 void gv_dup(void)
5122 int rc, t, r, r1;
5123 SValue sv;
5125 t = vtop->type.t;
5126 if ((t & VT_BTYPE) == VT_LLONG) {
5127 lexpand();
5128 gv_dup();
5129 vswap();
5130 vrotb(3);
5131 gv_dup();
5132 vrotb(4);
5133 /* stack: H L L1 H1 */
5134 lbuild(t);
5135 vrotb(3);
5136 vrotb(3);
5137 vswap();
5138 lbuild(t);
5139 vswap();
5140 } else {
5141 /* duplicate value */
5142 rc = RC_INT;
5143 sv.type.t = VT_INT;
5144 if (is_float(t)) {
5145 rc = RC_FLOAT;
5146 sv.type.t = t;
5148 r = gv(rc);
5149 r1 = get_reg(rc);
5150 sv.r = r;
5151 sv.c.ul = 0;
5152 load(r1, &sv); /* move r to r1 */
5153 vdup();
5154 /* duplicates value */
5155 vtop->r = r1;
5159 /* generate CPU independent (unsigned) long long operations */
5160 void gen_opl(int op)
5162 int t, a, b, op1, c, i;
5163 int func;
5164 SValue tmp;
5166 switch(op) {
5167 case '/':
5168 case TOK_PDIV:
5169 func = TOK___divdi3;
5170 goto gen_func;
5171 case TOK_UDIV:
5172 func = TOK___udivdi3;
5173 goto gen_func;
5174 case '%':
5175 func = TOK___moddi3;
5176 goto gen_func;
5177 case TOK_UMOD:
5178 func = TOK___umoddi3;
5179 gen_func:
5180 /* call generic long long function */
5181 vpush_global_sym(&func_old_type, func);
5182 vrott(3);
5183 gfunc_call(2);
5184 vpushi(0);
5185 vtop->r = REG_IRET;
5186 vtop->r2 = REG_LRET;
5187 break;
5188 case '^':
5189 case '&':
5190 case '|':
5191 case '*':
5192 case '+':
5193 case '-':
5194 t = vtop->type.t;
5195 vswap();
5196 lexpand();
5197 vrotb(3);
5198 lexpand();
5199 /* stack: L1 H1 L2 H2 */
5200 tmp = vtop[0];
5201 vtop[0] = vtop[-3];
5202 vtop[-3] = tmp;
5203 tmp = vtop[-2];
5204 vtop[-2] = vtop[-3];
5205 vtop[-3] = tmp;
5206 vswap();
5207 /* stack: H1 H2 L1 L2 */
5208 if (op == '*') {
5209 vpushv(vtop - 1);
5210 vpushv(vtop - 1);
5211 gen_op(TOK_UMULL);
5212 lexpand();
5213 /* stack: H1 H2 L1 L2 ML MH */
5214 for(i=0;i<4;i++)
5215 vrotb(6);
5216 /* stack: ML MH H1 H2 L1 L2 */
5217 tmp = vtop[0];
5218 vtop[0] = vtop[-2];
5219 vtop[-2] = tmp;
5220 /* stack: ML MH H1 L2 H2 L1 */
5221 gen_op('*');
5222 vrotb(3);
5223 vrotb(3);
5224 gen_op('*');
5225 /* stack: ML MH M1 M2 */
5226 gen_op('+');
5227 gen_op('+');
5228 } else if (op == '+' || op == '-') {
5229 /* XXX: add non carry method too (for MIPS or alpha) */
5230 if (op == '+')
5231 op1 = TOK_ADDC1;
5232 else
5233 op1 = TOK_SUBC1;
5234 gen_op(op1);
5235 /* stack: H1 H2 (L1 op L2) */
5236 vrotb(3);
5237 vrotb(3);
5238 gen_op(op1 + 1); /* TOK_xxxC2 */
5239 } else {
5240 gen_op(op);
5241 /* stack: H1 H2 (L1 op L2) */
5242 vrotb(3);
5243 vrotb(3);
5244 /* stack: (L1 op L2) H1 H2 */
5245 gen_op(op);
5246 /* stack: (L1 op L2) (H1 op H2) */
5248 /* stack: L H */
5249 lbuild(t);
5250 break;
5251 case TOK_SAR:
5252 case TOK_SHR:
5253 case TOK_SHL:
5254 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
5255 t = vtop[-1].type.t;
5256 vswap();
5257 lexpand();
5258 vrotb(3);
5259 /* stack: L H shift */
5260 c = (int)vtop->c.i;
5261 /* constant: simpler */
5262 /* NOTE: all comments are for SHL. the other cases are
5263 done by swaping words */
5264 vpop();
5265 if (op != TOK_SHL)
5266 vswap();
5267 if (c >= 32) {
5268 /* stack: L H */
5269 vpop();
5270 if (c > 32) {
5271 vpushi(c - 32);
5272 gen_op(op);
5274 if (op != TOK_SAR) {
5275 vpushi(0);
5276 } else {
5277 gv_dup();
5278 vpushi(31);
5279 gen_op(TOK_SAR);
5281 vswap();
5282 } else {
5283 vswap();
5284 gv_dup();
5285 /* stack: H L L */
5286 vpushi(c);
5287 gen_op(op);
5288 vswap();
5289 vpushi(32 - c);
5290 if (op == TOK_SHL)
5291 gen_op(TOK_SHR);
5292 else
5293 gen_op(TOK_SHL);
5294 vrotb(3);
5295 /* stack: L L H */
5296 vpushi(c);
5297 if (op == TOK_SHL)
5298 gen_op(TOK_SHL);
5299 else
5300 gen_op(TOK_SHR);
5301 gen_op('|');
5303 if (op != TOK_SHL)
5304 vswap();
5305 lbuild(t);
5306 } else {
5307 /* XXX: should provide a faster fallback on x86 ? */
5308 switch(op) {
5309 case TOK_SAR:
5310 func = TOK___sardi3;
5311 goto gen_func;
5312 case TOK_SHR:
5313 func = TOK___shrdi3;
5314 goto gen_func;
5315 case TOK_SHL:
5316 func = TOK___shldi3;
5317 goto gen_func;
5320 break;
5321 default:
5322 /* compare operations */
5323 t = vtop->type.t;
5324 vswap();
5325 lexpand();
5326 vrotb(3);
5327 lexpand();
5328 /* stack: L1 H1 L2 H2 */
5329 tmp = vtop[-1];
5330 vtop[-1] = vtop[-2];
5331 vtop[-2] = tmp;
5332 /* stack: L1 L2 H1 H2 */
5333 /* compare high */
5334 op1 = op;
5335 /* when values are equal, we need to compare low words. since
5336 the jump is inverted, we invert the test too. */
5337 if (op1 == TOK_LT)
5338 op1 = TOK_LE;
5339 else if (op1 == TOK_GT)
5340 op1 = TOK_GE;
5341 else if (op1 == TOK_ULT)
5342 op1 = TOK_ULE;
5343 else if (op1 == TOK_UGT)
5344 op1 = TOK_UGE;
5345 a = 0;
5346 b = 0;
5347 gen_op(op1);
5348 if (op1 != TOK_NE) {
5349 a = gtst(1, 0);
5351 if (op != TOK_EQ) {
5352 /* generate non equal test */
5353 /* XXX: NOT PORTABLE yet */
5354 if (a == 0) {
5355 b = gtst(0, 0);
5356 } else {
5357 #if defined(TCC_TARGET_I386)
5358 b = psym(0x850f, 0);
5359 #elif defined(TCC_TARGET_ARM)
5360 b = ind;
5361 o(0x1A000000 | encbranch(ind, 0, 1));
5362 #elif defined(TCC_TARGET_C67)
5363 error("not implemented");
5364 #else
5365 #error not supported
5366 #endif
5369 /* compare low. Always unsigned */
5370 op1 = op;
5371 if (op1 == TOK_LT)
5372 op1 = TOK_ULT;
5373 else if (op1 == TOK_LE)
5374 op1 = TOK_ULE;
5375 else if (op1 == TOK_GT)
5376 op1 = TOK_UGT;
5377 else if (op1 == TOK_GE)
5378 op1 = TOK_UGE;
5379 gen_op(op1);
5380 a = gtst(1, a);
5381 gsym(b);
5382 vseti(VT_JMPI, a);
5383 break;
5387 /* handle integer constant optimizations and various machine
5388 independent opt */
5389 void gen_opic(int op)
5391 int c1, c2, t1, t2, n, c;
5392 SValue *v1, *v2;
5393 long long l1, l2, l;
5394 typedef unsigned long long U;
5396 v1 = vtop - 1;
5397 v2 = vtop;
5398 t1 = v1->type.t & VT_BTYPE;
5399 t2 = v2->type.t & VT_BTYPE;
5400 l1 = (t1 == VT_LLONG) ? v1->c.ll : v1->c.i;
5401 l2 = (t2 == VT_LLONG) ? v2->c.ll : v2->c.i;
5403 /* currently, we cannot do computations with forward symbols */
5404 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5405 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5406 if (c1 && c2) {
5407 switch(op) {
5408 case '+': l1 += l2; break;
5409 case '-': l1 -= l2; break;
5410 case '&': l1 &= l2; break;
5411 case '^': l1 ^= l2; break;
5412 case '|': l1 |= l2; break;
5413 case '*': l1 *= l2; break;
5415 case TOK_PDIV:
5416 case '/':
5417 case '%':
5418 case TOK_UDIV:
5419 case TOK_UMOD:
5420 /* if division by zero, generate explicit division */
5421 if (l2 == 0) {
5422 if (const_wanted)
5423 error("division by zero in constant");
5424 goto general_case;
5426 switch(op) {
5427 default: l1 /= l2; break;
5428 case '%': l1 %= l2; break;
5429 case TOK_UDIV: l1 = (U)l1 / l2; break;
5430 case TOK_UMOD: l1 = (U)l1 % l2; break;
5432 break;
5433 case TOK_SHL: l1 <<= l2; break;
5434 case TOK_SHR: l1 = (U)l1 >> l2; break;
5435 case TOK_SAR: l1 >>= l2; break;
5436 /* tests */
5437 case TOK_ULT: l1 = (U)l1 < (U)l2; break;
5438 case TOK_UGE: l1 = (U)l1 >= (U)l2; break;
5439 case TOK_EQ: l1 = l1 == l2; break;
5440 case TOK_NE: l1 = l1 != l2; break;
5441 case TOK_ULE: l1 = (U)l1 <= (U)l2; break;
5442 case TOK_UGT: l1 = (U)l1 > (U)l2; break;
5443 case TOK_LT: l1 = l1 < l2; break;
5444 case TOK_GE: l1 = l1 >= l2; break;
5445 case TOK_LE: l1 = l1 <= l2; break;
5446 case TOK_GT: l1 = l1 > l2; break;
5447 /* logical */
5448 case TOK_LAND: l1 = l1 && l2; break;
5449 case TOK_LOR: l1 = l1 || l2; break;
5450 default:
5451 goto general_case;
5453 v1->c.ll = l1;
5454 vtop--;
5455 } else {
5456 /* if commutative ops, put c2 as constant */
5457 if (c1 && (op == '+' || op == '&' || op == '^' ||
5458 op == '|' || op == '*')) {
5459 vswap();
5460 c = c1, c1 = c2, c2 = c;
5461 l = l1, l1 = l2, l2 = l;
5463 /* Filter out NOP operations like x*1, x-0, x&-1... */
5464 if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
5465 op == TOK_PDIV) &&
5466 l2 == 1) ||
5467 ((op == '+' || op == '-' || op == '|' || op == '^' ||
5468 op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
5469 l2 == 0) ||
5470 (op == '&' &&
5471 l2 == -1))) {
5472 /* nothing to do */
5473 vtop--;
5474 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
5475 /* try to use shifts instead of muls or divs */
5476 if (l2 > 0 && (l2 & (l2 - 1)) == 0) {
5477 n = -1;
5478 while (l2) {
5479 l2 >>= 1;
5480 n++;
5482 vtop->c.ll = n;
5483 if (op == '*')
5484 op = TOK_SHL;
5485 else if (op == TOK_PDIV)
5486 op = TOK_SAR;
5487 else
5488 op = TOK_SHR;
5490 goto general_case;
5491 } else if (c2 && (op == '+' || op == '-') &&
5492 (vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) ==
5493 (VT_CONST | VT_SYM)) {
5494 /* symbol + constant case */
5495 if (op == '-')
5496 l2 = -l2;
5497 vtop--;
5498 vtop->c.ll += l2;
5499 } else {
5500 general_case:
5501 if (!nocode_wanted) {
5502 /* call low level op generator */
5503 if (t1 == VT_LLONG || t2 == VT_LLONG)
5504 gen_opl(op);
5505 else
5506 gen_opi(op);
5507 } else {
5508 vtop--;
5514 /* generate a floating point operation with constant propagation */
5515 void gen_opif(int op)
5517 int c1, c2;
5518 SValue *v1, *v2;
5519 long double f1, f2;
5521 v1 = vtop - 1;
5522 v2 = vtop;
5523 /* currently, we cannot do computations with forward symbols */
5524 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5525 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5526 if (c1 && c2) {
5527 if (v1->type.t == VT_FLOAT) {
5528 f1 = v1->c.f;
5529 f2 = v2->c.f;
5530 } else if (v1->type.t == VT_DOUBLE) {
5531 f1 = v1->c.d;
5532 f2 = v2->c.d;
5533 } else {
5534 f1 = v1->c.ld;
5535 f2 = v2->c.ld;
5538 /* NOTE: we only do constant propagation if finite number (not
5539 NaN or infinity) (ANSI spec) */
5540 if (!ieee_finite(f1) || !ieee_finite(f2))
5541 goto general_case;
5543 switch(op) {
5544 case '+': f1 += f2; break;
5545 case '-': f1 -= f2; break;
5546 case '*': f1 *= f2; break;
5547 case '/':
5548 if (f2 == 0.0) {
5549 if (const_wanted)
5550 error("division by zero in constant");
5551 goto general_case;
5553 f1 /= f2;
5554 break;
5555 /* XXX: also handles tests ? */
5556 default:
5557 goto general_case;
5559 /* XXX: overflow test ? */
5560 if (v1->type.t == VT_FLOAT) {
5561 v1->c.f = f1;
5562 } else if (v1->type.t == VT_DOUBLE) {
5563 v1->c.d = f1;
5564 } else {
5565 v1->c.ld = f1;
5567 vtop--;
5568 } else {
5569 general_case:
5570 if (!nocode_wanted) {
5571 gen_opf(op);
5572 } else {
5573 vtop--;
5578 static int pointed_size(CType *type)
5580 int align;
5581 return type_size(pointed_type(type), &align);
5584 static inline int is_null_pointer(SValue *p)
5586 if ((p->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
5587 return 0;
5588 return ((p->type.t & VT_BTYPE) == VT_INT && p->c.i == 0) ||
5589 ((p->type.t & VT_BTYPE) == VT_LLONG && p->c.ll == 0);
5592 static inline int is_integer_btype(int bt)
5594 return (bt == VT_BYTE || bt == VT_SHORT ||
5595 bt == VT_INT || bt == VT_LLONG);
5598 /* check types for comparison or substraction of pointers */
5599 static void check_comparison_pointer_types(SValue *p1, SValue *p2, int op)
5601 CType *type1, *type2, tmp_type1, tmp_type2;
5602 int bt1, bt2;
5604 /* null pointers are accepted for all comparisons as gcc */
5605 if (is_null_pointer(p1) || is_null_pointer(p2))
5606 return;
5607 type1 = &p1->type;
5608 type2 = &p2->type;
5609 bt1 = type1->t & VT_BTYPE;
5610 bt2 = type2->t & VT_BTYPE;
5611 /* accept comparison between pointer and integer with a warning */
5612 if ((is_integer_btype(bt1) || is_integer_btype(bt2)) && op != '-') {
5613 if (op != TOK_LOR && op != TOK_LAND )
5614 warning("comparison between pointer and integer");
5615 return;
5618 /* both must be pointers or implicit function pointers */
5619 if (bt1 == VT_PTR) {
5620 type1 = pointed_type(type1);
5621 } else if (bt1 != VT_FUNC)
5622 goto invalid_operands;
5624 if (bt2 == VT_PTR) {
5625 type2 = pointed_type(type2);
5626 } else if (bt2 != VT_FUNC) {
5627 invalid_operands:
5628 error("invalid operands to binary %s", get_tok_str(op, NULL));
5630 if ((type1->t & VT_BTYPE) == VT_VOID ||
5631 (type2->t & VT_BTYPE) == VT_VOID)
5632 return;
5633 tmp_type1 = *type1;
5634 tmp_type2 = *type2;
5635 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5636 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5637 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
5638 /* gcc-like error if '-' is used */
5639 if (op == '-')
5640 goto invalid_operands;
5641 else
5642 warning("comparison of distinct pointer types lacks a cast");
5646 /* generic gen_op: handles types problems */
5647 void gen_op(int op)
5649 int u, t1, t2, bt1, bt2, t;
5650 CType type1;
5652 t1 = vtop[-1].type.t;
5653 t2 = vtop[0].type.t;
5654 bt1 = t1 & VT_BTYPE;
5655 bt2 = t2 & VT_BTYPE;
5657 if (bt1 == VT_PTR || bt2 == VT_PTR) {
5658 /* at least one operand is a pointer */
5659 /* relationnal op: must be both pointers */
5660 if (op >= TOK_ULT && op <= TOK_LOR) {
5661 check_comparison_pointer_types(vtop - 1, vtop, op);
5662 /* pointers are handled are unsigned */
5663 t = VT_INT | VT_UNSIGNED;
5664 goto std_op;
5666 /* if both pointers, then it must be the '-' op */
5667 if (bt1 == VT_PTR && bt2 == VT_PTR) {
5668 if (op != '-')
5669 error("cannot use pointers here");
5670 check_comparison_pointer_types(vtop - 1, vtop, op);
5671 /* XXX: check that types are compatible */
5672 u = pointed_size(&vtop[-1].type);
5673 gen_opic(op);
5674 /* set to integer type */
5675 vtop->type.t = VT_INT;
5676 vpushi(u);
5677 gen_op(TOK_PDIV);
5678 } else {
5679 /* exactly one pointer : must be '+' or '-'. */
5680 if (op != '-' && op != '+')
5681 error("cannot use pointers here");
5682 /* Put pointer as first operand */
5683 if (bt2 == VT_PTR) {
5684 vswap();
5685 swap(&t1, &t2);
5687 type1 = vtop[-1].type;
5688 /* XXX: cast to int ? (long long case) */
5689 vpushi(pointed_size(&vtop[-1].type));
5690 gen_op('*');
5691 #ifdef CONFIG_TCC_BCHECK
5692 /* if evaluating constant expression, no code should be
5693 generated, so no bound check */
5694 if (do_bounds_check && !const_wanted) {
5695 /* if bounded pointers, we generate a special code to
5696 test bounds */
5697 if (op == '-') {
5698 vpushi(0);
5699 vswap();
5700 gen_op('-');
5702 gen_bounded_ptr_add();
5703 } else
5704 #endif
5706 gen_opic(op);
5708 /* put again type if gen_opic() swaped operands */
5709 vtop->type = type1;
5711 } else if (is_float(bt1) || is_float(bt2)) {
5712 /* compute bigger type and do implicit casts */
5713 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
5714 t = VT_LDOUBLE;
5715 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
5716 t = VT_DOUBLE;
5717 } else {
5718 t = VT_FLOAT;
5720 /* floats can only be used for a few operations */
5721 if (op != '+' && op != '-' && op != '*' && op != '/' &&
5722 (op < TOK_ULT || op > TOK_GT))
5723 error("invalid operands for binary operation");
5724 goto std_op;
5725 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
5726 /* cast to biggest op */
5727 t = VT_LLONG;
5728 /* convert to unsigned if it does not fit in a long long */
5729 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
5730 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
5731 t |= VT_UNSIGNED;
5732 goto std_op;
5733 } else {
5734 /* integer operations */
5735 t = VT_INT;
5736 /* convert to unsigned if it does not fit in an integer */
5737 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
5738 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
5739 t |= VT_UNSIGNED;
5740 std_op:
5741 /* XXX: currently, some unsigned operations are explicit, so
5742 we modify them here */
5743 if (t & VT_UNSIGNED) {
5744 if (op == TOK_SAR)
5745 op = TOK_SHR;
5746 else if (op == '/')
5747 op = TOK_UDIV;
5748 else if (op == '%')
5749 op = TOK_UMOD;
5750 else if (op == TOK_LT)
5751 op = TOK_ULT;
5752 else if (op == TOK_GT)
5753 op = TOK_UGT;
5754 else if (op == TOK_LE)
5755 op = TOK_ULE;
5756 else if (op == TOK_GE)
5757 op = TOK_UGE;
5759 vswap();
5760 type1.t = t;
5761 gen_cast(&type1);
5762 vswap();
5763 /* special case for shifts and long long: we keep the shift as
5764 an integer */
5765 if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL)
5766 type1.t = VT_INT;
5767 gen_cast(&type1);
5768 if (is_float(t))
5769 gen_opif(op);
5770 else
5771 gen_opic(op);
5772 if (op >= TOK_ULT && op <= TOK_GT) {
5773 /* relationnal op: the result is an int */
5774 vtop->type.t = VT_INT;
5775 } else {
5776 vtop->type.t = t;
5781 /* generic itof for unsigned long long case */
5782 void gen_cvt_itof1(int t)
5784 if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
5785 (VT_LLONG | VT_UNSIGNED)) {
5787 if (t == VT_FLOAT)
5788 vpush_global_sym(&func_old_type, TOK___ulltof);
5789 else if (t == VT_DOUBLE)
5790 vpush_global_sym(&func_old_type, TOK___ulltod);
5791 else
5792 vpush_global_sym(&func_old_type, TOK___ulltold);
5793 vrott(2);
5794 gfunc_call(1);
5795 vpushi(0);
5796 vtop->r = REG_FRET;
5797 } else {
5798 gen_cvt_itof(t);
5802 /* generic ftoi for unsigned long long case */
5803 void gen_cvt_ftoi1(int t)
5805 int st;
5807 if (t == (VT_LLONG | VT_UNSIGNED)) {
5808 /* not handled natively */
5809 st = vtop->type.t & VT_BTYPE;
5810 if (st == VT_FLOAT)
5811 vpush_global_sym(&func_old_type, TOK___fixunssfdi);
5812 else if (st == VT_DOUBLE)
5813 vpush_global_sym(&func_old_type, TOK___fixunsdfdi);
5814 else
5815 vpush_global_sym(&func_old_type, TOK___fixunsxfdi);
5816 vrott(2);
5817 gfunc_call(1);
5818 vpushi(0);
5819 vtop->r = REG_IRET;
5820 vtop->r2 = REG_LRET;
5821 } else {
5822 gen_cvt_ftoi(t);
5826 /* force char or short cast */
5827 void force_charshort_cast(int t)
5829 int bits, dbt;
5830 dbt = t & VT_BTYPE;
5831 /* XXX: add optimization if lvalue : just change type and offset */
5832 if (dbt == VT_BYTE)
5833 bits = 8;
5834 else
5835 bits = 16;
5836 if (t & VT_UNSIGNED) {
5837 vpushi((1 << bits) - 1);
5838 gen_op('&');
5839 } else {
5840 bits = 32 - bits;
5841 vpushi(bits);
5842 gen_op(TOK_SHL);
5843 /* result must be signed or the SAR is converted to an SHL
5844 This was not the case when "t" was a signed short
5845 and the last value on the stack was an unsigned int */
5846 vtop->type.t &= ~VT_UNSIGNED;
5847 vpushi(bits);
5848 gen_op(TOK_SAR);
5852 /* cast 'vtop' to 'type'. Casting to bitfields is forbidden. */
5853 static void gen_cast(CType *type)
5855 int sbt, dbt, sf, df, c;
5857 /* special delayed cast for char/short */
5858 /* XXX: in some cases (multiple cascaded casts), it may still
5859 be incorrect */
5860 if (vtop->r & VT_MUSTCAST) {
5861 vtop->r &= ~VT_MUSTCAST;
5862 force_charshort_cast(vtop->type.t);
5865 /* bitfields first get cast to ints */
5866 if (vtop->type.t & VT_BITFIELD) {
5867 gv(RC_INT);
5870 dbt = type->t & (VT_BTYPE | VT_UNSIGNED);
5871 sbt = vtop->type.t & (VT_BTYPE | VT_UNSIGNED);
5873 if (sbt != dbt && !nocode_wanted) {
5874 sf = is_float(sbt);
5875 df = is_float(dbt);
5876 c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5877 if (sf && df) {
5878 /* convert from fp to fp */
5879 if (c) {
5880 /* constant case: we can do it now */
5881 /* XXX: in ISOC, cannot do it if error in convert */
5882 if (dbt == VT_FLOAT && sbt == VT_DOUBLE)
5883 vtop->c.f = (float)vtop->c.d;
5884 else if (dbt == VT_FLOAT && sbt == VT_LDOUBLE)
5885 vtop->c.f = (float)vtop->c.ld;
5886 else if (dbt == VT_DOUBLE && sbt == VT_FLOAT)
5887 vtop->c.d = (double)vtop->c.f;
5888 else if (dbt == VT_DOUBLE && sbt == VT_LDOUBLE)
5889 vtop->c.d = (double)vtop->c.ld;
5890 else if (dbt == VT_LDOUBLE && sbt == VT_FLOAT)
5891 vtop->c.ld = (long double)vtop->c.f;
5892 else if (dbt == VT_LDOUBLE && sbt == VT_DOUBLE)
5893 vtop->c.ld = (long double)vtop->c.d;
5894 } else {
5895 /* non constant case: generate code */
5896 gen_cvt_ftof(dbt);
5898 } else if (df) {
5899 /* convert int to fp */
5900 if (c) {
5901 switch(sbt) {
5902 case VT_LLONG | VT_UNSIGNED:
5903 case VT_LLONG:
5904 /* XXX: add const cases for long long */
5905 goto do_itof;
5906 case VT_INT | VT_UNSIGNED:
5907 switch(dbt) {
5908 case VT_FLOAT: vtop->c.f = (float)vtop->c.ui; break;
5909 case VT_DOUBLE: vtop->c.d = (double)vtop->c.ui; break;
5910 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.ui; break;
5912 break;
5913 default:
5914 switch(dbt) {
5915 case VT_FLOAT: vtop->c.f = (float)vtop->c.i; break;
5916 case VT_DOUBLE: vtop->c.d = (double)vtop->c.i; break;
5917 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.i; break;
5919 break;
5921 } else {
5922 do_itof:
5923 #if !defined(TCC_TARGET_ARM)
5924 gen_cvt_itof1(dbt);
5925 #else
5926 gen_cvt_itof(dbt);
5927 #endif
5929 } else if (sf) {
5930 /* convert fp to int */
5931 if (dbt == VT_BOOL) {
5932 vpushi(0);
5933 gen_op(TOK_NE);
5934 } else {
5935 /* we handle char/short/etc... with generic code */
5936 if (dbt != (VT_INT | VT_UNSIGNED) &&
5937 dbt != (VT_LLONG | VT_UNSIGNED) &&
5938 dbt != VT_LLONG)
5939 dbt = VT_INT;
5940 if (c) {
5941 switch(dbt) {
5942 case VT_LLONG | VT_UNSIGNED:
5943 case VT_LLONG:
5944 /* XXX: add const cases for long long */
5945 goto do_ftoi;
5946 case VT_INT | VT_UNSIGNED:
5947 switch(sbt) {
5948 case VT_FLOAT: vtop->c.ui = (unsigned int)vtop->c.d; break;
5949 case VT_DOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
5950 case VT_LDOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
5952 break;
5953 default:
5954 /* int case */
5955 switch(sbt) {
5956 case VT_FLOAT: vtop->c.i = (int)vtop->c.d; break;
5957 case VT_DOUBLE: vtop->c.i = (int)vtop->c.d; break;
5958 case VT_LDOUBLE: vtop->c.i = (int)vtop->c.d; break;
5960 break;
5962 } else {
5963 do_ftoi:
5964 gen_cvt_ftoi1(dbt);
5966 if (dbt == VT_INT && (type->t & (VT_BTYPE | VT_UNSIGNED)) != dbt) {
5967 /* additional cast for char/short... */
5968 vtop->type.t = dbt;
5969 gen_cast(type);
5972 } else if ((dbt & VT_BTYPE) == VT_LLONG) {
5973 if ((sbt & VT_BTYPE) != VT_LLONG) {
5974 /* scalar to long long */
5975 if (c) {
5976 if (sbt == (VT_INT | VT_UNSIGNED))
5977 vtop->c.ll = vtop->c.ui;
5978 else
5979 vtop->c.ll = vtop->c.i;
5980 } else {
5981 /* machine independent conversion */
5982 gv(RC_INT);
5983 /* generate high word */
5984 if (sbt == (VT_INT | VT_UNSIGNED)) {
5985 vpushi(0);
5986 gv(RC_INT);
5987 } else {
5988 gv_dup();
5989 vpushi(31);
5990 gen_op(TOK_SAR);
5992 /* patch second register */
5993 vtop[-1].r2 = vtop->r;
5994 vpop();
5997 } else if (dbt == VT_BOOL) {
5998 /* scalar to bool */
5999 vpushi(0);
6000 gen_op(TOK_NE);
6001 } else if ((dbt & VT_BTYPE) == VT_BYTE ||
6002 (dbt & VT_BTYPE) == VT_SHORT) {
6003 if (sbt == VT_PTR) {
6004 vtop->type.t = VT_INT;
6005 warning("nonportable conversion from pointer to char/short");
6007 force_charshort_cast(dbt);
6008 } else if ((dbt & VT_BTYPE) == VT_INT) {
6009 /* scalar to int */
6010 if (sbt == VT_LLONG) {
6011 /* from long long: just take low order word */
6012 lexpand();
6013 vpop();
6015 /* if lvalue and single word type, nothing to do because
6016 the lvalue already contains the real type size (see
6017 VT_LVAL_xxx constants) */
6019 } else if ((dbt & VT_BTYPE) == VT_PTR && !(vtop->r & VT_LVAL)) {
6020 /* if we are casting between pointer types,
6021 we must update the VT_LVAL_xxx size */
6022 vtop->r = (vtop->r & ~VT_LVAL_TYPE)
6023 | (lvalue_type(type->ref->type.t) & VT_LVAL_TYPE);
6025 vtop->type = *type;
6028 /* return type size. Put alignment at 'a' */
6029 static int type_size(CType *type, int *a)
6031 Sym *s;
6032 int bt;
6034 bt = type->t & VT_BTYPE;
6035 if (bt == VT_STRUCT) {
6036 /* struct/union */
6037 s = type->ref;
6038 *a = s->r;
6039 return s->c;
6040 } else if (bt == VT_PTR) {
6041 if (type->t & VT_ARRAY) {
6042 s = type->ref;
6043 return type_size(&s->type, a) * s->c;
6044 } else {
6045 *a = PTR_SIZE;
6046 return PTR_SIZE;
6048 } else if (bt == VT_LDOUBLE) {
6049 *a = LDOUBLE_ALIGN;
6050 return LDOUBLE_SIZE;
6051 } else if (bt == VT_DOUBLE || bt == VT_LLONG) {
6052 #ifdef TCC_TARGET_I386
6053 *a = 4;
6054 #elif defined(TCC_TARGET_ARM)
6055 #ifdef TCC_ARM_EABI
6056 *a = 8;
6057 #else
6058 *a = 4;
6059 #endif
6060 #else
6061 *a = 8;
6062 #endif
6063 return 8;
6064 } else if (bt == VT_INT || bt == VT_ENUM || bt == VT_FLOAT) {
6065 *a = 4;
6066 return 4;
6067 } else if (bt == VT_SHORT) {
6068 *a = 2;
6069 return 2;
6070 } else {
6071 /* char, void, function, _Bool */
6072 *a = 1;
6073 return 1;
6077 /* return the pointed type of t */
6078 static inline CType *pointed_type(CType *type)
6080 return &type->ref->type;
6083 /* modify type so that its it is a pointer to type. */
6084 static void mk_pointer(CType *type)
6086 Sym *s;
6087 s = sym_push(SYM_FIELD, type, 0, -1);
6088 type->t = VT_PTR | (type->t & ~VT_TYPE);
6089 type->ref = s;
6092 /* compare function types. OLD functions match any new functions */
6093 static int is_compatible_func(CType *type1, CType *type2)
6095 Sym *s1, *s2;
6097 s1 = type1->ref;
6098 s2 = type2->ref;
6099 if (!is_compatible_types(&s1->type, &s2->type))
6100 return 0;
6101 /* check func_call */
6102 if (s1->r != s2->r)
6103 return 0;
6104 /* XXX: not complete */
6105 if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
6106 return 1;
6107 if (s1->c != s2->c)
6108 return 0;
6109 while (s1 != NULL) {
6110 if (s2 == NULL)
6111 return 0;
6112 if (!is_compatible_parameter_types(&s1->type, &s2->type))
6113 return 0;
6114 s1 = s1->next;
6115 s2 = s2->next;
6117 if (s2)
6118 return 0;
6119 return 1;
6122 /* return true if type1 and type2 are the same. If unqualified is
6123 true, qualifiers on the types are ignored.
6125 - enums are not checked as gcc __builtin_types_compatible_p ()
6127 static int compare_types(CType *type1, CType *type2, int unqualified)
6129 int bt1, t1, t2;
6131 t1 = type1->t & VT_TYPE;
6132 t2 = type2->t & VT_TYPE;
6133 if (unqualified) {
6134 /* strip qualifiers before comparing */
6135 t1 &= ~(VT_CONSTANT | VT_VOLATILE);
6136 t2 &= ~(VT_CONSTANT | VT_VOLATILE);
6138 /* XXX: bitfields ? */
6139 if (t1 != t2)
6140 return 0;
6141 /* test more complicated cases */
6142 bt1 = t1 & VT_BTYPE;
6143 if (bt1 == VT_PTR) {
6144 type1 = pointed_type(type1);
6145 type2 = pointed_type(type2);
6146 return is_compatible_types(type1, type2);
6147 } else if (bt1 == VT_STRUCT) {
6148 return (type1->ref == type2->ref);
6149 } else if (bt1 == VT_FUNC) {
6150 return is_compatible_func(type1, type2);
6151 } else {
6152 return 1;
6156 /* return true if type1 and type2 are exactly the same (including
6157 qualifiers).
6159 static int is_compatible_types(CType *type1, CType *type2)
6161 return compare_types(type1,type2,0);
6164 /* return true if type1 and type2 are the same (ignoring qualifiers).
6166 static int is_compatible_parameter_types(CType *type1, CType *type2)
6168 return compare_types(type1,type2,1);
6171 /* print a type. If 'varstr' is not NULL, then the variable is also
6172 printed in the type */
6173 /* XXX: union */
6174 /* XXX: add array and function pointers */
6175 void type_to_str(char *buf, int buf_size,
6176 CType *type, const char *varstr)
6178 int bt, v, t;
6179 Sym *s, *sa;
6180 char buf1[256];
6181 const char *tstr;
6183 t = type->t & VT_TYPE;
6184 bt = t & VT_BTYPE;
6185 buf[0] = '\0';
6186 if (t & VT_CONSTANT)
6187 pstrcat(buf, buf_size, "const ");
6188 if (t & VT_VOLATILE)
6189 pstrcat(buf, buf_size, "volatile ");
6190 if (t & VT_UNSIGNED)
6191 pstrcat(buf, buf_size, "unsigned ");
6192 switch(bt) {
6193 case VT_VOID:
6194 tstr = "void";
6195 goto add_tstr;
6196 case VT_BOOL:
6197 tstr = "_Bool";
6198 goto add_tstr;
6199 case VT_BYTE:
6200 tstr = "char";
6201 goto add_tstr;
6202 case VT_SHORT:
6203 tstr = "short";
6204 goto add_tstr;
6205 case VT_INT:
6206 tstr = "int";
6207 goto add_tstr;
6208 case VT_LONG:
6209 tstr = "long";
6210 goto add_tstr;
6211 case VT_LLONG:
6212 tstr = "long long";
6213 goto add_tstr;
6214 case VT_FLOAT:
6215 tstr = "float";
6216 goto add_tstr;
6217 case VT_DOUBLE:
6218 tstr = "double";
6219 goto add_tstr;
6220 case VT_LDOUBLE:
6221 tstr = "long double";
6222 add_tstr:
6223 pstrcat(buf, buf_size, tstr);
6224 break;
6225 case VT_ENUM:
6226 case VT_STRUCT:
6227 if (bt == VT_STRUCT)
6228 tstr = "struct ";
6229 else
6230 tstr = "enum ";
6231 pstrcat(buf, buf_size, tstr);
6232 v = type->ref->v & ~SYM_STRUCT;
6233 if (v >= SYM_FIRST_ANOM)
6234 pstrcat(buf, buf_size, "<anonymous>");
6235 else
6236 pstrcat(buf, buf_size, get_tok_str(v, NULL));
6237 break;
6238 case VT_FUNC:
6239 s = type->ref;
6240 type_to_str(buf, buf_size, &s->type, varstr);
6241 pstrcat(buf, buf_size, "(");
6242 sa = s->next;
6243 while (sa != NULL) {
6244 type_to_str(buf1, sizeof(buf1), &sa->type, NULL);
6245 pstrcat(buf, buf_size, buf1);
6246 sa = sa->next;
6247 if (sa)
6248 pstrcat(buf, buf_size, ", ");
6250 pstrcat(buf, buf_size, ")");
6251 goto no_var;
6252 case VT_PTR:
6253 s = type->ref;
6254 pstrcpy(buf1, sizeof(buf1), "*");
6255 if (varstr)
6256 pstrcat(buf1, sizeof(buf1), varstr);
6257 type_to_str(buf, buf_size, &s->type, buf1);
6258 goto no_var;
6260 if (varstr) {
6261 pstrcat(buf, buf_size, " ");
6262 pstrcat(buf, buf_size, varstr);
6264 no_var: ;
6267 /* verify type compatibility to store vtop in 'dt' type, and generate
6268 casts if needed. */
6269 static void gen_assign_cast(CType *dt)
6271 CType *st, *type1, *type2, tmp_type1, tmp_type2;
6272 char buf1[256], buf2[256];
6273 int dbt, sbt;
6275 st = &vtop->type; /* source type */
6276 dbt = dt->t & VT_BTYPE;
6277 sbt = st->t & VT_BTYPE;
6278 if (dt->t & VT_CONSTANT)
6279 warning("assignment of read-only location");
6280 switch(dbt) {
6281 case VT_PTR:
6282 /* special cases for pointers */
6283 /* '0' can also be a pointer */
6284 if (is_null_pointer(vtop))
6285 goto type_ok;
6286 /* accept implicit pointer to integer cast with warning */
6287 if (is_integer_btype(sbt)) {
6288 warning("assignment makes pointer from integer without a cast");
6289 goto type_ok;
6291 type1 = pointed_type(dt);
6292 /* a function is implicitely a function pointer */
6293 if (sbt == VT_FUNC) {
6294 if ((type1->t & VT_BTYPE) != VT_VOID &&
6295 !is_compatible_types(pointed_type(dt), st))
6296 goto error;
6297 else
6298 goto type_ok;
6300 if (sbt != VT_PTR)
6301 goto error;
6302 type2 = pointed_type(st);
6303 if ((type1->t & VT_BTYPE) == VT_VOID ||
6304 (type2->t & VT_BTYPE) == VT_VOID) {
6305 /* void * can match anything */
6306 } else {
6307 /* exact type match, except for unsigned */
6308 tmp_type1 = *type1;
6309 tmp_type2 = *type2;
6310 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
6311 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
6312 if (!is_compatible_types(&tmp_type1, &tmp_type2))
6313 warning("assignment from incompatible pointer type");
6315 /* check const and volatile */
6316 if ((!(type1->t & VT_CONSTANT) && (type2->t & VT_CONSTANT)) ||
6317 (!(type1->t & VT_VOLATILE) && (type2->t & VT_VOLATILE)))
6318 warning("assignment discards qualifiers from pointer target type");
6319 break;
6320 case VT_BYTE:
6321 case VT_SHORT:
6322 case VT_INT:
6323 case VT_LLONG:
6324 if (sbt == VT_PTR || sbt == VT_FUNC) {
6325 warning("assignment makes integer from pointer without a cast");
6327 /* XXX: more tests */
6328 break;
6329 case VT_STRUCT:
6330 tmp_type1 = *dt;
6331 tmp_type2 = *st;
6332 tmp_type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
6333 tmp_type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
6334 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
6335 error:
6336 type_to_str(buf1, sizeof(buf1), st, NULL);
6337 type_to_str(buf2, sizeof(buf2), dt, NULL);
6338 error("cannot cast '%s' to '%s'", buf1, buf2);
6340 break;
6342 type_ok:
6343 gen_cast(dt);
6346 /* store vtop in lvalue pushed on stack */
6347 void vstore(void)
6349 int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
6351 ft = vtop[-1].type.t;
6352 sbt = vtop->type.t & VT_BTYPE;
6353 dbt = ft & VT_BTYPE;
6354 if (((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
6355 (sbt == VT_INT && dbt == VT_SHORT)) {
6356 /* optimize char/short casts */
6357 delayed_cast = VT_MUSTCAST;
6358 vtop->type.t = ft & VT_TYPE;
6359 /* XXX: factorize */
6360 if (ft & VT_CONSTANT)
6361 warning("assignment of read-only location");
6362 } else {
6363 delayed_cast = 0;
6364 if (!(ft & VT_BITFIELD))
6365 gen_assign_cast(&vtop[-1].type);
6368 if (sbt == VT_STRUCT) {
6369 /* if structure, only generate pointer */
6370 /* structure assignment : generate memcpy */
6371 /* XXX: optimize if small size */
6372 if (!nocode_wanted) {
6373 size = type_size(&vtop->type, &align);
6375 #ifdef TCC_ARM_EABI
6376 if(!(align & 7))
6377 vpush_global_sym(&func_old_type, TOK_memcpy8);
6378 else if(!(align & 3))
6379 vpush_global_sym(&func_old_type, TOK_memcpy4);
6380 else
6381 #endif
6382 vpush_global_sym(&func_old_type, TOK_memcpy);
6384 /* destination */
6385 vpushv(vtop - 2);
6386 vtop->type.t = VT_INT;
6387 gaddrof();
6388 /* source */
6389 vpushv(vtop - 2);
6390 vtop->type.t = VT_INT;
6391 gaddrof();
6392 /* type size */
6393 vpushi(size);
6394 gfunc_call(3);
6396 vswap();
6397 vpop();
6398 } else {
6399 vswap();
6400 vpop();
6402 /* leave source on stack */
6403 } else if (ft & VT_BITFIELD) {
6404 /* bitfield store handling */
6405 bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
6406 bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
6407 /* remove bit field info to avoid loops */
6408 vtop[-1].type.t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
6410 /* duplicate source into other register */
6411 gv_dup();
6412 vswap();
6413 vrott(3);
6415 /* duplicate destination */
6416 vdup();
6417 vtop[-1] = vtop[-2];
6419 /* mask and shift source */
6420 vpushi((1 << bit_size) - 1);
6421 gen_op('&');
6422 vpushi(bit_pos);
6423 gen_op(TOK_SHL);
6424 /* load destination, mask and or with source */
6425 vswap();
6426 vpushi(~(((1 << bit_size) - 1) << bit_pos));
6427 gen_op('&');
6428 gen_op('|');
6429 /* store result */
6430 vstore();
6432 /* pop off shifted source from "duplicate source..." above */
6433 vpop();
6435 } else {
6436 #ifdef CONFIG_TCC_BCHECK
6437 /* bound check case */
6438 if (vtop[-1].r & VT_MUSTBOUND) {
6439 vswap();
6440 gbound();
6441 vswap();
6443 #endif
6444 if (!nocode_wanted) {
6445 rc = RC_INT;
6446 if (is_float(ft))
6447 rc = RC_FLOAT;
6448 r = gv(rc); /* generate value */
6449 /* if lvalue was saved on stack, must read it */
6450 if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
6451 SValue sv;
6452 t = get_reg(RC_INT);
6453 sv.type.t = VT_INT;
6454 sv.r = VT_LOCAL | VT_LVAL;
6455 sv.c.ul = vtop[-1].c.ul;
6456 load(t, &sv);
6457 vtop[-1].r = t | VT_LVAL;
6459 store(r, vtop - 1);
6460 /* two word case handling : store second register at word + 4 */
6461 if ((ft & VT_BTYPE) == VT_LLONG) {
6462 vswap();
6463 /* convert to int to increment easily */
6464 vtop->type.t = VT_INT;
6465 gaddrof();
6466 vpushi(4);
6467 gen_op('+');
6468 vtop->r |= VT_LVAL;
6469 vswap();
6470 /* XXX: it works because r2 is spilled last ! */
6471 store(vtop->r2, vtop - 1);
6474 vswap();
6475 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
6476 vtop->r |= delayed_cast;
6480 /* post defines POST/PRE add. c is the token ++ or -- */
6481 void inc(int post, int c)
6483 test_lvalue();
6484 vdup(); /* save lvalue */
6485 if (post) {
6486 gv_dup(); /* duplicate value */
6487 vrotb(3);
6488 vrotb(3);
6490 /* add constant */
6491 vpushi(c - TOK_MID);
6492 gen_op('+');
6493 vstore(); /* store value */
6494 if (post)
6495 vpop(); /* if post op, return saved value */
6498 /* Parse GNUC __attribute__ extension. Currently, the following
6499 extensions are recognized:
6500 - aligned(n) : set data/function alignment.
6501 - packed : force data alignment to 1
6502 - section(x) : generate data/code in this section.
6503 - unused : currently ignored, but may be used someday.
6504 - regparm(n) : pass function parameters in registers (i386 only)
6506 static void parse_attribute(AttributeDef *ad)
6508 int t, n;
6510 while (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) {
6511 next();
6512 skip('(');
6513 skip('(');
6514 while (tok != ')') {
6515 if (tok < TOK_IDENT)
6516 expect("attribute name");
6517 t = tok;
6518 next();
6519 switch(t) {
6520 case TOK_SECTION1:
6521 case TOK_SECTION2:
6522 skip('(');
6523 if (tok != TOK_STR)
6524 expect("section name");
6525 ad->section = find_section(tcc_state, (char *)tokc.cstr->data);
6526 next();
6527 skip(')');
6528 break;
6529 case TOK_ALIGNED1:
6530 case TOK_ALIGNED2:
6531 if (tok == '(') {
6532 next();
6533 n = expr_const();
6534 if (n <= 0 || (n & (n - 1)) != 0)
6535 error("alignment must be a positive power of two");
6536 skip(')');
6537 } else {
6538 n = MAX_ALIGN;
6540 ad->aligned = n;
6541 break;
6542 case TOK_PACKED1:
6543 case TOK_PACKED2:
6544 ad->packed = 1;
6545 break;
6546 case TOK_UNUSED1:
6547 case TOK_UNUSED2:
6548 /* currently, no need to handle it because tcc does not
6549 track unused objects */
6550 break;
6551 case TOK_NORETURN1:
6552 case TOK_NORETURN2:
6553 /* currently, no need to handle it because tcc does not
6554 track unused objects */
6555 break;
6556 case TOK_CDECL1:
6557 case TOK_CDECL2:
6558 case TOK_CDECL3:
6559 ad->func_call = FUNC_CDECL;
6560 break;
6561 case TOK_STDCALL1:
6562 case TOK_STDCALL2:
6563 case TOK_STDCALL3:
6564 ad->func_call = FUNC_STDCALL;
6565 break;
6566 #ifdef TCC_TARGET_I386
6567 case TOK_REGPARM1:
6568 case TOK_REGPARM2:
6569 skip('(');
6570 n = expr_const();
6571 if (n > 3)
6572 n = 3;
6573 else if (n < 0)
6574 n = 0;
6575 if (n > 0)
6576 ad->func_call = FUNC_FASTCALL1 + n - 1;
6577 skip(')');
6578 break;
6579 case TOK_FASTCALL1:
6580 case TOK_FASTCALL2:
6581 case TOK_FASTCALL3:
6582 ad->func_call = FUNC_FASTCALLW;
6583 break;
6584 #endif
6585 case TOK_DLLEXPORT:
6586 ad->dllexport = 1;
6587 break;
6588 default:
6589 if (tcc_state->warn_unsupported)
6590 warning("'%s' attribute ignored", get_tok_str(t, NULL));
6591 /* skip parameters */
6592 if (tok == '(') {
6593 int parenthesis = 0;
6594 do {
6595 if (tok == '(')
6596 parenthesis++;
6597 else if (tok == ')')
6598 parenthesis--;
6599 next();
6600 } while (parenthesis && tok != -1);
6602 break;
6604 if (tok != ',')
6605 break;
6606 next();
6608 skip(')');
6609 skip(')');
6613 /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
6614 static void struct_decl(CType *type, int u)
6616 int a, v, size, align, maxalign, c, offset;
6617 int bit_size, bit_pos, bsize, bt, lbit_pos;
6618 Sym *s, *ss, *ass, **ps;
6619 AttributeDef ad;
6620 CType type1, btype;
6622 a = tok; /* save decl type */
6623 next();
6624 if (tok != '{') {
6625 v = tok;
6626 next();
6627 /* struct already defined ? return it */
6628 if (v < TOK_IDENT)
6629 expect("struct/union/enum name");
6630 s = struct_find(v);
6631 if (s) {
6632 if (s->type.t != a)
6633 error("invalid type");
6634 goto do_decl;
6636 } else {
6637 v = anon_sym++;
6639 type1.t = a;
6640 /* we put an undefined size for struct/union */
6641 s = sym_push(v | SYM_STRUCT, &type1, 0, -1);
6642 s->r = 0; /* default alignment is zero as gcc */
6643 /* put struct/union/enum name in type */
6644 do_decl:
6645 type->t = u;
6646 type->ref = s;
6648 if (tok == '{') {
6649 next();
6650 if (s->c != -1)
6651 error("struct/union/enum already defined");
6652 /* cannot be empty */
6653 c = 0;
6654 /* non empty enums are not allowed */
6655 if (a == TOK_ENUM) {
6656 for(;;) {
6657 v = tok;
6658 if (v < TOK_UIDENT)
6659 expect("identifier");
6660 next();
6661 if (tok == '=') {
6662 next();
6663 c = expr_const();
6665 /* enum symbols have static storage */
6666 ss = sym_push(v, &int_type, VT_CONST, c);
6667 ss->type.t |= VT_STATIC;
6668 if (tok != ',')
6669 break;
6670 next();
6671 c++;
6672 /* NOTE: we accept a trailing comma */
6673 if (tok == '}')
6674 break;
6676 skip('}');
6677 } else {
6678 maxalign = 1;
6679 ps = &s->next;
6680 bit_pos = 0;
6681 offset = 0;
6682 while (tok != '}') {
6683 parse_btype(&btype, &ad);
6684 while (1) {
6685 bit_size = -1;
6686 v = 0;
6687 type1 = btype;
6688 if (tok != ':') {
6689 type_decl(&type1, &ad, &v, TYPE_DIRECT | TYPE_ABSTRACT);
6690 if (v == 0 && (type1.t & VT_BTYPE) != VT_STRUCT)
6691 expect("identifier");
6692 if ((type1.t & VT_BTYPE) == VT_FUNC ||
6693 (type1.t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN | VT_INLINE)))
6694 error("invalid type for '%s'",
6695 get_tok_str(v, NULL));
6697 if (tok == ':') {
6698 next();
6699 bit_size = expr_const();
6700 /* XXX: handle v = 0 case for messages */
6701 if (bit_size < 0)
6702 error("negative width in bit-field '%s'",
6703 get_tok_str(v, NULL));
6704 if (v && bit_size == 0)
6705 error("zero width for bit-field '%s'",
6706 get_tok_str(v, NULL));
6708 size = type_size(&type1, &align);
6709 if (ad.aligned) {
6710 if (align < ad.aligned)
6711 align = ad.aligned;
6712 } else if (ad.packed) {
6713 align = 1;
6714 } else if (*tcc_state->pack_stack_ptr) {
6715 if (align > *tcc_state->pack_stack_ptr)
6716 align = *tcc_state->pack_stack_ptr;
6718 lbit_pos = 0;
6719 if (bit_size >= 0) {
6720 bt = type1.t & VT_BTYPE;
6721 if (bt != VT_INT &&
6722 bt != VT_BYTE &&
6723 bt != VT_SHORT &&
6724 bt != VT_BOOL &&
6725 bt != VT_ENUM)
6726 error("bitfields must have scalar type");
6727 bsize = size * 8;
6728 if (bit_size > bsize) {
6729 error("width of '%s' exceeds its type",
6730 get_tok_str(v, NULL));
6731 } else if (bit_size == bsize) {
6732 /* no need for bit fields */
6733 bit_pos = 0;
6734 } else if (bit_size == 0) {
6735 /* XXX: what to do if only padding in a
6736 structure ? */
6737 /* zero size: means to pad */
6738 if (bit_pos > 0)
6739 bit_pos = bsize;
6740 } else {
6741 /* we do not have enough room ? */
6742 if ((bit_pos + bit_size) > bsize)
6743 bit_pos = 0;
6744 lbit_pos = bit_pos;
6745 /* XXX: handle LSB first */
6746 type1.t |= VT_BITFIELD |
6747 (bit_pos << VT_STRUCT_SHIFT) |
6748 (bit_size << (VT_STRUCT_SHIFT + 6));
6749 bit_pos += bit_size;
6751 } else {
6752 bit_pos = 0;
6754 if (v != 0 || (type1.t & VT_BTYPE) == VT_STRUCT) {
6755 /* add new memory data only if starting
6756 bit field */
6757 if (lbit_pos == 0) {
6758 if (a == TOK_STRUCT) {
6759 c = (c + align - 1) & -align;
6760 offset = c;
6761 if (size > 0)
6762 c += size;
6763 } else {
6764 offset = 0;
6765 if (size > c)
6766 c = size;
6768 if (align > maxalign)
6769 maxalign = align;
6771 #if 0
6772 printf("add field %s offset=%d",
6773 get_tok_str(v, NULL), offset);
6774 if (type1.t & VT_BITFIELD) {
6775 printf(" pos=%d size=%d",
6776 (type1.t >> VT_STRUCT_SHIFT) & 0x3f,
6777 (type1.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
6779 printf("\n");
6780 #endif
6782 if (v == 0 && (type1.t & VT_BTYPE) == VT_STRUCT) {
6783 ass = type1.ref;
6784 while ((ass = ass->next) != NULL) {
6785 ss = sym_push(ass->v, &ass->type, 0, offset + ass->c);
6786 *ps = ss;
6787 ps = &ss->next;
6789 } else if (v) {
6790 ss = sym_push(v | SYM_FIELD, &type1, 0, offset);
6791 *ps = ss;
6792 ps = &ss->next;
6794 if (tok == ';' || tok == TOK_EOF)
6795 break;
6796 skip(',');
6798 skip(';');
6800 skip('}');
6801 /* store size and alignment */
6802 s->c = (c + maxalign - 1) & -maxalign;
6803 s->r = maxalign;
6808 /* return 0 if no type declaration. otherwise, return the basic type
6809 and skip it.
6811 static int parse_btype(CType *type, AttributeDef *ad)
6813 int t, u, type_found, typespec_found, typedef_found;
6814 Sym *s;
6815 CType type1;
6817 memset(ad, 0, sizeof(AttributeDef));
6818 type_found = 0;
6819 typespec_found = 0;
6820 typedef_found = 0;
6821 t = 0;
6822 while(1) {
6823 switch(tok) {
6824 case TOK_EXTENSION:
6825 /* currently, we really ignore extension */
6826 next();
6827 continue;
6829 /* basic types */
6830 case TOK_CHAR:
6831 u = VT_BYTE;
6832 basic_type:
6833 next();
6834 basic_type1:
6835 if ((t & VT_BTYPE) != 0)
6836 error("too many basic types");
6837 t |= u;
6838 typespec_found = 1;
6839 break;
6840 case TOK_VOID:
6841 u = VT_VOID;
6842 goto basic_type;
6843 case TOK_SHORT:
6844 u = VT_SHORT;
6845 goto basic_type;
6846 case TOK_INT:
6847 next();
6848 typespec_found = 1;
6849 break;
6850 case TOK_LONG:
6851 next();
6852 if ((t & VT_BTYPE) == VT_DOUBLE) {
6853 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6854 } else if ((t & VT_BTYPE) == VT_LONG) {
6855 t = (t & ~VT_BTYPE) | VT_LLONG;
6856 } else {
6857 u = VT_LONG;
6858 goto basic_type1;
6860 break;
6861 case TOK_BOOL:
6862 u = VT_BOOL;
6863 goto basic_type;
6864 case TOK_FLOAT:
6865 u = VT_FLOAT;
6866 goto basic_type;
6867 case TOK_DOUBLE:
6868 next();
6869 if ((t & VT_BTYPE) == VT_LONG) {
6870 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6871 } else {
6872 u = VT_DOUBLE;
6873 goto basic_type1;
6875 break;
6876 case TOK_ENUM:
6877 struct_decl(&type1, VT_ENUM);
6878 basic_type2:
6879 u = type1.t;
6880 type->ref = type1.ref;
6881 goto basic_type1;
6882 case TOK_STRUCT:
6883 case TOK_UNION:
6884 struct_decl(&type1, VT_STRUCT);
6885 goto basic_type2;
6887 /* type modifiers */
6888 case TOK_CONST1:
6889 case TOK_CONST2:
6890 case TOK_CONST3:
6891 t |= VT_CONSTANT;
6892 next();
6893 break;
6894 case TOK_VOLATILE1:
6895 case TOK_VOLATILE2:
6896 case TOK_VOLATILE3:
6897 t |= VT_VOLATILE;
6898 next();
6899 break;
6900 case TOK_SIGNED1:
6901 case TOK_SIGNED2:
6902 case TOK_SIGNED3:
6903 typespec_found = 1;
6904 t |= VT_SIGNED;
6905 next();
6906 break;
6907 case TOK_REGISTER:
6908 case TOK_AUTO:
6909 case TOK_RESTRICT1:
6910 case TOK_RESTRICT2:
6911 case TOK_RESTRICT3:
6912 next();
6913 break;
6914 case TOK_UNSIGNED:
6915 t |= VT_UNSIGNED;
6916 next();
6917 typespec_found = 1;
6918 break;
6920 /* storage */
6921 case TOK_EXTERN:
6922 t |= VT_EXTERN;
6923 next();
6924 break;
6925 case TOK_STATIC:
6926 t |= VT_STATIC;
6927 next();
6928 break;
6929 case TOK_TYPEDEF:
6930 t |= VT_TYPEDEF;
6931 next();
6932 break;
6933 case TOK_INLINE1:
6934 case TOK_INLINE2:
6935 case TOK_INLINE3:
6936 t |= VT_INLINE;
6937 next();
6938 break;
6940 /* GNUC attribute */
6941 case TOK_ATTRIBUTE1:
6942 case TOK_ATTRIBUTE2:
6943 parse_attribute(ad);
6944 break;
6945 /* GNUC typeof */
6946 case TOK_TYPEOF1:
6947 case TOK_TYPEOF2:
6948 case TOK_TYPEOF3:
6949 next();
6950 parse_expr_type(&type1);
6951 goto basic_type2;
6952 default:
6953 if (typespec_found || typedef_found)
6954 goto the_end;
6955 s = sym_find(tok);
6956 if (!s || !(s->type.t & VT_TYPEDEF))
6957 goto the_end;
6958 typedef_found = 1;
6959 t |= (s->type.t & ~VT_TYPEDEF);
6960 type->ref = s->type.ref;
6961 next();
6962 typespec_found = 1;
6963 break;
6965 type_found = 1;
6967 the_end:
6968 if ((t & (VT_SIGNED|VT_UNSIGNED)) == (VT_SIGNED|VT_UNSIGNED))
6969 error("signed and unsigned modifier");
6970 if (tcc_state->char_is_unsigned) {
6971 if ((t & (VT_SIGNED|VT_UNSIGNED|VT_BTYPE)) == VT_BYTE)
6972 t |= VT_UNSIGNED;
6974 t &= ~VT_SIGNED;
6976 /* long is never used as type */
6977 if ((t & VT_BTYPE) == VT_LONG)
6978 t = (t & ~VT_BTYPE) | VT_INT;
6979 type->t = t;
6980 return type_found;
6983 /* convert a function parameter type (array to pointer and function to
6984 function pointer) */
6985 static inline void convert_parameter_type(CType *pt)
6987 /* remove const and volatile qualifiers (XXX: const could be used
6988 to indicate a const function parameter */
6989 pt->t &= ~(VT_CONSTANT | VT_VOLATILE);
6990 /* array must be transformed to pointer according to ANSI C */
6991 pt->t &= ~VT_ARRAY;
6992 if ((pt->t & VT_BTYPE) == VT_FUNC) {
6993 mk_pointer(pt);
6997 static void post_type(CType *type, AttributeDef *ad)
6999 int n, l, t1;
7000 Sym **plast, *s, *first;
7001 AttributeDef ad1;
7002 CType pt;
7004 if (tok == '(') {
7005 /* function declaration */
7006 next();
7007 l = 0;
7008 first = NULL;
7009 plast = &first;
7010 if (tok != ')') {
7011 for(;;) {
7012 /* read param name and compute offset */
7013 if (l != FUNC_OLD) {
7014 if (!parse_btype(&pt, &ad1)) {
7015 if (l) {
7016 error("invalid type");
7017 } else {
7018 l = FUNC_OLD;
7019 goto old_proto;
7022 l = FUNC_NEW;
7023 if ((pt.t & VT_BTYPE) == VT_VOID && tok == ')')
7024 break;
7025 type_decl(&pt, &ad1, &n, TYPE_DIRECT | TYPE_ABSTRACT);
7026 if ((pt.t & VT_BTYPE) == VT_VOID)
7027 error("parameter declared as void");
7028 } else {
7029 old_proto:
7030 n = tok;
7031 if (n < TOK_UIDENT)
7032 expect("identifier");
7033 pt.t = VT_INT;
7034 next();
7036 convert_parameter_type(&pt);
7037 s = sym_push(n | SYM_FIELD, &pt, 0, 0);
7038 *plast = s;
7039 plast = &s->next;
7040 if (tok == ')')
7041 break;
7042 skip(',');
7043 if (l == FUNC_NEW && tok == TOK_DOTS) {
7044 l = FUNC_ELLIPSIS;
7045 next();
7046 break;
7050 /* if no parameters, then old type prototype */
7051 if (l == 0)
7052 l = FUNC_OLD;
7053 skip(')');
7054 t1 = type->t & VT_STORAGE;
7055 /* NOTE: const is ignored in returned type as it has a special
7056 meaning in gcc / C++ */
7057 type->t &= ~(VT_STORAGE | VT_CONSTANT);
7058 post_type(type, ad);
7059 /* we push a anonymous symbol which will contain the function prototype */
7060 s = sym_push(SYM_FIELD, type, ad->func_call, l);
7061 s->next = first;
7062 type->t = t1 | VT_FUNC;
7063 type->ref = s;
7064 } else if (tok == '[') {
7065 /* array definition */
7066 next();
7067 n = -1;
7068 if (tok != ']') {
7069 n = expr_const();
7070 if (n < 0)
7071 error("invalid array size");
7073 skip(']');
7074 /* parse next post type */
7075 t1 = type->t & VT_STORAGE;
7076 type->t &= ~VT_STORAGE;
7077 post_type(type, ad);
7079 /* we push a anonymous symbol which will contain the array
7080 element type */
7081 s = sym_push(SYM_FIELD, type, 0, n);
7082 type->t = t1 | VT_ARRAY | VT_PTR;
7083 type->ref = s;
7087 /* Parse a type declaration (except basic type), and return the type
7088 in 'type'. 'td' is a bitmask indicating which kind of type decl is
7089 expected. 'type' should contain the basic type. 'ad' is the
7090 attribute definition of the basic type. It can be modified by
7091 type_decl().
7093 static void type_decl(CType *type, AttributeDef *ad, int *v, int td)
7095 Sym *s;
7096 CType type1, *type2;
7097 int qualifiers;
7099 while (tok == '*') {
7100 qualifiers = 0;
7101 redo:
7102 next();
7103 switch(tok) {
7104 case TOK_CONST1:
7105 case TOK_CONST2:
7106 case TOK_CONST3:
7107 qualifiers |= VT_CONSTANT;
7108 goto redo;
7109 case TOK_VOLATILE1:
7110 case TOK_VOLATILE2:
7111 case TOK_VOLATILE3:
7112 qualifiers |= VT_VOLATILE;
7113 goto redo;
7114 case TOK_RESTRICT1:
7115 case TOK_RESTRICT2:
7116 case TOK_RESTRICT3:
7117 goto redo;
7119 mk_pointer(type);
7120 type->t |= qualifiers;
7123 /* XXX: clarify attribute handling */
7124 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
7125 parse_attribute(ad);
7127 /* recursive type */
7128 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
7129 type1.t = 0; /* XXX: same as int */
7130 if (tok == '(') {
7131 next();
7132 /* XXX: this is not correct to modify 'ad' at this point, but
7133 the syntax is not clear */
7134 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
7135 parse_attribute(ad);
7136 type_decl(&type1, ad, v, td);
7137 skip(')');
7138 } else {
7139 /* type identifier */
7140 if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
7141 *v = tok;
7142 next();
7143 } else {
7144 if (!(td & TYPE_ABSTRACT))
7145 expect("identifier");
7146 *v = 0;
7149 post_type(type, ad);
7150 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
7151 parse_attribute(ad);
7152 if (!type1.t)
7153 return;
7154 /* append type at the end of type1 */
7155 type2 = &type1;
7156 for(;;) {
7157 s = type2->ref;
7158 type2 = &s->type;
7159 if (!type2->t) {
7160 *type2 = *type;
7161 break;
7164 *type = type1;
7167 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
7168 static int lvalue_type(int t)
7170 int bt, r;
7171 r = VT_LVAL;
7172 bt = t & VT_BTYPE;
7173 if (bt == VT_BYTE || bt == VT_BOOL)
7174 r |= VT_LVAL_BYTE;
7175 else if (bt == VT_SHORT)
7176 r |= VT_LVAL_SHORT;
7177 else
7178 return r;
7179 if (t & VT_UNSIGNED)
7180 r |= VT_LVAL_UNSIGNED;
7181 return r;
7184 /* indirection with full error checking and bound check */
7185 static void indir(void)
7187 if ((vtop->type.t & VT_BTYPE) != VT_PTR) {
7188 if ((vtop->type.t & VT_BTYPE) == VT_FUNC)
7189 return;
7190 expect("pointer");
7192 if ((vtop->r & VT_LVAL) && !nocode_wanted)
7193 gv(RC_INT);
7194 vtop->type = *pointed_type(&vtop->type);
7195 /* Arrays and functions are never lvalues */
7196 if (!(vtop->type.t & VT_ARRAY)
7197 && (vtop->type.t & VT_BTYPE) != VT_FUNC) {
7198 vtop->r |= lvalue_type(vtop->type.t);
7199 /* if bound checking, the referenced pointer must be checked */
7200 if (do_bounds_check)
7201 vtop->r |= VT_MUSTBOUND;
7205 /* pass a parameter to a function and do type checking and casting */
7206 static void gfunc_param_typed(Sym *func, Sym *arg)
7208 int func_type;
7209 CType type;
7211 func_type = func->c;
7212 if (func_type == FUNC_OLD ||
7213 (func_type == FUNC_ELLIPSIS && arg == NULL)) {
7214 /* default casting : only need to convert float to double */
7215 if ((vtop->type.t & VT_BTYPE) == VT_FLOAT) {
7216 type.t = VT_DOUBLE;
7217 gen_cast(&type);
7219 } else if (arg == NULL) {
7220 error("too many arguments to function");
7221 } else {
7222 type = arg->type;
7223 type.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
7224 gen_assign_cast(&type);
7228 /* parse an expression of the form '(type)' or '(expr)' and return its
7229 type */
7230 static void parse_expr_type(CType *type)
7232 int n;
7233 AttributeDef ad;
7235 skip('(');
7236 if (parse_btype(type, &ad)) {
7237 type_decl(type, &ad, &n, TYPE_ABSTRACT);
7238 } else {
7239 expr_type(type);
7241 skip(')');
7244 static void parse_type(CType *type)
7246 AttributeDef ad;
7247 int n;
7249 if (!parse_btype(type, &ad)) {
7250 expect("type");
7252 type_decl(type, &ad, &n, TYPE_ABSTRACT);
7255 static void vpush_tokc(int t)
7257 CType type;
7258 type.t = t;
7259 vsetc(&type, VT_CONST, &tokc);
7262 static void unary(void)
7264 int n, t, align, size, r;
7265 CType type;
7266 Sym *s;
7267 AttributeDef ad;
7269 /* XXX: GCC 2.95.3 does not generate a table although it should be
7270 better here */
7271 tok_next:
7272 switch(tok) {
7273 case TOK_EXTENSION:
7274 next();
7275 goto tok_next;
7276 case TOK_CINT:
7277 case TOK_CCHAR:
7278 case TOK_LCHAR:
7279 vpushi(tokc.i);
7280 next();
7281 break;
7282 case TOK_CUINT:
7283 vpush_tokc(VT_INT | VT_UNSIGNED);
7284 next();
7285 break;
7286 case TOK_CLLONG:
7287 vpush_tokc(VT_LLONG);
7288 next();
7289 break;
7290 case TOK_CULLONG:
7291 vpush_tokc(VT_LLONG | VT_UNSIGNED);
7292 next();
7293 break;
7294 case TOK_CFLOAT:
7295 vpush_tokc(VT_FLOAT);
7296 next();
7297 break;
7298 case TOK_CDOUBLE:
7299 vpush_tokc(VT_DOUBLE);
7300 next();
7301 break;
7302 case TOK_CLDOUBLE:
7303 vpush_tokc(VT_LDOUBLE);
7304 next();
7305 break;
7306 case TOK___FUNCTION__:
7307 if (!gnu_ext)
7308 goto tok_identifier;
7309 /* fall thru */
7310 case TOK___FUNC__:
7312 void *ptr;
7313 int len;
7314 /* special function name identifier */
7315 len = strlen(funcname) + 1;
7316 /* generate char[len] type */
7317 type.t = VT_BYTE;
7318 mk_pointer(&type);
7319 type.t |= VT_ARRAY;
7320 type.ref->c = len;
7321 vpush_ref(&type, data_section, data_section->data_offset, len);
7322 ptr = section_ptr_add(data_section, len);
7323 memcpy(ptr, funcname, len);
7324 next();
7326 break;
7327 case TOK_LSTR:
7328 #ifdef TCC_TARGET_PE
7329 t = VT_SHORT | VT_UNSIGNED;
7330 #else
7331 t = VT_INT;
7332 #endif
7333 goto str_init;
7334 case TOK_STR:
7335 /* string parsing */
7336 t = VT_BYTE;
7337 str_init:
7338 if (tcc_state->warn_write_strings)
7339 t |= VT_CONSTANT;
7340 type.t = t;
7341 mk_pointer(&type);
7342 type.t |= VT_ARRAY;
7343 memset(&ad, 0, sizeof(AttributeDef));
7344 decl_initializer_alloc(&type, &ad, VT_CONST, 2, 0, 0);
7345 break;
7346 case '(':
7347 next();
7348 /* cast ? */
7349 if (parse_btype(&type, &ad)) {
7350 type_decl(&type, &ad, &n, TYPE_ABSTRACT);
7351 skip(')');
7352 /* check ISOC99 compound literal */
7353 if (tok == '{') {
7354 /* data is allocated locally by default */
7355 if (global_expr)
7356 r = VT_CONST;
7357 else
7358 r = VT_LOCAL;
7359 /* all except arrays are lvalues */
7360 if (!(type.t & VT_ARRAY))
7361 r |= lvalue_type(type.t);
7362 memset(&ad, 0, sizeof(AttributeDef));
7363 decl_initializer_alloc(&type, &ad, r, 1, 0, 0);
7364 } else {
7365 unary();
7366 gen_cast(&type);
7368 } else if (tok == '{') {
7369 /* save all registers */
7370 save_regs(0);
7371 /* statement expression : we do not accept break/continue
7372 inside as GCC does */
7373 block(NULL, NULL, NULL, NULL, 0, 1);
7374 skip(')');
7375 } else {
7376 gexpr();
7377 skip(')');
7379 break;
7380 case '*':
7381 next();
7382 unary();
7383 indir();
7384 break;
7385 case '&':
7386 next();
7387 unary();
7388 /* functions names must be treated as function pointers,
7389 except for unary '&' and sizeof. Since we consider that
7390 functions are not lvalues, we only have to handle it
7391 there and in function calls. */
7392 /* arrays can also be used although they are not lvalues */
7393 if ((vtop->type.t & VT_BTYPE) != VT_FUNC &&
7394 !(vtop->type.t & VT_ARRAY) && !(vtop->type.t & VT_LLOCAL))
7395 test_lvalue();
7396 mk_pointer(&vtop->type);
7397 gaddrof();
7398 break;
7399 case '!':
7400 next();
7401 unary();
7402 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST)
7403 vtop->c.i = !vtop->c.i;
7404 else if ((vtop->r & VT_VALMASK) == VT_CMP)
7405 vtop->c.i = vtop->c.i ^ 1;
7406 else {
7407 save_regs(1);
7408 vseti(VT_JMP, gtst(1, 0));
7410 break;
7411 case '~':
7412 next();
7413 unary();
7414 vpushi(-1);
7415 gen_op('^');
7416 break;
7417 case '+':
7418 next();
7419 /* in order to force cast, we add zero */
7420 unary();
7421 if ((vtop->type.t & VT_BTYPE) == VT_PTR)
7422 error("pointer not accepted for unary plus");
7423 vpushi(0);
7424 gen_op('+');
7425 break;
7426 case TOK_SIZEOF:
7427 case TOK_ALIGNOF1:
7428 case TOK_ALIGNOF2:
7429 t = tok;
7430 next();
7431 if (tok == '(') {
7432 parse_expr_type(&type);
7433 } else {
7434 unary_type(&type);
7436 size = type_size(&type, &align);
7437 if (t == TOK_SIZEOF) {
7438 if (size < 0)
7439 error("sizeof applied to an incomplete type");
7440 vpushi(size);
7441 } else {
7442 vpushi(align);
7444 vtop->type.t |= VT_UNSIGNED;
7445 break;
7447 case TOK_builtin_types_compatible_p:
7449 CType type1, type2;
7450 next();
7451 skip('(');
7452 parse_type(&type1);
7453 skip(',');
7454 parse_type(&type2);
7455 skip(')');
7456 type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
7457 type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
7458 vpushi(is_compatible_types(&type1, &type2));
7460 break;
7461 case TOK_builtin_constant_p:
7463 int saved_nocode_wanted, res;
7464 next();
7465 skip('(');
7466 saved_nocode_wanted = nocode_wanted;
7467 nocode_wanted = 1;
7468 gexpr();
7469 res = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
7470 vpop();
7471 nocode_wanted = saved_nocode_wanted;
7472 skip(')');
7473 vpushi(res);
7475 break;
7476 case TOK_INC:
7477 case TOK_DEC:
7478 t = tok;
7479 next();
7480 unary();
7481 inc(0, t);
7482 break;
7483 case '-':
7484 next();
7485 vpushi(0);
7486 unary();
7487 gen_op('-');
7488 break;
7489 case TOK_LAND:
7490 if (!gnu_ext)
7491 goto tok_identifier;
7492 next();
7493 /* allow to take the address of a label */
7494 if (tok < TOK_UIDENT)
7495 expect("label identifier");
7496 s = label_find(tok);
7497 if (!s) {
7498 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
7499 } else {
7500 if (s->r == LABEL_DECLARED)
7501 s->r = LABEL_FORWARD;
7503 if (!s->type.t) {
7504 s->type.t = VT_VOID;
7505 mk_pointer(&s->type);
7506 s->type.t |= VT_STATIC;
7508 vset(&s->type, VT_CONST | VT_SYM, 0);
7509 vtop->sym = s;
7510 next();
7511 break;
7512 default:
7513 tok_identifier:
7514 t = tok;
7515 next();
7516 if (t < TOK_UIDENT)
7517 expect("identifier");
7518 s = sym_find(t);
7519 if (!s) {
7520 if (tok != '(')
7521 error("'%s' undeclared", get_tok_str(t, NULL));
7522 /* for simple function calls, we tolerate undeclared
7523 external reference to int() function */
7524 if (tcc_state->warn_implicit_function_declaration)
7525 warning("implicit declaration of function '%s'",
7526 get_tok_str(t, NULL));
7527 s = external_global_sym(t, &func_old_type, 0);
7529 if ((s->type.t & (VT_STATIC | VT_INLINE | VT_BTYPE)) ==
7530 (VT_STATIC | VT_INLINE | VT_FUNC)) {
7531 /* if referencing an inline function, then we generate a
7532 symbol to it if not already done. It will have the
7533 effect to generate code for it at the end of the
7534 compilation unit. Inline function as always
7535 generated in the text section. */
7536 if (!s->c)
7537 put_extern_sym(s, text_section, 0, 0);
7538 r = VT_SYM | VT_CONST;
7539 } else {
7540 r = s->r;
7542 vset(&s->type, r, s->c);
7543 /* if forward reference, we must point to s */
7544 if (vtop->r & VT_SYM) {
7545 vtop->sym = s;
7546 vtop->c.ul = 0;
7548 break;
7551 /* post operations */
7552 while (1) {
7553 if (tok == TOK_INC || tok == TOK_DEC) {
7554 inc(1, tok);
7555 next();
7556 } else if (tok == '.' || tok == TOK_ARROW) {
7557 /* field */
7558 if (tok == TOK_ARROW)
7559 indir();
7560 test_lvalue();
7561 gaddrof();
7562 next();
7563 /* expect pointer on structure */
7564 if ((vtop->type.t & VT_BTYPE) != VT_STRUCT)
7565 expect("struct or union");
7566 s = vtop->type.ref;
7567 /* find field */
7568 tok |= SYM_FIELD;
7569 while ((s = s->next) != NULL) {
7570 if (s->v == tok)
7571 break;
7573 if (!s)
7574 error("field not found");
7575 /* add field offset to pointer */
7576 vtop->type = char_pointer_type; /* change type to 'char *' */
7577 vpushi(s->c);
7578 gen_op('+');
7579 /* change type to field type, and set to lvalue */
7580 vtop->type = s->type;
7581 /* an array is never an lvalue */
7582 if (!(vtop->type.t & VT_ARRAY)) {
7583 vtop->r |= lvalue_type(vtop->type.t);
7584 /* if bound checking, the referenced pointer must be checked */
7585 if (do_bounds_check)
7586 vtop->r |= VT_MUSTBOUND;
7588 next();
7589 } else if (tok == '[') {
7590 next();
7591 gexpr();
7592 gen_op('+');
7593 indir();
7594 skip(']');
7595 } else if (tok == '(') {
7596 SValue ret;
7597 Sym *sa;
7598 int nb_args;
7600 /* function call */
7601 if ((vtop->type.t & VT_BTYPE) != VT_FUNC) {
7602 /* pointer test (no array accepted) */
7603 if ((vtop->type.t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
7604 vtop->type = *pointed_type(&vtop->type);
7605 if ((vtop->type.t & VT_BTYPE) != VT_FUNC)
7606 goto error_func;
7607 } else {
7608 error_func:
7609 expect("function pointer");
7611 } else {
7612 vtop->r &= ~VT_LVAL; /* no lvalue */
7614 /* get return type */
7615 s = vtop->type.ref;
7616 next();
7617 sa = s->next; /* first parameter */
7618 nb_args = 0;
7619 /* compute first implicit argument if a structure is returned */
7620 if ((s->type.t & VT_BTYPE) == VT_STRUCT) {
7621 /* get some space for the returned structure */
7622 size = type_size(&s->type, &align);
7623 loc = (loc - size) & -align;
7624 ret.type = s->type;
7625 ret.r = VT_LOCAL | VT_LVAL;
7626 /* pass it as 'int' to avoid structure arg passing
7627 problems */
7628 vseti(VT_LOCAL, loc);
7629 ret.c = vtop->c;
7630 nb_args++;
7631 } else {
7632 ret.type = s->type;
7633 ret.r2 = VT_CONST;
7634 /* return in register */
7635 if (is_float(ret.type.t)) {
7636 ret.r = REG_FRET;
7637 } else {
7638 if ((ret.type.t & VT_BTYPE) == VT_LLONG)
7639 ret.r2 = REG_LRET;
7640 ret.r = REG_IRET;
7642 ret.c.i = 0;
7644 if (tok != ')') {
7645 for(;;) {
7646 expr_eq();
7647 gfunc_param_typed(s, sa);
7648 nb_args++;
7649 if (sa)
7650 sa = sa->next;
7651 if (tok == ')')
7652 break;
7653 skip(',');
7656 if (sa)
7657 error("too few arguments to function");
7658 skip(')');
7659 if (!nocode_wanted) {
7660 gfunc_call(nb_args);
7661 } else {
7662 vtop -= (nb_args + 1);
7664 /* return value */
7665 vsetc(&ret.type, ret.r, &ret.c);
7666 vtop->r2 = ret.r2;
7667 } else {
7668 break;
7673 static void uneq(void)
7675 int t;
7677 unary();
7678 if (tok == '=' ||
7679 (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
7680 tok == TOK_A_XOR || tok == TOK_A_OR ||
7681 tok == TOK_A_SHL || tok == TOK_A_SAR) {
7682 test_lvalue();
7683 t = tok;
7684 next();
7685 if (t == '=') {
7686 expr_eq();
7687 } else {
7688 vdup();
7689 expr_eq();
7690 gen_op(t & 0x7f);
7692 vstore();
7696 static void expr_prod(void)
7698 int t;
7700 uneq();
7701 while (tok == '*' || tok == '/' || tok == '%') {
7702 t = tok;
7703 next();
7704 uneq();
7705 gen_op(t);
7709 static void expr_sum(void)
7711 int t;
7713 expr_prod();
7714 while (tok == '+' || tok == '-') {
7715 t = tok;
7716 next();
7717 expr_prod();
7718 gen_op(t);
7722 static void expr_shift(void)
7724 int t;
7726 expr_sum();
7727 while (tok == TOK_SHL || tok == TOK_SAR) {
7728 t = tok;
7729 next();
7730 expr_sum();
7731 gen_op(t);
7735 static void expr_cmp(void)
7737 int t;
7739 expr_shift();
7740 while ((tok >= TOK_ULE && tok <= TOK_GT) ||
7741 tok == TOK_ULT || tok == TOK_UGE) {
7742 t = tok;
7743 next();
7744 expr_shift();
7745 gen_op(t);
7749 static void expr_cmpeq(void)
7751 int t;
7753 expr_cmp();
7754 while (tok == TOK_EQ || tok == TOK_NE) {
7755 t = tok;
7756 next();
7757 expr_cmp();
7758 gen_op(t);
7762 static void expr_and(void)
7764 expr_cmpeq();
7765 while (tok == '&') {
7766 next();
7767 expr_cmpeq();
7768 gen_op('&');
7772 static void expr_xor(void)
7774 expr_and();
7775 while (tok == '^') {
7776 next();
7777 expr_and();
7778 gen_op('^');
7782 static void expr_or(void)
7784 expr_xor();
7785 while (tok == '|') {
7786 next();
7787 expr_xor();
7788 gen_op('|');
7792 /* XXX: fix this mess */
7793 static void expr_land_const(void)
7795 expr_or();
7796 while (tok == TOK_LAND) {
7797 next();
7798 expr_or();
7799 gen_op(TOK_LAND);
7803 /* XXX: fix this mess */
7804 static void expr_lor_const(void)
7806 expr_land_const();
7807 while (tok == TOK_LOR) {
7808 next();
7809 expr_land_const();
7810 gen_op(TOK_LOR);
7814 /* only used if non constant */
7815 static void expr_land(void)
7817 int t;
7819 expr_or();
7820 if (tok == TOK_LAND) {
7821 t = 0;
7822 save_regs(1);
7823 for(;;) {
7824 t = gtst(1, t);
7825 if (tok != TOK_LAND) {
7826 vseti(VT_JMPI, t);
7827 break;
7829 next();
7830 expr_or();
7835 static void expr_lor(void)
7837 int t;
7839 expr_land();
7840 if (tok == TOK_LOR) {
7841 t = 0;
7842 save_regs(1);
7843 for(;;) {
7844 t = gtst(0, t);
7845 if (tok != TOK_LOR) {
7846 vseti(VT_JMP, t);
7847 break;
7849 next();
7850 expr_land();
7855 /* XXX: better constant handling */
7856 static void expr_eq(void)
7858 int tt, u, r1, r2, rc, t1, t2, bt1, bt2;
7859 SValue sv;
7860 CType type, type1, type2;
7862 if (const_wanted) {
7863 int c1, c;
7864 expr_lor_const();
7865 if (tok == '?') {
7866 c = vtop->c.i;
7867 vpop();
7868 next();
7869 if (tok == ':' && gnu_ext) {
7870 c1 = c;
7871 } else {
7872 gexpr();
7873 c1 = vtop->c.i;
7874 vpop();
7876 skip(':');
7877 expr_eq();
7878 if (c)
7879 vtop->c.i = c1;
7881 } else {
7882 expr_lor();
7883 if (tok == '?') {
7884 next();
7885 if (vtop != vstack) {
7886 /* needed to avoid having different registers saved in
7887 each branch */
7888 if (is_float(vtop->type.t))
7889 rc = RC_FLOAT;
7890 else
7891 rc = RC_INT;
7892 gv(rc);
7893 save_regs(1);
7895 if (tok == ':' && gnu_ext) {
7896 gv_dup();
7897 tt = gtst(1, 0);
7898 } else {
7899 tt = gtst(1, 0);
7900 gexpr();
7902 type1 = vtop->type;
7903 sv = *vtop; /* save value to handle it later */
7904 vtop--; /* no vpop so that FP stack is not flushed */
7905 skip(':');
7906 u = gjmp(0);
7907 gsym(tt);
7908 expr_eq();
7909 type2 = vtop->type;
7911 t1 = type1.t;
7912 bt1 = t1 & VT_BTYPE;
7913 t2 = type2.t;
7914 bt2 = t2 & VT_BTYPE;
7915 /* cast operands to correct type according to ISOC rules */
7916 if (is_float(bt1) || is_float(bt2)) {
7917 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
7918 type.t = VT_LDOUBLE;
7919 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
7920 type.t = VT_DOUBLE;
7921 } else {
7922 type.t = VT_FLOAT;
7924 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
7925 /* cast to biggest op */
7926 type.t = VT_LLONG;
7927 /* convert to unsigned if it does not fit in a long long */
7928 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
7929 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
7930 type.t |= VT_UNSIGNED;
7931 } else if (bt1 == VT_PTR || bt2 == VT_PTR) {
7932 /* XXX: test pointer compatibility */
7933 type = type1;
7934 } else if (bt1 == VT_FUNC || bt2 == VT_FUNC) {
7935 /* XXX: test function pointer compatibility */
7936 type = type1;
7937 } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
7938 /* XXX: test structure compatibility */
7939 type = type1;
7940 } else if (bt1 == VT_VOID || bt2 == VT_VOID) {
7941 /* NOTE: as an extension, we accept void on only one side */
7942 type.t = VT_VOID;
7943 } else {
7944 /* integer operations */
7945 type.t = VT_INT;
7946 /* convert to unsigned if it does not fit in an integer */
7947 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
7948 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
7949 type.t |= VT_UNSIGNED;
7952 /* now we convert second operand */
7953 gen_cast(&type);
7954 if (VT_STRUCT == (vtop->type.t & VT_BTYPE))
7955 gaddrof();
7956 rc = RC_INT;
7957 if (is_float(type.t)) {
7958 rc = RC_FLOAT;
7959 } else if ((type.t & VT_BTYPE) == VT_LLONG) {
7960 /* for long longs, we use fixed registers to avoid having
7961 to handle a complicated move */
7962 rc = RC_IRET;
7965 r2 = gv(rc);
7966 /* this is horrible, but we must also convert first
7967 operand */
7968 tt = gjmp(0);
7969 gsym(u);
7970 /* put again first value and cast it */
7971 *vtop = sv;
7972 gen_cast(&type);
7973 if (VT_STRUCT == (vtop->type.t & VT_BTYPE))
7974 gaddrof();
7975 r1 = gv(rc);
7976 move_reg(r2, r1);
7977 vtop->r = r2;
7978 gsym(tt);
7983 static void gexpr(void)
7985 while (1) {
7986 expr_eq();
7987 if (tok != ',')
7988 break;
7989 vpop();
7990 next();
7994 /* parse an expression and return its type without any side effect. */
7995 static void expr_type(CType *type)
7997 int saved_nocode_wanted;
7999 saved_nocode_wanted = nocode_wanted;
8000 nocode_wanted = 1;
8001 gexpr();
8002 *type = vtop->type;
8003 vpop();
8004 nocode_wanted = saved_nocode_wanted;
8007 /* parse a unary expression and return its type without any side
8008 effect. */
8009 static void unary_type(CType *type)
8011 int a;
8013 a = nocode_wanted;
8014 nocode_wanted = 1;
8015 unary();
8016 *type = vtop->type;
8017 vpop();
8018 nocode_wanted = a;
8021 /* parse a constant expression and return value in vtop. */
8022 static void expr_const1(void)
8024 int a;
8025 a = const_wanted;
8026 const_wanted = 1;
8027 expr_eq();
8028 const_wanted = a;
8031 /* parse an integer constant and return its value. */
8032 static int expr_const(void)
8034 int c;
8035 expr_const1();
8036 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
8037 expect("constant expression");
8038 c = vtop->c.i;
8039 vpop();
8040 return c;
8043 /* return the label token if current token is a label, otherwise
8044 return zero */
8045 static int is_label(void)
8047 int last_tok;
8049 /* fast test first */
8050 if (tok < TOK_UIDENT)
8051 return 0;
8052 /* no need to save tokc because tok is an identifier */
8053 last_tok = tok;
8054 next();
8055 if (tok == ':') {
8056 next();
8057 return last_tok;
8058 } else {
8059 unget_tok(last_tok);
8060 return 0;
8064 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
8065 int case_reg, int is_expr)
8067 int a, b, c, d;
8068 Sym *s;
8070 /* generate line number info */
8071 if (do_debug &&
8072 (last_line_num != file->line_num || last_ind != ind)) {
8073 put_stabn(N_SLINE, 0, file->line_num, ind - func_ind);
8074 last_ind = ind;
8075 last_line_num = file->line_num;
8078 if (is_expr) {
8079 /* default return value is (void) */
8080 vpushi(0);
8081 vtop->type.t = VT_VOID;
8084 if (tok == TOK_IF) {
8085 /* if test */
8086 next();
8087 skip('(');
8088 gexpr();
8089 skip(')');
8090 a = gtst(1, 0);
8091 block(bsym, csym, case_sym, def_sym, case_reg, 0);
8092 c = tok;
8093 if (c == TOK_ELSE) {
8094 next();
8095 d = gjmp(0);
8096 gsym(a);
8097 block(bsym, csym, case_sym, def_sym, case_reg, 0);
8098 gsym(d); /* patch else jmp */
8099 } else
8100 gsym(a);
8101 } else if (tok == TOK_WHILE) {
8102 next();
8103 d = ind;
8104 skip('(');
8105 gexpr();
8106 skip(')');
8107 a = gtst(1, 0);
8108 b = 0;
8109 block(&a, &b, case_sym, def_sym, case_reg, 0);
8110 gjmp_addr(d);
8111 gsym(a);
8112 gsym_addr(b, d);
8113 } else if (tok == '{') {
8114 Sym *llabel;
8116 next();
8117 /* record local declaration stack position */
8118 s = local_stack;
8119 llabel = local_label_stack;
8120 /* handle local labels declarations */
8121 if (tok == TOK_LABEL) {
8122 next();
8123 for(;;) {
8124 if (tok < TOK_UIDENT)
8125 expect("label identifier");
8126 label_push(&local_label_stack, tok, LABEL_DECLARED);
8127 next();
8128 if (tok == ',') {
8129 next();
8130 } else {
8131 skip(';');
8132 break;
8136 while (tok != '}') {
8137 decl(VT_LOCAL);
8138 if (tok != '}') {
8139 if (is_expr)
8140 vpop();
8141 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
8144 /* pop locally defined labels */
8145 label_pop(&local_label_stack, llabel);
8146 /* pop locally defined symbols */
8147 sym_pop(&local_stack, s);
8148 next();
8149 } else if (tok == TOK_RETURN) {
8150 next();
8151 if (tok != ';') {
8152 gexpr();
8153 gen_assign_cast(&func_vt);
8154 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
8155 CType type;
8156 /* if returning structure, must copy it to implicit
8157 first pointer arg location */
8158 #ifdef TCC_ARM_EABI
8159 int align, size;
8160 size = type_size(&func_vt,&align);
8161 if(size <= 4)
8163 if((vtop->r != (VT_LOCAL | VT_LVAL) || (vtop->c.i & 3))
8164 && (align & 3))
8166 int addr;
8167 loc = (loc - size) & -4;
8168 addr = loc;
8169 type = func_vt;
8170 vset(&type, VT_LOCAL | VT_LVAL, addr);
8171 vswap();
8172 vstore();
8173 vset(&int_type, VT_LOCAL | VT_LVAL, addr);
8175 vtop->type = int_type;
8176 gv(RC_IRET);
8177 } else {
8178 #endif
8179 type = func_vt;
8180 mk_pointer(&type);
8181 vset(&type, VT_LOCAL | VT_LVAL, func_vc);
8182 indir();
8183 vswap();
8184 /* copy structure value to pointer */
8185 vstore();
8186 #ifdef TCC_ARM_EABI
8188 #endif
8189 } else if (is_float(func_vt.t)) {
8190 gv(RC_FRET);
8191 } else {
8192 gv(RC_IRET);
8194 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
8196 skip(';');
8197 rsym = gjmp(rsym); /* jmp */
8198 } else if (tok == TOK_BREAK) {
8199 /* compute jump */
8200 if (!bsym)
8201 error("cannot break");
8202 *bsym = gjmp(*bsym);
8203 next();
8204 skip(';');
8205 } else if (tok == TOK_CONTINUE) {
8206 /* compute jump */
8207 if (!csym)
8208 error("cannot continue");
8209 *csym = gjmp(*csym);
8210 next();
8211 skip(';');
8212 } else if (tok == TOK_FOR) {
8213 int e;
8214 next();
8215 skip('(');
8216 if (tok != ';') {
8217 gexpr();
8218 vpop();
8220 skip(';');
8221 d = ind;
8222 c = ind;
8223 a = 0;
8224 b = 0;
8225 if (tok != ';') {
8226 gexpr();
8227 a = gtst(1, 0);
8229 skip(';');
8230 if (tok != ')') {
8231 e = gjmp(0);
8232 c = ind;
8233 gexpr();
8234 vpop();
8235 gjmp_addr(d);
8236 gsym(e);
8238 skip(')');
8239 block(&a, &b, case_sym, def_sym, case_reg, 0);
8240 gjmp_addr(c);
8241 gsym(a);
8242 gsym_addr(b, c);
8243 } else
8244 if (tok == TOK_DO) {
8245 next();
8246 a = 0;
8247 b = 0;
8248 d = ind;
8249 block(&a, &b, case_sym, def_sym, case_reg, 0);
8250 skip(TOK_WHILE);
8251 skip('(');
8252 gsym(b);
8253 gexpr();
8254 c = gtst(0, 0);
8255 gsym_addr(c, d);
8256 skip(')');
8257 gsym(a);
8258 skip(';');
8259 } else
8260 if (tok == TOK_SWITCH) {
8261 next();
8262 skip('(');
8263 gexpr();
8264 /* XXX: other types than integer */
8265 case_reg = gv(RC_INT);
8266 vpop();
8267 skip(')');
8268 a = 0;
8269 b = gjmp(0); /* jump to first case */
8270 c = 0;
8271 block(&a, csym, &b, &c, case_reg, 0);
8272 /* if no default, jmp after switch */
8273 if (c == 0)
8274 c = ind;
8275 /* default label */
8276 gsym_addr(b, c);
8277 /* break label */
8278 gsym(a);
8279 } else
8280 if (tok == TOK_CASE) {
8281 int v1, v2;
8282 if (!case_sym)
8283 expect("switch");
8284 next();
8285 v1 = expr_const();
8286 v2 = v1;
8287 if (gnu_ext && tok == TOK_DOTS) {
8288 next();
8289 v2 = expr_const();
8290 if (v2 < v1)
8291 warning("empty case range");
8293 /* since a case is like a label, we must skip it with a jmp */
8294 b = gjmp(0);
8295 gsym(*case_sym);
8296 vseti(case_reg, 0);
8297 vpushi(v1);
8298 if (v1 == v2) {
8299 gen_op(TOK_EQ);
8300 *case_sym = gtst(1, 0);
8301 } else {
8302 gen_op(TOK_GE);
8303 *case_sym = gtst(1, 0);
8304 vseti(case_reg, 0);
8305 vpushi(v2);
8306 gen_op(TOK_LE);
8307 *case_sym = gtst(1, *case_sym);
8309 gsym(b);
8310 skip(':');
8311 is_expr = 0;
8312 goto block_after_label;
8313 } else
8314 if (tok == TOK_DEFAULT) {
8315 next();
8316 skip(':');
8317 if (!def_sym)
8318 expect("switch");
8319 if (*def_sym)
8320 error("too many 'default'");
8321 *def_sym = ind;
8322 is_expr = 0;
8323 goto block_after_label;
8324 } else
8325 if (tok == TOK_GOTO) {
8326 next();
8327 if (tok == '*' && gnu_ext) {
8328 /* computed goto */
8329 next();
8330 gexpr();
8331 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
8332 expect("pointer");
8333 ggoto();
8334 } else if (tok >= TOK_UIDENT) {
8335 s = label_find(tok);
8336 /* put forward definition if needed */
8337 if (!s) {
8338 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
8339 } else {
8340 if (s->r == LABEL_DECLARED)
8341 s->r = LABEL_FORWARD;
8343 /* label already defined */
8344 if (s->r & LABEL_FORWARD)
8345 s->next = (void *)gjmp((long)s->next);
8346 else
8347 gjmp_addr((long)s->next);
8348 next();
8349 } else {
8350 expect("label identifier");
8352 skip(';');
8353 } else if (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3) {
8354 asm_instr();
8355 } else {
8356 b = is_label();
8357 if (b) {
8358 /* label case */
8359 s = label_find(b);
8360 if (s) {
8361 if (s->r == LABEL_DEFINED)
8362 error("duplicate label '%s'", get_tok_str(s->v, NULL));
8363 gsym((long)s->next);
8364 s->r = LABEL_DEFINED;
8365 } else {
8366 s = label_push(&global_label_stack, b, LABEL_DEFINED);
8368 s->next = (void *)ind;
8369 /* we accept this, but it is a mistake */
8370 block_after_label:
8371 if (tok == '}') {
8372 warning("deprecated use of label at end of compound statement");
8373 } else {
8374 if (is_expr)
8375 vpop();
8376 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
8378 } else {
8379 /* expression case */
8380 if (tok != ';') {
8381 if (is_expr) {
8382 vpop();
8383 gexpr();
8384 } else {
8385 gexpr();
8386 vpop();
8389 skip(';');
8394 /* t is the array or struct type. c is the array or struct
8395 address. cur_index/cur_field is the pointer to the current
8396 value. 'size_only' is true if only size info is needed (only used
8397 in arrays) */
8398 static void decl_designator(CType *type, Section *sec, unsigned long c,
8399 int *cur_index, Sym **cur_field,
8400 int size_only)
8402 Sym *s, *f;
8403 int notfirst, index, index_last, align, l, nb_elems, elem_size;
8404 CType type1;
8406 notfirst = 0;
8407 elem_size = 0;
8408 nb_elems = 1;
8409 if (gnu_ext && (l = is_label()) != 0)
8410 goto struct_field;
8411 while (tok == '[' || tok == '.') {
8412 if (tok == '[') {
8413 if (!(type->t & VT_ARRAY))
8414 expect("array type");
8415 s = type->ref;
8416 next();
8417 index = expr_const();
8418 if (index < 0 || (s->c >= 0 && index >= s->c))
8419 expect("invalid index");
8420 if (tok == TOK_DOTS && gnu_ext) {
8421 next();
8422 index_last = expr_const();
8423 if (index_last < 0 ||
8424 (s->c >= 0 && index_last >= s->c) ||
8425 index_last < index)
8426 expect("invalid index");
8427 } else {
8428 index_last = index;
8430 skip(']');
8431 if (!notfirst)
8432 *cur_index = index_last;
8433 type = pointed_type(type);
8434 elem_size = type_size(type, &align);
8435 c += index * elem_size;
8436 /* NOTE: we only support ranges for last designator */
8437 nb_elems = index_last - index + 1;
8438 if (nb_elems != 1) {
8439 notfirst = 1;
8440 break;
8442 } else {
8443 next();
8444 l = tok;
8445 next();
8446 struct_field:
8447 if ((type->t & VT_BTYPE) != VT_STRUCT)
8448 expect("struct/union type");
8449 s = type->ref;
8450 l |= SYM_FIELD;
8451 f = s->next;
8452 while (f) {
8453 if (f->v == l)
8454 break;
8455 f = f->next;
8457 if (!f)
8458 expect("field");
8459 if (!notfirst)
8460 *cur_field = f;
8461 /* XXX: fix this mess by using explicit storage field */
8462 type1 = f->type;
8463 type1.t |= (type->t & ~VT_TYPE);
8464 type = &type1;
8465 c += f->c;
8467 notfirst = 1;
8469 if (notfirst) {
8470 if (tok == '=') {
8471 next();
8472 } else {
8473 if (!gnu_ext)
8474 expect("=");
8476 } else {
8477 if (type->t & VT_ARRAY) {
8478 index = *cur_index;
8479 type = pointed_type(type);
8480 c += index * type_size(type, &align);
8481 } else {
8482 f = *cur_field;
8483 if (!f)
8484 error("too many field init");
8485 /* XXX: fix this mess by using explicit storage field */
8486 type1 = f->type;
8487 type1.t |= (type->t & ~VT_TYPE);
8488 type = &type1;
8489 c += f->c;
8492 decl_initializer(type, sec, c, 0, size_only);
8494 /* XXX: make it more general */
8495 if (!size_only && nb_elems > 1) {
8496 unsigned long c_end;
8497 uint8_t *src, *dst;
8498 int i;
8500 if (!sec)
8501 error("range init not supported yet for dynamic storage");
8502 c_end = c + nb_elems * elem_size;
8503 if (c_end > sec->data_allocated)
8504 section_realloc(sec, c_end);
8505 src = sec->data + c;
8506 dst = src;
8507 for(i = 1; i < nb_elems; i++) {
8508 dst += elem_size;
8509 memcpy(dst, src, elem_size);
8514 #define EXPR_VAL 0
8515 #define EXPR_CONST 1
8516 #define EXPR_ANY 2
8518 /* store a value or an expression directly in global data or in local array */
8519 static void init_putv(CType *type, Section *sec, unsigned long c,
8520 int v, int expr_type)
8522 int saved_global_expr, bt, bit_pos, bit_size;
8523 void *ptr;
8524 unsigned long long bit_mask;
8525 CType dtype;
8527 switch(expr_type) {
8528 case EXPR_VAL:
8529 vpushi(v);
8530 break;
8531 case EXPR_CONST:
8532 /* compound literals must be allocated globally in this case */
8533 saved_global_expr = global_expr;
8534 global_expr = 1;
8535 expr_const1();
8536 global_expr = saved_global_expr;
8537 /* NOTE: symbols are accepted */
8538 if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST)
8539 error("initializer element is not constant");
8540 break;
8541 case EXPR_ANY:
8542 expr_eq();
8543 break;
8546 dtype = *type;
8547 dtype.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
8549 if (sec) {
8550 /* XXX: not portable */
8551 /* XXX: generate error if incorrect relocation */
8552 gen_assign_cast(&dtype);
8553 bt = type->t & VT_BTYPE;
8554 ptr = sec->data + c;
8555 /* XXX: make code faster ? */
8556 if (!(type->t & VT_BITFIELD)) {
8557 bit_pos = 0;
8558 bit_size = 32;
8559 bit_mask = -1LL;
8560 } else {
8561 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
8562 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
8563 bit_mask = (1LL << bit_size) - 1;
8565 if ((vtop->r & VT_SYM) &&
8566 (bt == VT_BYTE ||
8567 bt == VT_SHORT ||
8568 bt == VT_DOUBLE ||
8569 bt == VT_LDOUBLE ||
8570 bt == VT_LLONG ||
8571 (bt == VT_INT && bit_size != 32)))
8572 error("initializer element is not computable at load time");
8573 switch(bt) {
8574 case VT_BYTE:
8575 *(char *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8576 break;
8577 case VT_SHORT:
8578 *(short *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8579 break;
8580 case VT_DOUBLE:
8581 *(double *)ptr = vtop->c.d;
8582 break;
8583 case VT_LDOUBLE:
8584 *(long double *)ptr = vtop->c.ld;
8585 break;
8586 case VT_LLONG:
8587 *(long long *)ptr |= (vtop->c.ll & bit_mask) << bit_pos;
8588 break;
8589 default:
8590 if (vtop->r & VT_SYM) {
8591 greloc(sec, vtop->sym, c, R_DATA_32);
8593 *(int *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8594 break;
8596 vtop--;
8597 } else {
8598 vset(&dtype, VT_LOCAL|VT_LVAL, c);
8599 vswap();
8600 vstore();
8601 vpop();
8605 /* put zeros for variable based init */
8606 static void init_putz(CType *t, Section *sec, unsigned long c, int size)
8608 if (sec) {
8609 /* nothing to do because globals are already set to zero */
8610 } else {
8611 vpush_global_sym(&func_old_type, TOK_memset);
8612 vseti(VT_LOCAL, c);
8613 vpushi(0);
8614 vpushi(size);
8615 gfunc_call(3);
8619 /* 't' contains the type and storage info. 'c' is the offset of the
8620 object in section 'sec'. If 'sec' is NULL, it means stack based
8621 allocation. 'first' is true if array '{' must be read (multi
8622 dimension implicit array init handling). 'size_only' is true if
8623 size only evaluation is wanted (only for arrays). */
8624 static void decl_initializer(CType *type, Section *sec, unsigned long c,
8625 int first, int size_only)
8627 int index, array_length, n, no_oblock, nb, parlevel, i;
8628 int size1, align1, expr_type;
8629 Sym *s, *f;
8630 CType *t1;
8632 if (type->t & VT_ARRAY) {
8633 s = type->ref;
8634 n = s->c;
8635 array_length = 0;
8636 t1 = pointed_type(type);
8637 size1 = type_size(t1, &align1);
8639 no_oblock = 1;
8640 if ((first && tok != TOK_LSTR && tok != TOK_STR) ||
8641 tok == '{') {
8642 skip('{');
8643 no_oblock = 0;
8646 /* only parse strings here if correct type (otherwise: handle
8647 them as ((w)char *) expressions */
8648 if ((tok == TOK_LSTR &&
8649 #ifdef TCC_TARGET_PE
8650 (t1->t & VT_BTYPE) == VT_SHORT && (t1->t & VT_UNSIGNED)) ||
8651 #else
8652 (t1->t & VT_BTYPE) == VT_INT) ||
8653 #endif
8654 (tok == TOK_STR &&
8655 (t1->t & VT_BTYPE) == VT_BYTE)) {
8656 while (tok == TOK_STR || tok == TOK_LSTR) {
8657 int cstr_len, ch;
8658 CString *cstr;
8660 cstr = tokc.cstr;
8661 /* compute maximum number of chars wanted */
8662 if (tok == TOK_STR)
8663 cstr_len = cstr->size;
8664 else
8665 cstr_len = cstr->size / sizeof(nwchar_t);
8666 cstr_len--;
8667 nb = cstr_len;
8668 if (n >= 0 && nb > (n - array_length))
8669 nb = n - array_length;
8670 if (!size_only) {
8671 if (cstr_len > nb)
8672 warning("initializer-string for array is too long");
8673 /* in order to go faster for common case (char
8674 string in global variable, we handle it
8675 specifically */
8676 if (sec && tok == TOK_STR && size1 == 1) {
8677 memcpy(sec->data + c + array_length, cstr->data, nb);
8678 } else {
8679 for(i=0;i<nb;i++) {
8680 if (tok == TOK_STR)
8681 ch = ((unsigned char *)cstr->data)[i];
8682 else
8683 ch = ((nwchar_t *)cstr->data)[i];
8684 init_putv(t1, sec, c + (array_length + i) * size1,
8685 ch, EXPR_VAL);
8689 array_length += nb;
8690 next();
8692 /* only add trailing zero if enough storage (no
8693 warning in this case since it is standard) */
8694 if (n < 0 || array_length < n) {
8695 if (!size_only) {
8696 init_putv(t1, sec, c + (array_length * size1), 0, EXPR_VAL);
8698 array_length++;
8700 } else {
8701 index = 0;
8702 while (tok != '}') {
8703 decl_designator(type, sec, c, &index, NULL, size_only);
8704 if (n >= 0 && index >= n)
8705 error("index too large");
8706 /* must put zero in holes (note that doing it that way
8707 ensures that it even works with designators) */
8708 if (!size_only && array_length < index) {
8709 init_putz(t1, sec, c + array_length * size1,
8710 (index - array_length) * size1);
8712 index++;
8713 if (index > array_length)
8714 array_length = index;
8715 /* special test for multi dimensional arrays (may not
8716 be strictly correct if designators are used at the
8717 same time) */
8718 if (index >= n && no_oblock)
8719 break;
8720 if (tok == '}')
8721 break;
8722 skip(',');
8725 if (!no_oblock)
8726 skip('}');
8727 /* put zeros at the end */
8728 if (!size_only && n >= 0 && array_length < n) {
8729 init_putz(t1, sec, c + array_length * size1,
8730 (n - array_length) * size1);
8732 /* patch type size if needed */
8733 if (n < 0)
8734 s->c = array_length;
8735 } else if ((type->t & VT_BTYPE) == VT_STRUCT &&
8736 (sec || !first || tok == '{')) {
8737 int par_count;
8739 /* NOTE: the previous test is a specific case for automatic
8740 struct/union init */
8741 /* XXX: union needs only one init */
8743 /* XXX: this test is incorrect for local initializers
8744 beginning with ( without {. It would be much more difficult
8745 to do it correctly (ideally, the expression parser should
8746 be used in all cases) */
8747 par_count = 0;
8748 if (tok == '(') {
8749 AttributeDef ad1;
8750 CType type1;
8751 next();
8752 while (tok == '(') {
8753 par_count++;
8754 next();
8756 if (!parse_btype(&type1, &ad1))
8757 expect("cast");
8758 type_decl(&type1, &ad1, &n, TYPE_ABSTRACT);
8759 #if 0
8760 if (!is_assignable_types(type, &type1))
8761 error("invalid type for cast");
8762 #endif
8763 skip(')');
8765 no_oblock = 1;
8766 if (first || tok == '{') {
8767 skip('{');
8768 no_oblock = 0;
8770 s = type->ref;
8771 f = s->next;
8772 array_length = 0;
8773 index = 0;
8774 n = s->c;
8775 while (tok != '}') {
8776 decl_designator(type, sec, c, NULL, &f, size_only);
8777 index = f->c;
8778 if (!size_only && array_length < index) {
8779 init_putz(type, sec, c + array_length,
8780 index - array_length);
8782 index = index + type_size(&f->type, &align1);
8783 if (index > array_length)
8784 array_length = index;
8785 f = f->next;
8786 if (no_oblock && f == NULL)
8787 break;
8788 if (tok == '}')
8789 break;
8790 skip(',');
8792 /* put zeros at the end */
8793 if (!size_only && array_length < n) {
8794 init_putz(type, sec, c + array_length,
8795 n - array_length);
8797 if (!no_oblock)
8798 skip('}');
8799 while (par_count) {
8800 skip(')');
8801 par_count--;
8803 } else if (tok == '{') {
8804 next();
8805 decl_initializer(type, sec, c, first, size_only);
8806 skip('}');
8807 } else if (size_only) {
8808 /* just skip expression */
8809 parlevel = 0;
8810 while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
8811 tok != -1) {
8812 if (tok == '(')
8813 parlevel++;
8814 else if (tok == ')')
8815 parlevel--;
8816 next();
8818 } else {
8819 /* currently, we always use constant expression for globals
8820 (may change for scripting case) */
8821 expr_type = EXPR_CONST;
8822 if (!sec)
8823 expr_type = EXPR_ANY;
8824 init_putv(type, sec, c, 0, expr_type);
8828 /* parse an initializer for type 't' if 'has_init' is non zero, and
8829 allocate space in local or global data space ('r' is either
8830 VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
8831 variable 'v' of scope 'scope' is declared before initializers are
8832 parsed. If 'v' is zero, then a reference to the new object is put
8833 in the value stack. If 'has_init' is 2, a special parsing is done
8834 to handle string constants. */
8835 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
8836 int has_init, int v, int scope)
8838 int size, align, addr, data_offset;
8839 int level;
8840 ParseState saved_parse_state;
8841 TokenString init_str;
8842 Section *sec;
8844 size = type_size(type, &align);
8845 /* If unknown size, we must evaluate it before
8846 evaluating initializers because
8847 initializers can generate global data too
8848 (e.g. string pointers or ISOC99 compound
8849 literals). It also simplifies local
8850 initializers handling */
8851 tok_str_new(&init_str);
8852 if (size < 0) {
8853 if (!has_init)
8854 error("unknown type size");
8855 /* get all init string */
8856 if (has_init == 2) {
8857 /* only get strings */
8858 while (tok == TOK_STR || tok == TOK_LSTR) {
8859 tok_str_add_tok(&init_str);
8860 next();
8862 } else {
8863 level = 0;
8864 while (level > 0 || (tok != ',' && tok != ';')) {
8865 if (tok < 0)
8866 error("unexpected end of file in initializer");
8867 tok_str_add_tok(&init_str);
8868 if (tok == '{')
8869 level++;
8870 else if (tok == '}') {
8871 if (level == 0)
8872 break;
8873 level--;
8875 next();
8878 tok_str_add(&init_str, -1);
8879 tok_str_add(&init_str, 0);
8881 /* compute size */
8882 save_parse_state(&saved_parse_state);
8884 macro_ptr = init_str.str;
8885 next();
8886 decl_initializer(type, NULL, 0, 1, 1);
8887 /* prepare second initializer parsing */
8888 macro_ptr = init_str.str;
8889 next();
8891 /* if still unknown size, error */
8892 size = type_size(type, &align);
8893 if (size < 0)
8894 error("unknown type size");
8896 /* take into account specified alignment if bigger */
8897 if (ad->aligned) {
8898 if (ad->aligned > align)
8899 align = ad->aligned;
8900 } else if (ad->packed) {
8901 align = 1;
8903 if ((r & VT_VALMASK) == VT_LOCAL) {
8904 sec = NULL;
8905 if (do_bounds_check && (type->t & VT_ARRAY))
8906 loc--;
8907 loc = (loc - size) & -align;
8908 addr = loc;
8909 /* handles bounds */
8910 /* XXX: currently, since we do only one pass, we cannot track
8911 '&' operators, so we add only arrays */
8912 if (do_bounds_check && (type->t & VT_ARRAY)) {
8913 unsigned long *bounds_ptr;
8914 /* add padding between regions */
8915 loc--;
8916 /* then add local bound info */
8917 bounds_ptr = section_ptr_add(lbounds_section, 2 * sizeof(unsigned long));
8918 bounds_ptr[0] = addr;
8919 bounds_ptr[1] = size;
8921 if (v) {
8922 /* local variable */
8923 sym_push(v, type, r, addr);
8924 } else {
8925 /* push local reference */
8926 vset(type, r, addr);
8928 } else {
8929 Sym *sym;
8931 sym = NULL;
8932 if (v && scope == VT_CONST) {
8933 /* see if the symbol was already defined */
8934 sym = sym_find(v);
8935 if (sym) {
8936 if (!is_compatible_types(&sym->type, type))
8937 error("incompatible types for redefinition of '%s'",
8938 get_tok_str(v, NULL));
8939 if (sym->type.t & VT_EXTERN) {
8940 /* if the variable is extern, it was not allocated */
8941 sym->type.t &= ~VT_EXTERN;
8942 /* set array size if it was ommited in extern
8943 declaration */
8944 if ((sym->type.t & VT_ARRAY) &&
8945 sym->type.ref->c < 0 &&
8946 type->ref->c >= 0)
8947 sym->type.ref->c = type->ref->c;
8948 } else {
8949 /* we accept several definitions of the same
8950 global variable. this is tricky, because we
8951 must play with the SHN_COMMON type of the symbol */
8952 /* XXX: should check if the variable was already
8953 initialized. It is incorrect to initialized it
8954 twice */
8955 /* no init data, we won't add more to the symbol */
8956 if (!has_init)
8957 goto no_alloc;
8962 /* allocate symbol in corresponding section */
8963 sec = ad->section;
8964 if (!sec) {
8965 if (has_init)
8966 sec = data_section;
8967 else if (tcc_state->nocommon)
8968 sec = bss_section;
8970 if (sec) {
8971 data_offset = sec->data_offset;
8972 data_offset = (data_offset + align - 1) & -align;
8973 addr = data_offset;
8974 /* very important to increment global pointer at this time
8975 because initializers themselves can create new initializers */
8976 data_offset += size;
8977 /* add padding if bound check */
8978 if (do_bounds_check)
8979 data_offset++;
8980 sec->data_offset = data_offset;
8981 /* allocate section space to put the data */
8982 if (sec->sh_type != SHT_NOBITS &&
8983 data_offset > sec->data_allocated)
8984 section_realloc(sec, data_offset);
8985 /* align section if needed */
8986 if (align > sec->sh_addralign)
8987 sec->sh_addralign = align;
8988 } else {
8989 addr = 0; /* avoid warning */
8992 if (v) {
8993 if (scope != VT_CONST || !sym) {
8994 sym = sym_push(v, type, r | VT_SYM, 0);
8996 /* update symbol definition */
8997 if (sec) {
8998 put_extern_sym(sym, sec, addr, size);
8999 } else {
9000 Elf32_Sym *esym;
9001 /* put a common area */
9002 put_extern_sym(sym, NULL, align, size);
9003 /* XXX: find a nicer way */
9004 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
9005 esym->st_shndx = SHN_COMMON;
9007 } else {
9008 CValue cval;
9010 /* push global reference */
9011 sym = get_sym_ref(type, sec, addr, size);
9012 cval.ul = 0;
9013 vsetc(type, VT_CONST | VT_SYM, &cval);
9014 vtop->sym = sym;
9017 /* handles bounds now because the symbol must be defined
9018 before for the relocation */
9019 if (do_bounds_check) {
9020 unsigned long *bounds_ptr;
9022 greloc(bounds_section, sym, bounds_section->data_offset, R_DATA_32);
9023 /* then add global bound info */
9024 bounds_ptr = section_ptr_add(bounds_section, 2 * sizeof(long));
9025 bounds_ptr[0] = 0; /* relocated */
9026 bounds_ptr[1] = size;
9029 if (has_init) {
9030 decl_initializer(type, sec, addr, 1, 0);
9031 /* restore parse state if needed */
9032 if (init_str.str) {
9033 tok_str_free(init_str.str);
9034 restore_parse_state(&saved_parse_state);
9037 no_alloc: ;
9040 void put_func_debug(Sym *sym)
9042 char buf[512];
9044 /* stabs info */
9045 /* XXX: we put here a dummy type */
9046 snprintf(buf, sizeof(buf), "%s:%c1",
9047 funcname, sym->type.t & VT_STATIC ? 'f' : 'F');
9048 put_stabs_r(buf, N_FUN, 0, file->line_num, 0,
9049 cur_text_section, sym->c);
9050 last_ind = 0;
9051 last_line_num = 0;
9054 /* parse an old style function declaration list */
9055 /* XXX: check multiple parameter */
9056 static void func_decl_list(Sym *func_sym)
9058 AttributeDef ad;
9059 int v;
9060 Sym *s;
9061 CType btype, type;
9063 /* parse each declaration */
9064 while (tok != '{' && tok != ';' && tok != ',' && tok != TOK_EOF) {
9065 if (!parse_btype(&btype, &ad))
9066 expect("declaration list");
9067 if (((btype.t & VT_BTYPE) == VT_ENUM ||
9068 (btype.t & VT_BTYPE) == VT_STRUCT) &&
9069 tok == ';') {
9070 /* we accept no variable after */
9071 } else {
9072 for(;;) {
9073 type = btype;
9074 type_decl(&type, &ad, &v, TYPE_DIRECT);
9075 /* find parameter in function parameter list */
9076 s = func_sym->next;
9077 while (s != NULL) {
9078 if ((s->v & ~SYM_FIELD) == v)
9079 goto found;
9080 s = s->next;
9082 error("declaration for parameter '%s' but no such parameter",
9083 get_tok_str(v, NULL));
9084 found:
9085 /* check that no storage specifier except 'register' was given */
9086 if (type.t & VT_STORAGE)
9087 error("storage class specified for '%s'", get_tok_str(v, NULL));
9088 convert_parameter_type(&type);
9089 /* we can add the type (NOTE: it could be local to the function) */
9090 s->type = type;
9091 /* accept other parameters */
9092 if (tok == ',')
9093 next();
9094 else
9095 break;
9098 skip(';');
9102 /* parse a function defined by symbol 'sym' and generate its code in
9103 'cur_text_section' */
9104 static void gen_function(Sym *sym)
9106 int saved_nocode_wanted = nocode_wanted;
9107 nocode_wanted = 0;
9108 ind = cur_text_section->data_offset;
9109 /* NOTE: we patch the symbol size later */
9110 put_extern_sym(sym, cur_text_section, ind, 0);
9111 funcname = get_tok_str(sym->v, NULL);
9112 func_ind = ind;
9113 /* put debug symbol */
9114 if (do_debug)
9115 put_func_debug(sym);
9116 /* push a dummy symbol to enable local sym storage */
9117 sym_push2(&local_stack, SYM_FIELD, 0, 0);
9118 gfunc_prolog(&sym->type);
9119 rsym = 0;
9120 block(NULL, NULL, NULL, NULL, 0, 0);
9121 gsym(rsym);
9122 gfunc_epilog();
9123 cur_text_section->data_offset = ind;
9124 label_pop(&global_label_stack, NULL);
9125 sym_pop(&local_stack, NULL); /* reset local stack */
9126 /* end of function */
9127 /* patch symbol size */
9128 ((Elf32_Sym *)symtab_section->data)[sym->c].st_size =
9129 ind - func_ind;
9130 if (do_debug) {
9131 put_stabn(N_FUN, 0, 0, ind - func_ind);
9133 funcname = ""; /* for safety */
9134 func_vt.t = VT_VOID; /* for safety */
9135 ind = 0; /* for safety */
9136 nocode_wanted = saved_nocode_wanted;
9139 static void gen_inline_functions(void)
9141 Sym *sym;
9142 CType *type;
9143 int *str, inline_generated;
9145 /* iterate while inline function are referenced */
9146 for(;;) {
9147 inline_generated = 0;
9148 for(sym = global_stack; sym != NULL; sym = sym->prev) {
9149 type = &sym->type;
9150 if (((type->t & VT_BTYPE) == VT_FUNC) &&
9151 (type->t & (VT_STATIC | VT_INLINE)) ==
9152 (VT_STATIC | VT_INLINE) &&
9153 sym->c != 0) {
9154 /* the function was used: generate its code and
9155 convert it to a normal function */
9156 str = (int *)sym->r;
9157 sym->r = VT_SYM | VT_CONST;
9158 type->t &= ~VT_INLINE;
9160 macro_ptr = str;
9161 next();
9162 cur_text_section = text_section;
9163 gen_function(sym);
9164 macro_ptr = NULL; /* fail safe */
9166 tok_str_free(str);
9167 inline_generated = 1;
9170 if (!inline_generated)
9171 break;
9174 /* free all remaining inline function tokens */
9175 for(sym = global_stack; sym != NULL; sym = sym->prev) {
9176 type = &sym->type;
9177 if (((type->t & VT_BTYPE) == VT_FUNC) &&
9178 (type->t & (VT_STATIC | VT_INLINE)) ==
9179 (VT_STATIC | VT_INLINE)) {
9180 str = (int *)sym->r;
9181 tok_str_free(str);
9182 sym->r = 0; /* fail safe */
9187 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
9188 static void decl(int l)
9190 int v, has_init, r;
9191 CType type, btype;
9192 Sym *sym;
9193 AttributeDef ad;
9195 while (1) {
9196 if (!parse_btype(&btype, &ad)) {
9197 /* skip redundant ';' */
9198 /* XXX: find more elegant solution */
9199 if (tok == ';') {
9200 next();
9201 continue;
9203 if (l == VT_CONST &&
9204 (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3)) {
9205 /* global asm block */
9206 asm_global_instr();
9207 continue;
9209 /* special test for old K&R protos without explicit int
9210 type. Only accepted when defining global data */
9211 if (l == VT_LOCAL || tok < TOK_DEFINE)
9212 break;
9213 btype.t = VT_INT;
9215 if (((btype.t & VT_BTYPE) == VT_ENUM ||
9216 (btype.t & VT_BTYPE) == VT_STRUCT) &&
9217 tok == ';') {
9218 /* we accept no variable after */
9219 next();
9220 continue;
9222 while (1) { /* iterate thru each declaration */
9223 type = btype;
9224 type_decl(&type, &ad, &v, TYPE_DIRECT);
9225 #if 0
9227 char buf[500];
9228 type_to_str(buf, sizeof(buf), &type, get_tok_str(v, NULL));
9229 printf("type = '%s'\n", buf);
9231 #endif
9232 if ((type.t & VT_BTYPE) == VT_FUNC) {
9233 /* if old style function prototype, we accept a
9234 declaration list */
9235 sym = type.ref;
9236 if (sym->c == FUNC_OLD)
9237 func_decl_list(sym);
9240 if (tok == '{') {
9241 if (l == VT_LOCAL)
9242 error("cannot use local functions");
9243 if ((type.t & VT_BTYPE) != VT_FUNC)
9244 expect("function definition");
9246 /* reject abstract declarators in function definition */
9247 sym = type.ref;
9248 while ((sym = sym->next) != NULL)
9249 if (!(sym->v & ~SYM_FIELD))
9250 expect("identifier");
9252 /* XXX: cannot do better now: convert extern line to static inline */
9253 if ((type.t & (VT_EXTERN | VT_INLINE)) == (VT_EXTERN | VT_INLINE))
9254 type.t = (type.t & ~VT_EXTERN) | VT_STATIC;
9256 sym = sym_find(v);
9257 if (sym) {
9258 if ((sym->type.t & VT_BTYPE) != VT_FUNC)
9259 goto func_error1;
9260 /* specific case: if not func_call defined, we put
9261 the one of the prototype */
9262 /* XXX: should have default value */
9263 if (sym->type.ref->r != FUNC_CDECL &&
9264 type.ref->r == FUNC_CDECL)
9265 type.ref->r = sym->type.ref->r;
9266 if (!is_compatible_types(&sym->type, &type)) {
9267 func_error1:
9268 error("incompatible types for redefinition of '%s'",
9269 get_tok_str(v, NULL));
9271 /* if symbol is already defined, then put complete type */
9272 sym->type = type;
9273 } else {
9274 /* put function symbol */
9275 sym = global_identifier_push(v, type.t, 0);
9276 sym->type.ref = type.ref;
9279 /* static inline functions are just recorded as a kind
9280 of macro. Their code will be emitted at the end of
9281 the compilation unit only if they are used */
9282 if ((type.t & (VT_INLINE | VT_STATIC)) ==
9283 (VT_INLINE | VT_STATIC)) {
9284 TokenString func_str;
9285 int block_level;
9287 tok_str_new(&func_str);
9289 block_level = 0;
9290 for(;;) {
9291 int t;
9292 if (tok == TOK_EOF)
9293 error("unexpected end of file");
9294 tok_str_add_tok(&func_str);
9295 t = tok;
9296 next();
9297 if (t == '{') {
9298 block_level++;
9299 } else if (t == '}') {
9300 block_level--;
9301 if (block_level == 0)
9302 break;
9305 tok_str_add(&func_str, -1);
9306 tok_str_add(&func_str, 0);
9307 sym->r = (int)func_str.str;
9308 } else {
9309 /* compute text section */
9310 cur_text_section = ad.section;
9311 if (!cur_text_section)
9312 cur_text_section = text_section;
9313 sym->r = VT_SYM | VT_CONST;
9314 gen_function(sym);
9315 #ifdef TCC_TARGET_PE
9316 if (ad.dllexport) {
9317 ((Elf32_Sym *)symtab_section->data)[sym->c].st_other |= 1;
9319 #endif
9321 break;
9322 } else {
9323 if (btype.t & VT_TYPEDEF) {
9324 /* save typedefed type */
9325 /* XXX: test storage specifiers ? */
9326 sym = sym_push(v, &type, 0, 0);
9327 sym->type.t |= VT_TYPEDEF;
9328 } else if ((type.t & VT_BTYPE) == VT_FUNC) {
9329 /* external function definition */
9330 /* specific case for func_call attribute */
9331 if (ad.func_call)
9332 type.ref->r = ad.func_call;
9333 external_sym(v, &type, 0);
9334 } else {
9335 /* not lvalue if array */
9336 r = 0;
9337 if (!(type.t & VT_ARRAY))
9338 r |= lvalue_type(type.t);
9339 has_init = (tok == '=');
9340 if ((btype.t & VT_EXTERN) ||
9341 ((type.t & VT_ARRAY) && (type.t & VT_STATIC) &&
9342 !has_init && l == VT_CONST && type.ref->c < 0)) {
9343 /* external variable */
9344 /* NOTE: as GCC, uninitialized global static
9345 arrays of null size are considered as
9346 extern */
9347 external_sym(v, &type, r);
9348 } else {
9349 type.t |= (btype.t & VT_STATIC); /* Retain "static". */
9350 if (type.t & VT_STATIC)
9351 r |= VT_CONST;
9352 else
9353 r |= l;
9354 if (has_init)
9355 next();
9356 decl_initializer_alloc(&type, &ad, r,
9357 has_init, v, l);
9360 if (tok != ',') {
9361 skip(';');
9362 break;
9364 next();
9370 /* better than nothing, but needs extension to handle '-E' option
9371 correctly too */
9372 static void preprocess_init(TCCState *s1)
9374 s1->include_stack_ptr = s1->include_stack;
9375 /* XXX: move that before to avoid having to initialize
9376 file->ifdef_stack_ptr ? */
9377 s1->ifdef_stack_ptr = s1->ifdef_stack;
9378 file->ifdef_stack_ptr = s1->ifdef_stack_ptr;
9380 /* XXX: not ANSI compliant: bound checking says error */
9381 vtop = vstack - 1;
9382 s1->pack_stack[0] = 0;
9383 s1->pack_stack_ptr = s1->pack_stack;
9386 /* compile the C file opened in 'file'. Return non zero if errors. */
9387 static int tcc_compile(TCCState *s1)
9389 Sym *define_start;
9390 char buf[512];
9391 volatile int section_sym;
9393 #ifdef INC_DEBUG
9394 printf("%s: **** new file\n", file->filename);
9395 #endif
9396 preprocess_init(s1);
9398 funcname = "";
9399 anon_sym = SYM_FIRST_ANOM;
9401 /* file info: full path + filename */
9402 section_sym = 0; /* avoid warning */
9403 if (do_debug) {
9404 section_sym = put_elf_sym(symtab_section, 0, 0,
9405 ELF32_ST_INFO(STB_LOCAL, STT_SECTION), 0,
9406 text_section->sh_num, NULL);
9407 getcwd(buf, sizeof(buf));
9408 #ifdef _WIN32
9409 normalize_slashes(buf);
9410 #endif
9411 pstrcat(buf, sizeof(buf), "/");
9412 put_stabs_r(buf, N_SO, 0, 0,
9413 text_section->data_offset, text_section, section_sym);
9414 put_stabs_r(file->filename, N_SO, 0, 0,
9415 text_section->data_offset, text_section, section_sym);
9417 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
9418 symbols can be safely used */
9419 put_elf_sym(symtab_section, 0, 0,
9420 ELF32_ST_INFO(STB_LOCAL, STT_FILE), 0,
9421 SHN_ABS, file->filename);
9423 /* define some often used types */
9424 int_type.t = VT_INT;
9426 char_pointer_type.t = VT_BYTE;
9427 mk_pointer(&char_pointer_type);
9429 func_old_type.t = VT_FUNC;
9430 func_old_type.ref = sym_push(SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD);
9432 #if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)
9433 float_type.t = VT_FLOAT;
9434 double_type.t = VT_DOUBLE;
9436 func_float_type.t = VT_FUNC;
9437 func_float_type.ref = sym_push(SYM_FIELD, &float_type, FUNC_CDECL, FUNC_OLD);
9438 func_double_type.t = VT_FUNC;
9439 func_double_type.ref = sym_push(SYM_FIELD, &double_type, FUNC_CDECL, FUNC_OLD);
9440 #endif
9442 #if 0
9443 /* define 'void *alloca(unsigned int)' builtin function */
9445 Sym *s1;
9447 p = anon_sym++;
9448 sym = sym_push(p, mk_pointer(VT_VOID), FUNC_CDECL, FUNC_NEW);
9449 s1 = sym_push(SYM_FIELD, VT_UNSIGNED | VT_INT, 0, 0);
9450 s1->next = NULL;
9451 sym->next = s1;
9452 sym_push(TOK_alloca, VT_FUNC | (p << VT_STRUCT_SHIFT), VT_CONST, 0);
9454 #endif
9456 define_start = define_stack;
9457 nocode_wanted = 1;
9459 if (setjmp(s1->error_jmp_buf) == 0) {
9460 s1->nb_errors = 0;
9461 s1->error_set_jmp_enabled = 1;
9463 ch = file->buf_ptr[0];
9464 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
9465 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM;
9466 next();
9467 decl(VT_CONST);
9468 if (tok != TOK_EOF)
9469 expect("declaration");
9471 /* end of translation unit info */
9472 if (do_debug) {
9473 put_stabs_r(NULL, N_SO, 0, 0,
9474 text_section->data_offset, text_section, section_sym);
9477 s1->error_set_jmp_enabled = 0;
9479 /* reset define stack, but leave -Dsymbols (may be incorrect if
9480 they are undefined) */
9481 free_defines(define_start);
9483 gen_inline_functions();
9485 sym_pop(&global_stack, NULL);
9487 return s1->nb_errors != 0 ? -1 : 0;
9490 /* Preprocess the current file */
9491 /* XXX: add line and file infos, add options to preserve spaces */
9492 static int tcc_preprocess(TCCState *s1)
9494 Sym *define_start;
9495 int last_is_space;
9497 preprocess_init(s1);
9499 define_start = define_stack;
9501 ch = file->buf_ptr[0];
9502 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
9503 parse_flags = PARSE_FLAG_ASM_COMMENTS | PARSE_FLAG_PREPROCESS |
9504 PARSE_FLAG_LINEFEED;
9505 last_is_space = 1;
9506 next();
9507 for(;;) {
9508 if (tok == TOK_EOF) {
9509 break;
9510 } else if (tok == TOK_LINEFEED) {
9511 last_is_space = 1;
9512 } else {
9513 if (!last_is_space)
9514 fputc(' ', s1->outfile);
9515 last_is_space = 0;
9517 fputs(get_tok_str(tok, &tokc), s1->outfile);
9518 next();
9520 free_defines(define_start);
9521 return 0;
9524 #ifdef LIBTCC
9525 int tcc_compile_string(TCCState *s, const char *str)
9527 BufferedFile bf1, *bf = &bf1;
9528 int ret, len;
9529 char *buf;
9531 /* init file structure */
9532 bf->fd = -1;
9533 /* XXX: avoid copying */
9534 len = strlen(str);
9535 buf = tcc_malloc(len + 1);
9536 if (!buf)
9537 return -1;
9538 memcpy(buf, str, len);
9539 buf[len] = CH_EOB;
9540 bf->buf_ptr = buf;
9541 bf->buf_end = buf + len;
9542 pstrcpy(bf->filename, sizeof(bf->filename), "<string>");
9543 bf->line_num = 1;
9544 file = bf;
9546 ret = tcc_compile(s);
9548 tcc_free(buf);
9550 /* currently, no need to close */
9551 return ret;
9553 #endif
9555 /* define a preprocessor symbol. A value can also be provided with the '=' operator */
9556 void tcc_define_symbol(TCCState *s1, const char *sym, const char *value)
9558 BufferedFile bf1, *bf = &bf1;
9560 pstrcpy(bf->buffer, IO_BUF_SIZE, sym);
9561 pstrcat(bf->buffer, IO_BUF_SIZE, " ");
9562 /* default value */
9563 if (!value)
9564 value = "1";
9565 pstrcat(bf->buffer, IO_BUF_SIZE, value);
9567 /* init file structure */
9568 bf->fd = -1;
9569 bf->buf_ptr = bf->buffer;
9570 bf->buf_end = bf->buffer + strlen(bf->buffer);
9571 *bf->buf_end = CH_EOB;
9572 bf->filename[0] = '\0';
9573 bf->line_num = 1;
9574 file = bf;
9576 s1->include_stack_ptr = s1->include_stack;
9578 /* parse with define parser */
9579 ch = file->buf_ptr[0];
9580 next_nomacro();
9581 parse_define();
9582 file = NULL;
9585 /* undefine a preprocessor symbol */
9586 void tcc_undefine_symbol(TCCState *s1, const char *sym)
9588 TokenSym *ts;
9589 Sym *s;
9590 ts = tok_alloc(sym, strlen(sym));
9591 s = define_find(ts->tok);
9592 /* undefine symbol by putting an invalid name */
9593 if (s)
9594 define_undef(s);
9597 #ifdef CONFIG_TCC_ASM
9599 #ifdef TCC_TARGET_I386
9600 #include "i386-asm.c"
9601 #endif
9602 #include "tccasm.c"
9604 #else
9605 static void asm_instr(void)
9607 error("inline asm() not supported");
9609 static void asm_global_instr(void)
9611 error("inline asm() not supported");
9613 #endif
9615 #include "tccelf.c"
9617 #ifdef TCC_TARGET_COFF
9618 #include "tcccoff.c"
9619 #endif
9621 #ifdef TCC_TARGET_PE
9622 #include "tccpe.c"
9623 #endif
9625 /* print the position in the source file of PC value 'pc' by reading
9626 the stabs debug information */
9627 static void rt_printline(unsigned long wanted_pc)
9629 Stab_Sym *sym, *sym_end;
9630 char func_name[128], last_func_name[128];
9631 unsigned long func_addr, last_pc, pc;
9632 const char *incl_files[INCLUDE_STACK_SIZE];
9633 int incl_index, len, last_line_num, i;
9634 const char *str, *p;
9636 fprintf(stderr, "0x%08lx:", wanted_pc);
9638 func_name[0] = '\0';
9639 func_addr = 0;
9640 incl_index = 0;
9641 last_func_name[0] = '\0';
9642 last_pc = 0xffffffff;
9643 last_line_num = 1;
9644 sym = (Stab_Sym *)stab_section->data + 1;
9645 sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset);
9646 while (sym < sym_end) {
9647 switch(sym->n_type) {
9648 /* function start or end */
9649 case N_FUN:
9650 if (sym->n_strx == 0) {
9651 /* we test if between last line and end of function */
9652 pc = sym->n_value + func_addr;
9653 if (wanted_pc >= last_pc && wanted_pc < pc)
9654 goto found;
9655 func_name[0] = '\0';
9656 func_addr = 0;
9657 } else {
9658 str = stabstr_section->data + sym->n_strx;
9659 p = strchr(str, ':');
9660 if (!p) {
9661 pstrcpy(func_name, sizeof(func_name), str);
9662 } else {
9663 len = p - str;
9664 if (len > sizeof(func_name) - 1)
9665 len = sizeof(func_name) - 1;
9666 memcpy(func_name, str, len);
9667 func_name[len] = '\0';
9669 func_addr = sym->n_value;
9671 break;
9672 /* line number info */
9673 case N_SLINE:
9674 pc = sym->n_value + func_addr;
9675 if (wanted_pc >= last_pc && wanted_pc < pc)
9676 goto found;
9677 last_pc = pc;
9678 last_line_num = sym->n_desc;
9679 /* XXX: slow! */
9680 strcpy(last_func_name, func_name);
9681 break;
9682 /* include files */
9683 case N_BINCL:
9684 str = stabstr_section->data + sym->n_strx;
9685 add_incl:
9686 if (incl_index < INCLUDE_STACK_SIZE) {
9687 incl_files[incl_index++] = str;
9689 break;
9690 case N_EINCL:
9691 if (incl_index > 1)
9692 incl_index--;
9693 break;
9694 case N_SO:
9695 if (sym->n_strx == 0) {
9696 incl_index = 0; /* end of translation unit */
9697 } else {
9698 str = stabstr_section->data + sym->n_strx;
9699 /* do not add path */
9700 len = strlen(str);
9701 if (len > 0 && str[len - 1] != '/')
9702 goto add_incl;
9704 break;
9706 sym++;
9709 /* second pass: we try symtab symbols (no line number info) */
9710 incl_index = 0;
9712 Elf32_Sym *sym, *sym_end;
9713 int type;
9715 sym_end = (Elf32_Sym *)(symtab_section->data + symtab_section->data_offset);
9716 for(sym = (Elf32_Sym *)symtab_section->data + 1;
9717 sym < sym_end;
9718 sym++) {
9719 type = ELF32_ST_TYPE(sym->st_info);
9720 if (type == STT_FUNC) {
9721 if (wanted_pc >= sym->st_value &&
9722 wanted_pc < sym->st_value + sym->st_size) {
9723 pstrcpy(last_func_name, sizeof(last_func_name),
9724 strtab_section->data + sym->st_name);
9725 goto found;
9730 /* did not find any info: */
9731 fprintf(stderr, " ???\n");
9732 return;
9733 found:
9734 if (last_func_name[0] != '\0') {
9735 fprintf(stderr, " %s()", last_func_name);
9737 if (incl_index > 0) {
9738 fprintf(stderr, " (%s:%d",
9739 incl_files[incl_index - 1], last_line_num);
9740 for(i = incl_index - 2; i >= 0; i--)
9741 fprintf(stderr, ", included from %s", incl_files[i]);
9742 fprintf(stderr, ")");
9744 fprintf(stderr, "\n");
9747 #if !defined(_WIN32) && !defined(CONFIG_TCCBOOT)
9749 #ifdef __i386__
9751 /* fix for glibc 2.1 */
9752 #ifndef REG_EIP
9753 #define REG_EIP EIP
9754 #define REG_EBP EBP
9755 #endif
9757 /* return the PC at frame level 'level'. Return non zero if not found */
9758 static int rt_get_caller_pc(unsigned long *paddr,
9759 ucontext_t *uc, int level)
9761 unsigned long fp;
9762 int i;
9764 if (level == 0) {
9765 #if defined(__FreeBSD__)
9766 *paddr = uc->uc_mcontext.mc_eip;
9767 #elif defined(__dietlibc__)
9768 *paddr = uc->uc_mcontext.eip;
9769 #else
9770 *paddr = uc->uc_mcontext.gregs[REG_EIP];
9771 #endif
9772 return 0;
9773 } else {
9774 #if defined(__FreeBSD__)
9775 fp = uc->uc_mcontext.mc_ebp;
9776 #elif defined(__dietlibc__)
9777 fp = uc->uc_mcontext.ebp;
9778 #else
9779 fp = uc->uc_mcontext.gregs[REG_EBP];
9780 #endif
9781 for(i=1;i<level;i++) {
9782 /* XXX: check address validity with program info */
9783 if (fp <= 0x1000 || fp >= 0xc0000000)
9784 return -1;
9785 fp = ((unsigned long *)fp)[0];
9787 *paddr = ((unsigned long *)fp)[1];
9788 return 0;
9791 #else
9793 #warning add arch specific rt_get_caller_pc()
9795 static int rt_get_caller_pc(unsigned long *paddr,
9796 ucontext_t *uc, int level)
9798 return -1;
9800 #endif
9802 /* emit a run time error at position 'pc' */
9803 void rt_error(ucontext_t *uc, const char *fmt, ...)
9805 va_list ap;
9806 unsigned long pc;
9807 int i;
9809 va_start(ap, fmt);
9810 fprintf(stderr, "Runtime error: ");
9811 vfprintf(stderr, fmt, ap);
9812 fprintf(stderr, "\n");
9813 for(i=0;i<num_callers;i++) {
9814 if (rt_get_caller_pc(&pc, uc, i) < 0)
9815 break;
9816 if (i == 0)
9817 fprintf(stderr, "at ");
9818 else
9819 fprintf(stderr, "by ");
9820 rt_printline(pc);
9822 exit(255);
9823 va_end(ap);
9826 /* signal handler for fatal errors */
9827 static void sig_error(int signum, siginfo_t *siginf, void *puc)
9829 ucontext_t *uc = puc;
9831 switch(signum) {
9832 case SIGFPE:
9833 switch(siginf->si_code) {
9834 case FPE_INTDIV:
9835 case FPE_FLTDIV:
9836 rt_error(uc, "division by zero");
9837 break;
9838 default:
9839 rt_error(uc, "floating point exception");
9840 break;
9842 break;
9843 case SIGBUS:
9844 case SIGSEGV:
9845 if (rt_bound_error_msg && *rt_bound_error_msg)
9846 rt_error(uc, *rt_bound_error_msg);
9847 else
9848 rt_error(uc, "dereferencing invalid pointer");
9849 break;
9850 case SIGILL:
9851 rt_error(uc, "illegal instruction");
9852 break;
9853 case SIGABRT:
9854 rt_error(uc, "abort() called");
9855 break;
9856 default:
9857 rt_error(uc, "caught signal %d", signum);
9858 break;
9860 exit(255);
9862 #endif
9864 /* do all relocations (needed before using tcc_get_symbol()) */
9865 int tcc_relocate(TCCState *s1)
9867 Section *s;
9868 int i;
9870 s1->nb_errors = 0;
9872 #ifdef TCC_TARGET_PE
9873 pe_add_runtime(s1);
9874 #else
9875 tcc_add_runtime(s1);
9876 #endif
9878 relocate_common_syms();
9880 tcc_add_linker_symbols(s1);
9882 build_got_entries(s1);
9884 /* compute relocation address : section are relocated in place. We
9885 also alloc the bss space */
9886 for(i = 1; i < s1->nb_sections; i++) {
9887 s = s1->sections[i];
9888 if (s->sh_flags & SHF_ALLOC) {
9889 if (s->sh_type == SHT_NOBITS)
9890 s->data = tcc_mallocz(s->data_offset);
9891 s->sh_addr = (unsigned long)s->data;
9895 relocate_syms(s1, 1);
9897 if (s1->nb_errors != 0)
9898 return -1;
9900 /* relocate each section */
9901 for(i = 1; i < s1->nb_sections; i++) {
9902 s = s1->sections[i];
9903 if (s->reloc)
9904 relocate_section(s1, s);
9907 /* mark executable sections as executable in memory */
9908 for(i = 1; i < s1->nb_sections; i++) {
9909 s = s1->sections[i];
9910 if ((s->sh_flags & (SHF_ALLOC | SHF_EXECINSTR)) ==
9911 (SHF_ALLOC | SHF_EXECINSTR))
9912 set_pages_executable(s->data, s->data_offset);
9914 return 0;
9917 /* launch the compiled program with the given arguments */
9918 int tcc_run(TCCState *s1, int argc, char **argv)
9920 int (*prog_main)(int, char **);
9922 if (tcc_relocate(s1) < 0)
9923 return -1;
9925 prog_main = tcc_get_symbol_err(s1, "main");
9927 if (do_debug) {
9928 #if defined(_WIN32) || defined(CONFIG_TCCBOOT)
9929 error("debug mode currently not available for Windows");
9930 #else
9931 struct sigaction sigact;
9932 /* install TCC signal handlers to print debug info on fatal
9933 runtime errors */
9934 sigact.sa_flags = SA_SIGINFO | SA_RESETHAND;
9935 sigact.sa_sigaction = sig_error;
9936 sigemptyset(&sigact.sa_mask);
9937 sigaction(SIGFPE, &sigact, NULL);
9938 sigaction(SIGILL, &sigact, NULL);
9939 sigaction(SIGSEGV, &sigact, NULL);
9940 sigaction(SIGBUS, &sigact, NULL);
9941 sigaction(SIGABRT, &sigact, NULL);
9942 #endif
9945 #ifdef CONFIG_TCC_BCHECK
9946 if (do_bounds_check) {
9947 void (*bound_init)(void);
9949 /* set error function */
9950 rt_bound_error_msg = (void *)tcc_get_symbol_err(s1,
9951 "__bound_error_msg");
9953 /* XXX: use .init section so that it also work in binary ? */
9954 bound_init = (void *)tcc_get_symbol_err(s1, "__bound_init");
9955 bound_init();
9957 #endif
9958 return (*prog_main)(argc, argv);
9961 TCCState *tcc_new(void)
9963 const char *p, *r;
9964 TCCState *s;
9965 TokenSym *ts;
9966 int i, c;
9968 s = tcc_mallocz(sizeof(TCCState));
9969 if (!s)
9970 return NULL;
9971 tcc_state = s;
9972 s->output_type = TCC_OUTPUT_MEMORY;
9974 /* init isid table */
9975 for(i=0;i<256;i++)
9976 isidnum_table[i] = isid(i) || isnum(i);
9978 /* add all tokens */
9979 table_ident = NULL;
9980 memset(hash_ident, 0, TOK_HASH_SIZE * sizeof(TokenSym *));
9982 tok_ident = TOK_IDENT;
9983 p = tcc_keywords;
9984 while (*p) {
9985 r = p;
9986 for(;;) {
9987 c = *r++;
9988 if (c == '\0')
9989 break;
9991 ts = tok_alloc(p, r - p - 1);
9992 p = r;
9995 /* we add dummy defines for some special macros to speed up tests
9996 and to have working defined() */
9997 define_push(TOK___LINE__, MACRO_OBJ, NULL, NULL);
9998 define_push(TOK___FILE__, MACRO_OBJ, NULL, NULL);
9999 define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL);
10000 define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL);
10002 /* standard defines */
10003 tcc_define_symbol(s, "__STDC__", NULL);
10004 #if defined(TCC_TARGET_I386)
10005 tcc_define_symbol(s, "__i386__", NULL);
10006 #endif
10007 #if defined(TCC_TARGET_ARM)
10008 tcc_define_symbol(s, "__ARM_ARCH_4__", NULL);
10009 tcc_define_symbol(s, "__arm_elf__", NULL);
10010 tcc_define_symbol(s, "__arm_elf", NULL);
10011 tcc_define_symbol(s, "arm_elf", NULL);
10012 tcc_define_symbol(s, "__arm__", NULL);
10013 tcc_define_symbol(s, "__arm", NULL);
10014 tcc_define_symbol(s, "arm", NULL);
10015 tcc_define_symbol(s, "__APCS_32__", NULL);
10016 #endif
10017 #ifdef TCC_TARGET_PE
10018 tcc_define_symbol(s, "_WIN32", NULL);
10019 #else
10020 tcc_define_symbol(s, "__unix__", NULL);
10021 tcc_define_symbol(s, "__unix", NULL);
10022 #if defined(__linux)
10023 tcc_define_symbol(s, "__linux__", NULL);
10024 tcc_define_symbol(s, "__linux", NULL);
10025 #endif
10026 #endif
10027 /* tiny C specific defines */
10028 tcc_define_symbol(s, "__TINYC__", NULL);
10030 /* tiny C & gcc defines */
10031 tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned int");
10032 tcc_define_symbol(s, "__PTRDIFF_TYPE__", "int");
10033 #ifdef TCC_TARGET_PE
10034 tcc_define_symbol(s, "__WCHAR_TYPE__", "unsigned short");
10035 #else
10036 tcc_define_symbol(s, "__WCHAR_TYPE__", "int");
10037 #endif
10039 /* default library paths */
10040 #ifdef TCC_TARGET_PE
10042 char buf[1024];
10043 snprintf(buf, sizeof(buf), "%s/lib", tcc_lib_path);
10044 tcc_add_library_path(s, buf);
10046 #else
10047 tcc_add_library_path(s, "/usr/local/lib");
10048 tcc_add_library_path(s, "/usr/lib");
10049 tcc_add_library_path(s, "/lib");
10050 #endif
10052 /* no section zero */
10053 dynarray_add((void ***)&s->sections, &s->nb_sections, NULL);
10055 /* create standard sections */
10056 text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
10057 data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
10058 bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
10060 /* symbols are always generated for linking stage */
10061 symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0,
10062 ".strtab",
10063 ".hashtab", SHF_PRIVATE);
10064 strtab_section = symtab_section->link;
10066 /* private symbol table for dynamic symbols */
10067 s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE,
10068 ".dynstrtab",
10069 ".dynhashtab", SHF_PRIVATE);
10070 s->alacarte_link = 1;
10072 #ifdef CHAR_IS_UNSIGNED
10073 s->char_is_unsigned = 1;
10074 #endif
10075 #if defined(TCC_TARGET_PE) && 0
10076 /* XXX: currently the PE linker is not ready to support that */
10077 s->leading_underscore = 1;
10078 #endif
10079 return s;
10082 void tcc_delete(TCCState *s1)
10084 int i, n;
10086 /* free -D defines */
10087 free_defines(NULL);
10089 /* free tokens */
10090 n = tok_ident - TOK_IDENT;
10091 for(i = 0; i < n; i++)
10092 tcc_free(table_ident[i]);
10093 tcc_free(table_ident);
10095 /* free all sections */
10097 free_section(symtab_section->hash);
10099 free_section(s1->dynsymtab_section->hash);
10100 free_section(s1->dynsymtab_section->link);
10101 free_section(s1->dynsymtab_section);
10103 for(i = 1; i < s1->nb_sections; i++)
10104 free_section(s1->sections[i]);
10105 tcc_free(s1->sections);
10107 /* free loaded dlls array */
10108 for(i = 0; i < s1->nb_loaded_dlls; i++)
10109 tcc_free(s1->loaded_dlls[i]);
10110 tcc_free(s1->loaded_dlls);
10112 /* library paths */
10113 for(i = 0; i < s1->nb_library_paths; i++)
10114 tcc_free(s1->library_paths[i]);
10115 tcc_free(s1->library_paths);
10117 /* cached includes */
10118 for(i = 0; i < s1->nb_cached_includes; i++)
10119 tcc_free(s1->cached_includes[i]);
10120 tcc_free(s1->cached_includes);
10122 for(i = 0; i < s1->nb_include_paths; i++)
10123 tcc_free(s1->include_paths[i]);
10124 tcc_free(s1->include_paths);
10126 for(i = 0; i < s1->nb_sysinclude_paths; i++)
10127 tcc_free(s1->sysinclude_paths[i]);
10128 tcc_free(s1->sysinclude_paths);
10130 tcc_free(s1);
10133 int tcc_add_include_path(TCCState *s1, const char *pathname)
10135 char *pathname1;
10137 pathname1 = tcc_strdup(pathname);
10138 dynarray_add((void ***)&s1->include_paths, &s1->nb_include_paths, pathname1);
10139 return 0;
10142 int tcc_add_sysinclude_path(TCCState *s1, const char *pathname)
10144 char *pathname1;
10146 pathname1 = tcc_strdup(pathname);
10147 dynarray_add((void ***)&s1->sysinclude_paths, &s1->nb_sysinclude_paths, pathname1);
10148 return 0;
10151 static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
10153 const char *ext, *filename1;
10154 Elf32_Ehdr ehdr;
10155 int fd, ret;
10156 BufferedFile *saved_file;
10158 /* find source file type with extension */
10159 filename1 = strrchr(filename, '/');
10160 if (filename1)
10161 filename1++;
10162 else
10163 filename1 = filename;
10164 ext = strrchr(filename1, '.');
10165 if (ext)
10166 ext++;
10168 /* open the file */
10169 saved_file = file;
10170 file = tcc_open(s1, filename);
10171 if (!file) {
10172 if (flags & AFF_PRINT_ERROR) {
10173 error_noabort("file '%s' not found", filename);
10175 ret = -1;
10176 goto fail1;
10179 if (flags & AFF_PREPROCESS) {
10180 ret = tcc_preprocess(s1);
10181 } else if (!ext || !strcmp(ext, "c")) {
10182 /* C file assumed */
10183 ret = tcc_compile(s1);
10184 } else
10185 #ifdef CONFIG_TCC_ASM
10186 if (!strcmp(ext, "S")) {
10187 /* preprocessed assembler */
10188 ret = tcc_assemble(s1, 1);
10189 } else if (!strcmp(ext, "s")) {
10190 /* non preprocessed assembler */
10191 ret = tcc_assemble(s1, 0);
10192 } else
10193 #endif
10194 #ifdef TCC_TARGET_PE
10195 if (!strcmp(ext, "def")) {
10196 ret = pe_load_def_file(s1, fdopen(file->fd, "rb"));
10197 } else
10198 #endif
10200 fd = file->fd;
10201 /* assume executable format: auto guess file type */
10202 ret = read(fd, &ehdr, sizeof(ehdr));
10203 lseek(fd, 0, SEEK_SET);
10204 if (ret <= 0) {
10205 error_noabort("could not read header");
10206 goto fail;
10207 } else if (ret != sizeof(ehdr)) {
10208 goto try_load_script;
10211 if (ehdr.e_ident[0] == ELFMAG0 &&
10212 ehdr.e_ident[1] == ELFMAG1 &&
10213 ehdr.e_ident[2] == ELFMAG2 &&
10214 ehdr.e_ident[3] == ELFMAG3) {
10215 file->line_num = 0; /* do not display line number if error */
10216 if (ehdr.e_type == ET_REL) {
10217 ret = tcc_load_object_file(s1, fd, 0);
10218 } else if (ehdr.e_type == ET_DYN) {
10219 if (s1->output_type == TCC_OUTPUT_MEMORY) {
10220 #ifdef TCC_TARGET_PE
10221 ret = -1;
10222 #else
10223 void *h;
10224 h = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY);
10225 if (h)
10226 ret = 0;
10227 else
10228 ret = -1;
10229 #endif
10230 } else {
10231 ret = tcc_load_dll(s1, fd, filename,
10232 (flags & AFF_REFERENCED_DLL) != 0);
10234 } else {
10235 error_noabort("unrecognized ELF file");
10236 goto fail;
10238 } else if (memcmp((char *)&ehdr, ARMAG, 8) == 0) {
10239 file->line_num = 0; /* do not display line number if error */
10240 ret = tcc_load_archive(s1, fd);
10241 } else
10242 #ifdef TCC_TARGET_COFF
10243 if (*(uint16_t *)(&ehdr) == COFF_C67_MAGIC) {
10244 ret = tcc_load_coff(s1, fd);
10245 } else
10246 #endif
10248 /* as GNU ld, consider it is an ld script if not recognized */
10249 try_load_script:
10250 ret = tcc_load_ldscript(s1);
10251 if (ret < 0) {
10252 error_noabort("unrecognized file type");
10253 goto fail;
10257 the_end:
10258 tcc_close(file);
10259 fail1:
10260 file = saved_file;
10261 return ret;
10262 fail:
10263 ret = -1;
10264 goto the_end;
10267 int tcc_add_file(TCCState *s, const char *filename)
10269 return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR);
10272 int tcc_add_library_path(TCCState *s, const char *pathname)
10274 char *pathname1;
10276 pathname1 = tcc_strdup(pathname);
10277 dynarray_add((void ***)&s->library_paths, &s->nb_library_paths, pathname1);
10278 return 0;
10281 /* find and load a dll. Return non zero if not found */
10282 /* XXX: add '-rpath' option support ? */
10283 static int tcc_add_dll(TCCState *s, const char *filename, int flags)
10285 char buf[1024];
10286 int i;
10288 for(i = 0; i < s->nb_library_paths; i++) {
10289 snprintf(buf, sizeof(buf), "%s/%s",
10290 s->library_paths[i], filename);
10291 if (tcc_add_file_internal(s, buf, flags) == 0)
10292 return 0;
10294 return -1;
10297 /* the library name is the same as the argument of the '-l' option */
10298 int tcc_add_library(TCCState *s, const char *libraryname)
10300 char buf[1024];
10301 int i;
10303 /* first we look for the dynamic library if not static linking */
10304 if (!s->static_link) {
10305 #ifdef TCC_TARGET_PE
10306 snprintf(buf, sizeof(buf), "%s.def", libraryname);
10307 #else
10308 snprintf(buf, sizeof(buf), "lib%s.so", libraryname);
10309 #endif
10310 if (tcc_add_dll(s, buf, 0) == 0)
10311 return 0;
10314 /* then we look for the static library */
10315 for(i = 0; i < s->nb_library_paths; i++) {
10316 snprintf(buf, sizeof(buf), "%s/lib%s.a",
10317 s->library_paths[i], libraryname);
10318 if (tcc_add_file_internal(s, buf, 0) == 0)
10319 return 0;
10321 return -1;
10324 int tcc_add_symbol(TCCState *s, const char *name, unsigned long val)
10326 add_elf_sym(symtab_section, val, 0,
10327 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
10328 SHN_ABS, name);
10329 return 0;
10332 int tcc_set_output_type(TCCState *s, int output_type)
10334 s->output_type = output_type;
10336 if (!s->nostdinc) {
10337 char buf[1024];
10339 /* default include paths */
10340 /* XXX: reverse order needed if -isystem support */
10341 #ifndef TCC_TARGET_PE
10342 tcc_add_sysinclude_path(s, "/usr/local/include");
10343 tcc_add_sysinclude_path(s, "/usr/include");
10344 #endif
10345 snprintf(buf, sizeof(buf), "%s/include", tcc_lib_path);
10346 tcc_add_sysinclude_path(s, buf);
10347 #ifdef TCC_TARGET_PE
10348 snprintf(buf, sizeof(buf), "%s/include/winapi", tcc_lib_path);
10349 tcc_add_sysinclude_path(s, buf);
10350 #endif
10353 /* if bound checking, then add corresponding sections */
10354 #ifdef CONFIG_TCC_BCHECK
10355 if (do_bounds_check) {
10356 /* define symbol */
10357 tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL);
10358 /* create bounds sections */
10359 bounds_section = new_section(s, ".bounds",
10360 SHT_PROGBITS, SHF_ALLOC);
10361 lbounds_section = new_section(s, ".lbounds",
10362 SHT_PROGBITS, SHF_ALLOC);
10364 #endif
10366 if (s->char_is_unsigned) {
10367 tcc_define_symbol(s, "__CHAR_UNSIGNED__", NULL);
10370 /* add debug sections */
10371 if (do_debug) {
10372 /* stab symbols */
10373 stab_section = new_section(s, ".stab", SHT_PROGBITS, 0);
10374 stab_section->sh_entsize = sizeof(Stab_Sym);
10375 stabstr_section = new_section(s, ".stabstr", SHT_STRTAB, 0);
10376 put_elf_str(stabstr_section, "");
10377 stab_section->link = stabstr_section;
10378 /* put first entry */
10379 put_stabs("", 0, 0, 0, 0);
10382 /* add libc crt1/crti objects */
10383 #ifndef TCC_TARGET_PE
10384 if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) &&
10385 !s->nostdlib) {
10386 if (output_type != TCC_OUTPUT_DLL)
10387 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crt1.o");
10388 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crti.o");
10390 #endif
10391 return 0;
10394 #define WD_ALL 0x0001 /* warning is activated when using -Wall */
10395 #define FD_INVERT 0x0002 /* invert value before storing */
10397 typedef struct FlagDef {
10398 uint16_t offset;
10399 uint16_t flags;
10400 const char *name;
10401 } FlagDef;
10403 static const FlagDef warning_defs[] = {
10404 { offsetof(TCCState, warn_unsupported), 0, "unsupported" },
10405 { offsetof(TCCState, warn_write_strings), 0, "write-strings" },
10406 { offsetof(TCCState, warn_error), 0, "error" },
10407 { offsetof(TCCState, warn_implicit_function_declaration), WD_ALL,
10408 "implicit-function-declaration" },
10411 static int set_flag(TCCState *s, const FlagDef *flags, int nb_flags,
10412 const char *name, int value)
10414 int i;
10415 const FlagDef *p;
10416 const char *r;
10418 r = name;
10419 if (r[0] == 'n' && r[1] == 'o' && r[2] == '-') {
10420 r += 3;
10421 value = !value;
10423 for(i = 0, p = flags; i < nb_flags; i++, p++) {
10424 if (!strcmp(r, p->name))
10425 goto found;
10427 return -1;
10428 found:
10429 if (p->flags & FD_INVERT)
10430 value = !value;
10431 *(int *)((uint8_t *)s + p->offset) = value;
10432 return 0;
10436 /* set/reset a warning */
10437 int tcc_set_warning(TCCState *s, const char *warning_name, int value)
10439 int i;
10440 const FlagDef *p;
10442 if (!strcmp(warning_name, "all")) {
10443 for(i = 0, p = warning_defs; i < countof(warning_defs); i++, p++) {
10444 if (p->flags & WD_ALL)
10445 *(int *)((uint8_t *)s + p->offset) = 1;
10447 return 0;
10448 } else {
10449 return set_flag(s, warning_defs, countof(warning_defs),
10450 warning_name, value);
10454 static const FlagDef flag_defs[] = {
10455 { offsetof(TCCState, char_is_unsigned), 0, "unsigned-char" },
10456 { offsetof(TCCState, char_is_unsigned), FD_INVERT, "signed-char" },
10457 { offsetof(TCCState, nocommon), FD_INVERT, "common" },
10458 { offsetof(TCCState, leading_underscore), 0, "leading-underscore" },
10461 /* set/reset a flag */
10462 int tcc_set_flag(TCCState *s, const char *flag_name, int value)
10464 return set_flag(s, flag_defs, countof(flag_defs),
10465 flag_name, value);
10468 /* extract the basename of a file */
10469 static char *tcc_basename(const char *name)
10471 char *p = strchr(name, 0);
10472 while (p > name
10473 && p[-1] != '/'
10474 #ifdef _WIN32
10475 && p[-1] != '\\'
10476 #endif
10478 --p;
10479 return p;
10482 #if !defined(LIBTCC)
10484 static int64_t getclock_us(void)
10486 #ifdef _WIN32
10487 struct _timeb tb;
10488 _ftime(&tb);
10489 return (tb.time * 1000LL + tb.millitm) * 1000LL;
10490 #else
10491 struct timeval tv;
10492 gettimeofday(&tv, NULL);
10493 return tv.tv_sec * 1000000LL + tv.tv_usec;
10494 #endif
10497 void help(void)
10499 printf("tcc version " TCC_VERSION " - Tiny C Compiler - Copyright (C) 2001-2006 Fabrice Bellard\n"
10500 "usage: tcc [-v] [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
10501 " [-Wwarn] [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-static]\n"
10502 " [infile1 infile2...] [-run infile args...]\n"
10503 "\n"
10504 "General options:\n"
10505 " -v display current version\n"
10506 " -c compile only - generate an object file\n"
10507 " -o outfile set output filename\n"
10508 " -Bdir set tcc internal library path\n"
10509 " -bench output compilation statistics\n"
10510 " -run run compiled source\n"
10511 " -fflag set or reset (with 'no-' prefix) 'flag' (see man page)\n"
10512 " -Wwarning set or reset (with 'no-' prefix) 'warning' (see man page)\n"
10513 " -w disable all warnings\n"
10514 "Preprocessor options:\n"
10515 " -E preprocess only\n"
10516 " -Idir add include path 'dir'\n"
10517 " -Dsym[=val] define 'sym' with value 'val'\n"
10518 " -Usym undefine 'sym'\n"
10519 "Linker options:\n"
10520 " -Ldir add library path 'dir'\n"
10521 " -llib link with dynamic or static library 'lib'\n"
10522 " -shared generate a shared library\n"
10523 " -static static linking\n"
10524 " -rdynamic export all global symbols to dynamic linker\n"
10525 " -r relocatable output\n"
10526 "Debugger options:\n"
10527 " -g generate runtime debug info\n"
10528 #ifdef CONFIG_TCC_BCHECK
10529 " -b compile with built-in memory and bounds checker (implies -g)\n"
10530 #endif
10531 " -bt N show N callers in stack traces\n"
10535 #define TCC_OPTION_HAS_ARG 0x0001
10536 #define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
10538 typedef struct TCCOption {
10539 const char *name;
10540 uint16_t index;
10541 uint16_t flags;
10542 } TCCOption;
10544 enum {
10545 TCC_OPTION_HELP,
10546 TCC_OPTION_I,
10547 TCC_OPTION_D,
10548 TCC_OPTION_U,
10549 TCC_OPTION_L,
10550 TCC_OPTION_B,
10551 TCC_OPTION_l,
10552 TCC_OPTION_bench,
10553 TCC_OPTION_bt,
10554 TCC_OPTION_b,
10555 TCC_OPTION_g,
10556 TCC_OPTION_c,
10557 TCC_OPTION_static,
10558 TCC_OPTION_shared,
10559 TCC_OPTION_o,
10560 TCC_OPTION_r,
10561 TCC_OPTION_Wl,
10562 TCC_OPTION_W,
10563 TCC_OPTION_O,
10564 TCC_OPTION_m,
10565 TCC_OPTION_f,
10566 TCC_OPTION_nostdinc,
10567 TCC_OPTION_nostdlib,
10568 TCC_OPTION_print_search_dirs,
10569 TCC_OPTION_rdynamic,
10570 TCC_OPTION_run,
10571 TCC_OPTION_v,
10572 TCC_OPTION_w,
10573 TCC_OPTION_pipe,
10574 TCC_OPTION_E,
10577 static const TCCOption tcc_options[] = {
10578 { "h", TCC_OPTION_HELP, 0 },
10579 { "?", TCC_OPTION_HELP, 0 },
10580 { "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG },
10581 { "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG },
10582 { "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG },
10583 { "L", TCC_OPTION_L, TCC_OPTION_HAS_ARG },
10584 { "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG },
10585 { "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10586 { "bench", TCC_OPTION_bench, 0 },
10587 { "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG },
10588 #ifdef CONFIG_TCC_BCHECK
10589 { "b", TCC_OPTION_b, 0 },
10590 #endif
10591 { "g", TCC_OPTION_g, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10592 { "c", TCC_OPTION_c, 0 },
10593 { "static", TCC_OPTION_static, 0 },
10594 { "shared", TCC_OPTION_shared, 0 },
10595 { "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG },
10596 { "run", TCC_OPTION_run, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10597 { "rdynamic", TCC_OPTION_rdynamic, 0 },
10598 { "r", TCC_OPTION_r, 0 },
10599 { "Wl,", TCC_OPTION_Wl, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10600 { "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10601 { "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10602 { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG },
10603 { "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10604 { "nostdinc", TCC_OPTION_nostdinc, 0 },
10605 { "nostdlib", TCC_OPTION_nostdlib, 0 },
10606 { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 },
10607 { "v", TCC_OPTION_v, 0 },
10608 { "w", TCC_OPTION_w, 0 },
10609 { "pipe", TCC_OPTION_pipe, 0},
10610 { "E", TCC_OPTION_E, 0},
10611 { NULL },
10614 /* convert 'str' into an array of space separated strings */
10615 static int expand_args(char ***pargv, const char *str)
10617 const char *s1;
10618 char **argv, *arg;
10619 int argc, len;
10621 argc = 0;
10622 argv = NULL;
10623 for(;;) {
10624 while (is_space(*str))
10625 str++;
10626 if (*str == '\0')
10627 break;
10628 s1 = str;
10629 while (*str != '\0' && !is_space(*str))
10630 str++;
10631 len = str - s1;
10632 arg = tcc_malloc(len + 1);
10633 memcpy(arg, s1, len);
10634 arg[len] = '\0';
10635 dynarray_add((void ***)&argv, &argc, arg);
10637 *pargv = argv;
10638 return argc;
10641 static char **files;
10642 static int nb_files, nb_libraries;
10643 static int multiple_files;
10644 static int print_search_dirs;
10645 static int output_type;
10646 static int reloc_output;
10647 static const char *outfile;
10649 int parse_args(TCCState *s, int argc, char **argv)
10651 int optind;
10652 const TCCOption *popt;
10653 const char *optarg, *p1, *r1;
10654 char *r;
10656 optind = 0;
10657 while (1) {
10658 if (optind >= argc) {
10659 if (nb_files == 0 && !print_search_dirs)
10660 goto show_help;
10661 else
10662 break;
10664 r = argv[optind++];
10665 if (r[0] != '-') {
10666 /* add a new file */
10667 dynarray_add((void ***)&files, &nb_files, r);
10668 if (!multiple_files) {
10669 optind--;
10670 /* argv[0] will be this file */
10671 break;
10673 } else {
10674 /* find option in table (match only the first chars */
10675 popt = tcc_options;
10676 for(;;) {
10677 p1 = popt->name;
10678 if (p1 == NULL)
10679 error("invalid option -- '%s'", r);
10680 r1 = r + 1;
10681 for(;;) {
10682 if (*p1 == '\0')
10683 goto option_found;
10684 if (*r1 != *p1)
10685 break;
10686 p1++;
10687 r1++;
10689 popt++;
10691 option_found:
10692 if (popt->flags & TCC_OPTION_HAS_ARG) {
10693 if (*r1 != '\0' || (popt->flags & TCC_OPTION_NOSEP)) {
10694 optarg = r1;
10695 } else {
10696 if (optind >= argc)
10697 error("argument to '%s' is missing", r);
10698 optarg = argv[optind++];
10700 } else {
10701 if (*r1 != '\0')
10702 goto show_help;
10703 optarg = NULL;
10706 switch(popt->index) {
10707 case TCC_OPTION_HELP:
10708 show_help:
10709 help();
10710 exit(1);
10711 case TCC_OPTION_I:
10712 if (tcc_add_include_path(s, optarg) < 0)
10713 error("too many include paths");
10714 break;
10715 case TCC_OPTION_D:
10717 char *sym, *value;
10718 sym = (char *)optarg;
10719 value = strchr(sym, '=');
10720 if (value) {
10721 *value = '\0';
10722 value++;
10724 tcc_define_symbol(s, sym, value);
10726 break;
10727 case TCC_OPTION_U:
10728 tcc_undefine_symbol(s, optarg);
10729 break;
10730 case TCC_OPTION_L:
10731 tcc_add_library_path(s, optarg);
10732 break;
10733 case TCC_OPTION_B:
10734 /* set tcc utilities path (mainly for tcc development) */
10735 tcc_lib_path = optarg;
10736 break;
10737 case TCC_OPTION_l:
10738 dynarray_add((void ***)&files, &nb_files, r);
10739 nb_libraries++;
10740 break;
10741 case TCC_OPTION_bench:
10742 do_bench = 1;
10743 break;
10744 case TCC_OPTION_bt:
10745 num_callers = atoi(optarg);
10746 break;
10747 #ifdef CONFIG_TCC_BCHECK
10748 case TCC_OPTION_b:
10749 do_bounds_check = 1;
10750 do_debug = 1;
10751 break;
10752 #endif
10753 case TCC_OPTION_g:
10754 do_debug = 1;
10755 break;
10756 case TCC_OPTION_c:
10757 multiple_files = 1;
10758 output_type = TCC_OUTPUT_OBJ;
10759 break;
10760 case TCC_OPTION_static:
10761 s->static_link = 1;
10762 break;
10763 case TCC_OPTION_shared:
10764 output_type = TCC_OUTPUT_DLL;
10765 break;
10766 case TCC_OPTION_o:
10767 multiple_files = 1;
10768 outfile = optarg;
10769 break;
10770 case TCC_OPTION_r:
10771 /* generate a .o merging several output files */
10772 reloc_output = 1;
10773 output_type = TCC_OUTPUT_OBJ;
10774 break;
10775 case TCC_OPTION_nostdinc:
10776 s->nostdinc = 1;
10777 break;
10778 case TCC_OPTION_nostdlib:
10779 s->nostdlib = 1;
10780 break;
10781 case TCC_OPTION_print_search_dirs:
10782 print_search_dirs = 1;
10783 break;
10784 case TCC_OPTION_run:
10786 int argc1;
10787 char **argv1;
10788 argc1 = expand_args(&argv1, optarg);
10789 if (argc1 > 0) {
10790 parse_args(s, argc1, argv1);
10792 multiple_files = 0;
10793 output_type = TCC_OUTPUT_MEMORY;
10795 break;
10796 case TCC_OPTION_v:
10797 printf("tcc version %s\n", TCC_VERSION);
10798 exit(0);
10799 case TCC_OPTION_f:
10800 if (tcc_set_flag(s, optarg, 1) < 0 && s->warn_unsupported)
10801 goto unsupported_option;
10802 break;
10803 case TCC_OPTION_W:
10804 if (tcc_set_warning(s, optarg, 1) < 0 &&
10805 s->warn_unsupported)
10806 goto unsupported_option;
10807 break;
10808 case TCC_OPTION_w:
10809 s->warn_none = 1;
10810 break;
10811 case TCC_OPTION_rdynamic:
10812 s->rdynamic = 1;
10813 break;
10814 case TCC_OPTION_Wl:
10816 const char *p;
10817 if (strstart(optarg, "-Ttext,", &p)) {
10818 s->text_addr = strtoul(p, NULL, 16);
10819 s->has_text_addr = 1;
10820 } else if (strstart(optarg, "--oformat,", &p)) {
10821 if (strstart(p, "elf32-", NULL)) {
10822 s->output_format = TCC_OUTPUT_FORMAT_ELF;
10823 } else if (!strcmp(p, "binary")) {
10824 s->output_format = TCC_OUTPUT_FORMAT_BINARY;
10825 } else
10826 #ifdef TCC_TARGET_COFF
10827 if (!strcmp(p, "coff")) {
10828 s->output_format = TCC_OUTPUT_FORMAT_COFF;
10829 } else
10830 #endif
10832 error("target %s not found", p);
10834 } else {
10835 error("unsupported linker option '%s'", optarg);
10838 break;
10839 case TCC_OPTION_E:
10840 output_type = TCC_OUTPUT_PREPROCESS;
10841 break;
10842 default:
10843 if (s->warn_unsupported) {
10844 unsupported_option:
10845 warning("unsupported option '%s'", r);
10847 break;
10851 return optind;
10854 int main(int argc, char **argv)
10856 int i;
10857 TCCState *s;
10858 int nb_objfiles, ret, optind;
10859 char objfilename[1024];
10860 int64_t start_time = 0;
10862 #ifdef _WIN32
10863 tcc_lib_path = w32_tcc_lib_path();
10864 #endif
10866 s = tcc_new();
10867 output_type = TCC_OUTPUT_EXE;
10868 outfile = NULL;
10869 multiple_files = 1;
10870 files = NULL;
10871 nb_files = 0;
10872 nb_libraries = 0;
10873 reloc_output = 0;
10874 print_search_dirs = 0;
10876 optind = parse_args(s, argc - 1, argv + 1) + 1;
10878 if (print_search_dirs) {
10879 /* enough for Linux kernel */
10880 printf("install: %s/\n", tcc_lib_path);
10881 return 0;
10884 nb_objfiles = nb_files - nb_libraries;
10886 /* if outfile provided without other options, we output an
10887 executable */
10888 if (outfile && output_type == TCC_OUTPUT_MEMORY)
10889 output_type = TCC_OUTPUT_EXE;
10891 /* check -c consistency : only single file handled. XXX: checks file type */
10892 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
10893 /* accepts only a single input file */
10894 if (nb_objfiles != 1)
10895 error("cannot specify multiple files with -c");
10896 if (nb_libraries != 0)
10897 error("cannot specify libraries with -c");
10901 if (output_type == TCC_OUTPUT_PREPROCESS) {
10902 if (!outfile) {
10903 s->outfile = stdout;
10904 } else {
10905 s->outfile = fopen(outfile, "wb");
10906 if (!s->outfile)
10907 error("could not open '%s", outfile);
10909 } else if (output_type != TCC_OUTPUT_MEMORY) {
10910 if (!outfile) {
10911 /* compute default outfile name */
10912 pstrcpy(objfilename, sizeof(objfilename) - 1,
10913 /* strip path */
10914 tcc_basename(files[0]));
10915 #ifdef TCC_TARGET_PE
10916 pe_guess_outfile(objfilename, output_type);
10917 #else
10918 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
10919 char *ext = strrchr(objfilename, '.');
10920 if (!ext)
10921 goto default_outfile;
10922 /* add .o extension */
10923 strcpy(ext + 1, "o");
10924 } else {
10925 default_outfile:
10926 pstrcpy(objfilename, sizeof(objfilename), "a.out");
10928 #endif
10929 outfile = objfilename;
10933 if (do_bench) {
10934 start_time = getclock_us();
10937 tcc_set_output_type(s, output_type);
10939 /* compile or add each files or library */
10940 for(i = 0;i < nb_files; i++) {
10941 const char *filename;
10943 filename = files[i];
10944 if (output_type == TCC_OUTPUT_PREPROCESS) {
10945 tcc_add_file_internal(s, filename,
10946 AFF_PRINT_ERROR | AFF_PREPROCESS);
10947 } else {
10948 if (filename[0] == '-') {
10949 if (tcc_add_library(s, filename + 2) < 0)
10950 error("cannot find %s", filename);
10951 } else {
10952 if (tcc_add_file(s, filename) < 0) {
10953 ret = 1;
10954 goto the_end;
10960 /* free all files */
10961 tcc_free(files);
10963 if (do_bench) {
10964 double total_time;
10965 total_time = (double)(getclock_us() - start_time) / 1000000.0;
10966 if (total_time < 0.001)
10967 total_time = 0.001;
10968 if (total_bytes < 1)
10969 total_bytes = 1;
10970 printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
10971 tok_ident - TOK_IDENT, total_lines, total_bytes,
10972 total_time, (int)(total_lines / total_time),
10973 total_bytes / total_time / 1000000.0);
10976 if (s->output_type == TCC_OUTPUT_PREPROCESS) {
10977 if (outfile)
10978 fclose(s->outfile);
10979 ret = 0;
10980 } else if (s->output_type == TCC_OUTPUT_MEMORY) {
10981 ret = tcc_run(s, argc - optind, argv + optind);
10982 } else
10983 #ifdef TCC_TARGET_PE
10984 if (s->output_type != TCC_OUTPUT_OBJ) {
10985 ret = tcc_output_pe(s, outfile);
10986 } else
10987 #endif
10989 ret = tcc_output_file(s, outfile) ? 1 : 0;
10991 the_end:
10992 /* XXX: cannot do it with bound checking because of the malloc hooks */
10993 if (!do_bounds_check)
10994 tcc_delete(s);
10996 #ifdef MEM_DEBUG
10997 if (do_bench) {
10998 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size, mem_max_size);
11000 #endif
11001 return ret;
11004 #endif