enable multiple states and fix minor memory leaks
[tinycc/k1w1.git] / tcc.c
blob55c96081b4b64944320dd4081bc8144183c37da8
1 /*
2 * TCC - Tiny C Compiler
3 *
4 * Copyright (c) 2001-2004 Fabrice Bellard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #define _GNU_SOURCE
21 #include "config.h"
23 #ifdef CONFIG_TCCBOOT
25 #include "tccboot.h"
26 #define CONFIG_TCC_STATIC
28 #else
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <stdarg.h>
33 #include <string.h>
34 #include <errno.h>
35 #include <math.h>
36 #include <unistd.h>
37 #include <signal.h>
38 #include <fcntl.h>
39 #include <setjmp.h>
40 #include <time.h>
41 #ifdef _WIN32
42 #include <sys/timeb.h>
43 #include <windows.h>
44 #endif
45 #ifndef _WIN32
46 #include <sys/time.h>
47 #include <sys/ucontext.h>
48 #include <sys/mman.h>
49 #endif
51 #endif /* !CONFIG_TCCBOOT */
53 #ifndef PAGESIZE
54 #define PAGESIZE 4096
55 #endif
57 #include "elf.h"
58 #include "stab.h"
60 #ifndef O_BINARY
61 #define O_BINARY 0
62 #endif
64 #include "libtcc.h"
66 /* parser debug */
67 //#define PARSE_DEBUG
68 /* preprocessor debug */
69 //#define PP_DEBUG
70 /* include file debug */
71 //#define INC_DEBUG
73 //#define MEM_DEBUG
75 /* assembler debug */
76 //#define ASM_DEBUG
78 /* target selection */
79 //#define TCC_TARGET_I386 /* i386 code generator */
80 //#define TCC_TARGET_ARM /* ARMv4 code generator */
81 //#define TCC_TARGET_C67 /* TMS320C67xx code generator */
83 /* default target is I386 */
84 #if !defined(TCC_TARGET_I386) && !defined(TCC_TARGET_ARM) && \
85 !defined(TCC_TARGET_C67)
86 #define TCC_TARGET_I386
87 #endif
89 #if !defined(_WIN32) && !defined(TCC_UCLIBC) && !defined(TCC_TARGET_ARM) && \
90 !defined(TCC_TARGET_C67)
91 #define CONFIG_TCC_BCHECK /* enable bound checking code */
92 #endif
94 #if defined(_WIN32) && !defined(TCC_TARGET_PE)
95 #define CONFIG_TCC_STATIC
96 #endif
98 /* define it to include assembler support */
99 #if !defined(TCC_TARGET_ARM) && !defined(TCC_TARGET_C67)
100 #define CONFIG_TCC_ASM
101 #endif
103 /* object format selection */
104 #if defined(TCC_TARGET_C67)
105 #define TCC_TARGET_COFF
106 #endif
108 #define FALSE 0
109 #define false 0
110 #define TRUE 1
111 #define true 1
112 typedef int BOOL;
114 /* path to find crt1.o, crti.o and crtn.o. Only needed when generating
115 executables or dlls */
116 #define CONFIG_TCC_CRT_PREFIX "/usr/lib"
118 #define INCLUDE_STACK_SIZE 32
119 #define IFDEF_STACK_SIZE 64
120 #define VSTACK_SIZE 256
121 #define STRING_MAX_SIZE 1024
122 #define PACK_STACK_SIZE 8
124 #define TOK_HASH_SIZE 8192 /* must be a power of two */
125 #define TOK_ALLOC_INCR 512 /* must be a power of two */
126 #define TOK_MAX_SIZE 4 /* token max size in int unit when stored in string */
128 /* token symbol management */
129 typedef struct TokenSym {
130 struct TokenSym *hash_next;
131 struct Sym *sym_define; /* direct pointer to define */
132 struct Sym *sym_label; /* direct pointer to label */
133 struct Sym *sym_struct; /* direct pointer to structure */
134 struct Sym *sym_identifier; /* direct pointer to identifier */
135 int tok; /* token number */
136 int len;
137 char str[1];
138 } TokenSym;
140 #ifdef TCC_TARGET_PE
141 typedef unsigned short nwchar_t;
142 #else
143 typedef int nwchar_t;
144 #endif
146 typedef struct CString {
147 int size; /* size in bytes */
148 void *data; /* either 'char *' or 'nwchar_t *' */
149 int size_allocated;
150 void *data_allocated; /* if non NULL, data has been malloced */
151 } CString;
153 /* type definition */
154 typedef struct CType {
155 int t;
156 struct Sym *ref;
157 } CType;
159 /* constant value */
160 typedef union CValue {
161 long double ld;
162 double d;
163 float f;
164 int i;
165 unsigned int ui;
166 unsigned int ul; /* address (should be unsigned long on 64 bit cpu) */
167 long long ll;
168 unsigned long long ull;
169 struct CString *cstr;
170 void *ptr;
171 int tab[1];
172 } CValue;
174 /* value on stack */
175 typedef struct SValue {
176 CType type; /* type */
177 unsigned short r; /* register + flags */
178 unsigned short r2; /* second register, used for 'long long'
179 type. If not used, set to VT_CONST */
180 CValue c; /* constant, if VT_CONST */
181 struct Sym *sym; /* symbol, if (VT_SYM | VT_CONST) */
182 } SValue;
184 /* symbol management */
185 typedef struct Sym {
186 int v; /* symbol token */
187 int r; /* associated register */
188 int c; /* associated number */
189 CType type; /* associated type */
190 struct Sym *next; /* next related symbol */
191 struct Sym *prev; /* prev symbol in stack */
192 struct Sym *prev_tok; /* previous symbol for this token */
193 } Sym;
195 /* section definition */
196 /* XXX: use directly ELF structure for parameters ? */
197 /* special flag to indicate that the section should not be linked to
198 the other ones */
199 #define SHF_PRIVATE 0x80000000
201 typedef struct Section {
202 unsigned long data_offset; /* current data offset */
203 unsigned char *data; /* section data */
204 unsigned long data_allocated; /* used for realloc() handling */
205 int sh_name; /* elf section name (only used during output) */
206 int sh_num; /* elf section number */
207 int sh_type; /* elf section type */
208 int sh_flags; /* elf section flags */
209 int sh_info; /* elf section info */
210 int sh_addralign; /* elf section alignment */
211 int sh_entsize; /* elf entry size */
212 unsigned long sh_size; /* section size (only used during output) */
213 unsigned long sh_addr; /* address at which the section is relocated */
214 unsigned long sh_offset; /* file offset */
215 int nb_hashed_syms; /* used to resize the hash table */
216 struct Section *link; /* link to another section */
217 struct Section *reloc; /* corresponding section for relocation, if any */
218 struct Section *hash; /* hash table for symbols */
219 struct Section *next;
220 char name[1]; /* section name */
221 } Section;
223 typedef struct DLLReference {
224 int level;
225 char name[1];
226 } DLLReference;
228 /* GNUC attribute definition */
229 typedef struct AttributeDef {
230 int aligned;
231 int packed;
232 Section *section;
233 int func_attr; /* calling convention, exports, ... */
234 } AttributeDef;
236 /* -------------------------------------------------- */
237 /* gr: wrappers for casting sym->r for other purposes */
238 typedef struct {
239 unsigned
240 func_call : 8,
241 func_args : 8,
242 func_export : 1;
243 } func_attr_t;
245 #define FUNC_CALL(r) (((func_attr_t*)&(r))->func_call)
246 #define FUNC_EXPORT(r) (((func_attr_t*)&(r))->func_export)
247 #define FUNC_ARGS(r) (((func_attr_t*)&(r))->func_args)
248 #define INLINE_DEF(r) (*(int **)&(r))
249 /* -------------------------------------------------- */
251 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
252 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
253 #define SYM_FIRST_ANOM 0x10000000 /* first anonymous sym */
255 /* stored in 'Sym.c' field */
256 #define FUNC_NEW 1 /* ansi function prototype */
257 #define FUNC_OLD 2 /* old function prototype */
258 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
260 /* stored in 'Sym.r' field */
261 #define FUNC_CDECL 0 /* standard c call */
262 #define FUNC_STDCALL 1 /* pascal c call */
263 #define FUNC_FASTCALL1 2 /* first param in %eax */
264 #define FUNC_FASTCALL2 3 /* first parameters in %eax, %edx */
265 #define FUNC_FASTCALL3 4 /* first parameter in %eax, %edx, %ecx */
266 #define FUNC_FASTCALLW 5 /* first parameter in %ecx, %edx */
268 /* field 'Sym.t' for macros */
269 #define MACRO_OBJ 0 /* object like macro */
270 #define MACRO_FUNC 1 /* function like macro */
272 /* field 'Sym.r' for C labels */
273 #define LABEL_DEFINED 0 /* label is defined */
274 #define LABEL_FORWARD 1 /* label is forward defined */
275 #define LABEL_DECLARED 2 /* label is declared but never used */
277 /* type_decl() types */
278 #define TYPE_ABSTRACT 1 /* type without variable */
279 #define TYPE_DIRECT 2 /* type with variable */
281 #define IO_BUF_SIZE 8192
283 typedef struct BufferedFile {
284 uint8_t *buf_ptr;
285 uint8_t *buf_end;
286 int fd;
287 int line_num; /* current line number - here to simplify code */
288 int ifndef_macro; /* #ifndef macro / #endif search */
289 int ifndef_macro_saved; /* saved ifndef_macro */
290 int *ifdef_stack_ptr; /* ifdef_stack value at the start of the file */
291 char inc_type; /* type of include */
292 char inc_filename[512]; /* filename specified by the user */
293 char filename[1024]; /* current filename - here to simplify code */
294 unsigned char buffer[IO_BUF_SIZE + 1]; /* extra size for CH_EOB char */
295 } BufferedFile;
297 #define CH_EOB '\\' /* end of buffer or '\0' char in file */
298 #define CH_EOF (-1) /* end of file */
300 /* parsing state (used to save parser state to reparse part of the
301 source several times) */
302 typedef struct ParseState {
303 int *macro_ptr;
304 int line_num;
305 int tok;
306 CValue tokc;
307 } ParseState;
309 /* used to record tokens */
310 typedef struct TokenString {
311 int *str;
312 int len;
313 int allocated_len;
314 int last_line_num;
315 } TokenString;
317 /* include file cache, used to find files faster and also to eliminate
318 inclusion if the include file is protected by #ifndef ... #endif */
319 typedef struct CachedInclude {
320 int ifndef_macro;
321 int hash_next; /* -1 if none */
322 char type; /* '"' or '>' to give include type */
323 char filename[1]; /* path specified in #include */
324 } CachedInclude;
326 #define CACHED_INCLUDES_HASH_SIZE 512
328 /* parser */
329 static struct BufferedFile *file;
330 static int ch, tok;
331 static CValue tokc;
332 static CString tokcstr; /* current parsed string, if any */
333 /* additional informations about token */
334 static int tok_flags;
335 #define TOK_FLAG_BOL 0x0001 /* beginning of line before */
336 #define TOK_FLAG_BOF 0x0002 /* beginning of file before */
337 #define TOK_FLAG_ENDIF 0x0004 /* a endif was found matching starting #ifdef */
338 #define TOK_FLAG_EOF 0x0008 /* end of file */
340 static int *macro_ptr, *macro_ptr_allocated;
341 static int *unget_saved_macro_ptr;
342 static int unget_saved_buffer[TOK_MAX_SIZE + 1];
343 static int unget_buffer_enabled;
344 static int parse_flags;
345 #define PARSE_FLAG_PREPROCESS 0x0001 /* activate preprocessing */
346 #define PARSE_FLAG_TOK_NUM 0x0002 /* return numbers instead of TOK_PPNUM */
347 #define PARSE_FLAG_LINEFEED 0x0004 /* line feed is returned as a
348 token. line feed is also
349 returned at eof */
350 #define PARSE_FLAG_ASM_COMMENTS 0x0008 /* '#' can be used for line comment */
352 static Section *text_section, *data_section, *bss_section; /* predefined sections */
353 static Section *cur_text_section; /* current section where function code is
354 generated */
355 #ifdef CONFIG_TCC_ASM
356 static Section *last_text_section; /* to handle .previous asm directive */
357 #endif
358 /* bound check related sections */
359 static Section *bounds_section; /* contains global data bound description */
360 static Section *lbounds_section; /* contains local data bound description */
361 /* symbol sections */
362 static Section *symtab_section, *strtab_section;
364 /* debug sections */
365 static Section *stab_section, *stabstr_section;
367 /* loc : local variable index
368 ind : output code index
369 rsym: return symbol
370 anon_sym: anonymous symbol index
372 static int rsym, anon_sym, ind, loc;
373 /* expression generation modifiers */
374 static int const_wanted; /* true if constant wanted */
375 static int nocode_wanted; /* true if no code generation wanted for an expression */
376 static int global_expr; /* true if compound literals must be allocated
377 globally (used during initializers parsing */
378 static CType func_vt; /* current function return type (used by return
379 instruction) */
380 static int func_vc;
381 static int last_line_num, last_ind, func_ind; /* debug last line number and pc */
382 static int tok_ident;
383 static TokenSym **table_ident;
384 static TokenSym *hash_ident[TOK_HASH_SIZE];
385 static char token_buf[STRING_MAX_SIZE + 1];
386 static char *funcname;
387 static Sym *global_stack, *local_stack;
388 static Sym *define_stack;
389 static Sym *global_label_stack, *local_label_stack;
390 /* symbol allocator */
391 #define SYM_POOL_NB (8192 / sizeof(Sym))
392 static Sym *sym_free_first;
393 static void **sym_pools;
394 static int nb_sym_pools;
396 static SValue vstack[VSTACK_SIZE], *vtop;
397 /* some predefined types */
398 static CType char_pointer_type, func_old_type, int_type;
399 /* true if isid(c) || isnum(c) */
400 static unsigned char isidnum_table[256];
402 /* display some information during compilation */
403 static int verbose = 0;
405 /* compile with debug symbol (and use them if error during execution) */
406 static int do_debug = 0;
408 /* compile with built-in memory and bounds checker */
409 static int do_bounds_check = 0;
411 /* display benchmark infos */
412 #if !defined(LIBTCC)
413 static int do_bench = 0;
414 #endif
415 static int total_lines;
416 static int total_bytes;
418 /* use GNU C extensions */
419 static int gnu_ext = 1;
421 /* use Tiny C extensions */
422 static int tcc_ext = 1;
424 /* max number of callers shown if error */
425 static int num_callers = 6;
426 static const char **rt_bound_error_msg;
428 /* XXX: get rid of this ASAP */
429 static struct TCCState *tcc_state;
431 /* give the path of the tcc libraries */
432 static const char *tcc_lib_path = CONFIG_TCCDIR;
434 struct TCCState {
435 int output_type;
437 BufferedFile **include_stack_ptr;
438 int *ifdef_stack_ptr;
440 /* include file handling */
441 char **include_paths;
442 int nb_include_paths;
443 char **sysinclude_paths;
444 int nb_sysinclude_paths;
445 CachedInclude **cached_includes;
446 int nb_cached_includes;
448 char **library_paths;
449 int nb_library_paths;
451 /* array of all loaded dlls (including those referenced by loaded
452 dlls) */
453 DLLReference **loaded_dlls;
454 int nb_loaded_dlls;
456 /* sections */
457 Section **sections;
458 int nb_sections; /* number of sections, including first dummy section */
460 /* got handling */
461 Section *got;
462 Section *plt;
463 unsigned long *got_offsets;
464 int nb_got_offsets;
465 /* give the correspondance from symtab indexes to dynsym indexes */
466 int *symtab_to_dynsym;
468 /* temporary dynamic symbol sections (for dll loading) */
469 Section *dynsymtab_section;
470 /* exported dynamic symbol section */
471 Section *dynsym;
473 int nostdinc; /* if true, no standard headers are added */
474 int nostdlib; /* if true, no standard libraries are added */
476 int nocommon; /* if true, do not use common symbols for .bss data */
478 /* if true, static linking is performed */
479 int static_link;
481 /* soname as specified on the command line (-soname) */
482 const char *soname;
484 /* if true, all symbols are exported */
485 int rdynamic;
487 /* if true, only link in referenced objects from archive */
488 int alacarte_link;
490 /* address of text section */
491 unsigned long text_addr;
492 int has_text_addr;
494 /* output format, see TCC_OUTPUT_FORMAT_xxx */
495 int output_format;
497 /* C language options */
498 int char_is_unsigned;
499 int leading_underscore;
501 /* warning switches */
502 int warn_write_strings;
503 int warn_unsupported;
504 int warn_error;
505 int warn_none;
506 int warn_implicit_function_declaration;
508 /* error handling */
509 void *error_opaque;
510 void (*error_func)(void *opaque, const char *msg);
511 int error_set_jmp_enabled;
512 jmp_buf error_jmp_buf;
513 int nb_errors;
515 /* tiny assembler state */
516 Sym *asm_labels;
518 /* see include_stack_ptr */
519 BufferedFile *include_stack[INCLUDE_STACK_SIZE];
521 /* see ifdef_stack_ptr */
522 int ifdef_stack[IFDEF_STACK_SIZE];
524 /* see cached_includes */
525 int cached_includes_hash[CACHED_INCLUDES_HASH_SIZE];
527 /* pack stack */
528 int pack_stack[PACK_STACK_SIZE];
529 int *pack_stack_ptr;
531 /* output file for preprocessing */
532 FILE *outfile;
535 /* The current value can be: */
536 #define VT_VALMASK 0x00ff
537 #define VT_CONST 0x00f0 /* constant in vc
538 (must be first non register value) */
539 #define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */
540 #define VT_LOCAL 0x00f2 /* offset on stack */
541 #define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */
542 #define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */
543 #define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */
544 #define VT_LVAL 0x0100 /* var is an lvalue */
545 #define VT_SYM 0x0200 /* a symbol value is added */
546 #define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for
547 char/short stored in integer registers) */
548 #define VT_MUSTBOUND 0x0800 /* bound checking must be done before
549 dereferencing value */
550 #define VT_BOUNDED 0x8000 /* value is bounded. The address of the
551 bounding function call point is in vc */
552 #define VT_LVAL_BYTE 0x1000 /* lvalue is a byte */
553 #define VT_LVAL_SHORT 0x2000 /* lvalue is a short */
554 #define VT_LVAL_UNSIGNED 0x4000 /* lvalue is unsigned */
555 #define VT_LVAL_TYPE (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)
557 /* types */
558 #define VT_INT 0 /* integer type */
559 #define VT_BYTE 1 /* signed byte type */
560 #define VT_SHORT 2 /* short type */
561 #define VT_VOID 3 /* void type */
562 #define VT_PTR 4 /* pointer */
563 #define VT_ENUM 5 /* enum definition */
564 #define VT_FUNC 6 /* function type */
565 #define VT_STRUCT 7 /* struct/union definition */
566 #define VT_FLOAT 8 /* IEEE float */
567 #define VT_DOUBLE 9 /* IEEE double */
568 #define VT_LDOUBLE 10 /* IEEE long double */
569 #define VT_BOOL 11 /* ISOC99 boolean type */
570 #define VT_LLONG 12 /* 64 bit integer */
571 #define VT_LONG 13 /* long integer (NEVER USED as type, only
572 during parsing) */
573 #define VT_BTYPE 0x000f /* mask for basic type */
574 #define VT_UNSIGNED 0x0010 /* unsigned type */
575 #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
576 #define VT_BITFIELD 0x0040 /* bitfield modifier */
577 #define VT_CONSTANT 0x0800 /* const modifier */
578 #define VT_VOLATILE 0x1000 /* volatile modifier */
579 #define VT_SIGNED 0x2000 /* signed type */
581 /* storage */
582 #define VT_EXTERN 0x00000080 /* extern definition */
583 #define VT_STATIC 0x00000100 /* static variable */
584 #define VT_TYPEDEF 0x00000200 /* typedef definition */
585 #define VT_INLINE 0x00000400 /* inline definition */
587 #define VT_STRUCT_SHIFT 16 /* shift for bitfield shift values */
589 /* type mask (except storage) */
590 #define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE)
591 #define VT_TYPE (~(VT_STORAGE))
593 /* token values */
595 /* warning: the following compare tokens depend on i386 asm code */
596 #define TOK_ULT 0x92
597 #define TOK_UGE 0x93
598 #define TOK_EQ 0x94
599 #define TOK_NE 0x95
600 #define TOK_ULE 0x96
601 #define TOK_UGT 0x97
602 #define TOK_Nset 0x98
603 #define TOK_Nclear 0x99
604 #define TOK_LT 0x9c
605 #define TOK_GE 0x9d
606 #define TOK_LE 0x9e
607 #define TOK_GT 0x9f
609 #define TOK_LAND 0xa0
610 #define TOK_LOR 0xa1
612 #define TOK_DEC 0xa2
613 #define TOK_MID 0xa3 /* inc/dec, to void constant */
614 #define TOK_INC 0xa4
615 #define TOK_UDIV 0xb0 /* unsigned division */
616 #define TOK_UMOD 0xb1 /* unsigned modulo */
617 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
618 #define TOK_CINT 0xb3 /* number in tokc */
619 #define TOK_CCHAR 0xb4 /* char constant in tokc */
620 #define TOK_STR 0xb5 /* pointer to string in tokc */
621 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
622 #define TOK_LCHAR 0xb7
623 #define TOK_LSTR 0xb8
624 #define TOK_CFLOAT 0xb9 /* float constant */
625 #define TOK_LINENUM 0xba /* line number info */
626 #define TOK_CDOUBLE 0xc0 /* double constant */
627 #define TOK_CLDOUBLE 0xc1 /* long double constant */
628 #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
629 #define TOK_ADDC1 0xc3 /* add with carry generation */
630 #define TOK_ADDC2 0xc4 /* add with carry use */
631 #define TOK_SUBC1 0xc5 /* add with carry generation */
632 #define TOK_SUBC2 0xc6 /* add with carry use */
633 #define TOK_CUINT 0xc8 /* unsigned int constant */
634 #define TOK_CLLONG 0xc9 /* long long constant */
635 #define TOK_CULLONG 0xca /* unsigned long long constant */
636 #define TOK_ARROW 0xcb
637 #define TOK_DOTS 0xcc /* three dots */
638 #define TOK_SHR 0xcd /* unsigned shift right */
639 #define TOK_PPNUM 0xce /* preprocessor number */
641 #define TOK_SHL 0x01 /* shift left */
642 #define TOK_SAR 0x02 /* signed shift right */
644 /* assignement operators : normal operator or 0x80 */
645 #define TOK_A_MOD 0xa5
646 #define TOK_A_AND 0xa6
647 #define TOK_A_MUL 0xaa
648 #define TOK_A_ADD 0xab
649 #define TOK_A_SUB 0xad
650 #define TOK_A_DIV 0xaf
651 #define TOK_A_XOR 0xde
652 #define TOK_A_OR 0xfc
653 #define TOK_A_SHL 0x81
654 #define TOK_A_SAR 0x82
656 #ifndef offsetof
657 #define offsetof(type, field) ((size_t) &((type *)0)->field)
658 #endif
660 #ifndef countof
661 #define countof(tab) (sizeof(tab) / sizeof((tab)[0]))
662 #endif
664 /* WARNING: the content of this string encodes token numbers */
665 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";
667 #define TOK_EOF (-1) /* end of file */
668 #define TOK_LINEFEED 10 /* line feed */
670 /* all identificators and strings have token above that */
671 #define TOK_IDENT 256
673 /* only used for i386 asm opcodes definitions */
674 #define DEF_ASM(x) DEF(TOK_ASM_ ## x, #x)
676 #define DEF_BWL(x) \
677 DEF(TOK_ASM_ ## x ## b, #x "b") \
678 DEF(TOK_ASM_ ## x ## w, #x "w") \
679 DEF(TOK_ASM_ ## x ## l, #x "l") \
680 DEF(TOK_ASM_ ## x, #x)
682 #define DEF_WL(x) \
683 DEF(TOK_ASM_ ## x ## w, #x "w") \
684 DEF(TOK_ASM_ ## x ## l, #x "l") \
685 DEF(TOK_ASM_ ## x, #x)
687 #define DEF_FP1(x) \
688 DEF(TOK_ASM_ ## f ## x ## s, "f" #x "s") \
689 DEF(TOK_ASM_ ## fi ## x ## l, "fi" #x "l") \
690 DEF(TOK_ASM_ ## f ## x ## l, "f" #x "l") \
691 DEF(TOK_ASM_ ## fi ## x ## s, "fi" #x "s")
693 #define DEF_FP(x) \
694 DEF(TOK_ASM_ ## f ## x, "f" #x ) \
695 DEF(TOK_ASM_ ## f ## x ## p, "f" #x "p") \
696 DEF_FP1(x)
698 #define DEF_ASMTEST(x) \
699 DEF_ASM(x ## o) \
700 DEF_ASM(x ## no) \
701 DEF_ASM(x ## b) \
702 DEF_ASM(x ## c) \
703 DEF_ASM(x ## nae) \
704 DEF_ASM(x ## nb) \
705 DEF_ASM(x ## nc) \
706 DEF_ASM(x ## ae) \
707 DEF_ASM(x ## e) \
708 DEF_ASM(x ## z) \
709 DEF_ASM(x ## ne) \
710 DEF_ASM(x ## nz) \
711 DEF_ASM(x ## be) \
712 DEF_ASM(x ## na) \
713 DEF_ASM(x ## nbe) \
714 DEF_ASM(x ## a) \
715 DEF_ASM(x ## s) \
716 DEF_ASM(x ## ns) \
717 DEF_ASM(x ## p) \
718 DEF_ASM(x ## pe) \
719 DEF_ASM(x ## np) \
720 DEF_ASM(x ## po) \
721 DEF_ASM(x ## l) \
722 DEF_ASM(x ## nge) \
723 DEF_ASM(x ## nl) \
724 DEF_ASM(x ## ge) \
725 DEF_ASM(x ## le) \
726 DEF_ASM(x ## ng) \
727 DEF_ASM(x ## nle) \
728 DEF_ASM(x ## g)
730 #define TOK_ASM_int TOK_INT
732 enum tcc_token {
733 TOK_LAST = TOK_IDENT - 1,
734 #define DEF(id, str) id,
735 #include "tcctok.h"
736 #undef DEF
739 static const char tcc_keywords[] =
740 #define DEF(id, str) str "\0"
741 #include "tcctok.h"
742 #undef DEF
745 #define TOK_UIDENT TOK_DEFINE
747 #ifdef _WIN32
748 #define snprintf _snprintf
749 #define vsnprintf _vsnprintf
750 #ifndef __GNUC__
751 #define strtold (long double)strtod
752 #define strtof (float)strtod
753 #define strtoll (long long)strtol
754 #endif
755 #elif defined(TCC_UCLIBC) || defined(__FreeBSD__) || defined(__DragonFly__) \
756 || defined(__OpenBSD__)
757 /* currently incorrect */
758 long double strtold(const char *nptr, char **endptr)
760 return (long double)strtod(nptr, endptr);
762 float strtof(const char *nptr, char **endptr)
764 return (float)strtod(nptr, endptr);
766 #else
767 /* XXX: need to define this to use them in non ISOC99 context */
768 extern float strtof (const char *__nptr, char **__endptr);
769 extern long double strtold (const char *__nptr, char **__endptr);
770 #endif
772 static char *pstrcpy(char *buf, int buf_size, const char *s);
773 static char *pstrcat(char *buf, int buf_size, const char *s);
774 static char *tcc_basename(const char *name);
775 static char *tcc_fileextension (const char *p);
777 static void next(void);
778 static void next_nomacro(void);
779 static void parse_expr_type(CType *type);
780 static void expr_type(CType *type);
781 static void unary_type(CType *type);
782 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
783 int case_reg, int is_expr);
784 static int expr_const(void);
785 static void expr_eq(void);
786 static void gexpr(void);
787 static void gen_inline_functions(void);
788 static void decl(int l);
789 static void decl_initializer(CType *type, Section *sec, unsigned long c,
790 int first, int size_only);
791 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
792 int has_init, int v, int scope);
793 int gv(int rc);
794 void gv2(int rc1, int rc2);
795 void move_reg(int r, int s);
796 void save_regs(int n);
797 void save_reg(int r);
798 void vpop(void);
799 void vswap(void);
800 void vdup(void);
801 int get_reg(int rc);
802 int get_reg_ex(int rc,int rc2);
804 struct macro_level {
805 struct macro_level *prev;
806 int *p;
809 static void macro_subst(TokenString *tok_str, Sym **nested_list,
810 const int *macro_str, struct macro_level **can_read_stream);
811 void gen_op(int op);
812 void force_charshort_cast(int t);
813 static void gen_cast(CType *type);
814 void vstore(void);
815 static Sym *sym_find(int v);
816 static Sym *sym_push(int v, CType *type, int r, int c);
818 /* type handling */
819 static int type_size(CType *type, int *a);
820 static inline CType *pointed_type(CType *type);
821 static int pointed_size(CType *type);
822 static int lvalue_type(int t);
823 static int parse_btype(CType *type, AttributeDef *ad);
824 static void type_decl(CType *type, AttributeDef *ad, int *v, int td);
825 static int compare_types(CType *type1, CType *type2, int unqualified);
826 static int is_compatible_types(CType *type1, CType *type2);
827 static int is_compatible_parameter_types(CType *type1, CType *type2);
829 int ieee_finite(double d);
830 void error(const char *fmt, ...);
831 void vpushi(int v);
832 void vrott(int n);
833 void vnrott(int n);
834 void lexpand_nr(void);
835 static void vpush_global_sym(CType *type, int v);
836 void vset(CType *type, int r, int v);
837 void type_to_str(char *buf, int buf_size,
838 CType *type, const char *varstr);
839 char *get_tok_str(int v, CValue *cv);
840 static Sym *get_sym_ref(CType *type, Section *sec,
841 unsigned long offset, unsigned long size);
842 static Sym *external_global_sym(int v, CType *type, int r);
844 /* section generation */
845 static void section_realloc(Section *sec, unsigned long new_size);
846 static void *section_ptr_add(Section *sec, unsigned long size);
847 static void put_extern_sym(Sym *sym, Section *section,
848 unsigned long value, unsigned long size);
849 static void greloc(Section *s, Sym *sym, unsigned long addr, int type);
850 static int put_elf_str(Section *s, const char *sym);
851 static int put_elf_sym(Section *s,
852 unsigned long value, unsigned long size,
853 int info, int other, int shndx, const char *name);
854 static int add_elf_sym(Section *s, unsigned long value, unsigned long size,
855 int info, int other, int sh_num, const char *name);
856 static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
857 int type, int symbol);
858 static void put_stabs(const char *str, int type, int other, int desc,
859 unsigned long value);
860 static void put_stabs_r(const char *str, int type, int other, int desc,
861 unsigned long value, Section *sec, int sym_index);
862 static void put_stabn(int type, int other, int desc, int value);
863 static void put_stabd(int type, int other, int desc);
864 static int tcc_add_dll(TCCState *s, const char *filename, int flags);
866 #define AFF_PRINT_ERROR 0x0001 /* print error if file not found */
867 #define AFF_REFERENCED_DLL 0x0002 /* load a referenced dll from another dll */
868 #define AFF_PREPROCESS 0x0004 /* preprocess file */
869 static int tcc_add_file_internal(TCCState *s, const char *filename, int flags);
871 /* tcccoff.c */
872 int tcc_output_coff(TCCState *s1, FILE *f);
874 /* tccpe.c */
875 void *resolve_sym(TCCState *s1, const char *sym, int type);
876 int pe_load_def_file(struct TCCState *s1, int fd);
877 int pe_test_res_file(void *v, int size);
878 int pe_load_res_file(struct TCCState *s1, int fd);
879 void pe_add_runtime(struct TCCState *s1);
880 void pe_guess_outfile(char *objfilename, int output_type);
881 int pe_output_file(struct TCCState *s1, const char *filename);
883 /* tccasm.c */
885 #ifdef CONFIG_TCC_ASM
887 typedef struct ExprValue {
888 uint32_t v;
889 Sym *sym;
890 } ExprValue;
892 #define MAX_ASM_OPERANDS 30
894 typedef struct ASMOperand {
895 int id; /* GCC 3 optionnal identifier (0 if number only supported */
896 char *constraint;
897 char asm_str[16]; /* computed asm string for operand */
898 SValue *vt; /* C value of the expression */
899 int ref_index; /* if >= 0, gives reference to a output constraint */
900 int input_index; /* if >= 0, gives reference to an input constraint */
901 int priority; /* priority, used to assign registers */
902 int reg; /* if >= 0, register number used for this operand */
903 int is_llong; /* true if double register value */
904 int is_memory; /* true if memory operand */
905 int is_rw; /* for '+' modifier */
906 } ASMOperand;
908 static void asm_expr(TCCState *s1, ExprValue *pe);
909 static int asm_int_expr(TCCState *s1);
910 static int find_constraint(ASMOperand *operands, int nb_operands,
911 const char *name, const char **pp);
913 static int tcc_assemble(TCCState *s1, int do_preprocess);
915 #endif
917 static void asm_instr(void);
918 static void asm_global_instr(void);
920 /* true if float/double/long double type */
921 static inline int is_float(int t)
923 int bt;
924 bt = t & VT_BTYPE;
925 return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT;
928 #ifdef TCC_TARGET_I386
929 #include "i386-gen.c"
930 #endif
932 #ifdef TCC_TARGET_ARM
933 #include "arm-gen.c"
934 #endif
936 #ifdef TCC_TARGET_C67
937 #include "c67-gen.c"
938 #endif
940 #ifdef CONFIG_TCC_STATIC
942 #define RTLD_LAZY 0x001
943 #define RTLD_NOW 0x002
944 #define RTLD_GLOBAL 0x100
945 #define RTLD_DEFAULT NULL
947 /* dummy function for profiling */
948 void *dlopen(const char *filename, int flag)
950 return NULL;
953 const char *dlerror(void)
955 return "error";
958 typedef struct TCCSyms {
959 char *str;
960 void *ptr;
961 } TCCSyms;
963 #define TCCSYM(a) { #a, &a, },
965 /* add the symbol you want here if no dynamic linking is done */
966 static TCCSyms tcc_syms[] = {
967 #if !defined(CONFIG_TCCBOOT)
968 TCCSYM(printf)
969 TCCSYM(fprintf)
970 TCCSYM(fopen)
971 TCCSYM(fclose)
972 #endif
973 { NULL, NULL },
976 void *resolve_sym(TCCState *s1, const char *symbol, int type)
978 TCCSyms *p;
979 p = tcc_syms;
980 while (p->str != NULL) {
981 if (!strcmp(p->str, symbol))
982 return p->ptr;
983 p++;
985 return NULL;
988 #elif !defined(_WIN32)
990 #include <dlfcn.h>
992 void *resolve_sym(TCCState *s1, const char *sym, int type)
994 return dlsym(RTLD_DEFAULT, sym);
997 #endif
999 /********************************************************/
1001 /* we use our own 'finite' function to avoid potential problems with
1002 non standard math libs */
1003 /* XXX: endianness dependent */
1004 int ieee_finite(double d)
1006 int *p = (int *)&d;
1007 return ((unsigned)((p[1] | 0x800fffff) + 1)) >> 31;
1010 /* copy a string and truncate it. */
1011 static char *pstrcpy(char *buf, int buf_size, const char *s)
1013 char *q, *q_end;
1014 int c;
1016 if (buf_size > 0) {
1017 q = buf;
1018 q_end = buf + buf_size - 1;
1019 while (q < q_end) {
1020 c = *s++;
1021 if (c == '\0')
1022 break;
1023 *q++ = c;
1025 *q = '\0';
1027 return buf;
1030 /* strcat and truncate. */
1031 static char *pstrcat(char *buf, int buf_size, const char *s)
1033 int len;
1034 len = strlen(buf);
1035 if (len < buf_size)
1036 pstrcpy(buf + len, buf_size - len, s);
1037 return buf;
1040 #ifndef LIBTCC
1041 static int strstart(const char *str, const char *val, const char **ptr)
1043 const char *p, *q;
1044 p = str;
1045 q = val;
1046 while (*q != '\0') {
1047 if (*p != *q)
1048 return 0;
1049 p++;
1050 q++;
1052 if (ptr)
1053 *ptr = p;
1054 return 1;
1056 #endif
1058 /* extract the basename of a file */
1059 static char *tcc_basename(const char *name)
1061 char *p = strchr(name, 0);
1062 while (p > name
1063 && p[-1] != '/'
1064 #ifdef _WIN32
1065 && p[-1] != '\\'
1066 #endif
1068 --p;
1069 return p;
1072 static char *tcc_fileextension (const char *name)
1074 char *b = tcc_basename(name);
1075 char *e = strrchr(b, '.');
1076 return e ? e : strchr(b, 0);
1079 #ifdef _WIN32
1080 char *normalize_slashes(char *path)
1082 char *p;
1083 for (p = path; *p; ++p)
1084 if (*p == '\\')
1085 *p = '/';
1086 return path;
1089 char *w32_tcc_lib_path(void)
1091 /* on win32, we suppose the lib and includes are at the location
1092 of 'tcc.exe' */
1093 char path[1024], *p;
1094 GetModuleFileNameA(NULL, path, sizeof path);
1095 p = tcc_basename(normalize_slashes(strlwr(path)));
1096 if (p - 5 > path && 0 == strncmp(p - 5, "/bin/", 5))
1097 p -= 5;
1098 else if (p > path)
1099 p--;
1100 *p = 0;
1101 return strdup(path);
1103 #endif
1105 void set_pages_executable(void *ptr, unsigned long length)
1107 #ifdef _WIN32
1108 unsigned long old_protect;
1109 VirtualProtect(ptr, length, PAGE_EXECUTE_READWRITE, &old_protect);
1110 #else
1111 unsigned long start, end;
1112 start = (unsigned long)ptr & ~(PAGESIZE - 1);
1113 end = (unsigned long)ptr + length;
1114 end = (end + PAGESIZE - 1) & ~(PAGESIZE - 1);
1115 mprotect((void *)start, end - start, PROT_READ | PROT_WRITE | PROT_EXEC);
1116 #endif
1119 /* memory management */
1120 #ifdef MEM_DEBUG
1121 int mem_cur_size;
1122 int mem_max_size;
1123 unsigned malloc_usable_size(void*);
1124 #endif
1126 static inline void tcc_free(void *ptr)
1128 #ifdef MEM_DEBUG
1129 mem_cur_size -= malloc_usable_size(ptr);
1130 #endif
1131 free(ptr);
1134 static void *tcc_malloc(unsigned long size)
1136 void *ptr;
1137 ptr = malloc(size);
1138 if (!ptr && size)
1139 error("memory full");
1140 #ifdef MEM_DEBUG
1141 mem_cur_size += malloc_usable_size(ptr);
1142 if (mem_cur_size > mem_max_size)
1143 mem_max_size = mem_cur_size;
1144 #endif
1145 return ptr;
1148 static void *tcc_mallocz(unsigned long size)
1150 void *ptr;
1151 ptr = tcc_malloc(size);
1152 memset(ptr, 0, size);
1153 return ptr;
1156 static inline void *tcc_realloc(void *ptr, unsigned long size)
1158 void *ptr1;
1159 #ifdef MEM_DEBUG
1160 mem_cur_size -= malloc_usable_size(ptr);
1161 #endif
1162 ptr1 = realloc(ptr, size);
1163 #ifdef MEM_DEBUG
1164 /* NOTE: count not correct if alloc error, but not critical */
1165 mem_cur_size += malloc_usable_size(ptr1);
1166 if (mem_cur_size > mem_max_size)
1167 mem_max_size = mem_cur_size;
1168 #endif
1169 return ptr1;
1172 static char *tcc_strdup(const char *str)
1174 char *ptr;
1175 ptr = tcc_malloc(strlen(str) + 1);
1176 strcpy(ptr, str);
1177 return ptr;
1180 #define free(p) use_tcc_free(p)
1181 #define malloc(s) use_tcc_malloc(s)
1182 #define realloc(p, s) use_tcc_realloc(p, s)
1184 static void dynarray_add(void ***ptab, int *nb_ptr, void *data)
1186 int nb, nb_alloc;
1187 void **pp;
1189 nb = *nb_ptr;
1190 pp = *ptab;
1191 /* every power of two we double array size */
1192 if ((nb & (nb - 1)) == 0) {
1193 if (!nb)
1194 nb_alloc = 1;
1195 else
1196 nb_alloc = nb * 2;
1197 pp = tcc_realloc(pp, nb_alloc * sizeof(void *));
1198 if (!pp)
1199 error("memory full");
1200 *ptab = pp;
1202 pp[nb++] = data;
1203 *nb_ptr = nb;
1206 static void dynarray_reset(void *pp, int *n)
1208 void **p;
1209 for (p = *(void***)pp; *n; ++p, --*n)
1210 if (*p)
1211 tcc_free(*p);
1212 tcc_free(*(void**)pp);
1213 *(void**)pp = NULL;
1216 /* symbol allocator */
1217 static Sym *__sym_malloc(void)
1219 Sym *sym_pool, *sym, *last_sym;
1220 int i;
1222 sym_pool = tcc_malloc(SYM_POOL_NB * sizeof(Sym));
1223 dynarray_add(&sym_pools, &nb_sym_pools, sym_pool);
1225 last_sym = sym_free_first;
1226 sym = sym_pool;
1227 for(i = 0; i < SYM_POOL_NB; i++) {
1228 sym->next = last_sym;
1229 last_sym = sym;
1230 sym++;
1232 sym_free_first = last_sym;
1233 return last_sym;
1236 static inline Sym *sym_malloc(void)
1238 Sym *sym;
1239 sym = sym_free_first;
1240 if (!sym)
1241 sym = __sym_malloc();
1242 sym_free_first = sym->next;
1243 return sym;
1246 static inline void sym_free(Sym *sym)
1248 sym->next = sym_free_first;
1249 sym_free_first = sym;
1252 Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags)
1254 Section *sec;
1256 sec = tcc_mallocz(sizeof(Section) + strlen(name));
1257 strcpy(sec->name, name);
1258 sec->sh_type = sh_type;
1259 sec->sh_flags = sh_flags;
1260 switch(sh_type) {
1261 case SHT_HASH:
1262 case SHT_REL:
1263 case SHT_DYNSYM:
1264 case SHT_SYMTAB:
1265 case SHT_DYNAMIC:
1266 sec->sh_addralign = 4;
1267 break;
1268 case SHT_STRTAB:
1269 sec->sh_addralign = 1;
1270 break;
1271 default:
1272 sec->sh_addralign = 32; /* default conservative alignment */
1273 break;
1276 /* only add section if not private */
1277 if (!(sh_flags & SHF_PRIVATE)) {
1278 sec->sh_num = s1->nb_sections;
1279 dynarray_add((void ***)&s1->sections, &s1->nb_sections, sec);
1281 return sec;
1284 static void free_section(Section *s)
1286 if (s->link && 0 == s->link->sh_num)
1287 free_section(s->link);
1288 if (s->hash && 0 == s->hash->sh_num)
1289 s->hash->link = NULL, free_section(s->hash);
1290 tcc_free(s->data);
1291 tcc_free(s);
1294 /* realloc section and set its content to zero */
1295 static void section_realloc(Section *sec, unsigned long new_size)
1297 unsigned long size;
1298 unsigned char *data;
1300 size = sec->data_allocated;
1301 if (size == 0)
1302 size = 1;
1303 while (size < new_size)
1304 size = size * 2;
1305 data = tcc_realloc(sec->data, size);
1306 if (!data)
1307 error("memory full");
1308 memset(data + sec->data_allocated, 0, size - sec->data_allocated);
1309 sec->data = data;
1310 sec->data_allocated = size;
1313 /* reserve at least 'size' bytes in section 'sec' from
1314 sec->data_offset. */
1315 static void *section_ptr_add(Section *sec, unsigned long size)
1317 unsigned long offset, offset1;
1319 offset = sec->data_offset;
1320 offset1 = offset + size;
1321 if (offset1 > sec->data_allocated)
1322 section_realloc(sec, offset1);
1323 sec->data_offset = offset1;
1324 return sec->data + offset;
1327 /* return a reference to a section, and create it if it does not
1328 exists */
1329 Section *find_section(TCCState *s1, const char *name)
1331 Section *sec;
1332 int i;
1333 for(i = 1; i < s1->nb_sections; i++) {
1334 sec = s1->sections[i];
1335 if (!strcmp(name, sec->name))
1336 return sec;
1338 /* sections are created as PROGBITS */
1339 return new_section(s1, name, SHT_PROGBITS, SHF_ALLOC);
1342 #define SECTION_ABS ((void *)1)
1344 /* update sym->c so that it points to an external symbol in section
1345 'section' with value 'value' */
1346 static void put_extern_sym2(Sym *sym, Section *section,
1347 unsigned long value, unsigned long size,
1348 int can_add_underscore)
1350 int sym_type, sym_bind, sh_num, info, other, attr;
1351 Elf32_Sym *esym;
1352 const char *name;
1353 char buf1[256];
1355 if (section == NULL)
1356 sh_num = SHN_UNDEF;
1357 else if (section == SECTION_ABS)
1358 sh_num = SHN_ABS;
1359 else
1360 sh_num = section->sh_num;
1362 other = attr = 0;
1364 if ((sym->type.t & VT_BTYPE) == VT_FUNC) {
1365 sym_type = STT_FUNC;
1366 #ifdef TCC_TARGET_PE
1367 if (sym->type.ref)
1368 attr = sym->type.ref->r;
1369 if (FUNC_EXPORT(attr))
1370 other |= 1;
1371 if (FUNC_CALL(attr) == FUNC_STDCALL)
1372 other |= 2;
1373 #endif
1374 } else {
1375 sym_type = STT_OBJECT;
1378 if (sym->type.t & VT_STATIC)
1379 sym_bind = STB_LOCAL;
1380 else
1381 sym_bind = STB_GLOBAL;
1383 if (!sym->c) {
1384 name = get_tok_str(sym->v, NULL);
1385 #ifdef CONFIG_TCC_BCHECK
1386 if (do_bounds_check) {
1387 char buf[32];
1389 /* XXX: avoid doing that for statics ? */
1390 /* if bound checking is activated, we change some function
1391 names by adding the "__bound" prefix */
1392 switch(sym->v) {
1393 #if 0
1394 /* XXX: we rely only on malloc hooks */
1395 case TOK_malloc:
1396 case TOK_free:
1397 case TOK_realloc:
1398 case TOK_memalign:
1399 case TOK_calloc:
1400 #endif
1401 case TOK_memcpy:
1402 case TOK_memmove:
1403 case TOK_memset:
1404 case TOK_strlen:
1405 case TOK_strcpy:
1406 case TOK__alloca:
1407 strcpy(buf, "__bound_");
1408 strcat(buf, name);
1409 name = buf;
1410 break;
1413 #endif
1415 #ifdef TCC_TARGET_PE
1416 if ((other & 2) && can_add_underscore) {
1417 sprintf(buf1, "_%s@%d", name, FUNC_ARGS(attr));
1418 name = buf1;
1419 } else
1420 #endif
1421 if (tcc_state->leading_underscore && can_add_underscore) {
1422 buf1[0] = '_';
1423 pstrcpy(buf1 + 1, sizeof(buf1) - 1, name);
1424 name = buf1;
1426 info = ELF32_ST_INFO(sym_bind, sym_type);
1427 sym->c = add_elf_sym(symtab_section, value, size, info, other, sh_num, name);
1428 } else {
1429 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
1430 esym->st_value = value;
1431 esym->st_size = size;
1432 esym->st_shndx = sh_num;
1433 esym->st_other |= other;
1437 static void put_extern_sym(Sym *sym, Section *section,
1438 unsigned long value, unsigned long size)
1440 put_extern_sym2(sym, section, value, size, 1);
1443 /* add a new relocation entry to symbol 'sym' in section 's' */
1444 static void greloc(Section *s, Sym *sym, unsigned long offset, int type)
1446 if (!sym->c)
1447 put_extern_sym(sym, NULL, 0, 0);
1448 /* now we can add ELF relocation info */
1449 put_elf_reloc(symtab_section, s, offset, type, sym->c);
1452 static inline int isid(int c)
1454 return (c >= 'a' && c <= 'z') ||
1455 (c >= 'A' && c <= 'Z') ||
1456 c == '_';
1459 static inline int isnum(int c)
1461 return c >= '0' && c <= '9';
1464 static inline int isoct(int c)
1466 return c >= '0' && c <= '7';
1469 static inline int toup(int c)
1471 if (c >= 'a' && c <= 'z')
1472 return c - 'a' + 'A';
1473 else
1474 return c;
1477 static void strcat_vprintf(char *buf, int buf_size, const char *fmt, va_list ap)
1479 int len;
1480 len = strlen(buf);
1481 vsnprintf(buf + len, buf_size - len, fmt, ap);
1484 static void strcat_printf(char *buf, int buf_size, const char *fmt, ...)
1486 va_list ap;
1487 va_start(ap, fmt);
1488 strcat_vprintf(buf, buf_size, fmt, ap);
1489 va_end(ap);
1492 void error1(TCCState *s1, int is_warning, const char *fmt, va_list ap)
1494 char buf[2048];
1495 BufferedFile **f;
1497 buf[0] = '\0';
1498 if (file) {
1499 for(f = s1->include_stack; f < s1->include_stack_ptr; f++)
1500 strcat_printf(buf, sizeof(buf), "In file included from %s:%d:\n",
1501 (*f)->filename, (*f)->line_num);
1502 if (file->line_num > 0) {
1503 strcat_printf(buf, sizeof(buf),
1504 "%s:%d: ", file->filename, file->line_num);
1505 } else {
1506 strcat_printf(buf, sizeof(buf),
1507 "%s: ", file->filename);
1509 } else {
1510 strcat_printf(buf, sizeof(buf),
1511 "tcc: ");
1513 if (is_warning)
1514 strcat_printf(buf, sizeof(buf), "warning: ");
1515 strcat_vprintf(buf, sizeof(buf), fmt, ap);
1517 if (!s1->error_func) {
1518 /* default case: stderr */
1519 fprintf(stderr, "%s\n", buf);
1520 } else {
1521 s1->error_func(s1->error_opaque, buf);
1523 if (!is_warning || s1->warn_error)
1524 s1->nb_errors++;
1527 #ifdef LIBTCC
1528 void tcc_set_error_func(TCCState *s, void *error_opaque,
1529 void (*error_func)(void *opaque, const char *msg))
1531 s->error_opaque = error_opaque;
1532 s->error_func = error_func;
1534 #endif
1536 /* error without aborting current compilation */
1537 void error_noabort(const char *fmt, ...)
1539 TCCState *s1 = tcc_state;
1540 va_list ap;
1542 va_start(ap, fmt);
1543 error1(s1, 0, fmt, ap);
1544 va_end(ap);
1547 void error(const char *fmt, ...)
1549 TCCState *s1 = tcc_state;
1550 va_list ap;
1552 va_start(ap, fmt);
1553 error1(s1, 0, fmt, ap);
1554 va_end(ap);
1555 /* better than nothing: in some cases, we accept to handle errors */
1556 if (s1->error_set_jmp_enabled) {
1557 longjmp(s1->error_jmp_buf, 1);
1558 } else {
1559 /* XXX: eliminate this someday */
1560 exit(1);
1564 void expect(const char *msg)
1566 error("%s expected", msg);
1569 void warning(const char *fmt, ...)
1571 TCCState *s1 = tcc_state;
1572 va_list ap;
1574 if (s1->warn_none)
1575 return;
1577 va_start(ap, fmt);
1578 error1(s1, 1, fmt, ap);
1579 va_end(ap);
1582 void skip(int c)
1584 if (tok != c)
1585 error("'%c' expected", c);
1586 next();
1589 static void test_lvalue(void)
1591 if (!(vtop->r & VT_LVAL))
1592 expect("lvalue");
1595 /* allocate a new token */
1596 static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len)
1598 TokenSym *ts, **ptable;
1599 int i;
1601 if (tok_ident >= SYM_FIRST_ANOM)
1602 error("memory full");
1604 /* expand token table if needed */
1605 i = tok_ident - TOK_IDENT;
1606 if ((i % TOK_ALLOC_INCR) == 0) {
1607 ptable = tcc_realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *));
1608 if (!ptable)
1609 error("memory full");
1610 table_ident = ptable;
1613 ts = tcc_malloc(sizeof(TokenSym) + len);
1614 table_ident[i] = ts;
1615 ts->tok = tok_ident++;
1616 ts->sym_define = NULL;
1617 ts->sym_label = NULL;
1618 ts->sym_struct = NULL;
1619 ts->sym_identifier = NULL;
1620 ts->len = len;
1621 ts->hash_next = NULL;
1622 memcpy(ts->str, str, len);
1623 ts->str[len] = '\0';
1624 *pts = ts;
1625 return ts;
1628 #define TOK_HASH_INIT 1
1629 #define TOK_HASH_FUNC(h, c) ((h) * 263 + (c))
1631 /* find a token and add it if not found */
1632 static TokenSym *tok_alloc(const char *str, int len)
1634 TokenSym *ts, **pts;
1635 int i;
1636 unsigned int h;
1638 h = TOK_HASH_INIT;
1639 for(i=0;i<len;i++)
1640 h = TOK_HASH_FUNC(h, ((unsigned char *)str)[i]);
1641 h &= (TOK_HASH_SIZE - 1);
1643 pts = &hash_ident[h];
1644 for(;;) {
1645 ts = *pts;
1646 if (!ts)
1647 break;
1648 if (ts->len == len && !memcmp(ts->str, str, len))
1649 return ts;
1650 pts = &(ts->hash_next);
1652 return tok_alloc_new(pts, str, len);
1655 /* CString handling */
1657 static void cstr_realloc(CString *cstr, int new_size)
1659 int size;
1660 void *data;
1662 size = cstr->size_allocated;
1663 if (size == 0)
1664 size = 8; /* no need to allocate a too small first string */
1665 while (size < new_size)
1666 size = size * 2;
1667 data = tcc_realloc(cstr->data_allocated, size);
1668 if (!data)
1669 error("memory full");
1670 cstr->data_allocated = data;
1671 cstr->size_allocated = size;
1672 cstr->data = data;
1675 /* add a byte */
1676 static inline void cstr_ccat(CString *cstr, int ch)
1678 int size;
1679 size = cstr->size + 1;
1680 if (size > cstr->size_allocated)
1681 cstr_realloc(cstr, size);
1682 ((unsigned char *)cstr->data)[size - 1] = ch;
1683 cstr->size = size;
1686 static void cstr_cat(CString *cstr, const char *str)
1688 int c;
1689 for(;;) {
1690 c = *str;
1691 if (c == '\0')
1692 break;
1693 cstr_ccat(cstr, c);
1694 str++;
1698 /* add a wide char */
1699 static void cstr_wccat(CString *cstr, int ch)
1701 int size;
1702 size = cstr->size + sizeof(nwchar_t);
1703 if (size > cstr->size_allocated)
1704 cstr_realloc(cstr, size);
1705 *(nwchar_t *)(((unsigned char *)cstr->data) + size - sizeof(nwchar_t)) = ch;
1706 cstr->size = size;
1709 static void cstr_new(CString *cstr)
1711 memset(cstr, 0, sizeof(CString));
1714 /* free string and reset it to NULL */
1715 static void cstr_free(CString *cstr)
1717 tcc_free(cstr->data_allocated);
1718 cstr_new(cstr);
1721 #define cstr_reset(cstr) cstr_free(cstr)
1723 /* XXX: unicode ? */
1724 static void add_char(CString *cstr, int c)
1726 if (c == '\'' || c == '\"' || c == '\\') {
1727 /* XXX: could be more precise if char or string */
1728 cstr_ccat(cstr, '\\');
1730 if (c >= 32 && c <= 126) {
1731 cstr_ccat(cstr, c);
1732 } else {
1733 cstr_ccat(cstr, '\\');
1734 if (c == '\n') {
1735 cstr_ccat(cstr, 'n');
1736 } else {
1737 cstr_ccat(cstr, '0' + ((c >> 6) & 7));
1738 cstr_ccat(cstr, '0' + ((c >> 3) & 7));
1739 cstr_ccat(cstr, '0' + (c & 7));
1744 /* XXX: buffer overflow */
1745 /* XXX: float tokens */
1746 char *get_tok_str(int v, CValue *cv)
1748 static char buf[STRING_MAX_SIZE + 1];
1749 static CString cstr_buf;
1750 CString *cstr;
1751 unsigned char *q;
1752 char *p;
1753 int i, len;
1755 /* NOTE: to go faster, we give a fixed buffer for small strings */
1756 cstr_reset(&cstr_buf);
1757 cstr_buf.data = buf;
1758 cstr_buf.size_allocated = sizeof(buf);
1759 p = buf;
1761 switch(v) {
1762 case TOK_CINT:
1763 case TOK_CUINT:
1764 /* XXX: not quite exact, but only useful for testing */
1765 sprintf(p, "%u", cv->ui);
1766 break;
1767 case TOK_CLLONG:
1768 case TOK_CULLONG:
1769 /* XXX: not quite exact, but only useful for testing */
1770 sprintf(p, "%Lu", cv->ull);
1771 break;
1772 case TOK_CCHAR:
1773 case TOK_LCHAR:
1774 cstr_ccat(&cstr_buf, '\'');
1775 add_char(&cstr_buf, cv->i);
1776 cstr_ccat(&cstr_buf, '\'');
1777 cstr_ccat(&cstr_buf, '\0');
1778 break;
1779 case TOK_PPNUM:
1780 cstr = cv->cstr;
1781 len = cstr->size - 1;
1782 for(i=0;i<len;i++)
1783 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1784 cstr_ccat(&cstr_buf, '\0');
1785 break;
1786 case TOK_STR:
1787 case TOK_LSTR:
1788 cstr = cv->cstr;
1789 cstr_ccat(&cstr_buf, '\"');
1790 if (v == TOK_STR) {
1791 len = cstr->size - 1;
1792 for(i=0;i<len;i++)
1793 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1794 } else {
1795 len = (cstr->size / sizeof(nwchar_t)) - 1;
1796 for(i=0;i<len;i++)
1797 add_char(&cstr_buf, ((nwchar_t *)cstr->data)[i]);
1799 cstr_ccat(&cstr_buf, '\"');
1800 cstr_ccat(&cstr_buf, '\0');
1801 break;
1802 case TOK_LT:
1803 v = '<';
1804 goto addv;
1805 case TOK_GT:
1806 v = '>';
1807 goto addv;
1808 case TOK_DOTS:
1809 return strcpy(p, "...");
1810 case TOK_A_SHL:
1811 return strcpy(p, "<<=");
1812 case TOK_A_SAR:
1813 return strcpy(p, ">>=");
1814 default:
1815 if (v < TOK_IDENT) {
1816 /* search in two bytes table */
1817 q = tok_two_chars;
1818 while (*q) {
1819 if (q[2] == v) {
1820 *p++ = q[0];
1821 *p++ = q[1];
1822 *p = '\0';
1823 return buf;
1825 q += 3;
1827 addv:
1828 *p++ = v;
1829 *p = '\0';
1830 } else if (v < tok_ident) {
1831 return table_ident[v - TOK_IDENT]->str;
1832 } else if (v >= SYM_FIRST_ANOM) {
1833 /* special name for anonymous symbol */
1834 sprintf(p, "L.%u", v - SYM_FIRST_ANOM);
1835 } else {
1836 /* should never happen */
1837 return NULL;
1839 break;
1841 return cstr_buf.data;
1844 /* push, without hashing */
1845 static Sym *sym_push2(Sym **ps, int v, int t, int c)
1847 Sym *s;
1848 s = sym_malloc();
1849 s->v = v;
1850 s->type.t = t;
1851 s->c = c;
1852 s->next = NULL;
1853 /* add in stack */
1854 s->prev = *ps;
1855 *ps = s;
1856 return s;
1859 /* find a symbol and return its associated structure. 's' is the top
1860 of the symbol stack */
1861 static Sym *sym_find2(Sym *s, int v)
1863 while (s) {
1864 if (s->v == v)
1865 return s;
1866 s = s->prev;
1868 return NULL;
1871 /* structure lookup */
1872 static inline Sym *struct_find(int v)
1874 v -= TOK_IDENT;
1875 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1876 return NULL;
1877 return table_ident[v]->sym_struct;
1880 /* find an identifier */
1881 static inline Sym *sym_find(int v)
1883 v -= TOK_IDENT;
1884 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1885 return NULL;
1886 return table_ident[v]->sym_identifier;
1889 /* push a given symbol on the symbol stack */
1890 static Sym *sym_push(int v, CType *type, int r, int c)
1892 Sym *s, **ps;
1893 TokenSym *ts;
1895 if (local_stack)
1896 ps = &local_stack;
1897 else
1898 ps = &global_stack;
1899 s = sym_push2(ps, v, type->t, c);
1900 s->type.ref = type->ref;
1901 s->r = r;
1902 /* don't record fields or anonymous symbols */
1903 /* XXX: simplify */
1904 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1905 /* record symbol in token array */
1906 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1907 if (v & SYM_STRUCT)
1908 ps = &ts->sym_struct;
1909 else
1910 ps = &ts->sym_identifier;
1911 s->prev_tok = *ps;
1912 *ps = s;
1914 return s;
1917 /* push a global identifier */
1918 static Sym *global_identifier_push(int v, int t, int c)
1920 Sym *s, **ps;
1921 s = sym_push2(&global_stack, v, t, c);
1922 /* don't record anonymous symbol */
1923 if (v < SYM_FIRST_ANOM) {
1924 ps = &table_ident[v - TOK_IDENT]->sym_identifier;
1925 /* modify the top most local identifier, so that
1926 sym_identifier will point to 's' when popped */
1927 while (*ps != NULL)
1928 ps = &(*ps)->prev_tok;
1929 s->prev_tok = NULL;
1930 *ps = s;
1932 return s;
1935 /* pop symbols until top reaches 'b' */
1936 static void sym_pop(Sym **ptop, Sym *b)
1938 Sym *s, *ss, **ps;
1939 TokenSym *ts;
1940 int v;
1942 s = *ptop;
1943 while(s != b) {
1944 ss = s->prev;
1945 v = s->v;
1946 /* remove symbol in token array */
1947 /* XXX: simplify */
1948 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1949 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1950 if (v & SYM_STRUCT)
1951 ps = &ts->sym_struct;
1952 else
1953 ps = &ts->sym_identifier;
1954 *ps = s->prev_tok;
1956 sym_free(s);
1957 s = ss;
1959 *ptop = b;
1962 /* I/O layer */
1964 BufferedFile *tcc_open(TCCState *s1, const char *filename)
1966 int fd;
1967 BufferedFile *bf;
1969 if (strcmp(filename, "-") == 0)
1970 fd = 0, filename = "stdin";
1971 else
1972 fd = open(filename, O_RDONLY | O_BINARY);
1973 if ((verbose == 2 && fd >= 0) || verbose == 3)
1974 printf("%s %*s%s\n", fd < 0 ? "nf":"->",
1975 (s1->include_stack_ptr - s1->include_stack), "", filename);
1976 if (fd < 0)
1977 return NULL;
1978 bf = tcc_malloc(sizeof(BufferedFile));
1979 bf->fd = fd;
1980 bf->buf_ptr = bf->buffer;
1981 bf->buf_end = bf->buffer;
1982 bf->buffer[0] = CH_EOB; /* put eob symbol */
1983 pstrcpy(bf->filename, sizeof(bf->filename), filename);
1984 #ifdef _WIN32
1985 normalize_slashes(bf->filename);
1986 #endif
1987 bf->line_num = 1;
1988 bf->ifndef_macro = 0;
1989 bf->ifdef_stack_ptr = s1->ifdef_stack_ptr;
1990 // printf("opening '%s'\n", filename);
1991 return bf;
1994 void tcc_close(BufferedFile *bf)
1996 total_lines += bf->line_num;
1997 close(bf->fd);
1998 tcc_free(bf);
2001 /* fill input buffer and peek next char */
2002 static int tcc_peekc_slow(BufferedFile *bf)
2004 int len;
2005 /* only tries to read if really end of buffer */
2006 if (bf->buf_ptr >= bf->buf_end) {
2007 if (bf->fd != -1) {
2008 #if defined(PARSE_DEBUG)
2009 len = 8;
2010 #else
2011 len = IO_BUF_SIZE;
2012 #endif
2013 len = read(bf->fd, bf->buffer, len);
2014 if (len < 0)
2015 len = 0;
2016 } else {
2017 len = 0;
2019 total_bytes += len;
2020 bf->buf_ptr = bf->buffer;
2021 bf->buf_end = bf->buffer + len;
2022 *bf->buf_end = CH_EOB;
2024 if (bf->buf_ptr < bf->buf_end) {
2025 return bf->buf_ptr[0];
2026 } else {
2027 bf->buf_ptr = bf->buf_end;
2028 return CH_EOF;
2032 /* return the current character, handling end of block if necessary
2033 (but not stray) */
2034 static int handle_eob(void)
2036 return tcc_peekc_slow(file);
2039 /* read next char from current input file and handle end of input buffer */
2040 static inline void inp(void)
2042 ch = *(++(file->buf_ptr));
2043 /* end of buffer/file handling */
2044 if (ch == CH_EOB)
2045 ch = handle_eob();
2048 /* handle '\[\r]\n' */
2049 static int handle_stray_noerror(void)
2051 while (ch == '\\') {
2052 inp();
2053 if (ch == '\n') {
2054 file->line_num++;
2055 inp();
2056 } else if (ch == '\r') {
2057 inp();
2058 if (ch != '\n')
2059 goto fail;
2060 file->line_num++;
2061 inp();
2062 } else {
2063 fail:
2064 return 1;
2067 return 0;
2070 static void handle_stray(void)
2072 if (handle_stray_noerror())
2073 error("stray '\\' in program");
2076 /* skip the stray and handle the \\n case. Output an error if
2077 incorrect char after the stray */
2078 static int handle_stray1(uint8_t *p)
2080 int c;
2082 if (p >= file->buf_end) {
2083 file->buf_ptr = p;
2084 c = handle_eob();
2085 p = file->buf_ptr;
2086 if (c == '\\')
2087 goto parse_stray;
2088 } else {
2089 parse_stray:
2090 file->buf_ptr = p;
2091 ch = *p;
2092 handle_stray();
2093 p = file->buf_ptr;
2094 c = *p;
2096 return c;
2099 /* handle just the EOB case, but not stray */
2100 #define PEEKC_EOB(c, p)\
2102 p++;\
2103 c = *p;\
2104 if (c == '\\') {\
2105 file->buf_ptr = p;\
2106 c = handle_eob();\
2107 p = file->buf_ptr;\
2111 /* handle the complicated stray case */
2112 #define PEEKC(c, p)\
2114 p++;\
2115 c = *p;\
2116 if (c == '\\') {\
2117 c = handle_stray1(p);\
2118 p = file->buf_ptr;\
2122 /* input with '\[\r]\n' handling. Note that this function cannot
2123 handle other characters after '\', so you cannot call it inside
2124 strings or comments */
2125 static void minp(void)
2127 inp();
2128 if (ch == '\\')
2129 handle_stray();
2133 /* single line C++ comments */
2134 static uint8_t *parse_line_comment(uint8_t *p)
2136 int c;
2138 p++;
2139 for(;;) {
2140 c = *p;
2141 redo:
2142 if (c == '\n' || c == CH_EOF) {
2143 break;
2144 } else if (c == '\\') {
2145 file->buf_ptr = p;
2146 c = handle_eob();
2147 p = file->buf_ptr;
2148 if (c == '\\') {
2149 PEEKC_EOB(c, p);
2150 if (c == '\n') {
2151 file->line_num++;
2152 PEEKC_EOB(c, p);
2153 } else if (c == '\r') {
2154 PEEKC_EOB(c, p);
2155 if (c == '\n') {
2156 file->line_num++;
2157 PEEKC_EOB(c, p);
2160 } else {
2161 goto redo;
2163 } else {
2164 p++;
2167 return p;
2170 /* C comments */
2171 static uint8_t *parse_comment(uint8_t *p)
2173 int c;
2175 p++;
2176 for(;;) {
2177 /* fast skip loop */
2178 for(;;) {
2179 c = *p;
2180 if (c == '\n' || c == '*' || c == '\\')
2181 break;
2182 p++;
2183 c = *p;
2184 if (c == '\n' || c == '*' || c == '\\')
2185 break;
2186 p++;
2188 /* now we can handle all the cases */
2189 if (c == '\n') {
2190 file->line_num++;
2191 p++;
2192 } else if (c == '*') {
2193 p++;
2194 for(;;) {
2195 c = *p;
2196 if (c == '*') {
2197 p++;
2198 } else if (c == '/') {
2199 goto end_of_comment;
2200 } else if (c == '\\') {
2201 file->buf_ptr = p;
2202 c = handle_eob();
2203 p = file->buf_ptr;
2204 if (c == '\\') {
2205 /* skip '\[\r]\n', otherwise just skip the stray */
2206 while (c == '\\') {
2207 PEEKC_EOB(c, p);
2208 if (c == '\n') {
2209 file->line_num++;
2210 PEEKC_EOB(c, p);
2211 } else if (c == '\r') {
2212 PEEKC_EOB(c, p);
2213 if (c == '\n') {
2214 file->line_num++;
2215 PEEKC_EOB(c, p);
2217 } else {
2218 goto after_star;
2222 } else {
2223 break;
2226 after_star: ;
2227 } else {
2228 /* stray, eob or eof */
2229 file->buf_ptr = p;
2230 c = handle_eob();
2231 p = file->buf_ptr;
2232 if (c == CH_EOF) {
2233 error("unexpected end of file in comment");
2234 } else if (c == '\\') {
2235 p++;
2239 end_of_comment:
2240 p++;
2241 return p;
2244 #define cinp minp
2246 /* space exlcuding newline */
2247 static inline int is_space(int ch)
2249 return ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f' || ch == '\r';
2252 static inline void skip_spaces(void)
2254 while (is_space(ch))
2255 cinp();
2258 /* parse a string without interpreting escapes */
2259 static uint8_t *parse_pp_string(uint8_t *p,
2260 int sep, CString *str)
2262 int c;
2263 p++;
2264 for(;;) {
2265 c = *p;
2266 if (c == sep) {
2267 break;
2268 } else if (c == '\\') {
2269 file->buf_ptr = p;
2270 c = handle_eob();
2271 p = file->buf_ptr;
2272 if (c == CH_EOF) {
2273 unterminated_string:
2274 /* XXX: indicate line number of start of string */
2275 error("missing terminating %c character", sep);
2276 } else if (c == '\\') {
2277 /* escape : just skip \[\r]\n */
2278 PEEKC_EOB(c, p);
2279 if (c == '\n') {
2280 file->line_num++;
2281 p++;
2282 } else if (c == '\r') {
2283 PEEKC_EOB(c, p);
2284 if (c != '\n')
2285 expect("'\n' after '\r'");
2286 file->line_num++;
2287 p++;
2288 } else if (c == CH_EOF) {
2289 goto unterminated_string;
2290 } else {
2291 if (str) {
2292 cstr_ccat(str, '\\');
2293 cstr_ccat(str, c);
2295 p++;
2298 } else if (c == '\n') {
2299 file->line_num++;
2300 goto add_char;
2301 } else if (c == '\r') {
2302 PEEKC_EOB(c, p);
2303 if (c != '\n') {
2304 if (str)
2305 cstr_ccat(str, '\r');
2306 } else {
2307 file->line_num++;
2308 goto add_char;
2310 } else {
2311 add_char:
2312 if (str)
2313 cstr_ccat(str, c);
2314 p++;
2317 p++;
2318 return p;
2321 /* skip block of text until #else, #elif or #endif. skip also pairs of
2322 #if/#endif */
2323 void preprocess_skip(void)
2325 int a, start_of_line, c, in_warn_or_error;
2326 uint8_t *p;
2328 p = file->buf_ptr;
2329 a = 0;
2330 redo_start:
2331 start_of_line = 1;
2332 in_warn_or_error = 0;
2333 for(;;) {
2334 redo_no_start:
2335 c = *p;
2336 switch(c) {
2337 case ' ':
2338 case '\t':
2339 case '\f':
2340 case '\v':
2341 case '\r':
2342 p++;
2343 goto redo_no_start;
2344 case '\n':
2345 file->line_num++;
2346 p++;
2347 goto redo_start;
2348 case '\\':
2349 file->buf_ptr = p;
2350 c = handle_eob();
2351 if (c == CH_EOF) {
2352 expect("#endif");
2353 } else if (c == '\\') {
2354 ch = file->buf_ptr[0];
2355 handle_stray_noerror();
2357 p = file->buf_ptr;
2358 goto redo_no_start;
2359 /* skip strings */
2360 case '\"':
2361 case '\'':
2362 if (in_warn_or_error)
2363 goto _default;
2364 p = parse_pp_string(p, c, NULL);
2365 break;
2366 /* skip comments */
2367 case '/':
2368 if (in_warn_or_error)
2369 goto _default;
2370 file->buf_ptr = p;
2371 ch = *p;
2372 minp();
2373 p = file->buf_ptr;
2374 if (ch == '*') {
2375 p = parse_comment(p);
2376 } else if (ch == '/') {
2377 p = parse_line_comment(p);
2379 break;
2380 case '#':
2381 p++;
2382 if (start_of_line) {
2383 file->buf_ptr = p;
2384 next_nomacro();
2385 p = file->buf_ptr;
2386 if (a == 0 &&
2387 (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
2388 goto the_end;
2389 if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
2390 a++;
2391 else if (tok == TOK_ENDIF)
2392 a--;
2393 else if( tok == TOK_ERROR || tok == TOK_WARNING)
2394 in_warn_or_error = 1;
2396 break;
2397 _default:
2398 default:
2399 p++;
2400 break;
2402 start_of_line = 0;
2404 the_end: ;
2405 file->buf_ptr = p;
2408 /* ParseState handling */
2410 /* XXX: currently, no include file info is stored. Thus, we cannot display
2411 accurate messages if the function or data definition spans multiple
2412 files */
2414 /* save current parse state in 's' */
2415 void save_parse_state(ParseState *s)
2417 s->line_num = file->line_num;
2418 s->macro_ptr = macro_ptr;
2419 s->tok = tok;
2420 s->tokc = tokc;
2423 /* restore parse state from 's' */
2424 void restore_parse_state(ParseState *s)
2426 file->line_num = s->line_num;
2427 macro_ptr = s->macro_ptr;
2428 tok = s->tok;
2429 tokc = s->tokc;
2432 /* return the number of additional 'ints' necessary to store the
2433 token */
2434 static inline int tok_ext_size(int t)
2436 switch(t) {
2437 /* 4 bytes */
2438 case TOK_CINT:
2439 case TOK_CUINT:
2440 case TOK_CCHAR:
2441 case TOK_LCHAR:
2442 case TOK_CFLOAT:
2443 case TOK_LINENUM:
2444 return 1;
2445 case TOK_STR:
2446 case TOK_LSTR:
2447 case TOK_PPNUM:
2448 error("unsupported token");
2449 return 1;
2450 case TOK_CDOUBLE:
2451 case TOK_CLLONG:
2452 case TOK_CULLONG:
2453 return 2;
2454 case TOK_CLDOUBLE:
2455 return LDOUBLE_SIZE / 4;
2456 default:
2457 return 0;
2461 /* token string handling */
2463 static inline void tok_str_new(TokenString *s)
2465 s->str = NULL;
2466 s->len = 0;
2467 s->allocated_len = 0;
2468 s->last_line_num = -1;
2471 static void tok_str_free(int *str)
2473 tcc_free(str);
2476 static int *tok_str_realloc(TokenString *s)
2478 int *str, len;
2480 if (s->allocated_len == 0) {
2481 len = 8;
2482 } else {
2483 len = s->allocated_len * 2;
2485 str = tcc_realloc(s->str, len * sizeof(int));
2486 if (!str)
2487 error("memory full");
2488 s->allocated_len = len;
2489 s->str = str;
2490 return str;
2493 static void tok_str_add(TokenString *s, int t)
2495 int len, *str;
2497 len = s->len;
2498 str = s->str;
2499 if (len >= s->allocated_len)
2500 str = tok_str_realloc(s);
2501 str[len++] = t;
2502 s->len = len;
2505 static void tok_str_add2(TokenString *s, int t, CValue *cv)
2507 int len, *str;
2509 len = s->len;
2510 str = s->str;
2512 /* allocate space for worst case */
2513 if (len + TOK_MAX_SIZE > s->allocated_len)
2514 str = tok_str_realloc(s);
2515 str[len++] = t;
2516 switch(t) {
2517 case TOK_CINT:
2518 case TOK_CUINT:
2519 case TOK_CCHAR:
2520 case TOK_LCHAR:
2521 case TOK_CFLOAT:
2522 case TOK_LINENUM:
2523 str[len++] = cv->tab[0];
2524 break;
2525 case TOK_PPNUM:
2526 case TOK_STR:
2527 case TOK_LSTR:
2529 int nb_words;
2530 CString *cstr;
2532 nb_words = (sizeof(CString) + cv->cstr->size + 3) >> 2;
2533 while ((len + nb_words) > s->allocated_len)
2534 str = tok_str_realloc(s);
2535 cstr = (CString *)(str + len);
2536 cstr->data = NULL;
2537 cstr->size = cv->cstr->size;
2538 cstr->data_allocated = NULL;
2539 cstr->size_allocated = cstr->size;
2540 memcpy((char *)cstr + sizeof(CString),
2541 cv->cstr->data, cstr->size);
2542 len += nb_words;
2544 break;
2545 case TOK_CDOUBLE:
2546 case TOK_CLLONG:
2547 case TOK_CULLONG:
2548 #if LDOUBLE_SIZE == 8
2549 case TOK_CLDOUBLE:
2550 #endif
2551 str[len++] = cv->tab[0];
2552 str[len++] = cv->tab[1];
2553 break;
2554 #if LDOUBLE_SIZE == 12
2555 case TOK_CLDOUBLE:
2556 str[len++] = cv->tab[0];
2557 str[len++] = cv->tab[1];
2558 str[len++] = cv->tab[2];
2559 #elif LDOUBLE_SIZE != 8
2560 #error add long double size support
2561 #endif
2562 break;
2563 default:
2564 break;
2566 s->len = len;
2569 /* add the current parse token in token string 's' */
2570 static void tok_str_add_tok(TokenString *s)
2572 CValue cval;
2574 /* save line number info */
2575 if (file->line_num != s->last_line_num) {
2576 s->last_line_num = file->line_num;
2577 cval.i = s->last_line_num;
2578 tok_str_add2(s, TOK_LINENUM, &cval);
2580 tok_str_add2(s, tok, &tokc);
2583 #if LDOUBLE_SIZE == 12
2584 #define LDOUBLE_GET(p, cv) \
2585 cv.tab[0] = p[0]; \
2586 cv.tab[1] = p[1]; \
2587 cv.tab[2] = p[2];
2588 #elif LDOUBLE_SIZE == 8
2589 #define LDOUBLE_GET(p, cv) \
2590 cv.tab[0] = p[0]; \
2591 cv.tab[1] = p[1];
2592 #else
2593 #error add long double size support
2594 #endif
2597 /* get a token from an integer array and increment pointer
2598 accordingly. we code it as a macro to avoid pointer aliasing. */
2599 #define TOK_GET(t, p, cv) \
2601 t = *p++; \
2602 switch(t) { \
2603 case TOK_CINT: \
2604 case TOK_CUINT: \
2605 case TOK_CCHAR: \
2606 case TOK_LCHAR: \
2607 case TOK_CFLOAT: \
2608 case TOK_LINENUM: \
2609 cv.tab[0] = *p++; \
2610 break; \
2611 case TOK_STR: \
2612 case TOK_LSTR: \
2613 case TOK_PPNUM: \
2614 cv.cstr = (CString *)p; \
2615 cv.cstr->data = (char *)p + sizeof(CString);\
2616 p += (sizeof(CString) + cv.cstr->size + 3) >> 2;\
2617 break; \
2618 case TOK_CDOUBLE: \
2619 case TOK_CLLONG: \
2620 case TOK_CULLONG: \
2621 cv.tab[0] = p[0]; \
2622 cv.tab[1] = p[1]; \
2623 p += 2; \
2624 break; \
2625 case TOK_CLDOUBLE: \
2626 LDOUBLE_GET(p, cv); \
2627 p += LDOUBLE_SIZE / 4; \
2628 break; \
2629 default: \
2630 break; \
2634 /* defines handling */
2635 static inline void define_push(int v, int macro_type, int *str, Sym *first_arg)
2637 Sym *s;
2639 s = sym_push2(&define_stack, v, macro_type, (int)str);
2640 s->next = first_arg;
2641 table_ident[v - TOK_IDENT]->sym_define = s;
2644 /* undefined a define symbol. Its name is just set to zero */
2645 static void define_undef(Sym *s)
2647 int v;
2648 v = s->v;
2649 if (v >= TOK_IDENT && v < tok_ident)
2650 table_ident[v - TOK_IDENT]->sym_define = NULL;
2651 s->v = 0;
2654 static inline Sym *define_find(int v)
2656 v -= TOK_IDENT;
2657 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2658 return NULL;
2659 return table_ident[v]->sym_define;
2662 /* free define stack until top reaches 'b' */
2663 static void free_defines(Sym *b)
2665 Sym *top, *top1;
2666 int v;
2668 top = define_stack;
2669 while (top != b) {
2670 top1 = top->prev;
2671 /* do not free args or predefined defines */
2672 if (top->c)
2673 tok_str_free((int *)top->c);
2674 v = top->v;
2675 if (v >= TOK_IDENT && v < tok_ident)
2676 table_ident[v - TOK_IDENT]->sym_define = NULL;
2677 sym_free(top);
2678 top = top1;
2680 define_stack = b;
2683 /* label lookup */
2684 static Sym *label_find(int v)
2686 v -= TOK_IDENT;
2687 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2688 return NULL;
2689 return table_ident[v]->sym_label;
2692 static Sym *label_push(Sym **ptop, int v, int flags)
2694 Sym *s, **ps;
2695 s = sym_push2(ptop, v, 0, 0);
2696 s->r = flags;
2697 ps = &table_ident[v - TOK_IDENT]->sym_label;
2698 if (ptop == &global_label_stack) {
2699 /* modify the top most local identifier, so that
2700 sym_identifier will point to 's' when popped */
2701 while (*ps != NULL)
2702 ps = &(*ps)->prev_tok;
2704 s->prev_tok = *ps;
2705 *ps = s;
2706 return s;
2709 /* pop labels until element last is reached. Look if any labels are
2710 undefined. Define symbols if '&&label' was used. */
2711 static void label_pop(Sym **ptop, Sym *slast)
2713 Sym *s, *s1;
2714 for(s = *ptop; s != slast; s = s1) {
2715 s1 = s->prev;
2716 if (s->r == LABEL_DECLARED) {
2717 warning("label '%s' declared but not used", get_tok_str(s->v, NULL));
2718 } else if (s->r == LABEL_FORWARD) {
2719 error("label '%s' used but not defined",
2720 get_tok_str(s->v, NULL));
2721 } else {
2722 if (s->c) {
2723 /* define corresponding symbol. A size of
2724 1 is put. */
2725 put_extern_sym(s, cur_text_section, (long)s->next, 1);
2728 /* remove label */
2729 table_ident[s->v - TOK_IDENT]->sym_label = s->prev_tok;
2730 sym_free(s);
2732 *ptop = slast;
2735 /* eval an expression for #if/#elif */
2736 static int expr_preprocess(void)
2738 int c, t;
2739 TokenString str;
2741 tok_str_new(&str);
2742 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2743 next(); /* do macro subst */
2744 if (tok == TOK_DEFINED) {
2745 next_nomacro();
2746 t = tok;
2747 if (t == '(')
2748 next_nomacro();
2749 c = define_find(tok) != 0;
2750 if (t == '(')
2751 next_nomacro();
2752 tok = TOK_CINT;
2753 tokc.i = c;
2754 } else if (tok >= TOK_IDENT) {
2755 /* if undefined macro */
2756 tok = TOK_CINT;
2757 tokc.i = 0;
2759 tok_str_add_tok(&str);
2761 tok_str_add(&str, -1); /* simulate end of file */
2762 tok_str_add(&str, 0);
2763 /* now evaluate C constant expression */
2764 macro_ptr = str.str;
2765 next();
2766 c = expr_const();
2767 macro_ptr = NULL;
2768 tok_str_free(str.str);
2769 return c != 0;
2772 #if defined(PARSE_DEBUG) || defined(PP_DEBUG)
2773 static void tok_print(int *str)
2775 int t;
2776 CValue cval;
2778 while (1) {
2779 TOK_GET(t, str, cval);
2780 if (!t)
2781 break;
2782 printf(" %s", get_tok_str(t, &cval));
2784 printf("\n");
2786 #endif
2788 /* parse after #define */
2789 static void parse_define(void)
2791 Sym *s, *first, **ps;
2792 int v, t, varg, is_vaargs, c;
2793 TokenString str;
2795 v = tok;
2796 if (v < TOK_IDENT)
2797 error("invalid macro name '%s'", get_tok_str(tok, &tokc));
2798 /* XXX: should check if same macro (ANSI) */
2799 first = NULL;
2800 t = MACRO_OBJ;
2801 /* '(' must be just after macro definition for MACRO_FUNC */
2802 c = file->buf_ptr[0];
2803 if (c == '\\')
2804 c = handle_stray1(file->buf_ptr);
2805 if (c == '(') {
2806 next_nomacro();
2807 next_nomacro();
2808 ps = &first;
2809 while (tok != ')') {
2810 varg = tok;
2811 next_nomacro();
2812 is_vaargs = 0;
2813 if (varg == TOK_DOTS) {
2814 varg = TOK___VA_ARGS__;
2815 is_vaargs = 1;
2816 } else if (tok == TOK_DOTS && gnu_ext) {
2817 is_vaargs = 1;
2818 next_nomacro();
2820 if (varg < TOK_IDENT)
2821 error("badly punctuated parameter list");
2822 s = sym_push2(&define_stack, varg | SYM_FIELD, is_vaargs, 0);
2823 *ps = s;
2824 ps = &s->next;
2825 if (tok != ',')
2826 break;
2827 next_nomacro();
2829 t = MACRO_FUNC;
2831 tok_str_new(&str);
2832 next_nomacro();
2833 /* EOF testing necessary for '-D' handling */
2834 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2835 tok_str_add2(&str, tok, &tokc);
2836 next_nomacro();
2838 tok_str_add(&str, 0);
2839 #ifdef PP_DEBUG
2840 printf("define %s %d: ", get_tok_str(v, NULL), t);
2841 tok_print(str.str);
2842 #endif
2843 define_push(v, t, str.str, first);
2846 static inline int hash_cached_include(int type, const char *filename)
2848 const unsigned char *s;
2849 unsigned int h;
2851 h = TOK_HASH_INIT;
2852 h = TOK_HASH_FUNC(h, type);
2853 s = filename;
2854 while (*s) {
2855 h = TOK_HASH_FUNC(h, *s);
2856 s++;
2858 h &= (CACHED_INCLUDES_HASH_SIZE - 1);
2859 return h;
2862 /* XXX: use a token or a hash table to accelerate matching ? */
2863 static CachedInclude *search_cached_include(TCCState *s1,
2864 int type, const char *filename)
2866 CachedInclude *e;
2867 int i, h;
2868 h = hash_cached_include(type, filename);
2869 i = s1->cached_includes_hash[h];
2870 for(;;) {
2871 if (i == 0)
2872 break;
2873 e = s1->cached_includes[i - 1];
2874 if (e->type == type && !strcmp(e->filename, filename))
2875 return e;
2876 i = e->hash_next;
2878 return NULL;
2881 static inline void add_cached_include(TCCState *s1, int type,
2882 const char *filename, int ifndef_macro)
2884 CachedInclude *e;
2885 int h;
2887 if (search_cached_include(s1, type, filename))
2888 return;
2889 #ifdef INC_DEBUG
2890 printf("adding cached '%s' %s\n", filename, get_tok_str(ifndef_macro, NULL));
2891 #endif
2892 e = tcc_malloc(sizeof(CachedInclude) + strlen(filename));
2893 if (!e)
2894 return;
2895 e->type = type;
2896 strcpy(e->filename, filename);
2897 e->ifndef_macro = ifndef_macro;
2898 dynarray_add((void ***)&s1->cached_includes, &s1->nb_cached_includes, e);
2899 /* add in hash table */
2900 h = hash_cached_include(type, filename);
2901 e->hash_next = s1->cached_includes_hash[h];
2902 s1->cached_includes_hash[h] = s1->nb_cached_includes;
2905 static void pragma_parse(TCCState *s1)
2907 int val;
2909 next();
2910 if (tok == TOK_pack) {
2912 This may be:
2913 #pragma pack(1) // set
2914 #pragma pack() // reset to default
2915 #pragma pack(push,1) // push & set
2916 #pragma pack(pop) // restore previous
2918 next();
2919 skip('(');
2920 if (tok == TOK_ASM_pop) {
2921 next();
2922 if (s1->pack_stack_ptr <= s1->pack_stack) {
2923 stk_error:
2924 error("out of pack stack");
2926 s1->pack_stack_ptr--;
2927 } else {
2928 val = 0;
2929 if (tok != ')') {
2930 if (tok == TOK_ASM_push) {
2931 next();
2932 if (s1->pack_stack_ptr >= s1->pack_stack + PACK_STACK_SIZE - 1)
2933 goto stk_error;
2934 s1->pack_stack_ptr++;
2935 skip(',');
2937 if (tok != TOK_CINT) {
2938 pack_error:
2939 error("invalid pack pragma");
2941 val = tokc.i;
2942 if (val < 1 || val > 16 || (val & (val - 1)) != 0)
2943 goto pack_error;
2944 next();
2946 *s1->pack_stack_ptr = val;
2947 skip(')');
2952 /* is_bof is true if first non space token at beginning of file */
2953 static void preprocess(int is_bof)
2955 TCCState *s1 = tcc_state;
2956 int size, i, c, n, saved_parse_flags;
2957 char buf[1024], *q;
2958 char buf1[1024];
2959 BufferedFile *f;
2960 Sym *s;
2961 CachedInclude *e;
2963 saved_parse_flags = parse_flags;
2964 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM |
2965 PARSE_FLAG_LINEFEED;
2966 next_nomacro();
2967 redo:
2968 switch(tok) {
2969 case TOK_DEFINE:
2970 next_nomacro();
2971 parse_define();
2972 break;
2973 case TOK_UNDEF:
2974 next_nomacro();
2975 s = define_find(tok);
2976 /* undefine symbol by putting an invalid name */
2977 if (s)
2978 define_undef(s);
2979 break;
2980 case TOK_INCLUDE:
2981 case TOK_INCLUDE_NEXT:
2982 ch = file->buf_ptr[0];
2983 /* XXX: incorrect if comments : use next_nomacro with a special mode */
2984 skip_spaces();
2985 if (ch == '<') {
2986 c = '>';
2987 goto read_name;
2988 } else if (ch == '\"') {
2989 c = ch;
2990 read_name:
2991 inp();
2992 q = buf;
2993 while (ch != c && ch != '\n' && ch != CH_EOF) {
2994 if ((q - buf) < sizeof(buf) - 1)
2995 *q++ = ch;
2996 if (ch == '\\') {
2997 if (handle_stray_noerror() == 0)
2998 --q;
2999 } else
3000 inp();
3002 *q = '\0';
3003 minp();
3004 #if 0
3005 /* eat all spaces and comments after include */
3006 /* XXX: slightly incorrect */
3007 while (ch1 != '\n' && ch1 != CH_EOF)
3008 inp();
3009 #endif
3010 } else {
3011 /* computed #include : either we have only strings or
3012 we have anything enclosed in '<>' */
3013 next();
3014 buf[0] = '\0';
3015 if (tok == TOK_STR) {
3016 while (tok != TOK_LINEFEED) {
3017 if (tok != TOK_STR) {
3018 include_syntax:
3019 error("'#include' expects \"FILENAME\" or <FILENAME>");
3021 pstrcat(buf, sizeof(buf), (char *)tokc.cstr->data);
3022 next();
3024 c = '\"';
3025 } else {
3026 int len;
3027 while (tok != TOK_LINEFEED) {
3028 pstrcat(buf, sizeof(buf), get_tok_str(tok, &tokc));
3029 next();
3031 len = strlen(buf);
3032 /* check syntax and remove '<>' */
3033 if (len < 2 || buf[0] != '<' || buf[len - 1] != '>')
3034 goto include_syntax;
3035 memmove(buf, buf + 1, len - 2);
3036 buf[len - 2] = '\0';
3037 c = '>';
3041 e = search_cached_include(s1, c, buf);
3042 if (e && define_find(e->ifndef_macro)) {
3043 /* no need to parse the include because the 'ifndef macro'
3044 is defined */
3045 #ifdef INC_DEBUG
3046 printf("%s: skipping %s\n", file->filename, buf);
3047 #endif
3048 } else {
3049 if (s1->include_stack_ptr >= s1->include_stack + INCLUDE_STACK_SIZE)
3050 error("#include recursion too deep");
3051 /* push current file in stack */
3052 /* XXX: fix current line init */
3053 *s1->include_stack_ptr++ = file;
3054 if (c == '\"') {
3055 /* first search in current dir if "header.h" */
3056 size = tcc_basename(file->filename) - file->filename;
3057 if (size > sizeof(buf1) - 1)
3058 size = sizeof(buf1) - 1;
3059 memcpy(buf1, file->filename, size);
3060 buf1[size] = '\0';
3061 pstrcat(buf1, sizeof(buf1), buf);
3062 f = tcc_open(s1, buf1);
3063 if (f) {
3064 if (tok == TOK_INCLUDE_NEXT)
3065 tok = TOK_INCLUDE;
3066 else
3067 goto found;
3070 /* now search in all the include paths */
3071 n = s1->nb_include_paths + s1->nb_sysinclude_paths;
3072 for(i = 0; i < n; i++) {
3073 const char *path;
3074 if (i < s1->nb_include_paths)
3075 path = s1->include_paths[i];
3076 else
3077 path = s1->sysinclude_paths[i - s1->nb_include_paths];
3078 pstrcpy(buf1, sizeof(buf1), path);
3079 pstrcat(buf1, sizeof(buf1), "/");
3080 pstrcat(buf1, sizeof(buf1), buf);
3081 f = tcc_open(s1, buf1);
3082 if (f) {
3083 if (tok == TOK_INCLUDE_NEXT)
3084 tok = TOK_INCLUDE;
3085 else
3086 goto found;
3089 --s1->include_stack_ptr;
3090 error("include file '%s' not found", buf);
3091 break;
3092 found:
3093 #ifdef INC_DEBUG
3094 printf("%s: including %s\n", file->filename, buf1);
3095 #endif
3096 f->inc_type = c;
3097 pstrcpy(f->inc_filename, sizeof(f->inc_filename), buf);
3098 file = f;
3099 /* add include file debug info */
3100 if (do_debug) {
3101 put_stabs(file->filename, N_BINCL, 0, 0, 0);
3103 tok_flags |= TOK_FLAG_BOF | TOK_FLAG_BOL;
3104 ch = file->buf_ptr[0];
3105 goto the_end;
3107 break;
3108 case TOK_IFNDEF:
3109 c = 1;
3110 goto do_ifdef;
3111 case TOK_IF:
3112 c = expr_preprocess();
3113 goto do_if;
3114 case TOK_IFDEF:
3115 c = 0;
3116 do_ifdef:
3117 next_nomacro();
3118 if (tok < TOK_IDENT)
3119 error("invalid argument for '#if%sdef'", c ? "n" : "");
3120 if (is_bof) {
3121 if (c) {
3122 #ifdef INC_DEBUG
3123 printf("#ifndef %s\n", get_tok_str(tok, NULL));
3124 #endif
3125 file->ifndef_macro = tok;
3128 c = (define_find(tok) != 0) ^ c;
3129 do_if:
3130 if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE)
3131 error("memory full");
3132 *s1->ifdef_stack_ptr++ = c;
3133 goto test_skip;
3134 case TOK_ELSE:
3135 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
3136 error("#else without matching #if");
3137 if (s1->ifdef_stack_ptr[-1] & 2)
3138 error("#else after #else");
3139 c = (s1->ifdef_stack_ptr[-1] ^= 3);
3140 goto test_skip;
3141 case TOK_ELIF:
3142 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
3143 error("#elif without matching #if");
3144 c = s1->ifdef_stack_ptr[-1];
3145 if (c > 1)
3146 error("#elif after #else");
3147 /* last #if/#elif expression was true: we skip */
3148 if (c == 1)
3149 goto skip;
3150 c = expr_preprocess();
3151 s1->ifdef_stack_ptr[-1] = c;
3152 test_skip:
3153 if (!(c & 1)) {
3154 skip:
3155 preprocess_skip();
3156 is_bof = 0;
3157 goto redo;
3159 break;
3160 case TOK_ENDIF:
3161 if (s1->ifdef_stack_ptr <= file->ifdef_stack_ptr)
3162 error("#endif without matching #if");
3163 s1->ifdef_stack_ptr--;
3164 /* '#ifndef macro' was at the start of file. Now we check if
3165 an '#endif' is exactly at the end of file */
3166 if (file->ifndef_macro &&
3167 s1->ifdef_stack_ptr == file->ifdef_stack_ptr) {
3168 file->ifndef_macro_saved = file->ifndef_macro;
3169 /* need to set to zero to avoid false matches if another
3170 #ifndef at middle of file */
3171 file->ifndef_macro = 0;
3172 while (tok != TOK_LINEFEED)
3173 next_nomacro();
3174 tok_flags |= TOK_FLAG_ENDIF;
3175 goto the_end;
3177 break;
3178 case TOK_LINE:
3179 next();
3180 if (tok != TOK_CINT)
3181 error("#line");
3182 file->line_num = tokc.i - 1; /* the line number will be incremented after */
3183 next();
3184 if (tok != TOK_LINEFEED) {
3185 if (tok != TOK_STR)
3186 error("#line");
3187 pstrcpy(file->filename, sizeof(file->filename),
3188 (char *)tokc.cstr->data);
3190 break;
3191 case TOK_ERROR:
3192 case TOK_WARNING:
3193 c = tok;
3194 ch = file->buf_ptr[0];
3195 skip_spaces();
3196 q = buf;
3197 while (ch != '\n' && ch != CH_EOF) {
3198 if ((q - buf) < sizeof(buf) - 1)
3199 *q++ = ch;
3200 if (ch == '\\') {
3201 if (handle_stray_noerror() == 0)
3202 --q;
3203 } else
3204 inp();
3206 *q = '\0';
3207 if (c == TOK_ERROR)
3208 error("#error %s", buf);
3209 else
3210 warning("#warning %s", buf);
3211 break;
3212 case TOK_PRAGMA:
3213 pragma_parse(s1);
3214 break;
3215 default:
3216 if (tok == TOK_LINEFEED || tok == '!' || tok == TOK_CINT) {
3217 /* '!' is ignored to allow C scripts. numbers are ignored
3218 to emulate cpp behaviour */
3219 } else {
3220 if (!(saved_parse_flags & PARSE_FLAG_ASM_COMMENTS))
3221 warning("Ignoring unknown preprocessing directive #%s", get_tok_str(tok, &tokc));
3223 break;
3225 /* ignore other preprocess commands or #! for C scripts */
3226 while (tok != TOK_LINEFEED)
3227 next_nomacro();
3228 the_end:
3229 parse_flags = saved_parse_flags;
3232 /* evaluate escape codes in a string. */
3233 static void parse_escape_string(CString *outstr, const uint8_t *buf, int is_long)
3235 int c, n;
3236 const uint8_t *p;
3238 p = buf;
3239 for(;;) {
3240 c = *p;
3241 if (c == '\0')
3242 break;
3243 if (c == '\\') {
3244 p++;
3245 /* escape */
3246 c = *p;
3247 switch(c) {
3248 case '0': case '1': case '2': case '3':
3249 case '4': case '5': case '6': case '7':
3250 /* at most three octal digits */
3251 n = c - '0';
3252 p++;
3253 c = *p;
3254 if (isoct(c)) {
3255 n = n * 8 + c - '0';
3256 p++;
3257 c = *p;
3258 if (isoct(c)) {
3259 n = n * 8 + c - '0';
3260 p++;
3263 c = n;
3264 goto add_char_nonext;
3265 case 'x':
3266 case 'u':
3267 case 'U':
3268 p++;
3269 n = 0;
3270 for(;;) {
3271 c = *p;
3272 if (c >= 'a' && c <= 'f')
3273 c = c - 'a' + 10;
3274 else if (c >= 'A' && c <= 'F')
3275 c = c - 'A' + 10;
3276 else if (isnum(c))
3277 c = c - '0';
3278 else
3279 break;
3280 n = n * 16 + c;
3281 p++;
3283 c = n;
3284 goto add_char_nonext;
3285 case 'a':
3286 c = '\a';
3287 break;
3288 case 'b':
3289 c = '\b';
3290 break;
3291 case 'f':
3292 c = '\f';
3293 break;
3294 case 'n':
3295 c = '\n';
3296 break;
3297 case 'r':
3298 c = '\r';
3299 break;
3300 case 't':
3301 c = '\t';
3302 break;
3303 case 'v':
3304 c = '\v';
3305 break;
3306 case 'e':
3307 if (!gnu_ext)
3308 goto invalid_escape;
3309 c = 27;
3310 break;
3311 case '\'':
3312 case '\"':
3313 case '\\':
3314 case '?':
3315 break;
3316 default:
3317 invalid_escape:
3318 if (c >= '!' && c <= '~')
3319 warning("unknown escape sequence: \'\\%c\'", c);
3320 else
3321 warning("unknown escape sequence: \'\\x%x\'", c);
3322 break;
3325 p++;
3326 add_char_nonext:
3327 if (!is_long)
3328 cstr_ccat(outstr, c);
3329 else
3330 cstr_wccat(outstr, c);
3332 /* add a trailing '\0' */
3333 if (!is_long)
3334 cstr_ccat(outstr, '\0');
3335 else
3336 cstr_wccat(outstr, '\0');
3339 /* we use 64 bit numbers */
3340 #define BN_SIZE 2
3342 /* bn = (bn << shift) | or_val */
3343 void bn_lshift(unsigned int *bn, int shift, int or_val)
3345 int i;
3346 unsigned int v;
3347 for(i=0;i<BN_SIZE;i++) {
3348 v = bn[i];
3349 bn[i] = (v << shift) | or_val;
3350 or_val = v >> (32 - shift);
3354 void bn_zero(unsigned int *bn)
3356 int i;
3357 for(i=0;i<BN_SIZE;i++) {
3358 bn[i] = 0;
3362 /* parse number in null terminated string 'p' and return it in the
3363 current token */
3364 void parse_number(const char *p)
3366 int b, t, shift, frac_bits, s, exp_val, ch;
3367 char *q;
3368 unsigned int bn[BN_SIZE];
3369 double d;
3371 /* number */
3372 q = token_buf;
3373 ch = *p++;
3374 t = ch;
3375 ch = *p++;
3376 *q++ = t;
3377 b = 10;
3378 if (t == '.') {
3379 goto float_frac_parse;
3380 } else if (t == '0') {
3381 if (ch == 'x' || ch == 'X') {
3382 q--;
3383 ch = *p++;
3384 b = 16;
3385 } else if (tcc_ext && (ch == 'b' || ch == 'B')) {
3386 q--;
3387 ch = *p++;
3388 b = 2;
3391 /* parse all digits. cannot check octal numbers at this stage
3392 because of floating point constants */
3393 while (1) {
3394 if (ch >= 'a' && ch <= 'f')
3395 t = ch - 'a' + 10;
3396 else if (ch >= 'A' && ch <= 'F')
3397 t = ch - 'A' + 10;
3398 else if (isnum(ch))
3399 t = ch - '0';
3400 else
3401 break;
3402 if (t >= b)
3403 break;
3404 if (q >= token_buf + STRING_MAX_SIZE) {
3405 num_too_long:
3406 error("number too long");
3408 *q++ = ch;
3409 ch = *p++;
3411 if (ch == '.' ||
3412 ((ch == 'e' || ch == 'E') && b == 10) ||
3413 ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
3414 if (b != 10) {
3415 /* NOTE: strtox should support that for hexa numbers, but
3416 non ISOC99 libcs do not support it, so we prefer to do
3417 it by hand */
3418 /* hexadecimal or binary floats */
3419 /* XXX: handle overflows */
3420 *q = '\0';
3421 if (b == 16)
3422 shift = 4;
3423 else
3424 shift = 2;
3425 bn_zero(bn);
3426 q = token_buf;
3427 while (1) {
3428 t = *q++;
3429 if (t == '\0') {
3430 break;
3431 } else if (t >= 'a') {
3432 t = t - 'a' + 10;
3433 } else if (t >= 'A') {
3434 t = t - 'A' + 10;
3435 } else {
3436 t = t - '0';
3438 bn_lshift(bn, shift, t);
3440 frac_bits = 0;
3441 if (ch == '.') {
3442 ch = *p++;
3443 while (1) {
3444 t = ch;
3445 if (t >= 'a' && t <= 'f') {
3446 t = t - 'a' + 10;
3447 } else if (t >= 'A' && t <= 'F') {
3448 t = t - 'A' + 10;
3449 } else if (t >= '0' && t <= '9') {
3450 t = t - '0';
3451 } else {
3452 break;
3454 if (t >= b)
3455 error("invalid digit");
3456 bn_lshift(bn, shift, t);
3457 frac_bits += shift;
3458 ch = *p++;
3461 if (ch != 'p' && ch != 'P')
3462 expect("exponent");
3463 ch = *p++;
3464 s = 1;
3465 exp_val = 0;
3466 if (ch == '+') {
3467 ch = *p++;
3468 } else if (ch == '-') {
3469 s = -1;
3470 ch = *p++;
3472 if (ch < '0' || ch > '9')
3473 expect("exponent digits");
3474 while (ch >= '0' && ch <= '9') {
3475 exp_val = exp_val * 10 + ch - '0';
3476 ch = *p++;
3478 exp_val = exp_val * s;
3480 /* now we can generate the number */
3481 /* XXX: should patch directly float number */
3482 d = (double)bn[1] * 4294967296.0 + (double)bn[0];
3483 d = ldexp(d, exp_val - frac_bits);
3484 t = toup(ch);
3485 if (t == 'F') {
3486 ch = *p++;
3487 tok = TOK_CFLOAT;
3488 /* float : should handle overflow */
3489 tokc.f = (float)d;
3490 } else if (t == 'L') {
3491 ch = *p++;
3492 tok = TOK_CLDOUBLE;
3493 /* XXX: not large enough */
3494 tokc.ld = (long double)d;
3495 } else {
3496 tok = TOK_CDOUBLE;
3497 tokc.d = d;
3499 } else {
3500 /* decimal floats */
3501 if (ch == '.') {
3502 if (q >= token_buf + STRING_MAX_SIZE)
3503 goto num_too_long;
3504 *q++ = ch;
3505 ch = *p++;
3506 float_frac_parse:
3507 while (ch >= '0' && ch <= '9') {
3508 if (q >= token_buf + STRING_MAX_SIZE)
3509 goto num_too_long;
3510 *q++ = ch;
3511 ch = *p++;
3514 if (ch == 'e' || ch == 'E') {
3515 if (q >= token_buf + STRING_MAX_SIZE)
3516 goto num_too_long;
3517 *q++ = ch;
3518 ch = *p++;
3519 if (ch == '-' || ch == '+') {
3520 if (q >= token_buf + STRING_MAX_SIZE)
3521 goto num_too_long;
3522 *q++ = ch;
3523 ch = *p++;
3525 if (ch < '0' || ch > '9')
3526 expect("exponent digits");
3527 while (ch >= '0' && ch <= '9') {
3528 if (q >= token_buf + STRING_MAX_SIZE)
3529 goto num_too_long;
3530 *q++ = ch;
3531 ch = *p++;
3534 *q = '\0';
3535 t = toup(ch);
3536 errno = 0;
3537 if (t == 'F') {
3538 ch = *p++;
3539 tok = TOK_CFLOAT;
3540 tokc.f = strtof(token_buf, NULL);
3541 } else if (t == 'L') {
3542 ch = *p++;
3543 tok = TOK_CLDOUBLE;
3544 tokc.ld = strtold(token_buf, NULL);
3545 } else {
3546 tok = TOK_CDOUBLE;
3547 tokc.d = strtod(token_buf, NULL);
3550 } else {
3551 unsigned long long n, n1;
3552 int lcount, ucount;
3554 /* integer number */
3555 *q = '\0';
3556 q = token_buf;
3557 if (b == 10 && *q == '0') {
3558 b = 8;
3559 q++;
3561 n = 0;
3562 while(1) {
3563 t = *q++;
3564 /* no need for checks except for base 10 / 8 errors */
3565 if (t == '\0') {
3566 break;
3567 } else if (t >= 'a') {
3568 t = t - 'a' + 10;
3569 } else if (t >= 'A') {
3570 t = t - 'A' + 10;
3571 } else {
3572 t = t - '0';
3573 if (t >= b)
3574 error("invalid digit");
3576 n1 = n;
3577 n = n * b + t;
3578 /* detect overflow */
3579 /* XXX: this test is not reliable */
3580 if (n < n1)
3581 error("integer constant overflow");
3584 /* XXX: not exactly ANSI compliant */
3585 if ((n & 0xffffffff00000000LL) != 0) {
3586 if ((n >> 63) != 0)
3587 tok = TOK_CULLONG;
3588 else
3589 tok = TOK_CLLONG;
3590 } else if (n > 0x7fffffff) {
3591 tok = TOK_CUINT;
3592 } else {
3593 tok = TOK_CINT;
3595 lcount = 0;
3596 ucount = 0;
3597 for(;;) {
3598 t = toup(ch);
3599 if (t == 'L') {
3600 if (lcount >= 2)
3601 error("three 'l's in integer constant");
3602 lcount++;
3603 if (lcount == 2) {
3604 if (tok == TOK_CINT)
3605 tok = TOK_CLLONG;
3606 else if (tok == TOK_CUINT)
3607 tok = TOK_CULLONG;
3609 ch = *p++;
3610 } else if (t == 'U') {
3611 if (ucount >= 1)
3612 error("two 'u's in integer constant");
3613 ucount++;
3614 if (tok == TOK_CINT)
3615 tok = TOK_CUINT;
3616 else if (tok == TOK_CLLONG)
3617 tok = TOK_CULLONG;
3618 ch = *p++;
3619 } else {
3620 break;
3623 if (tok == TOK_CINT || tok == TOK_CUINT)
3624 tokc.ui = n;
3625 else
3626 tokc.ull = n;
3631 #define PARSE2(c1, tok1, c2, tok2) \
3632 case c1: \
3633 PEEKC(c, p); \
3634 if (c == c2) { \
3635 p++; \
3636 tok = tok2; \
3637 } else { \
3638 tok = tok1; \
3640 break;
3642 /* return next token without macro substitution */
3643 static inline void next_nomacro1(void)
3645 int t, c, is_long;
3646 TokenSym *ts;
3647 uint8_t *p, *p1;
3648 unsigned int h;
3650 p = file->buf_ptr;
3651 redo_no_start:
3652 c = *p;
3653 switch(c) {
3654 case ' ':
3655 case '\t':
3656 case '\f':
3657 case '\v':
3658 case '\r':
3659 p++;
3660 goto redo_no_start;
3662 case '\\':
3663 /* first look if it is in fact an end of buffer */
3664 if (p >= file->buf_end) {
3665 file->buf_ptr = p;
3666 handle_eob();
3667 p = file->buf_ptr;
3668 if (p >= file->buf_end)
3669 goto parse_eof;
3670 else
3671 goto redo_no_start;
3672 } else {
3673 file->buf_ptr = p;
3674 ch = *p;
3675 handle_stray();
3676 p = file->buf_ptr;
3677 goto redo_no_start;
3679 parse_eof:
3681 TCCState *s1 = tcc_state;
3682 if ((parse_flags & PARSE_FLAG_LINEFEED)
3683 && !(tok_flags & TOK_FLAG_EOF)) {
3684 tok_flags |= TOK_FLAG_EOF;
3685 tok = TOK_LINEFEED;
3686 goto keep_tok_flags;
3687 } else if (s1->include_stack_ptr == s1->include_stack ||
3688 !(parse_flags & PARSE_FLAG_PREPROCESS)) {
3689 /* no include left : end of file. */
3690 tok = TOK_EOF;
3691 } else {
3692 tok_flags &= ~TOK_FLAG_EOF;
3693 /* pop include file */
3695 /* test if previous '#endif' was after a #ifdef at
3696 start of file */
3697 if (tok_flags & TOK_FLAG_ENDIF) {
3698 #ifdef INC_DEBUG
3699 printf("#endif %s\n", get_tok_str(file->ifndef_macro_saved, NULL));
3700 #endif
3701 add_cached_include(s1, file->inc_type, file->inc_filename,
3702 file->ifndef_macro_saved);
3705 /* add end of include file debug info */
3706 if (do_debug) {
3707 put_stabd(N_EINCL, 0, 0);
3709 /* pop include stack */
3710 tcc_close(file);
3711 s1->include_stack_ptr--;
3712 file = *s1->include_stack_ptr;
3713 p = file->buf_ptr;
3714 goto redo_no_start;
3717 break;
3719 case '\n':
3720 file->line_num++;
3721 tok_flags |= TOK_FLAG_BOL;
3722 p++;
3723 if (0 == (parse_flags & PARSE_FLAG_LINEFEED))
3724 goto redo_no_start;
3725 tok = TOK_LINEFEED;
3726 goto keep_tok_flags;
3728 case '#':
3729 /* XXX: simplify */
3730 PEEKC(c, p);
3731 if ((tok_flags & TOK_FLAG_BOL) &&
3732 (parse_flags & PARSE_FLAG_PREPROCESS)) {
3733 file->buf_ptr = p;
3734 preprocess(tok_flags & TOK_FLAG_BOF);
3735 p = file->buf_ptr;
3736 goto redo_no_start;
3737 } else {
3738 if (c == '#') {
3739 p++;
3740 tok = TOK_TWOSHARPS;
3741 } else {
3742 if (parse_flags & PARSE_FLAG_ASM_COMMENTS) {
3743 p = parse_line_comment(p - 1);
3744 goto redo_no_start;
3745 } else {
3746 tok = '#';
3750 break;
3752 case 'a': case 'b': case 'c': case 'd':
3753 case 'e': case 'f': case 'g': case 'h':
3754 case 'i': case 'j': case 'k': case 'l':
3755 case 'm': case 'n': case 'o': case 'p':
3756 case 'q': case 'r': case 's': case 't':
3757 case 'u': case 'v': case 'w': case 'x':
3758 case 'y': case 'z':
3759 case 'A': case 'B': case 'C': case 'D':
3760 case 'E': case 'F': case 'G': case 'H':
3761 case 'I': case 'J': case 'K':
3762 case 'M': case 'N': case 'O': case 'P':
3763 case 'Q': case 'R': case 'S': case 'T':
3764 case 'U': case 'V': case 'W': case 'X':
3765 case 'Y': case 'Z':
3766 case '_':
3767 parse_ident_fast:
3768 p1 = p;
3769 h = TOK_HASH_INIT;
3770 h = TOK_HASH_FUNC(h, c);
3771 p++;
3772 for(;;) {
3773 c = *p;
3774 if (!isidnum_table[c])
3775 break;
3776 h = TOK_HASH_FUNC(h, c);
3777 p++;
3779 if (c != '\\') {
3780 TokenSym **pts;
3781 int len;
3783 /* fast case : no stray found, so we have the full token
3784 and we have already hashed it */
3785 len = p - p1;
3786 h &= (TOK_HASH_SIZE - 1);
3787 pts = &hash_ident[h];
3788 for(;;) {
3789 ts = *pts;
3790 if (!ts)
3791 break;
3792 if (ts->len == len && !memcmp(ts->str, p1, len))
3793 goto token_found;
3794 pts = &(ts->hash_next);
3796 ts = tok_alloc_new(pts, p1, len);
3797 token_found: ;
3798 } else {
3799 /* slower case */
3800 cstr_reset(&tokcstr);
3802 while (p1 < p) {
3803 cstr_ccat(&tokcstr, *p1);
3804 p1++;
3806 p--;
3807 PEEKC(c, p);
3808 parse_ident_slow:
3809 while (isidnum_table[c]) {
3810 cstr_ccat(&tokcstr, c);
3811 PEEKC(c, p);
3813 ts = tok_alloc(tokcstr.data, tokcstr.size);
3815 tok = ts->tok;
3816 break;
3817 case 'L':
3818 t = p[1];
3819 if (t != '\\' && t != '\'' && t != '\"') {
3820 /* fast case */
3821 goto parse_ident_fast;
3822 } else {
3823 PEEKC(c, p);
3824 if (c == '\'' || c == '\"') {
3825 is_long = 1;
3826 goto str_const;
3827 } else {
3828 cstr_reset(&tokcstr);
3829 cstr_ccat(&tokcstr, 'L');
3830 goto parse_ident_slow;
3833 break;
3834 case '0': case '1': case '2': case '3':
3835 case '4': case '5': case '6': case '7':
3836 case '8': case '9':
3838 cstr_reset(&tokcstr);
3839 /* after the first digit, accept digits, alpha, '.' or sign if
3840 prefixed by 'eEpP' */
3841 parse_num:
3842 for(;;) {
3843 t = c;
3844 cstr_ccat(&tokcstr, c);
3845 PEEKC(c, p);
3846 if (!(isnum(c) || isid(c) || c == '.' ||
3847 ((c == '+' || c == '-') &&
3848 (t == 'e' || t == 'E' || t == 'p' || t == 'P'))))
3849 break;
3851 /* We add a trailing '\0' to ease parsing */
3852 cstr_ccat(&tokcstr, '\0');
3853 tokc.cstr = &tokcstr;
3854 tok = TOK_PPNUM;
3855 break;
3856 case '.':
3857 /* special dot handling because it can also start a number */
3858 PEEKC(c, p);
3859 if (isnum(c)) {
3860 cstr_reset(&tokcstr);
3861 cstr_ccat(&tokcstr, '.');
3862 goto parse_num;
3863 } else if (c == '.') {
3864 PEEKC(c, p);
3865 if (c != '.')
3866 expect("'.'");
3867 PEEKC(c, p);
3868 tok = TOK_DOTS;
3869 } else {
3870 tok = '.';
3872 break;
3873 case '\'':
3874 case '\"':
3875 is_long = 0;
3876 str_const:
3878 CString str;
3879 int sep;
3881 sep = c;
3883 /* parse the string */
3884 cstr_new(&str);
3885 p = parse_pp_string(p, sep, &str);
3886 cstr_ccat(&str, '\0');
3888 /* eval the escape (should be done as TOK_PPNUM) */
3889 cstr_reset(&tokcstr);
3890 parse_escape_string(&tokcstr, str.data, is_long);
3891 cstr_free(&str);
3893 if (sep == '\'') {
3894 int char_size;
3895 /* XXX: make it portable */
3896 if (!is_long)
3897 char_size = 1;
3898 else
3899 char_size = sizeof(nwchar_t);
3900 if (tokcstr.size <= char_size)
3901 error("empty character constant");
3902 if (tokcstr.size > 2 * char_size)
3903 warning("multi-character character constant");
3904 if (!is_long) {
3905 tokc.i = *(int8_t *)tokcstr.data;
3906 tok = TOK_CCHAR;
3907 } else {
3908 tokc.i = *(nwchar_t *)tokcstr.data;
3909 tok = TOK_LCHAR;
3911 } else {
3912 tokc.cstr = &tokcstr;
3913 if (!is_long)
3914 tok = TOK_STR;
3915 else
3916 tok = TOK_LSTR;
3919 break;
3921 case '<':
3922 PEEKC(c, p);
3923 if (c == '=') {
3924 p++;
3925 tok = TOK_LE;
3926 } else if (c == '<') {
3927 PEEKC(c, p);
3928 if (c == '=') {
3929 p++;
3930 tok = TOK_A_SHL;
3931 } else {
3932 tok = TOK_SHL;
3934 } else {
3935 tok = TOK_LT;
3937 break;
3939 case '>':
3940 PEEKC(c, p);
3941 if (c == '=') {
3942 p++;
3943 tok = TOK_GE;
3944 } else if (c == '>') {
3945 PEEKC(c, p);
3946 if (c == '=') {
3947 p++;
3948 tok = TOK_A_SAR;
3949 } else {
3950 tok = TOK_SAR;
3952 } else {
3953 tok = TOK_GT;
3955 break;
3957 case '&':
3958 PEEKC(c, p);
3959 if (c == '&') {
3960 p++;
3961 tok = TOK_LAND;
3962 } else if (c == '=') {
3963 p++;
3964 tok = TOK_A_AND;
3965 } else {
3966 tok = '&';
3968 break;
3970 case '|':
3971 PEEKC(c, p);
3972 if (c == '|') {
3973 p++;
3974 tok = TOK_LOR;
3975 } else if (c == '=') {
3976 p++;
3977 tok = TOK_A_OR;
3978 } else {
3979 tok = '|';
3981 break;
3983 case '+':
3984 PEEKC(c, p);
3985 if (c == '+') {
3986 p++;
3987 tok = TOK_INC;
3988 } else if (c == '=') {
3989 p++;
3990 tok = TOK_A_ADD;
3991 } else {
3992 tok = '+';
3994 break;
3996 case '-':
3997 PEEKC(c, p);
3998 if (c == '-') {
3999 p++;
4000 tok = TOK_DEC;
4001 } else if (c == '=') {
4002 p++;
4003 tok = TOK_A_SUB;
4004 } else if (c == '>') {
4005 p++;
4006 tok = TOK_ARROW;
4007 } else {
4008 tok = '-';
4010 break;
4012 PARSE2('!', '!', '=', TOK_NE)
4013 PARSE2('=', '=', '=', TOK_EQ)
4014 PARSE2('*', '*', '=', TOK_A_MUL)
4015 PARSE2('%', '%', '=', TOK_A_MOD)
4016 PARSE2('^', '^', '=', TOK_A_XOR)
4018 /* comments or operator */
4019 case '/':
4020 PEEKC(c, p);
4021 if (c == '*') {
4022 p = parse_comment(p);
4023 goto redo_no_start;
4024 } else if (c == '/') {
4025 p = parse_line_comment(p);
4026 goto redo_no_start;
4027 } else if (c == '=') {
4028 p++;
4029 tok = TOK_A_DIV;
4030 } else {
4031 tok = '/';
4033 break;
4035 /* simple tokens */
4036 case '(':
4037 case ')':
4038 case '[':
4039 case ']':
4040 case '{':
4041 case '}':
4042 case ',':
4043 case ';':
4044 case ':':
4045 case '?':
4046 case '~':
4047 case '$': /* only used in assembler */
4048 case '@': /* dito */
4049 tok = c;
4050 p++;
4051 break;
4052 default:
4053 error("unrecognized character \\x%02x", c);
4054 break;
4056 tok_flags = 0;
4057 keep_tok_flags:
4058 file->buf_ptr = p;
4059 #if defined(PARSE_DEBUG)
4060 printf("token = %s\n", get_tok_str(tok, &tokc));
4061 #endif
4064 /* return next token without macro substitution. Can read input from
4065 macro_ptr buffer */
4066 static void next_nomacro(void)
4068 if (macro_ptr) {
4069 redo:
4070 tok = *macro_ptr;
4071 if (tok) {
4072 TOK_GET(tok, macro_ptr, tokc);
4073 if (tok == TOK_LINENUM) {
4074 file->line_num = tokc.i;
4075 goto redo;
4078 } else {
4079 next_nomacro1();
4083 /* substitute args in macro_str and return allocated string */
4084 static int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
4086 int *st, last_tok, t, notfirst;
4087 Sym *s;
4088 CValue cval;
4089 TokenString str;
4090 CString cstr;
4092 tok_str_new(&str);
4093 last_tok = 0;
4094 while(1) {
4095 TOK_GET(t, macro_str, cval);
4096 if (!t)
4097 break;
4098 if (t == '#') {
4099 /* stringize */
4100 TOK_GET(t, macro_str, cval);
4101 if (!t)
4102 break;
4103 s = sym_find2(args, t);
4104 if (s) {
4105 cstr_new(&cstr);
4106 st = (int *)s->c;
4107 notfirst = 0;
4108 while (*st) {
4109 if (notfirst)
4110 cstr_ccat(&cstr, ' ');
4111 TOK_GET(t, st, cval);
4112 cstr_cat(&cstr, get_tok_str(t, &cval));
4113 #ifndef PP_NOSPACES
4114 notfirst = 1;
4115 #endif
4117 cstr_ccat(&cstr, '\0');
4118 #ifdef PP_DEBUG
4119 printf("stringize: %s\n", (char *)cstr.data);
4120 #endif
4121 /* add string */
4122 cval.cstr = &cstr;
4123 tok_str_add2(&str, TOK_STR, &cval);
4124 cstr_free(&cstr);
4125 } else {
4126 tok_str_add2(&str, t, &cval);
4128 } else if (t >= TOK_IDENT) {
4129 s = sym_find2(args, t);
4130 if (s) {
4131 st = (int *)s->c;
4132 /* if '##' is present before or after, no arg substitution */
4133 if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) {
4134 /* special case for var arg macros : ## eats the
4135 ',' if empty VA_ARGS variable. */
4136 /* XXX: test of the ',' is not 100%
4137 reliable. should fix it to avoid security
4138 problems */
4139 if (gnu_ext && s->type.t &&
4140 last_tok == TOK_TWOSHARPS &&
4141 str.len >= 2 && str.str[str.len - 2] == ',') {
4142 if (*st == 0) {
4143 /* suppress ',' '##' */
4144 str.len -= 2;
4145 } else {
4146 /* suppress '##' and add variable */
4147 str.len--;
4148 goto add_var;
4150 } else {
4151 int t1;
4152 add_var:
4153 for(;;) {
4154 TOK_GET(t1, st, cval);
4155 if (!t1)
4156 break;
4157 tok_str_add2(&str, t1, &cval);
4160 } else {
4161 /* NOTE: the stream cannot be read when macro
4162 substituing an argument */
4163 macro_subst(&str, nested_list, st, NULL);
4165 } else {
4166 tok_str_add(&str, t);
4168 } else {
4169 tok_str_add2(&str, t, &cval);
4171 last_tok = t;
4173 tok_str_add(&str, 0);
4174 return str.str;
4177 static char const ab_month_name[12][4] =
4179 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
4180 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
4183 /* do macro substitution of current token with macro 's' and add
4184 result to (tok_str,tok_len). 'nested_list' is the list of all
4185 macros we got inside to avoid recursing. Return non zero if no
4186 substitution needs to be done */
4187 static int macro_subst_tok(TokenString *tok_str,
4188 Sym **nested_list, Sym *s, struct macro_level **can_read_stream)
4190 Sym *args, *sa, *sa1;
4191 int mstr_allocated, parlevel, *mstr, t, t1;
4192 TokenString str;
4193 char *cstrval;
4194 CValue cval;
4195 CString cstr;
4196 char buf[32];
4198 /* if symbol is a macro, prepare substitution */
4199 /* special macros */
4200 if (tok == TOK___LINE__) {
4201 snprintf(buf, sizeof(buf), "%d", file->line_num);
4202 cstrval = buf;
4203 t1 = TOK_PPNUM;
4204 goto add_cstr1;
4205 } else if (tok == TOK___FILE__) {
4206 cstrval = file->filename;
4207 goto add_cstr;
4208 } else if (tok == TOK___DATE__ || tok == TOK___TIME__) {
4209 time_t ti;
4210 struct tm *tm;
4212 time(&ti);
4213 tm = localtime(&ti);
4214 if (tok == TOK___DATE__) {
4215 snprintf(buf, sizeof(buf), "%s %2d %d",
4216 ab_month_name[tm->tm_mon], tm->tm_mday, tm->tm_year + 1900);
4217 } else {
4218 snprintf(buf, sizeof(buf), "%02d:%02d:%02d",
4219 tm->tm_hour, tm->tm_min, tm->tm_sec);
4221 cstrval = buf;
4222 add_cstr:
4223 t1 = TOK_STR;
4224 add_cstr1:
4225 cstr_new(&cstr);
4226 cstr_cat(&cstr, cstrval);
4227 cstr_ccat(&cstr, '\0');
4228 cval.cstr = &cstr;
4229 tok_str_add2(tok_str, t1, &cval);
4230 cstr_free(&cstr);
4231 } else {
4232 mstr = (int *)s->c;
4233 mstr_allocated = 0;
4234 if (s->type.t == MACRO_FUNC) {
4235 /* NOTE: we do not use next_nomacro to avoid eating the
4236 next token. XXX: find better solution */
4237 redo:
4238 if (macro_ptr) {
4239 t = *macro_ptr;
4240 if (t == 0 && can_read_stream) {
4241 /* end of macro stream: we must look at the token
4242 after in the file */
4243 struct macro_level *ml = *can_read_stream;
4244 macro_ptr = NULL;
4245 if (ml)
4247 macro_ptr = ml->p;
4248 ml->p = NULL;
4249 *can_read_stream = ml -> prev;
4251 goto redo;
4253 } else {
4254 /* XXX: incorrect with comments */
4255 ch = file->buf_ptr[0];
4256 while (is_space(ch) || ch == '\n')
4257 cinp();
4258 t = ch;
4260 if (t != '(') /* no macro subst */
4261 return -1;
4263 /* argument macro */
4264 next_nomacro();
4265 next_nomacro();
4266 args = NULL;
4267 sa = s->next;
4268 /* NOTE: empty args are allowed, except if no args */
4269 for(;;) {
4270 /* handle '()' case */
4271 if (!args && !sa && tok == ')')
4272 break;
4273 if (!sa)
4274 error("macro '%s' used with too many args",
4275 get_tok_str(s->v, 0));
4276 tok_str_new(&str);
4277 parlevel = 0;
4278 /* NOTE: non zero sa->t indicates VA_ARGS */
4279 while ((parlevel > 0 ||
4280 (tok != ')' &&
4281 (tok != ',' || sa->type.t))) &&
4282 tok != -1) {
4283 if (tok == '(')
4284 parlevel++;
4285 else if (tok == ')')
4286 parlevel--;
4287 if (tok != TOK_LINEFEED)
4288 tok_str_add2(&str, tok, &tokc);
4289 next_nomacro();
4291 tok_str_add(&str, 0);
4292 sym_push2(&args, sa->v & ~SYM_FIELD, sa->type.t, (int)str.str);
4293 sa = sa->next;
4294 if (tok == ')') {
4295 /* special case for gcc var args: add an empty
4296 var arg argument if it is omitted */
4297 if (sa && sa->type.t && gnu_ext)
4298 continue;
4299 else
4300 break;
4302 if (tok != ',')
4303 expect(",");
4304 next_nomacro();
4306 if (sa) {
4307 error("macro '%s' used with too few args",
4308 get_tok_str(s->v, 0));
4311 /* now subst each arg */
4312 mstr = macro_arg_subst(nested_list, mstr, args);
4313 /* free memory */
4314 sa = args;
4315 while (sa) {
4316 sa1 = sa->prev;
4317 tok_str_free((int *)sa->c);
4318 sym_free(sa);
4319 sa = sa1;
4321 mstr_allocated = 1;
4323 sym_push2(nested_list, s->v, 0, 0);
4324 macro_subst(tok_str, nested_list, mstr, can_read_stream);
4325 /* pop nested defined symbol */
4326 sa1 = *nested_list;
4327 *nested_list = sa1->prev;
4328 sym_free(sa1);
4329 if (mstr_allocated)
4330 tok_str_free(mstr);
4332 return 0;
4335 /* handle the '##' operator. Return NULL if no '##' seen. Otherwise
4336 return the resulting string (which must be freed). */
4337 static inline int *macro_twosharps(const int *macro_str)
4339 TokenSym *ts;
4340 const int *macro_ptr1, *start_macro_ptr, *ptr, *saved_macro_ptr;
4341 int t;
4342 const char *p1, *p2;
4343 CValue cval;
4344 TokenString macro_str1;
4345 CString cstr;
4347 start_macro_ptr = macro_str;
4348 /* we search the first '##' */
4349 for(;;) {
4350 macro_ptr1 = macro_str;
4351 TOK_GET(t, macro_str, cval);
4352 /* nothing more to do if end of string */
4353 if (t == 0)
4354 return NULL;
4355 if (*macro_str == TOK_TWOSHARPS)
4356 break;
4359 /* we saw '##', so we need more processing to handle it */
4360 cstr_new(&cstr);
4361 tok_str_new(&macro_str1);
4362 tok = t;
4363 tokc = cval;
4365 /* add all tokens seen so far */
4366 for(ptr = start_macro_ptr; ptr < macro_ptr1;) {
4367 TOK_GET(t, ptr, cval);
4368 tok_str_add2(&macro_str1, t, &cval);
4370 saved_macro_ptr = macro_ptr;
4371 /* XXX: get rid of the use of macro_ptr here */
4372 macro_ptr = (int *)macro_str;
4373 for(;;) {
4374 while (*macro_ptr == TOK_TWOSHARPS) {
4375 macro_ptr++;
4376 macro_ptr1 = macro_ptr;
4377 t = *macro_ptr;
4378 if (t) {
4379 TOK_GET(t, macro_ptr, cval);
4380 /* We concatenate the two tokens if we have an
4381 identifier or a preprocessing number */
4382 cstr_reset(&cstr);
4383 p1 = get_tok_str(tok, &tokc);
4384 cstr_cat(&cstr, p1);
4385 p2 = get_tok_str(t, &cval);
4386 cstr_cat(&cstr, p2);
4387 cstr_ccat(&cstr, '\0');
4389 if ((tok >= TOK_IDENT || tok == TOK_PPNUM) &&
4390 (t >= TOK_IDENT || t == TOK_PPNUM)) {
4391 if (tok == TOK_PPNUM) {
4392 /* if number, then create a number token */
4393 /* NOTE: no need to allocate because
4394 tok_str_add2() does it */
4395 cstr_reset(&tokcstr);
4396 tokcstr = cstr;
4397 cstr_new(&cstr);
4398 tokc.cstr = &tokcstr;
4399 } else {
4400 /* if identifier, we must do a test to
4401 validate we have a correct identifier */
4402 if (t == TOK_PPNUM) {
4403 const char *p;
4404 int c;
4406 p = p2;
4407 for(;;) {
4408 c = *p;
4409 if (c == '\0')
4410 break;
4411 p++;
4412 if (!isnum(c) && !isid(c))
4413 goto error_pasting;
4416 ts = tok_alloc(cstr.data, strlen(cstr.data));
4417 tok = ts->tok; /* modify current token */
4419 } else {
4420 const char *str = cstr.data;
4421 const unsigned char *q;
4423 /* we look for a valid token */
4424 /* XXX: do more extensive checks */
4425 if (!strcmp(str, ">>=")) {
4426 tok = TOK_A_SAR;
4427 } else if (!strcmp(str, "<<=")) {
4428 tok = TOK_A_SHL;
4429 } else if (strlen(str) == 2) {
4430 /* search in two bytes table */
4431 q = tok_two_chars;
4432 for(;;) {
4433 if (!*q)
4434 goto error_pasting;
4435 if (q[0] == str[0] && q[1] == str[1])
4436 break;
4437 q += 3;
4439 tok = q[2];
4440 } else {
4441 error_pasting:
4442 /* NOTE: because get_tok_str use a static buffer,
4443 we must save it */
4444 cstr_reset(&cstr);
4445 p1 = get_tok_str(tok, &tokc);
4446 cstr_cat(&cstr, p1);
4447 cstr_ccat(&cstr, '\0');
4448 p2 = get_tok_str(t, &cval);
4449 warning("pasting \"%s\" and \"%s\" does not give a valid preprocessing token", cstr.data, p2);
4450 /* cannot merge tokens: just add them separately */
4451 tok_str_add2(&macro_str1, tok, &tokc);
4452 /* XXX: free associated memory ? */
4453 tok = t;
4454 tokc = cval;
4459 tok_str_add2(&macro_str1, tok, &tokc);
4460 next_nomacro();
4461 if (tok == 0)
4462 break;
4464 macro_ptr = (int *)saved_macro_ptr;
4465 cstr_free(&cstr);
4466 tok_str_add(&macro_str1, 0);
4467 return macro_str1.str;
4471 /* do macro substitution of macro_str and add result to
4472 (tok_str,tok_len). 'nested_list' is the list of all macros we got
4473 inside to avoid recursing. */
4474 static void macro_subst(TokenString *tok_str, Sym **nested_list,
4475 const int *macro_str, struct macro_level ** can_read_stream)
4477 Sym *s;
4478 int *macro_str1;
4479 const int *ptr;
4480 int t, ret;
4481 CValue cval;
4482 struct macro_level ml;
4484 /* first scan for '##' operator handling */
4485 ptr = macro_str;
4486 macro_str1 = macro_twosharps(ptr);
4487 if (macro_str1)
4488 ptr = macro_str1;
4489 while (1) {
4490 /* NOTE: ptr == NULL can only happen if tokens are read from
4491 file stream due to a macro function call */
4492 if (ptr == NULL)
4493 break;
4494 TOK_GET(t, ptr, cval);
4495 if (t == 0)
4496 break;
4497 s = define_find(t);
4498 if (s != NULL) {
4499 /* if nested substitution, do nothing */
4500 if (sym_find2(*nested_list, t))
4501 goto no_subst;
4502 ml.p = macro_ptr;
4503 if (can_read_stream)
4504 ml.prev = *can_read_stream, *can_read_stream = &ml;
4505 macro_ptr = (int *)ptr;
4506 tok = t;
4507 ret = macro_subst_tok(tok_str, nested_list, s, can_read_stream);
4508 ptr = (int *)macro_ptr;
4509 macro_ptr = ml.p;
4510 if (can_read_stream && *can_read_stream == &ml)
4511 *can_read_stream = ml.prev;
4512 if (ret != 0)
4513 goto no_subst;
4514 } else {
4515 no_subst:
4516 tok_str_add2(tok_str, t, &cval);
4519 if (macro_str1)
4520 tok_str_free(macro_str1);
4523 /* return next token with macro substitution */
4524 static void next(void)
4526 Sym *nested_list, *s;
4527 TokenString str;
4528 struct macro_level *ml;
4530 redo:
4531 next_nomacro();
4532 if (!macro_ptr) {
4533 /* if not reading from macro substituted string, then try
4534 to substitute macros */
4535 if (tok >= TOK_IDENT &&
4536 (parse_flags & PARSE_FLAG_PREPROCESS)) {
4537 s = define_find(tok);
4538 if (s) {
4539 /* we have a macro: we try to substitute */
4540 tok_str_new(&str);
4541 nested_list = NULL;
4542 ml = NULL;
4543 if (macro_subst_tok(&str, &nested_list, s, &ml) == 0) {
4544 /* substitution done, NOTE: maybe empty */
4545 tok_str_add(&str, 0);
4546 macro_ptr = str.str;
4547 macro_ptr_allocated = str.str;
4548 goto redo;
4552 } else {
4553 if (tok == 0) {
4554 /* end of macro or end of unget buffer */
4555 if (unget_buffer_enabled) {
4556 macro_ptr = unget_saved_macro_ptr;
4557 unget_buffer_enabled = 0;
4558 } else {
4559 /* end of macro string: free it */
4560 tok_str_free(macro_ptr_allocated);
4561 macro_ptr = NULL;
4563 goto redo;
4567 /* convert preprocessor tokens into C tokens */
4568 if (tok == TOK_PPNUM &&
4569 (parse_flags & PARSE_FLAG_TOK_NUM)) {
4570 parse_number((char *)tokc.cstr->data);
4574 /* push back current token and set current token to 'last_tok'. Only
4575 identifier case handled for labels. */
4576 static inline void unget_tok(int last_tok)
4578 int i, n;
4579 int *q;
4580 unget_saved_macro_ptr = macro_ptr;
4581 unget_buffer_enabled = 1;
4582 q = unget_saved_buffer;
4583 macro_ptr = q;
4584 *q++ = tok;
4585 n = tok_ext_size(tok) - 1;
4586 for(i=0;i<n;i++)
4587 *q++ = tokc.tab[i];
4588 *q = 0; /* end of token string */
4589 tok = last_tok;
4593 void swap(int *p, int *q)
4595 int t;
4596 t = *p;
4597 *p = *q;
4598 *q = t;
4601 void vsetc(CType *type, int r, CValue *vc)
4603 int v;
4605 if (vtop >= vstack + (VSTACK_SIZE - 1))
4606 error("memory full");
4607 /* cannot let cpu flags if other instruction are generated. Also
4608 avoid leaving VT_JMP anywhere except on the top of the stack
4609 because it would complicate the code generator. */
4610 if (vtop >= vstack) {
4611 v = vtop->r & VT_VALMASK;
4612 if (v == VT_CMP || (v & ~1) == VT_JMP)
4613 gv(RC_INT);
4615 vtop++;
4616 vtop->type = *type;
4617 vtop->r = r;
4618 vtop->r2 = VT_CONST;
4619 vtop->c = *vc;
4622 /* push integer constant */
4623 void vpushi(int v)
4625 CValue cval;
4626 cval.i = v;
4627 vsetc(&int_type, VT_CONST, &cval);
4630 /* Return a static symbol pointing to a section */
4631 static Sym *get_sym_ref(CType *type, Section *sec,
4632 unsigned long offset, unsigned long size)
4634 int v;
4635 Sym *sym;
4637 v = anon_sym++;
4638 sym = global_identifier_push(v, type->t | VT_STATIC, 0);
4639 sym->type.ref = type->ref;
4640 sym->r = VT_CONST | VT_SYM;
4641 put_extern_sym(sym, sec, offset, size);
4642 return sym;
4645 /* push a reference to a section offset by adding a dummy symbol */
4646 static void vpush_ref(CType *type, Section *sec, unsigned long offset, unsigned long size)
4648 CValue cval;
4650 cval.ul = 0;
4651 vsetc(type, VT_CONST | VT_SYM, &cval);
4652 vtop->sym = get_sym_ref(type, sec, offset, size);
4655 /* define a new external reference to a symbol 'v' of type 'u' */
4656 static Sym *external_global_sym(int v, CType *type, int r)
4658 Sym *s;
4660 s = sym_find(v);
4661 if (!s) {
4662 /* push forward reference */
4663 s = global_identifier_push(v, type->t | VT_EXTERN, 0);
4664 s->type.ref = type->ref;
4665 s->r = r | VT_CONST | VT_SYM;
4667 return s;
4670 /* define a new external reference to a symbol 'v' of type 'u' */
4671 static Sym *external_sym(int v, CType *type, int r)
4673 Sym *s;
4675 s = sym_find(v);
4676 if (!s) {
4677 /* push forward reference */
4678 s = sym_push(v, type, r | VT_CONST | VT_SYM, 0);
4679 s->type.t |= VT_EXTERN;
4680 } else {
4681 if (!is_compatible_types(&s->type, type))
4682 error("incompatible types for redefinition of '%s'",
4683 get_tok_str(v, NULL));
4685 return s;
4688 /* push a reference to global symbol v */
4689 static void vpush_global_sym(CType *type, int v)
4691 Sym *sym;
4692 CValue cval;
4694 sym = external_global_sym(v, type, 0);
4695 cval.ul = 0;
4696 vsetc(type, VT_CONST | VT_SYM, &cval);
4697 vtop->sym = sym;
4700 void vset(CType *type, int r, int v)
4702 CValue cval;
4704 cval.i = v;
4705 vsetc(type, r, &cval);
4708 void vseti(int r, int v)
4710 CType type;
4711 type.t = VT_INT;
4712 vset(&type, r, v);
4715 void vswap(void)
4717 SValue tmp;
4719 tmp = vtop[0];
4720 vtop[0] = vtop[-1];
4721 vtop[-1] = tmp;
4724 void vpushv(SValue *v)
4726 if (vtop >= vstack + (VSTACK_SIZE - 1))
4727 error("memory full");
4728 vtop++;
4729 *vtop = *v;
4732 void vdup(void)
4734 vpushv(vtop);
4737 /* save r to the memory stack, and mark it as being free */
4738 void save_reg(int r)
4740 int l, saved, size, align;
4741 SValue *p, sv;
4742 CType *type;
4744 /* modify all stack values */
4745 saved = 0;
4746 l = 0;
4747 for(p=vstack;p<=vtop;p++) {
4748 if ((p->r & VT_VALMASK) == r ||
4749 ((p->type.t & VT_BTYPE) == VT_LLONG && (p->r2 & VT_VALMASK) == r)) {
4750 /* must save value on stack if not already done */
4751 if (!saved) {
4752 /* NOTE: must reload 'r' because r might be equal to r2 */
4753 r = p->r & VT_VALMASK;
4754 /* store register in the stack */
4755 type = &p->type;
4756 if ((p->r & VT_LVAL) ||
4757 (!is_float(type->t) && (type->t & VT_BTYPE) != VT_LLONG))
4758 type = &int_type;
4759 size = type_size(type, &align);
4760 loc = (loc - size) & -align;
4761 sv.type.t = type->t;
4762 sv.r = VT_LOCAL | VT_LVAL;
4763 sv.c.ul = loc;
4764 store(r, &sv);
4765 #ifdef TCC_TARGET_I386
4766 /* x86 specific: need to pop fp register ST0 if saved */
4767 if (r == TREG_ST0) {
4768 o(0xd9dd); /* fstp %st(1) */
4770 #endif
4771 /* special long long case */
4772 if ((type->t & VT_BTYPE) == VT_LLONG) {
4773 sv.c.ul += 4;
4774 store(p->r2, &sv);
4776 l = loc;
4777 saved = 1;
4779 /* mark that stack entry as being saved on the stack */
4780 if (p->r & VT_LVAL) {
4781 /* also clear the bounded flag because the
4782 relocation address of the function was stored in
4783 p->c.ul */
4784 p->r = (p->r & ~(VT_VALMASK | VT_BOUNDED)) | VT_LLOCAL;
4785 } else {
4786 p->r = lvalue_type(p->type.t) | VT_LOCAL;
4788 p->r2 = VT_CONST;
4789 p->c.ul = l;
4794 /* find a register of class 'rc2' with at most one reference on stack.
4795 * If none, call get_reg(rc) */
4796 int get_reg_ex(int rc, int rc2)
4798 int r;
4799 SValue *p;
4801 for(r=0;r<NB_REGS;r++) {
4802 if (reg_classes[r] & rc2) {
4803 int n;
4804 n=0;
4805 for(p = vstack; p <= vtop; p++) {
4806 if ((p->r & VT_VALMASK) == r ||
4807 (p->r2 & VT_VALMASK) == r)
4808 n++;
4810 if (n <= 1)
4811 return r;
4814 return get_reg(rc);
4817 /* find a free register of class 'rc'. If none, save one register */
4818 int get_reg(int rc)
4820 int r;
4821 SValue *p;
4823 /* find a free register */
4824 for(r=0;r<NB_REGS;r++) {
4825 if (reg_classes[r] & rc) {
4826 for(p=vstack;p<=vtop;p++) {
4827 if ((p->r & VT_VALMASK) == r ||
4828 (p->r2 & VT_VALMASK) == r)
4829 goto notfound;
4831 return r;
4833 notfound: ;
4836 /* no register left : free the first one on the stack (VERY
4837 IMPORTANT to start from the bottom to ensure that we don't
4838 spill registers used in gen_opi()) */
4839 for(p=vstack;p<=vtop;p++) {
4840 r = p->r & VT_VALMASK;
4841 if (r < VT_CONST && (reg_classes[r] & rc))
4842 goto save_found;
4843 /* also look at second register (if long long) */
4844 r = p->r2 & VT_VALMASK;
4845 if (r < VT_CONST && (reg_classes[r] & rc)) {
4846 save_found:
4847 save_reg(r);
4848 return r;
4851 /* Should never comes here */
4852 return -1;
4855 /* save registers up to (vtop - n) stack entry */
4856 void save_regs(int n)
4858 int r;
4859 SValue *p, *p1;
4860 p1 = vtop - n;
4861 for(p = vstack;p <= p1; p++) {
4862 r = p->r & VT_VALMASK;
4863 if (r < VT_CONST) {
4864 save_reg(r);
4869 /* move register 's' to 'r', and flush previous value of r to memory
4870 if needed */
4871 void move_reg(int r, int s)
4873 SValue sv;
4875 if (r != s) {
4876 save_reg(r);
4877 sv.type.t = VT_INT;
4878 sv.r = s;
4879 sv.c.ul = 0;
4880 load(r, &sv);
4884 /* get address of vtop (vtop MUST BE an lvalue) */
4885 void gaddrof(void)
4887 vtop->r &= ~VT_LVAL;
4888 /* tricky: if saved lvalue, then we can go back to lvalue */
4889 if ((vtop->r & VT_VALMASK) == VT_LLOCAL)
4890 vtop->r = (vtop->r & ~(VT_VALMASK | VT_LVAL_TYPE)) | VT_LOCAL | VT_LVAL;
4893 #ifdef CONFIG_TCC_BCHECK
4894 /* generate lvalue bound code */
4895 void gbound(void)
4897 int lval_type;
4898 CType type1;
4900 vtop->r &= ~VT_MUSTBOUND;
4901 /* if lvalue, then use checking code before dereferencing */
4902 if (vtop->r & VT_LVAL) {
4903 /* if not VT_BOUNDED value, then make one */
4904 if (!(vtop->r & VT_BOUNDED)) {
4905 lval_type = vtop->r & (VT_LVAL_TYPE | VT_LVAL);
4906 /* must save type because we must set it to int to get pointer */
4907 type1 = vtop->type;
4908 vtop->type.t = VT_INT;
4909 gaddrof();
4910 vpushi(0);
4911 gen_bounded_ptr_add();
4912 vtop->r |= lval_type;
4913 vtop->type = type1;
4915 /* then check for dereferencing */
4916 gen_bounded_ptr_deref();
4919 #endif
4921 /* store vtop a register belonging to class 'rc'. lvalues are
4922 converted to values. Cannot be used if cannot be converted to
4923 register value (such as structures). */
4924 int gv(int rc)
4926 int r, r2, rc2, bit_pos, bit_size, size, align, i;
4927 unsigned long long ll;
4929 /* NOTE: get_reg can modify vstack[] */
4930 if (vtop->type.t & VT_BITFIELD) {
4931 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
4932 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
4933 /* remove bit field info to avoid loops */
4934 vtop->type.t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
4935 /* generate shifts */
4936 vpushi(32 - (bit_pos + bit_size));
4937 gen_op(TOK_SHL);
4938 vpushi(32 - bit_size);
4939 /* NOTE: transformed to SHR if unsigned */
4940 gen_op(TOK_SAR);
4941 r = gv(rc);
4942 } else {
4943 if (is_float(vtop->type.t) &&
4944 (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4945 Sym *sym;
4946 int *ptr;
4947 unsigned long offset;
4948 #if defined(TCC_TARGET_ARM) && !defined(TCC_ARM_VFP)
4949 CValue check;
4950 #endif
4952 /* XXX: unify with initializers handling ? */
4953 /* CPUs usually cannot use float constants, so we store them
4954 generically in data segment */
4955 size = type_size(&vtop->type, &align);
4956 offset = (data_section->data_offset + align - 1) & -align;
4957 data_section->data_offset = offset;
4958 /* XXX: not portable yet */
4959 #ifdef __i386__
4960 /* Zero pad x87 tenbyte long doubles */
4961 if (size == 12)
4962 vtop->c.tab[2] &= 0xffff;
4963 #endif
4964 ptr = section_ptr_add(data_section, size);
4965 size = size >> 2;
4966 #if defined(TCC_TARGET_ARM) && !defined(TCC_ARM_VFP)
4967 check.d = 1;
4968 if(check.tab[0])
4969 for(i=0;i<size;i++)
4970 ptr[i] = vtop->c.tab[size-1-i];
4971 else
4972 #endif
4973 for(i=0;i<size;i++)
4974 ptr[i] = vtop->c.tab[i];
4975 sym = get_sym_ref(&vtop->type, data_section, offset, size << 2);
4976 vtop->r |= VT_LVAL | VT_SYM;
4977 vtop->sym = sym;
4978 vtop->c.ul = 0;
4980 #ifdef CONFIG_TCC_BCHECK
4981 if (vtop->r & VT_MUSTBOUND)
4982 gbound();
4983 #endif
4985 r = vtop->r & VT_VALMASK;
4986 /* need to reload if:
4987 - constant
4988 - lvalue (need to dereference pointer)
4989 - already a register, but not in the right class */
4990 if (r >= VT_CONST ||
4991 (vtop->r & VT_LVAL) ||
4992 !(reg_classes[r] & rc) ||
4993 ((vtop->type.t & VT_BTYPE) == VT_LLONG &&
4994 !(reg_classes[vtop->r2] & rc))) {
4995 r = get_reg(rc);
4996 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
4997 /* two register type load : expand to two words
4998 temporarily */
4999 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
5000 /* load constant */
5001 ll = vtop->c.ull;
5002 vtop->c.ui = ll; /* first word */
5003 load(r, vtop);
5004 vtop->r = r; /* save register value */
5005 vpushi(ll >> 32); /* second word */
5006 } else if (r >= VT_CONST || /* XXX: test to VT_CONST incorrect ? */
5007 (vtop->r & VT_LVAL)) {
5008 /* We do not want to modifier the long long
5009 pointer here, so the safest (and less
5010 efficient) is to save all the other registers
5011 in the stack. XXX: totally inefficient. */
5012 save_regs(1);
5013 /* load from memory */
5014 load(r, vtop);
5015 vdup();
5016 vtop[-1].r = r; /* save register value */
5017 /* increment pointer to get second word */
5018 vtop->type.t = VT_INT;
5019 gaddrof();
5020 vpushi(4);
5021 gen_op('+');
5022 vtop->r |= VT_LVAL;
5023 } else {
5024 /* move registers */
5025 load(r, vtop);
5026 vdup();
5027 vtop[-1].r = r; /* save register value */
5028 vtop->r = vtop[-1].r2;
5030 /* allocate second register */
5031 rc2 = RC_INT;
5032 if (rc == RC_IRET)
5033 rc2 = RC_LRET;
5034 r2 = get_reg(rc2);
5035 load(r2, vtop);
5036 vpop();
5037 /* write second register */
5038 vtop->r2 = r2;
5039 } else if ((vtop->r & VT_LVAL) && !is_float(vtop->type.t)) {
5040 int t1, t;
5041 /* lvalue of scalar type : need to use lvalue type
5042 because of possible cast */
5043 t = vtop->type.t;
5044 t1 = t;
5045 /* compute memory access type */
5046 if (vtop->r & VT_LVAL_BYTE)
5047 t = VT_BYTE;
5048 else if (vtop->r & VT_LVAL_SHORT)
5049 t = VT_SHORT;
5050 if (vtop->r & VT_LVAL_UNSIGNED)
5051 t |= VT_UNSIGNED;
5052 vtop->type.t = t;
5053 load(r, vtop);
5054 /* restore wanted type */
5055 vtop->type.t = t1;
5056 } else {
5057 /* one register type load */
5058 load(r, vtop);
5061 vtop->r = r;
5062 #ifdef TCC_TARGET_C67
5063 /* uses register pairs for doubles */
5064 if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE)
5065 vtop->r2 = r+1;
5066 #endif
5068 return r;
5071 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
5072 void gv2(int rc1, int rc2)
5074 int v;
5076 /* generate more generic register first. But VT_JMP or VT_CMP
5077 values must be generated first in all cases to avoid possible
5078 reload errors */
5079 v = vtop[0].r & VT_VALMASK;
5080 if (v != VT_CMP && (v & ~1) != VT_JMP && rc1 <= rc2) {
5081 vswap();
5082 gv(rc1);
5083 vswap();
5084 gv(rc2);
5085 /* test if reload is needed for first register */
5086 if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
5087 vswap();
5088 gv(rc1);
5089 vswap();
5091 } else {
5092 gv(rc2);
5093 vswap();
5094 gv(rc1);
5095 vswap();
5096 /* test if reload is needed for first register */
5097 if ((vtop[0].r & VT_VALMASK) >= VT_CONST) {
5098 gv(rc2);
5103 /* expand long long on stack in two int registers */
5104 void lexpand(void)
5106 int u;
5108 u = vtop->type.t & VT_UNSIGNED;
5109 gv(RC_INT);
5110 vdup();
5111 vtop[0].r = vtop[-1].r2;
5112 vtop[0].r2 = VT_CONST;
5113 vtop[-1].r2 = VT_CONST;
5114 vtop[0].type.t = VT_INT | u;
5115 vtop[-1].type.t = VT_INT | u;
5118 #ifdef TCC_TARGET_ARM
5119 /* expand long long on stack */
5120 void lexpand_nr(void)
5122 int u,v;
5124 u = vtop->type.t & VT_UNSIGNED;
5125 vdup();
5126 vtop->r2 = VT_CONST;
5127 vtop->type.t = VT_INT | u;
5128 v=vtop[-1].r & (VT_VALMASK | VT_LVAL);
5129 if (v == VT_CONST) {
5130 vtop[-1].c.ui = vtop->c.ull;
5131 vtop->c.ui = vtop->c.ull >> 32;
5132 vtop->r = VT_CONST;
5133 } else if (v == (VT_LVAL|VT_CONST) || v == (VT_LVAL|VT_LOCAL)) {
5134 vtop->c.ui += 4;
5135 vtop->r = vtop[-1].r;
5136 } else if (v > VT_CONST) {
5137 vtop--;
5138 lexpand();
5139 } else
5140 vtop->r = vtop[-1].r2;
5141 vtop[-1].r2 = VT_CONST;
5142 vtop[-1].type.t = VT_INT | u;
5144 #endif
5146 /* build a long long from two ints */
5147 void lbuild(int t)
5149 gv2(RC_INT, RC_INT);
5150 vtop[-1].r2 = vtop[0].r;
5151 vtop[-1].type.t = t;
5152 vpop();
5155 /* rotate n first stack elements to the bottom
5156 I1 ... In -> I2 ... In I1 [top is right]
5158 void vrotb(int n)
5160 int i;
5161 SValue tmp;
5163 tmp = vtop[-n + 1];
5164 for(i=-n+1;i!=0;i++)
5165 vtop[i] = vtop[i+1];
5166 vtop[0] = tmp;
5169 /* rotate n first stack elements to the top
5170 I1 ... In -> In I1 ... I(n-1) [top is right]
5172 void vrott(int n)
5174 int i;
5175 SValue tmp;
5177 tmp = vtop[0];
5178 for(i = 0;i < n - 1; i++)
5179 vtop[-i] = vtop[-i - 1];
5180 vtop[-n + 1] = tmp;
5183 #ifdef TCC_TARGET_ARM
5184 /* like vrott but in other direction
5185 In ... I1 -> I(n-1) ... I1 In [top is right]
5187 void vnrott(int n)
5189 int i;
5190 SValue tmp;
5192 tmp = vtop[-n + 1];
5193 for(i = n - 1; i > 0; i--)
5194 vtop[-i] = vtop[-i + 1];
5195 vtop[0] = tmp;
5197 #endif
5199 /* pop stack value */
5200 void vpop(void)
5202 int v;
5203 v = vtop->r & VT_VALMASK;
5204 #ifdef TCC_TARGET_I386
5205 /* for x86, we need to pop the FP stack */
5206 if (v == TREG_ST0 && !nocode_wanted) {
5207 o(0xd9dd); /* fstp %st(1) */
5208 } else
5209 #endif
5210 if (v == VT_JMP || v == VT_JMPI) {
5211 /* need to put correct jump if && or || without test */
5212 gsym(vtop->c.ul);
5214 vtop--;
5217 /* convert stack entry to register and duplicate its value in another
5218 register */
5219 void gv_dup(void)
5221 int rc, t, r, r1;
5222 SValue sv;
5224 t = vtop->type.t;
5225 if ((t & VT_BTYPE) == VT_LLONG) {
5226 lexpand();
5227 gv_dup();
5228 vswap();
5229 vrotb(3);
5230 gv_dup();
5231 vrotb(4);
5232 /* stack: H L L1 H1 */
5233 lbuild(t);
5234 vrotb(3);
5235 vrotb(3);
5236 vswap();
5237 lbuild(t);
5238 vswap();
5239 } else {
5240 /* duplicate value */
5241 rc = RC_INT;
5242 sv.type.t = VT_INT;
5243 if (is_float(t)) {
5244 rc = RC_FLOAT;
5245 sv.type.t = t;
5247 r = gv(rc);
5248 r1 = get_reg(rc);
5249 sv.r = r;
5250 sv.c.ul = 0;
5251 load(r1, &sv); /* move r to r1 */
5252 vdup();
5253 /* duplicates value */
5254 vtop->r = r1;
5258 /* generate CPU independent (unsigned) long long operations */
5259 void gen_opl(int op)
5261 int t, a, b, op1, c, i;
5262 int func;
5263 SValue tmp;
5265 switch(op) {
5266 case '/':
5267 case TOK_PDIV:
5268 func = TOK___divdi3;
5269 goto gen_func;
5270 case TOK_UDIV:
5271 func = TOK___udivdi3;
5272 goto gen_func;
5273 case '%':
5274 func = TOK___moddi3;
5275 goto gen_func;
5276 case TOK_UMOD:
5277 func = TOK___umoddi3;
5278 gen_func:
5279 /* call generic long long function */
5280 vpush_global_sym(&func_old_type, func);
5281 vrott(3);
5282 gfunc_call(2);
5283 vpushi(0);
5284 vtop->r = REG_IRET;
5285 vtop->r2 = REG_LRET;
5286 break;
5287 case '^':
5288 case '&':
5289 case '|':
5290 case '*':
5291 case '+':
5292 case '-':
5293 t = vtop->type.t;
5294 vswap();
5295 lexpand();
5296 vrotb(3);
5297 lexpand();
5298 /* stack: L1 H1 L2 H2 */
5299 tmp = vtop[0];
5300 vtop[0] = vtop[-3];
5301 vtop[-3] = tmp;
5302 tmp = vtop[-2];
5303 vtop[-2] = vtop[-3];
5304 vtop[-3] = tmp;
5305 vswap();
5306 /* stack: H1 H2 L1 L2 */
5307 if (op == '*') {
5308 vpushv(vtop - 1);
5309 vpushv(vtop - 1);
5310 gen_op(TOK_UMULL);
5311 lexpand();
5312 /* stack: H1 H2 L1 L2 ML MH */
5313 for(i=0;i<4;i++)
5314 vrotb(6);
5315 /* stack: ML MH H1 H2 L1 L2 */
5316 tmp = vtop[0];
5317 vtop[0] = vtop[-2];
5318 vtop[-2] = tmp;
5319 /* stack: ML MH H1 L2 H2 L1 */
5320 gen_op('*');
5321 vrotb(3);
5322 vrotb(3);
5323 gen_op('*');
5324 /* stack: ML MH M1 M2 */
5325 gen_op('+');
5326 gen_op('+');
5327 } else if (op == '+' || op == '-') {
5328 /* XXX: add non carry method too (for MIPS or alpha) */
5329 if (op == '+')
5330 op1 = TOK_ADDC1;
5331 else
5332 op1 = TOK_SUBC1;
5333 gen_op(op1);
5334 /* stack: H1 H2 (L1 op L2) */
5335 vrotb(3);
5336 vrotb(3);
5337 gen_op(op1 + 1); /* TOK_xxxC2 */
5338 } else {
5339 gen_op(op);
5340 /* stack: H1 H2 (L1 op L2) */
5341 vrotb(3);
5342 vrotb(3);
5343 /* stack: (L1 op L2) H1 H2 */
5344 gen_op(op);
5345 /* stack: (L1 op L2) (H1 op H2) */
5347 /* stack: L H */
5348 lbuild(t);
5349 break;
5350 case TOK_SAR:
5351 case TOK_SHR:
5352 case TOK_SHL:
5353 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
5354 t = vtop[-1].type.t;
5355 vswap();
5356 lexpand();
5357 vrotb(3);
5358 /* stack: L H shift */
5359 c = (int)vtop->c.i;
5360 /* constant: simpler */
5361 /* NOTE: all comments are for SHL. the other cases are
5362 done by swaping words */
5363 vpop();
5364 if (op != TOK_SHL)
5365 vswap();
5366 if (c >= 32) {
5367 /* stack: L H */
5368 vpop();
5369 if (c > 32) {
5370 vpushi(c - 32);
5371 gen_op(op);
5373 if (op != TOK_SAR) {
5374 vpushi(0);
5375 } else {
5376 gv_dup();
5377 vpushi(31);
5378 gen_op(TOK_SAR);
5380 vswap();
5381 } else {
5382 vswap();
5383 gv_dup();
5384 /* stack: H L L */
5385 vpushi(c);
5386 gen_op(op);
5387 vswap();
5388 vpushi(32 - c);
5389 if (op == TOK_SHL)
5390 gen_op(TOK_SHR);
5391 else
5392 gen_op(TOK_SHL);
5393 vrotb(3);
5394 /* stack: L L H */
5395 vpushi(c);
5396 if (op == TOK_SHL)
5397 gen_op(TOK_SHL);
5398 else
5399 gen_op(TOK_SHR);
5400 gen_op('|');
5402 if (op != TOK_SHL)
5403 vswap();
5404 lbuild(t);
5405 } else {
5406 /* XXX: should provide a faster fallback on x86 ? */
5407 switch(op) {
5408 case TOK_SAR:
5409 func = TOK___sardi3;
5410 goto gen_func;
5411 case TOK_SHR:
5412 func = TOK___shrdi3;
5413 goto gen_func;
5414 case TOK_SHL:
5415 func = TOK___shldi3;
5416 goto gen_func;
5419 break;
5420 default:
5421 /* compare operations */
5422 t = vtop->type.t;
5423 vswap();
5424 lexpand();
5425 vrotb(3);
5426 lexpand();
5427 /* stack: L1 H1 L2 H2 */
5428 tmp = vtop[-1];
5429 vtop[-1] = vtop[-2];
5430 vtop[-2] = tmp;
5431 /* stack: L1 L2 H1 H2 */
5432 /* compare high */
5433 op1 = op;
5434 /* when values are equal, we need to compare low words. since
5435 the jump is inverted, we invert the test too. */
5436 if (op1 == TOK_LT)
5437 op1 = TOK_LE;
5438 else if (op1 == TOK_GT)
5439 op1 = TOK_GE;
5440 else if (op1 == TOK_ULT)
5441 op1 = TOK_ULE;
5442 else if (op1 == TOK_UGT)
5443 op1 = TOK_UGE;
5444 a = 0;
5445 b = 0;
5446 gen_op(op1);
5447 if (op1 != TOK_NE) {
5448 a = gtst(1, 0);
5450 if (op != TOK_EQ) {
5451 /* generate non equal test */
5452 /* XXX: NOT PORTABLE yet */
5453 if (a == 0) {
5454 b = gtst(0, 0);
5455 } else {
5456 #if defined(TCC_TARGET_I386)
5457 b = psym(0x850f, 0);
5458 #elif defined(TCC_TARGET_ARM)
5459 b = ind;
5460 o(0x1A000000 | encbranch(ind, 0, 1));
5461 #elif defined(TCC_TARGET_C67)
5462 error("not implemented");
5463 #else
5464 #error not supported
5465 #endif
5468 /* compare low. Always unsigned */
5469 op1 = op;
5470 if (op1 == TOK_LT)
5471 op1 = TOK_ULT;
5472 else if (op1 == TOK_LE)
5473 op1 = TOK_ULE;
5474 else if (op1 == TOK_GT)
5475 op1 = TOK_UGT;
5476 else if (op1 == TOK_GE)
5477 op1 = TOK_UGE;
5478 gen_op(op1);
5479 a = gtst(1, a);
5480 gsym(b);
5481 vseti(VT_JMPI, a);
5482 break;
5486 /* handle integer constant optimizations and various machine
5487 independent opt */
5488 void gen_opic(int op)
5490 int c1, c2, t1, t2, n;
5491 SValue *v1, *v2;
5492 long long l1, l2;
5493 typedef unsigned long long U;
5495 v1 = vtop - 1;
5496 v2 = vtop;
5497 t1 = v1->type.t & VT_BTYPE;
5498 t2 = v2->type.t & VT_BTYPE;
5499 l1 = (t1 == VT_LLONG) ? v1->c.ll : v1->c.i;
5500 l2 = (t2 == VT_LLONG) ? v2->c.ll : v2->c.i;
5502 /* currently, we cannot do computations with forward symbols */
5503 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5504 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5505 if (c1 && c2) {
5506 switch(op) {
5507 case '+': l1 += l2; break;
5508 case '-': l1 -= l2; break;
5509 case '&': l1 &= l2; break;
5510 case '^': l1 ^= l2; break;
5511 case '|': l1 |= l2; break;
5512 case '*': l1 *= l2; break;
5514 case TOK_PDIV:
5515 case '/':
5516 case '%':
5517 case TOK_UDIV:
5518 case TOK_UMOD:
5519 /* if division by zero, generate explicit division */
5520 if (l2 == 0) {
5521 if (const_wanted)
5522 error("division by zero in constant");
5523 goto general_case;
5525 switch(op) {
5526 default: l1 /= l2; break;
5527 case '%': l1 %= l2; break;
5528 case TOK_UDIV: l1 = (U)l1 / l2; break;
5529 case TOK_UMOD: l1 = (U)l1 % l2; break;
5531 break;
5532 case TOK_SHL: l1 <<= l2; break;
5533 case TOK_SHR: l1 = (U)l1 >> l2; break;
5534 case TOK_SAR: l1 >>= l2; break;
5535 /* tests */
5536 case TOK_ULT: l1 = (U)l1 < (U)l2; break;
5537 case TOK_UGE: l1 = (U)l1 >= (U)l2; break;
5538 case TOK_EQ: l1 = l1 == l2; break;
5539 case TOK_NE: l1 = l1 != l2; break;
5540 case TOK_ULE: l1 = (U)l1 <= (U)l2; break;
5541 case TOK_UGT: l1 = (U)l1 > (U)l2; break;
5542 case TOK_LT: l1 = l1 < l2; break;
5543 case TOK_GE: l1 = l1 >= l2; break;
5544 case TOK_LE: l1 = l1 <= l2; break;
5545 case TOK_GT: l1 = l1 > l2; break;
5546 /* logical */
5547 case TOK_LAND: l1 = l1 && l2; break;
5548 case TOK_LOR: l1 = l1 || l2; break;
5549 default:
5550 goto general_case;
5552 v1->c.ll = l1;
5553 vtop--;
5554 } else {
5555 /* if commutative ops, put c2 as constant */
5556 if (c1 && (op == '+' || op == '&' || op == '^' ||
5557 op == '|' || op == '*')) {
5558 vswap();
5559 c2 = c1; //c = c1, c1 = c2, c2 = c;
5560 l2 = l1; //l = l1, l1 = l2, l2 = l;
5562 /* Filter out NOP operations like x*1, x-0, x&-1... */
5563 if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
5564 op == TOK_PDIV) &&
5565 l2 == 1) ||
5566 ((op == '+' || op == '-' || op == '|' || op == '^' ||
5567 op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
5568 l2 == 0) ||
5569 (op == '&' &&
5570 l2 == -1))) {
5571 /* nothing to do */
5572 vtop--;
5573 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
5574 /* try to use shifts instead of muls or divs */
5575 if (l2 > 0 && (l2 & (l2 - 1)) == 0) {
5576 n = -1;
5577 while (l2) {
5578 l2 >>= 1;
5579 n++;
5581 vtop->c.ll = n;
5582 if (op == '*')
5583 op = TOK_SHL;
5584 else if (op == TOK_PDIV)
5585 op = TOK_SAR;
5586 else
5587 op = TOK_SHR;
5589 goto general_case;
5590 } else if (c2 && (op == '+' || op == '-') &&
5591 (vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) ==
5592 (VT_CONST | VT_SYM)) {
5593 /* symbol + constant case */
5594 if (op == '-')
5595 l2 = -l2;
5596 vtop--;
5597 vtop->c.ll += l2;
5598 } else {
5599 general_case:
5600 if (!nocode_wanted) {
5601 /* call low level op generator */
5602 if (t1 == VT_LLONG || t2 == VT_LLONG)
5603 gen_opl(op);
5604 else
5605 gen_opi(op);
5606 } else {
5607 vtop--;
5613 /* generate a floating point operation with constant propagation */
5614 void gen_opif(int op)
5616 int c1, c2;
5617 SValue *v1, *v2;
5618 long double f1, f2;
5620 v1 = vtop - 1;
5621 v2 = vtop;
5622 /* currently, we cannot do computations with forward symbols */
5623 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5624 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5625 if (c1 && c2) {
5626 if (v1->type.t == VT_FLOAT) {
5627 f1 = v1->c.f;
5628 f2 = v2->c.f;
5629 } else if (v1->type.t == VT_DOUBLE) {
5630 f1 = v1->c.d;
5631 f2 = v2->c.d;
5632 } else {
5633 f1 = v1->c.ld;
5634 f2 = v2->c.ld;
5637 /* NOTE: we only do constant propagation if finite number (not
5638 NaN or infinity) (ANSI spec) */
5639 if (!ieee_finite(f1) || !ieee_finite(f2))
5640 goto general_case;
5642 switch(op) {
5643 case '+': f1 += f2; break;
5644 case '-': f1 -= f2; break;
5645 case '*': f1 *= f2; break;
5646 case '/':
5647 if (f2 == 0.0) {
5648 if (const_wanted)
5649 error("division by zero in constant");
5650 goto general_case;
5652 f1 /= f2;
5653 break;
5654 /* XXX: also handles tests ? */
5655 default:
5656 goto general_case;
5658 /* XXX: overflow test ? */
5659 if (v1->type.t == VT_FLOAT) {
5660 v1->c.f = f1;
5661 } else if (v1->type.t == VT_DOUBLE) {
5662 v1->c.d = f1;
5663 } else {
5664 v1->c.ld = f1;
5666 vtop--;
5667 } else {
5668 general_case:
5669 if (!nocode_wanted) {
5670 gen_opf(op);
5671 } else {
5672 vtop--;
5677 static int pointed_size(CType *type)
5679 int align;
5680 return type_size(pointed_type(type), &align);
5683 static inline int is_null_pointer(SValue *p)
5685 if ((p->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
5686 return 0;
5687 return ((p->type.t & VT_BTYPE) == VT_INT && p->c.i == 0) ||
5688 ((p->type.t & VT_BTYPE) == VT_LLONG && p->c.ll == 0);
5691 static inline int is_integer_btype(int bt)
5693 return (bt == VT_BYTE || bt == VT_SHORT ||
5694 bt == VT_INT || bt == VT_LLONG);
5697 /* check types for comparison or substraction of pointers */
5698 static void check_comparison_pointer_types(SValue *p1, SValue *p2, int op)
5700 CType *type1, *type2, tmp_type1, tmp_type2;
5701 int bt1, bt2;
5703 /* null pointers are accepted for all comparisons as gcc */
5704 if (is_null_pointer(p1) || is_null_pointer(p2))
5705 return;
5706 type1 = &p1->type;
5707 type2 = &p2->type;
5708 bt1 = type1->t & VT_BTYPE;
5709 bt2 = type2->t & VT_BTYPE;
5710 /* accept comparison between pointer and integer with a warning */
5711 if ((is_integer_btype(bt1) || is_integer_btype(bt2)) && op != '-') {
5712 if (op != TOK_LOR && op != TOK_LAND )
5713 warning("comparison between pointer and integer");
5714 return;
5717 /* both must be pointers or implicit function pointers */
5718 if (bt1 == VT_PTR) {
5719 type1 = pointed_type(type1);
5720 } else if (bt1 != VT_FUNC)
5721 goto invalid_operands;
5723 if (bt2 == VT_PTR) {
5724 type2 = pointed_type(type2);
5725 } else if (bt2 != VT_FUNC) {
5726 invalid_operands:
5727 error("invalid operands to binary %s", get_tok_str(op, NULL));
5729 if ((type1->t & VT_BTYPE) == VT_VOID ||
5730 (type2->t & VT_BTYPE) == VT_VOID)
5731 return;
5732 tmp_type1 = *type1;
5733 tmp_type2 = *type2;
5734 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5735 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5736 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
5737 /* gcc-like error if '-' is used */
5738 if (op == '-')
5739 goto invalid_operands;
5740 else
5741 warning("comparison of distinct pointer types lacks a cast");
5745 /* generic gen_op: handles types problems */
5746 void gen_op(int op)
5748 int u, t1, t2, bt1, bt2, t;
5749 CType type1;
5751 t1 = vtop[-1].type.t;
5752 t2 = vtop[0].type.t;
5753 bt1 = t1 & VT_BTYPE;
5754 bt2 = t2 & VT_BTYPE;
5756 if (bt1 == VT_PTR || bt2 == VT_PTR) {
5757 /* at least one operand is a pointer */
5758 /* relationnal op: must be both pointers */
5759 if (op >= TOK_ULT && op <= TOK_LOR) {
5760 check_comparison_pointer_types(vtop - 1, vtop, op);
5761 /* pointers are handled are unsigned */
5762 t = VT_INT | VT_UNSIGNED;
5763 goto std_op;
5765 /* if both pointers, then it must be the '-' op */
5766 if (bt1 == VT_PTR && bt2 == VT_PTR) {
5767 if (op != '-')
5768 error("cannot use pointers here");
5769 check_comparison_pointer_types(vtop - 1, vtop, op);
5770 /* XXX: check that types are compatible */
5771 u = pointed_size(&vtop[-1].type);
5772 gen_opic(op);
5773 /* set to integer type */
5774 vtop->type.t = VT_INT;
5775 vpushi(u);
5776 gen_op(TOK_PDIV);
5777 } else {
5778 /* exactly one pointer : must be '+' or '-'. */
5779 if (op != '-' && op != '+')
5780 error("cannot use pointers here");
5781 /* Put pointer as first operand */
5782 if (bt2 == VT_PTR) {
5783 vswap();
5784 swap(&t1, &t2);
5786 type1 = vtop[-1].type;
5787 /* XXX: cast to int ? (long long case) */
5788 vpushi(pointed_size(&vtop[-1].type));
5789 gen_op('*');
5790 #ifdef CONFIG_TCC_BCHECK
5791 /* if evaluating constant expression, no code should be
5792 generated, so no bound check */
5793 if (do_bounds_check && !const_wanted) {
5794 /* if bounded pointers, we generate a special code to
5795 test bounds */
5796 if (op == '-') {
5797 vpushi(0);
5798 vswap();
5799 gen_op('-');
5801 gen_bounded_ptr_add();
5802 } else
5803 #endif
5805 gen_opic(op);
5807 /* put again type if gen_opic() swaped operands */
5808 vtop->type = type1;
5810 } else if (is_float(bt1) || is_float(bt2)) {
5811 /* compute bigger type and do implicit casts */
5812 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
5813 t = VT_LDOUBLE;
5814 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
5815 t = VT_DOUBLE;
5816 } else {
5817 t = VT_FLOAT;
5819 /* floats can only be used for a few operations */
5820 if (op != '+' && op != '-' && op != '*' && op != '/' &&
5821 (op < TOK_ULT || op > TOK_GT))
5822 error("invalid operands for binary operation");
5823 goto std_op;
5824 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
5825 /* cast to biggest op */
5826 t = VT_LLONG;
5827 /* convert to unsigned if it does not fit in a long long */
5828 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
5829 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
5830 t |= VT_UNSIGNED;
5831 goto std_op;
5832 } else {
5833 /* integer operations */
5834 t = VT_INT;
5835 /* convert to unsigned if it does not fit in an integer */
5836 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
5837 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
5838 t |= VT_UNSIGNED;
5839 std_op:
5840 /* XXX: currently, some unsigned operations are explicit, so
5841 we modify them here */
5842 if (t & VT_UNSIGNED) {
5843 if (op == TOK_SAR)
5844 op = TOK_SHR;
5845 else if (op == '/')
5846 op = TOK_UDIV;
5847 else if (op == '%')
5848 op = TOK_UMOD;
5849 else if (op == TOK_LT)
5850 op = TOK_ULT;
5851 else if (op == TOK_GT)
5852 op = TOK_UGT;
5853 else if (op == TOK_LE)
5854 op = TOK_ULE;
5855 else if (op == TOK_GE)
5856 op = TOK_UGE;
5858 vswap();
5859 type1.t = t;
5860 gen_cast(&type1);
5861 vswap();
5862 /* special case for shifts and long long: we keep the shift as
5863 an integer */
5864 if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL)
5865 type1.t = VT_INT;
5866 gen_cast(&type1);
5867 if (is_float(t))
5868 gen_opif(op);
5869 else
5870 gen_opic(op);
5871 if (op >= TOK_ULT && op <= TOK_GT) {
5872 /* relationnal op: the result is an int */
5873 vtop->type.t = VT_INT;
5874 } else {
5875 vtop->type.t = t;
5880 /* generic itof for unsigned long long case */
5881 void gen_cvt_itof1(int t)
5883 if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
5884 (VT_LLONG | VT_UNSIGNED)) {
5886 if (t == VT_FLOAT)
5887 vpush_global_sym(&func_old_type, TOK___ulltof);
5888 else if (t == VT_DOUBLE)
5889 vpush_global_sym(&func_old_type, TOK___ulltod);
5890 else
5891 vpush_global_sym(&func_old_type, TOK___ulltold);
5892 vrott(2);
5893 gfunc_call(1);
5894 vpushi(0);
5895 vtop->r = REG_FRET;
5896 } else {
5897 gen_cvt_itof(t);
5901 /* generic ftoi for unsigned long long case */
5902 void gen_cvt_ftoi1(int t)
5904 int st;
5906 if (t == (VT_LLONG | VT_UNSIGNED)) {
5907 /* not handled natively */
5908 st = vtop->type.t & VT_BTYPE;
5909 if (st == VT_FLOAT)
5910 vpush_global_sym(&func_old_type, TOK___fixunssfdi);
5911 else if (st == VT_DOUBLE)
5912 vpush_global_sym(&func_old_type, TOK___fixunsdfdi);
5913 else
5914 vpush_global_sym(&func_old_type, TOK___fixunsxfdi);
5915 vrott(2);
5916 gfunc_call(1);
5917 vpushi(0);
5918 vtop->r = REG_IRET;
5919 vtop->r2 = REG_LRET;
5920 } else {
5921 gen_cvt_ftoi(t);
5925 /* force char or short cast */
5926 void force_charshort_cast(int t)
5928 int bits, dbt;
5929 dbt = t & VT_BTYPE;
5930 /* XXX: add optimization if lvalue : just change type and offset */
5931 if (dbt == VT_BYTE)
5932 bits = 8;
5933 else
5934 bits = 16;
5935 if (t & VT_UNSIGNED) {
5936 vpushi((1 << bits) - 1);
5937 gen_op('&');
5938 } else {
5939 bits = 32 - bits;
5940 vpushi(bits);
5941 gen_op(TOK_SHL);
5942 /* result must be signed or the SAR is converted to an SHL
5943 This was not the case when "t" was a signed short
5944 and the last value on the stack was an unsigned int */
5945 vtop->type.t &= ~VT_UNSIGNED;
5946 vpushi(bits);
5947 gen_op(TOK_SAR);
5951 /* cast 'vtop' to 'type'. Casting to bitfields is forbidden. */
5952 static void gen_cast(CType *type)
5954 int sbt, dbt, sf, df, c;
5956 /* special delayed cast for char/short */
5957 /* XXX: in some cases (multiple cascaded casts), it may still
5958 be incorrect */
5959 if (vtop->r & VT_MUSTCAST) {
5960 vtop->r &= ~VT_MUSTCAST;
5961 force_charshort_cast(vtop->type.t);
5964 /* bitfields first get cast to ints */
5965 if (vtop->type.t & VT_BITFIELD) {
5966 gv(RC_INT);
5969 dbt = type->t & (VT_BTYPE | VT_UNSIGNED);
5970 sbt = vtop->type.t & (VT_BTYPE | VT_UNSIGNED);
5972 if (sbt != dbt && !nocode_wanted) {
5973 sf = is_float(sbt);
5974 df = is_float(dbt);
5975 c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5976 if (sf && df) {
5977 /* convert from fp to fp */
5978 if (c) {
5979 /* constant case: we can do it now */
5980 /* XXX: in ISOC, cannot do it if error in convert */
5981 if (dbt == VT_FLOAT && sbt == VT_DOUBLE)
5982 vtop->c.f = (float)vtop->c.d;
5983 else if (dbt == VT_FLOAT && sbt == VT_LDOUBLE)
5984 vtop->c.f = (float)vtop->c.ld;
5985 else if (dbt == VT_DOUBLE && sbt == VT_FLOAT)
5986 vtop->c.d = (double)vtop->c.f;
5987 else if (dbt == VT_DOUBLE && sbt == VT_LDOUBLE)
5988 vtop->c.d = (double)vtop->c.ld;
5989 else if (dbt == VT_LDOUBLE && sbt == VT_FLOAT)
5990 vtop->c.ld = (long double)vtop->c.f;
5991 else if (dbt == VT_LDOUBLE && sbt == VT_DOUBLE)
5992 vtop->c.ld = (long double)vtop->c.d;
5993 } else {
5994 /* non constant case: generate code */
5995 gen_cvt_ftof(dbt);
5997 } else if (df) {
5998 /* convert int to fp */
5999 if (c) {
6000 switch(sbt) {
6001 case VT_LLONG | VT_UNSIGNED:
6002 case VT_LLONG:
6003 /* XXX: add const cases for long long */
6004 goto do_itof;
6005 case VT_INT | VT_UNSIGNED:
6006 switch(dbt) {
6007 case VT_FLOAT: vtop->c.f = (float)vtop->c.ui; break;
6008 case VT_DOUBLE: vtop->c.d = (double)vtop->c.ui; break;
6009 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.ui; break;
6011 break;
6012 default:
6013 switch(dbt) {
6014 case VT_FLOAT: vtop->c.f = (float)vtop->c.i; break;
6015 case VT_DOUBLE: vtop->c.d = (double)vtop->c.i; break;
6016 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.i; break;
6018 break;
6020 } else {
6021 do_itof:
6022 #if !defined(TCC_TARGET_ARM)
6023 gen_cvt_itof1(dbt);
6024 #else
6025 gen_cvt_itof(dbt);
6026 #endif
6028 } else if (sf) {
6029 /* convert fp to int */
6030 if (dbt == VT_BOOL) {
6031 vpushi(0);
6032 gen_op(TOK_NE);
6033 } else {
6034 /* we handle char/short/etc... with generic code */
6035 if (dbt != (VT_INT | VT_UNSIGNED) &&
6036 dbt != (VT_LLONG | VT_UNSIGNED) &&
6037 dbt != VT_LLONG)
6038 dbt = VT_INT;
6039 if (c) {
6040 switch(dbt) {
6041 case VT_LLONG | VT_UNSIGNED:
6042 case VT_LLONG:
6043 /* XXX: add const cases for long long */
6044 goto do_ftoi;
6045 case VT_INT | VT_UNSIGNED:
6046 switch(sbt) {
6047 case VT_FLOAT: vtop->c.ui = (unsigned int)vtop->c.d; break;
6048 case VT_DOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
6049 case VT_LDOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
6051 break;
6052 default:
6053 /* int case */
6054 switch(sbt) {
6055 case VT_FLOAT: vtop->c.i = (int)vtop->c.d; break;
6056 case VT_DOUBLE: vtop->c.i = (int)vtop->c.d; break;
6057 case VT_LDOUBLE: vtop->c.i = (int)vtop->c.d; break;
6059 break;
6061 } else {
6062 do_ftoi:
6063 gen_cvt_ftoi1(dbt);
6065 if (dbt == VT_INT && (type->t & (VT_BTYPE | VT_UNSIGNED)) != dbt) {
6066 /* additional cast for char/short... */
6067 vtop->type.t = dbt;
6068 gen_cast(type);
6071 } else if ((dbt & VT_BTYPE) == VT_LLONG) {
6072 if ((sbt & VT_BTYPE) != VT_LLONG) {
6073 /* scalar to long long */
6074 if (c) {
6075 if (sbt == (VT_INT | VT_UNSIGNED))
6076 vtop->c.ll = vtop->c.ui;
6077 else
6078 vtop->c.ll = vtop->c.i;
6079 } else {
6080 /* machine independent conversion */
6081 gv(RC_INT);
6082 /* generate high word */
6083 if (sbt == (VT_INT | VT_UNSIGNED)) {
6084 vpushi(0);
6085 gv(RC_INT);
6086 } else {
6087 gv_dup();
6088 vpushi(31);
6089 gen_op(TOK_SAR);
6091 /* patch second register */
6092 vtop[-1].r2 = vtop->r;
6093 vpop();
6096 } else if (dbt == VT_BOOL) {
6097 /* scalar to bool */
6098 vpushi(0);
6099 gen_op(TOK_NE);
6100 } else if ((dbt & VT_BTYPE) == VT_BYTE ||
6101 (dbt & VT_BTYPE) == VT_SHORT) {
6102 if (sbt == VT_PTR) {
6103 vtop->type.t = VT_INT;
6104 warning("nonportable conversion from pointer to char/short");
6106 force_charshort_cast(dbt);
6107 } else if ((dbt & VT_BTYPE) == VT_INT) {
6108 /* scalar to int */
6109 if (sbt == VT_LLONG) {
6110 /* from long long: just take low order word */
6111 lexpand();
6112 vpop();
6114 /* if lvalue and single word type, nothing to do because
6115 the lvalue already contains the real type size (see
6116 VT_LVAL_xxx constants) */
6118 } else if ((dbt & VT_BTYPE) == VT_PTR && !(vtop->r & VT_LVAL)) {
6119 /* if we are casting between pointer types,
6120 we must update the VT_LVAL_xxx size */
6121 vtop->r = (vtop->r & ~VT_LVAL_TYPE)
6122 | (lvalue_type(type->ref->type.t) & VT_LVAL_TYPE);
6124 vtop->type = *type;
6127 /* return type size. Put alignment at 'a' */
6128 static int type_size(CType *type, int *a)
6130 Sym *s;
6131 int bt;
6133 bt = type->t & VT_BTYPE;
6134 if (bt == VT_STRUCT) {
6135 /* struct/union */
6136 s = type->ref;
6137 *a = s->r;
6138 return s->c;
6139 } else if (bt == VT_PTR) {
6140 if (type->t & VT_ARRAY) {
6141 s = type->ref;
6142 return type_size(&s->type, a) * s->c;
6143 } else {
6144 *a = PTR_SIZE;
6145 return PTR_SIZE;
6147 } else if (bt == VT_LDOUBLE) {
6148 *a = LDOUBLE_ALIGN;
6149 return LDOUBLE_SIZE;
6150 } else if (bt == VT_DOUBLE || bt == VT_LLONG) {
6151 #ifdef TCC_TARGET_I386
6152 *a = 4;
6153 #elif defined(TCC_TARGET_ARM)
6154 #ifdef TCC_ARM_EABI
6155 *a = 8;
6156 #else
6157 *a = 4;
6158 #endif
6159 #else
6160 *a = 8;
6161 #endif
6162 return 8;
6163 } else if (bt == VT_INT || bt == VT_ENUM || bt == VT_FLOAT) {
6164 *a = 4;
6165 return 4;
6166 } else if (bt == VT_SHORT) {
6167 *a = 2;
6168 return 2;
6169 } else {
6170 /* char, void, function, _Bool */
6171 *a = 1;
6172 return 1;
6176 /* return the pointed type of t */
6177 static inline CType *pointed_type(CType *type)
6179 return &type->ref->type;
6182 /* modify type so that its it is a pointer to type. */
6183 static void mk_pointer(CType *type)
6185 Sym *s;
6186 s = sym_push(SYM_FIELD, type, 0, -1);
6187 type->t = VT_PTR | (type->t & ~VT_TYPE);
6188 type->ref = s;
6191 /* compare function types. OLD functions match any new functions */
6192 static int is_compatible_func(CType *type1, CType *type2)
6194 Sym *s1, *s2;
6196 s1 = type1->ref;
6197 s2 = type2->ref;
6198 if (!is_compatible_types(&s1->type, &s2->type))
6199 return 0;
6200 /* check func_call */
6201 if (FUNC_CALL(s1->r) != FUNC_CALL(s2->r))
6202 return 0;
6203 /* XXX: not complete */
6204 if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
6205 return 1;
6206 if (s1->c != s2->c)
6207 return 0;
6208 while (s1 != NULL) {
6209 if (s2 == NULL)
6210 return 0;
6211 if (!is_compatible_parameter_types(&s1->type, &s2->type))
6212 return 0;
6213 s1 = s1->next;
6214 s2 = s2->next;
6216 if (s2)
6217 return 0;
6218 return 1;
6221 /* return true if type1 and type2 are the same. If unqualified is
6222 true, qualifiers on the types are ignored.
6224 - enums are not checked as gcc __builtin_types_compatible_p ()
6226 static int compare_types(CType *type1, CType *type2, int unqualified)
6228 int bt1, t1, t2;
6230 t1 = type1->t & VT_TYPE;
6231 t2 = type2->t & VT_TYPE;
6232 if (unqualified) {
6233 /* strip qualifiers before comparing */
6234 t1 &= ~(VT_CONSTANT | VT_VOLATILE);
6235 t2 &= ~(VT_CONSTANT | VT_VOLATILE);
6237 /* XXX: bitfields ? */
6238 if (t1 != t2)
6239 return 0;
6240 /* test more complicated cases */
6241 bt1 = t1 & VT_BTYPE;
6242 if (bt1 == VT_PTR) {
6243 type1 = pointed_type(type1);
6244 type2 = pointed_type(type2);
6245 return is_compatible_types(type1, type2);
6246 } else if (bt1 == VT_STRUCT) {
6247 return (type1->ref == type2->ref);
6248 } else if (bt1 == VT_FUNC) {
6249 return is_compatible_func(type1, type2);
6250 } else {
6251 return 1;
6255 /* return true if type1 and type2 are exactly the same (including
6256 qualifiers).
6258 static int is_compatible_types(CType *type1, CType *type2)
6260 return compare_types(type1,type2,0);
6263 /* return true if type1 and type2 are the same (ignoring qualifiers).
6265 static int is_compatible_parameter_types(CType *type1, CType *type2)
6267 return compare_types(type1,type2,1);
6270 /* print a type. If 'varstr' is not NULL, then the variable is also
6271 printed in the type */
6272 /* XXX: union */
6273 /* XXX: add array and function pointers */
6274 void type_to_str(char *buf, int buf_size,
6275 CType *type, const char *varstr)
6277 int bt, v, t;
6278 Sym *s, *sa;
6279 char buf1[256];
6280 const char *tstr;
6282 t = type->t & VT_TYPE;
6283 bt = t & VT_BTYPE;
6284 buf[0] = '\0';
6285 if (t & VT_CONSTANT)
6286 pstrcat(buf, buf_size, "const ");
6287 if (t & VT_VOLATILE)
6288 pstrcat(buf, buf_size, "volatile ");
6289 if (t & VT_UNSIGNED)
6290 pstrcat(buf, buf_size, "unsigned ");
6291 switch(bt) {
6292 case VT_VOID:
6293 tstr = "void";
6294 goto add_tstr;
6295 case VT_BOOL:
6296 tstr = "_Bool";
6297 goto add_tstr;
6298 case VT_BYTE:
6299 tstr = "char";
6300 goto add_tstr;
6301 case VT_SHORT:
6302 tstr = "short";
6303 goto add_tstr;
6304 case VT_INT:
6305 tstr = "int";
6306 goto add_tstr;
6307 case VT_LONG:
6308 tstr = "long";
6309 goto add_tstr;
6310 case VT_LLONG:
6311 tstr = "long long";
6312 goto add_tstr;
6313 case VT_FLOAT:
6314 tstr = "float";
6315 goto add_tstr;
6316 case VT_DOUBLE:
6317 tstr = "double";
6318 goto add_tstr;
6319 case VT_LDOUBLE:
6320 tstr = "long double";
6321 add_tstr:
6322 pstrcat(buf, buf_size, tstr);
6323 break;
6324 case VT_ENUM:
6325 case VT_STRUCT:
6326 if (bt == VT_STRUCT)
6327 tstr = "struct ";
6328 else
6329 tstr = "enum ";
6330 pstrcat(buf, buf_size, tstr);
6331 v = type->ref->v & ~SYM_STRUCT;
6332 if (v >= SYM_FIRST_ANOM)
6333 pstrcat(buf, buf_size, "<anonymous>");
6334 else
6335 pstrcat(buf, buf_size, get_tok_str(v, NULL));
6336 break;
6337 case VT_FUNC:
6338 s = type->ref;
6339 type_to_str(buf, buf_size, &s->type, varstr);
6340 pstrcat(buf, buf_size, "(");
6341 sa = s->next;
6342 while (sa != NULL) {
6343 type_to_str(buf1, sizeof(buf1), &sa->type, NULL);
6344 pstrcat(buf, buf_size, buf1);
6345 sa = sa->next;
6346 if (sa)
6347 pstrcat(buf, buf_size, ", ");
6349 pstrcat(buf, buf_size, ")");
6350 goto no_var;
6351 case VT_PTR:
6352 s = type->ref;
6353 pstrcpy(buf1, sizeof(buf1), "*");
6354 if (varstr)
6355 pstrcat(buf1, sizeof(buf1), varstr);
6356 type_to_str(buf, buf_size, &s->type, buf1);
6357 goto no_var;
6359 if (varstr) {
6360 pstrcat(buf, buf_size, " ");
6361 pstrcat(buf, buf_size, varstr);
6363 no_var: ;
6366 /* verify type compatibility to store vtop in 'dt' type, and generate
6367 casts if needed. */
6368 static void gen_assign_cast(CType *dt)
6370 CType *st, *type1, *type2, tmp_type1, tmp_type2;
6371 char buf1[256], buf2[256];
6372 int dbt, sbt;
6374 st = &vtop->type; /* source type */
6375 dbt = dt->t & VT_BTYPE;
6376 sbt = st->t & VT_BTYPE;
6377 if (dt->t & VT_CONSTANT)
6378 warning("assignment of read-only location");
6379 switch(dbt) {
6380 case VT_PTR:
6381 /* special cases for pointers */
6382 /* '0' can also be a pointer */
6383 if (is_null_pointer(vtop))
6384 goto type_ok;
6385 /* accept implicit pointer to integer cast with warning */
6386 if (is_integer_btype(sbt)) {
6387 warning("assignment makes pointer from integer without a cast");
6388 goto type_ok;
6390 type1 = pointed_type(dt);
6391 /* a function is implicitely a function pointer */
6392 if (sbt == VT_FUNC) {
6393 if ((type1->t & VT_BTYPE) != VT_VOID &&
6394 !is_compatible_types(pointed_type(dt), st))
6395 goto error;
6396 else
6397 goto type_ok;
6399 if (sbt != VT_PTR)
6400 goto error;
6401 type2 = pointed_type(st);
6402 if ((type1->t & VT_BTYPE) == VT_VOID ||
6403 (type2->t & VT_BTYPE) == VT_VOID) {
6404 /* void * can match anything */
6405 } else {
6406 /* exact type match, except for unsigned */
6407 tmp_type1 = *type1;
6408 tmp_type2 = *type2;
6409 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
6410 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
6411 if (!is_compatible_types(&tmp_type1, &tmp_type2))
6412 warning("assignment from incompatible pointer type");
6414 /* check const and volatile */
6415 if ((!(type1->t & VT_CONSTANT) && (type2->t & VT_CONSTANT)) ||
6416 (!(type1->t & VT_VOLATILE) && (type2->t & VT_VOLATILE)))
6417 warning("assignment discards qualifiers from pointer target type");
6418 break;
6419 case VT_BYTE:
6420 case VT_SHORT:
6421 case VT_INT:
6422 case VT_LLONG:
6423 if (sbt == VT_PTR || sbt == VT_FUNC) {
6424 warning("assignment makes integer from pointer without a cast");
6426 /* XXX: more tests */
6427 break;
6428 case VT_STRUCT:
6429 tmp_type1 = *dt;
6430 tmp_type2 = *st;
6431 tmp_type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
6432 tmp_type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
6433 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
6434 error:
6435 type_to_str(buf1, sizeof(buf1), st, NULL);
6436 type_to_str(buf2, sizeof(buf2), dt, NULL);
6437 error("cannot cast '%s' to '%s'", buf1, buf2);
6439 break;
6441 type_ok:
6442 gen_cast(dt);
6445 /* store vtop in lvalue pushed on stack */
6446 void vstore(void)
6448 int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
6450 ft = vtop[-1].type.t;
6451 sbt = vtop->type.t & VT_BTYPE;
6452 dbt = ft & VT_BTYPE;
6453 if (((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
6454 (sbt == VT_INT && dbt == VT_SHORT)) {
6455 /* optimize char/short casts */
6456 delayed_cast = VT_MUSTCAST;
6457 vtop->type.t = ft & VT_TYPE;
6458 /* XXX: factorize */
6459 if (ft & VT_CONSTANT)
6460 warning("assignment of read-only location");
6461 } else {
6462 delayed_cast = 0;
6463 if (!(ft & VT_BITFIELD))
6464 gen_assign_cast(&vtop[-1].type);
6467 if (sbt == VT_STRUCT) {
6468 /* if structure, only generate pointer */
6469 /* structure assignment : generate memcpy */
6470 /* XXX: optimize if small size */
6471 if (!nocode_wanted) {
6472 size = type_size(&vtop->type, &align);
6474 #ifdef TCC_ARM_EABI
6475 if(!(align & 7))
6476 vpush_global_sym(&func_old_type, TOK_memcpy8);
6477 else if(!(align & 3))
6478 vpush_global_sym(&func_old_type, TOK_memcpy4);
6479 else
6480 #endif
6481 vpush_global_sym(&func_old_type, TOK_memcpy);
6483 /* destination */
6484 vpushv(vtop - 2);
6485 vtop->type.t = VT_INT;
6486 gaddrof();
6487 /* source */
6488 vpushv(vtop - 2);
6489 vtop->type.t = VT_INT;
6490 gaddrof();
6491 /* type size */
6492 vpushi(size);
6493 gfunc_call(3);
6495 vswap();
6496 vpop();
6497 } else {
6498 vswap();
6499 vpop();
6501 /* leave source on stack */
6502 } else if (ft & VT_BITFIELD) {
6503 /* bitfield store handling */
6504 bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
6505 bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
6506 /* remove bit field info to avoid loops */
6507 vtop[-1].type.t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
6509 /* duplicate source into other register */
6510 gv_dup();
6511 vswap();
6512 vrott(3);
6514 /* duplicate destination */
6515 vdup();
6516 vtop[-1] = vtop[-2];
6518 /* mask and shift source */
6519 vpushi((1 << bit_size) - 1);
6520 gen_op('&');
6521 vpushi(bit_pos);
6522 gen_op(TOK_SHL);
6523 /* load destination, mask and or with source */
6524 vswap();
6525 vpushi(~(((1 << bit_size) - 1) << bit_pos));
6526 gen_op('&');
6527 gen_op('|');
6528 /* store result */
6529 vstore();
6531 /* pop off shifted source from "duplicate source..." above */
6532 vpop();
6534 } else {
6535 #ifdef CONFIG_TCC_BCHECK
6536 /* bound check case */
6537 if (vtop[-1].r & VT_MUSTBOUND) {
6538 vswap();
6539 gbound();
6540 vswap();
6542 #endif
6543 if (!nocode_wanted) {
6544 rc = RC_INT;
6545 if (is_float(ft))
6546 rc = RC_FLOAT;
6547 r = gv(rc); /* generate value */
6548 /* if lvalue was saved on stack, must read it */
6549 if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
6550 SValue sv;
6551 t = get_reg(RC_INT);
6552 sv.type.t = VT_INT;
6553 sv.r = VT_LOCAL | VT_LVAL;
6554 sv.c.ul = vtop[-1].c.ul;
6555 load(t, &sv);
6556 vtop[-1].r = t | VT_LVAL;
6558 store(r, vtop - 1);
6559 /* two word case handling : store second register at word + 4 */
6560 if ((ft & VT_BTYPE) == VT_LLONG) {
6561 vswap();
6562 /* convert to int to increment easily */
6563 vtop->type.t = VT_INT;
6564 gaddrof();
6565 vpushi(4);
6566 gen_op('+');
6567 vtop->r |= VT_LVAL;
6568 vswap();
6569 /* XXX: it works because r2 is spilled last ! */
6570 store(vtop->r2, vtop - 1);
6573 vswap();
6574 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
6575 vtop->r |= delayed_cast;
6579 /* post defines POST/PRE add. c is the token ++ or -- */
6580 void inc(int post, int c)
6582 test_lvalue();
6583 vdup(); /* save lvalue */
6584 if (post) {
6585 gv_dup(); /* duplicate value */
6586 vrotb(3);
6587 vrotb(3);
6589 /* add constant */
6590 vpushi(c - TOK_MID);
6591 gen_op('+');
6592 vstore(); /* store value */
6593 if (post)
6594 vpop(); /* if post op, return saved value */
6597 /* Parse GNUC __attribute__ extension. Currently, the following
6598 extensions are recognized:
6599 - aligned(n) : set data/function alignment.
6600 - packed : force data alignment to 1
6601 - section(x) : generate data/code in this section.
6602 - unused : currently ignored, but may be used someday.
6603 - regparm(n) : pass function parameters in registers (i386 only)
6605 static void parse_attribute(AttributeDef *ad)
6607 int t, n;
6609 while (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) {
6610 next();
6611 skip('(');
6612 skip('(');
6613 while (tok != ')') {
6614 if (tok < TOK_IDENT)
6615 expect("attribute name");
6616 t = tok;
6617 next();
6618 switch(t) {
6619 case TOK_SECTION1:
6620 case TOK_SECTION2:
6621 skip('(');
6622 if (tok != TOK_STR)
6623 expect("section name");
6624 ad->section = find_section(tcc_state, (char *)tokc.cstr->data);
6625 next();
6626 skip(')');
6627 break;
6628 case TOK_ALIGNED1:
6629 case TOK_ALIGNED2:
6630 if (tok == '(') {
6631 next();
6632 n = expr_const();
6633 if (n <= 0 || (n & (n - 1)) != 0)
6634 error("alignment must be a positive power of two");
6635 skip(')');
6636 } else {
6637 n = MAX_ALIGN;
6639 ad->aligned = n;
6640 break;
6641 case TOK_PACKED1:
6642 case TOK_PACKED2:
6643 ad->packed = 1;
6644 break;
6645 case TOK_UNUSED1:
6646 case TOK_UNUSED2:
6647 /* currently, no need to handle it because tcc does not
6648 track unused objects */
6649 break;
6650 case TOK_NORETURN1:
6651 case TOK_NORETURN2:
6652 /* currently, no need to handle it because tcc does not
6653 track unused objects */
6654 break;
6655 case TOK_CDECL1:
6656 case TOK_CDECL2:
6657 case TOK_CDECL3:
6658 FUNC_CALL(ad->func_attr) = FUNC_CDECL;
6659 break;
6660 case TOK_STDCALL1:
6661 case TOK_STDCALL2:
6662 case TOK_STDCALL3:
6663 FUNC_CALL(ad->func_attr) = FUNC_STDCALL;
6664 break;
6665 #ifdef TCC_TARGET_I386
6666 case TOK_REGPARM1:
6667 case TOK_REGPARM2:
6668 skip('(');
6669 n = expr_const();
6670 if (n > 3)
6671 n = 3;
6672 else if (n < 0)
6673 n = 0;
6674 if (n > 0)
6675 FUNC_CALL(ad->func_attr) = FUNC_FASTCALL1 + n - 1;
6676 skip(')');
6677 break;
6678 case TOK_FASTCALL1:
6679 case TOK_FASTCALL2:
6680 case TOK_FASTCALL3:
6681 FUNC_CALL(ad->func_attr) = FUNC_FASTCALLW;
6682 break;
6683 #endif
6684 case TOK_DLLEXPORT:
6685 FUNC_EXPORT(ad->func_attr) = 1;
6686 break;
6687 default:
6688 if (tcc_state->warn_unsupported)
6689 warning("'%s' attribute ignored", get_tok_str(t, NULL));
6690 /* skip parameters */
6691 if (tok == '(') {
6692 int parenthesis = 0;
6693 do {
6694 if (tok == '(')
6695 parenthesis++;
6696 else if (tok == ')')
6697 parenthesis--;
6698 next();
6699 } while (parenthesis && tok != -1);
6701 break;
6703 if (tok != ',')
6704 break;
6705 next();
6707 skip(')');
6708 skip(')');
6712 /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
6713 static void struct_decl(CType *type, int u)
6715 int a, v, size, align, maxalign, c, offset;
6716 int bit_size, bit_pos, bsize, bt, lbit_pos;
6717 Sym *s, *ss, *ass, **ps;
6718 AttributeDef ad;
6719 CType type1, btype;
6721 a = tok; /* save decl type */
6722 next();
6723 if (tok != '{') {
6724 v = tok;
6725 next();
6726 /* struct already defined ? return it */
6727 if (v < TOK_IDENT)
6728 expect("struct/union/enum name");
6729 s = struct_find(v);
6730 if (s) {
6731 if (s->type.t != a)
6732 error("invalid type");
6733 goto do_decl;
6735 } else {
6736 v = anon_sym++;
6738 type1.t = a;
6739 /* we put an undefined size for struct/union */
6740 s = sym_push(v | SYM_STRUCT, &type1, 0, -1);
6741 s->r = 0; /* default alignment is zero as gcc */
6742 /* put struct/union/enum name in type */
6743 do_decl:
6744 type->t = u;
6745 type->ref = s;
6747 if (tok == '{') {
6748 next();
6749 if (s->c != -1)
6750 error("struct/union/enum already defined");
6751 /* cannot be empty */
6752 c = 0;
6753 /* non empty enums are not allowed */
6754 if (a == TOK_ENUM) {
6755 for(;;) {
6756 v = tok;
6757 if (v < TOK_UIDENT)
6758 expect("identifier");
6759 next();
6760 if (tok == '=') {
6761 next();
6762 c = expr_const();
6764 /* enum symbols have static storage */
6765 ss = sym_push(v, &int_type, VT_CONST, c);
6766 ss->type.t |= VT_STATIC;
6767 if (tok != ',')
6768 break;
6769 next();
6770 c++;
6771 /* NOTE: we accept a trailing comma */
6772 if (tok == '}')
6773 break;
6775 skip('}');
6776 } else {
6777 maxalign = 1;
6778 ps = &s->next;
6779 bit_pos = 0;
6780 offset = 0;
6781 while (tok != '}') {
6782 parse_btype(&btype, &ad);
6783 while (1) {
6784 bit_size = -1;
6785 v = 0;
6786 type1 = btype;
6787 if (tok != ':') {
6788 type_decl(&type1, &ad, &v, TYPE_DIRECT | TYPE_ABSTRACT);
6789 if (v == 0 && (type1.t & VT_BTYPE) != VT_STRUCT)
6790 expect("identifier");
6791 if ((type1.t & VT_BTYPE) == VT_FUNC ||
6792 (type1.t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN | VT_INLINE)))
6793 error("invalid type for '%s'",
6794 get_tok_str(v, NULL));
6796 if (tok == ':') {
6797 next();
6798 bit_size = expr_const();
6799 /* XXX: handle v = 0 case for messages */
6800 if (bit_size < 0)
6801 error("negative width in bit-field '%s'",
6802 get_tok_str(v, NULL));
6803 if (v && bit_size == 0)
6804 error("zero width for bit-field '%s'",
6805 get_tok_str(v, NULL));
6807 size = type_size(&type1, &align);
6808 if (ad.aligned) {
6809 if (align < ad.aligned)
6810 align = ad.aligned;
6811 } else if (ad.packed) {
6812 align = 1;
6813 } else if (*tcc_state->pack_stack_ptr) {
6814 if (align > *tcc_state->pack_stack_ptr)
6815 align = *tcc_state->pack_stack_ptr;
6817 lbit_pos = 0;
6818 if (bit_size >= 0) {
6819 bt = type1.t & VT_BTYPE;
6820 if (bt != VT_INT &&
6821 bt != VT_BYTE &&
6822 bt != VT_SHORT &&
6823 bt != VT_BOOL &&
6824 bt != VT_ENUM)
6825 error("bitfields must have scalar type");
6826 bsize = size * 8;
6827 if (bit_size > bsize) {
6828 error("width of '%s' exceeds its type",
6829 get_tok_str(v, NULL));
6830 } else if (bit_size == bsize) {
6831 /* no need for bit fields */
6832 bit_pos = 0;
6833 } else if (bit_size == 0) {
6834 /* XXX: what to do if only padding in a
6835 structure ? */
6836 /* zero size: means to pad */
6837 if (bit_pos > 0)
6838 bit_pos = bsize;
6839 } else {
6840 /* we do not have enough room ? */
6841 if ((bit_pos + bit_size) > bsize)
6842 bit_pos = 0;
6843 lbit_pos = bit_pos;
6844 /* XXX: handle LSB first */
6845 type1.t |= VT_BITFIELD |
6846 (bit_pos << VT_STRUCT_SHIFT) |
6847 (bit_size << (VT_STRUCT_SHIFT + 6));
6848 bit_pos += bit_size;
6850 } else {
6851 bit_pos = 0;
6853 if (v != 0 || (type1.t & VT_BTYPE) == VT_STRUCT) {
6854 /* add new memory data only if starting
6855 bit field */
6856 if (lbit_pos == 0) {
6857 if (a == TOK_STRUCT) {
6858 c = (c + align - 1) & -align;
6859 offset = c;
6860 if (size > 0)
6861 c += size;
6862 } else {
6863 offset = 0;
6864 if (size > c)
6865 c = size;
6867 if (align > maxalign)
6868 maxalign = align;
6870 #if 0
6871 printf("add field %s offset=%d",
6872 get_tok_str(v, NULL), offset);
6873 if (type1.t & VT_BITFIELD) {
6874 printf(" pos=%d size=%d",
6875 (type1.t >> VT_STRUCT_SHIFT) & 0x3f,
6876 (type1.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
6878 printf("\n");
6879 #endif
6881 if (v == 0 && (type1.t & VT_BTYPE) == VT_STRUCT) {
6882 ass = type1.ref;
6883 while ((ass = ass->next) != NULL) {
6884 ss = sym_push(ass->v, &ass->type, 0, offset + ass->c);
6885 *ps = ss;
6886 ps = &ss->next;
6888 } else if (v) {
6889 ss = sym_push(v | SYM_FIELD, &type1, 0, offset);
6890 *ps = ss;
6891 ps = &ss->next;
6893 if (tok == ';' || tok == TOK_EOF)
6894 break;
6895 skip(',');
6897 skip(';');
6899 skip('}');
6900 /* store size and alignment */
6901 s->c = (c + maxalign - 1) & -maxalign;
6902 s->r = maxalign;
6907 /* return 0 if no type declaration. otherwise, return the basic type
6908 and skip it.
6910 static int parse_btype(CType *type, AttributeDef *ad)
6912 int t, u, type_found, typespec_found, typedef_found;
6913 Sym *s;
6914 CType type1;
6916 memset(ad, 0, sizeof(AttributeDef));
6917 type_found = 0;
6918 typespec_found = 0;
6919 typedef_found = 0;
6920 t = 0;
6921 while(1) {
6922 switch(tok) {
6923 case TOK_EXTENSION:
6924 /* currently, we really ignore extension */
6925 next();
6926 continue;
6928 /* basic types */
6929 case TOK_CHAR:
6930 u = VT_BYTE;
6931 basic_type:
6932 next();
6933 basic_type1:
6934 if ((t & VT_BTYPE) != 0)
6935 error("too many basic types");
6936 t |= u;
6937 typespec_found = 1;
6938 break;
6939 case TOK_VOID:
6940 u = VT_VOID;
6941 goto basic_type;
6942 case TOK_SHORT:
6943 u = VT_SHORT;
6944 goto basic_type;
6945 case TOK_INT:
6946 next();
6947 typespec_found = 1;
6948 break;
6949 case TOK_LONG:
6950 next();
6951 if ((t & VT_BTYPE) == VT_DOUBLE) {
6952 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6953 } else if ((t & VT_BTYPE) == VT_LONG) {
6954 t = (t & ~VT_BTYPE) | VT_LLONG;
6955 } else {
6956 u = VT_LONG;
6957 goto basic_type1;
6959 break;
6960 case TOK_BOOL:
6961 u = VT_BOOL;
6962 goto basic_type;
6963 case TOK_FLOAT:
6964 u = VT_FLOAT;
6965 goto basic_type;
6966 case TOK_DOUBLE:
6967 next();
6968 if ((t & VT_BTYPE) == VT_LONG) {
6969 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6970 } else {
6971 u = VT_DOUBLE;
6972 goto basic_type1;
6974 break;
6975 case TOK_ENUM:
6976 struct_decl(&type1, VT_ENUM);
6977 basic_type2:
6978 u = type1.t;
6979 type->ref = type1.ref;
6980 goto basic_type1;
6981 case TOK_STRUCT:
6982 case TOK_UNION:
6983 struct_decl(&type1, VT_STRUCT);
6984 goto basic_type2;
6986 /* type modifiers */
6987 case TOK_CONST1:
6988 case TOK_CONST2:
6989 case TOK_CONST3:
6990 t |= VT_CONSTANT;
6991 next();
6992 break;
6993 case TOK_VOLATILE1:
6994 case TOK_VOLATILE2:
6995 case TOK_VOLATILE3:
6996 t |= VT_VOLATILE;
6997 next();
6998 break;
6999 case TOK_SIGNED1:
7000 case TOK_SIGNED2:
7001 case TOK_SIGNED3:
7002 typespec_found = 1;
7003 t |= VT_SIGNED;
7004 next();
7005 break;
7006 case TOK_REGISTER:
7007 case TOK_AUTO:
7008 case TOK_RESTRICT1:
7009 case TOK_RESTRICT2:
7010 case TOK_RESTRICT3:
7011 next();
7012 break;
7013 case TOK_UNSIGNED:
7014 t |= VT_UNSIGNED;
7015 next();
7016 typespec_found = 1;
7017 break;
7019 /* storage */
7020 case TOK_EXTERN:
7021 t |= VT_EXTERN;
7022 next();
7023 break;
7024 case TOK_STATIC:
7025 t |= VT_STATIC;
7026 next();
7027 break;
7028 case TOK_TYPEDEF:
7029 t |= VT_TYPEDEF;
7030 next();
7031 break;
7032 case TOK_INLINE1:
7033 case TOK_INLINE2:
7034 case TOK_INLINE3:
7035 t |= VT_INLINE;
7036 next();
7037 break;
7039 /* GNUC attribute */
7040 case TOK_ATTRIBUTE1:
7041 case TOK_ATTRIBUTE2:
7042 parse_attribute(ad);
7043 break;
7044 /* GNUC typeof */
7045 case TOK_TYPEOF1:
7046 case TOK_TYPEOF2:
7047 case TOK_TYPEOF3:
7048 next();
7049 parse_expr_type(&type1);
7050 goto basic_type2;
7051 default:
7052 if (typespec_found || typedef_found)
7053 goto the_end;
7054 s = sym_find(tok);
7055 if (!s || !(s->type.t & VT_TYPEDEF))
7056 goto the_end;
7057 typedef_found = 1;
7058 t |= (s->type.t & ~VT_TYPEDEF);
7059 type->ref = s->type.ref;
7060 next();
7061 typespec_found = 1;
7062 break;
7064 type_found = 1;
7066 the_end:
7067 if ((t & (VT_SIGNED|VT_UNSIGNED)) == (VT_SIGNED|VT_UNSIGNED))
7068 error("signed and unsigned modifier");
7069 if (tcc_state->char_is_unsigned) {
7070 if ((t & (VT_SIGNED|VT_UNSIGNED|VT_BTYPE)) == VT_BYTE)
7071 t |= VT_UNSIGNED;
7073 t &= ~VT_SIGNED;
7075 /* long is never used as type */
7076 if ((t & VT_BTYPE) == VT_LONG)
7077 t = (t & ~VT_BTYPE) | VT_INT;
7078 type->t = t;
7079 return type_found;
7082 /* convert a function parameter type (array to pointer and function to
7083 function pointer) */
7084 static inline void convert_parameter_type(CType *pt)
7086 /* remove const and volatile qualifiers (XXX: const could be used
7087 to indicate a const function parameter */
7088 pt->t &= ~(VT_CONSTANT | VT_VOLATILE);
7089 /* array must be transformed to pointer according to ANSI C */
7090 pt->t &= ~VT_ARRAY;
7091 if ((pt->t & VT_BTYPE) == VT_FUNC) {
7092 mk_pointer(pt);
7096 static void post_type(CType *type, AttributeDef *ad)
7098 int n, l, t1, arg_size, align;
7099 Sym **plast, *s, *first;
7100 AttributeDef ad1;
7101 CType pt;
7103 if (tok == '(') {
7104 /* function declaration */
7105 next();
7106 l = 0;
7107 first = NULL;
7108 plast = &first;
7109 arg_size = 0;
7110 if (tok != ')') {
7111 for(;;) {
7112 /* read param name and compute offset */
7113 if (l != FUNC_OLD) {
7114 if (!parse_btype(&pt, &ad1)) {
7115 if (l) {
7116 error("invalid type");
7117 } else {
7118 l = FUNC_OLD;
7119 goto old_proto;
7122 l = FUNC_NEW;
7123 if ((pt.t & VT_BTYPE) == VT_VOID && tok == ')')
7124 break;
7125 type_decl(&pt, &ad1, &n, TYPE_DIRECT | TYPE_ABSTRACT);
7126 if ((pt.t & VT_BTYPE) == VT_VOID)
7127 error("parameter declared as void");
7128 arg_size += (type_size(&pt, &align) + 3) & ~3;
7129 } else {
7130 old_proto:
7131 n = tok;
7132 if (n < TOK_UIDENT)
7133 expect("identifier");
7134 pt.t = VT_INT;
7135 next();
7137 convert_parameter_type(&pt);
7138 s = sym_push(n | SYM_FIELD, &pt, 0, 0);
7139 *plast = s;
7140 plast = &s->next;
7141 if (tok == ')')
7142 break;
7143 skip(',');
7144 if (l == FUNC_NEW && tok == TOK_DOTS) {
7145 l = FUNC_ELLIPSIS;
7146 next();
7147 break;
7151 /* if no parameters, then old type prototype */
7152 if (l == 0)
7153 l = FUNC_OLD;
7154 skip(')');
7155 t1 = type->t & VT_STORAGE;
7156 /* NOTE: const is ignored in returned type as it has a special
7157 meaning in gcc / C++ */
7158 type->t &= ~(VT_STORAGE | VT_CONSTANT);
7159 post_type(type, ad);
7160 /* we push a anonymous symbol which will contain the function prototype */
7161 FUNC_ARGS(ad->func_attr) = arg_size;
7162 s = sym_push(SYM_FIELD, type, ad->func_attr, l);
7163 s->next = first;
7164 type->t = t1 | VT_FUNC;
7165 type->ref = s;
7166 } else if (tok == '[') {
7167 /* array definition */
7168 next();
7169 n = -1;
7170 if (tok != ']') {
7171 n = expr_const();
7172 if (n < 0)
7173 error("invalid array size");
7175 skip(']');
7176 /* parse next post type */
7177 t1 = type->t & VT_STORAGE;
7178 type->t &= ~VT_STORAGE;
7179 post_type(type, ad);
7181 /* we push a anonymous symbol which will contain the array
7182 element type */
7183 s = sym_push(SYM_FIELD, type, 0, n);
7184 type->t = t1 | VT_ARRAY | VT_PTR;
7185 type->ref = s;
7189 /* Parse a type declaration (except basic type), and return the type
7190 in 'type'. 'td' is a bitmask indicating which kind of type decl is
7191 expected. 'type' should contain the basic type. 'ad' is the
7192 attribute definition of the basic type. It can be modified by
7193 type_decl().
7195 static void type_decl(CType *type, AttributeDef *ad, int *v, int td)
7197 Sym *s;
7198 CType type1, *type2;
7199 int qualifiers;
7201 while (tok == '*') {
7202 qualifiers = 0;
7203 redo:
7204 next();
7205 switch(tok) {
7206 case TOK_CONST1:
7207 case TOK_CONST2:
7208 case TOK_CONST3:
7209 qualifiers |= VT_CONSTANT;
7210 goto redo;
7211 case TOK_VOLATILE1:
7212 case TOK_VOLATILE2:
7213 case TOK_VOLATILE3:
7214 qualifiers |= VT_VOLATILE;
7215 goto redo;
7216 case TOK_RESTRICT1:
7217 case TOK_RESTRICT2:
7218 case TOK_RESTRICT3:
7219 goto redo;
7221 mk_pointer(type);
7222 type->t |= qualifiers;
7225 /* XXX: clarify attribute handling */
7226 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
7227 parse_attribute(ad);
7229 /* recursive type */
7230 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
7231 type1.t = 0; /* XXX: same as int */
7232 if (tok == '(') {
7233 next();
7234 /* XXX: this is not correct to modify 'ad' at this point, but
7235 the syntax is not clear */
7236 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
7237 parse_attribute(ad);
7238 type_decl(&type1, ad, v, td);
7239 skip(')');
7240 } else {
7241 /* type identifier */
7242 if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
7243 *v = tok;
7244 next();
7245 } else {
7246 if (!(td & TYPE_ABSTRACT))
7247 expect("identifier");
7248 *v = 0;
7251 post_type(type, ad);
7252 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
7253 parse_attribute(ad);
7254 if (!type1.t)
7255 return;
7256 /* append type at the end of type1 */
7257 type2 = &type1;
7258 for(;;) {
7259 s = type2->ref;
7260 type2 = &s->type;
7261 if (!type2->t) {
7262 *type2 = *type;
7263 break;
7266 *type = type1;
7269 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
7270 static int lvalue_type(int t)
7272 int bt, r;
7273 r = VT_LVAL;
7274 bt = t & VT_BTYPE;
7275 if (bt == VT_BYTE || bt == VT_BOOL)
7276 r |= VT_LVAL_BYTE;
7277 else if (bt == VT_SHORT)
7278 r |= VT_LVAL_SHORT;
7279 else
7280 return r;
7281 if (t & VT_UNSIGNED)
7282 r |= VT_LVAL_UNSIGNED;
7283 return r;
7286 /* indirection with full error checking and bound check */
7287 static void indir(void)
7289 if ((vtop->type.t & VT_BTYPE) != VT_PTR) {
7290 if ((vtop->type.t & VT_BTYPE) == VT_FUNC)
7291 return;
7292 expect("pointer");
7294 if ((vtop->r & VT_LVAL) && !nocode_wanted)
7295 gv(RC_INT);
7296 vtop->type = *pointed_type(&vtop->type);
7297 /* Arrays and functions are never lvalues */
7298 if (!(vtop->type.t & VT_ARRAY)
7299 && (vtop->type.t & VT_BTYPE) != VT_FUNC) {
7300 vtop->r |= lvalue_type(vtop->type.t);
7301 /* if bound checking, the referenced pointer must be checked */
7302 if (do_bounds_check)
7303 vtop->r |= VT_MUSTBOUND;
7307 /* pass a parameter to a function and do type checking and casting */
7308 static void gfunc_param_typed(Sym *func, Sym *arg)
7310 int func_type;
7311 CType type;
7313 func_type = func->c;
7314 if (func_type == FUNC_OLD ||
7315 (func_type == FUNC_ELLIPSIS && arg == NULL)) {
7316 /* default casting : only need to convert float to double */
7317 if ((vtop->type.t & VT_BTYPE) == VT_FLOAT) {
7318 type.t = VT_DOUBLE;
7319 gen_cast(&type);
7321 } else if (arg == NULL) {
7322 error("too many arguments to function");
7323 } else {
7324 type = arg->type;
7325 type.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
7326 gen_assign_cast(&type);
7330 /* parse an expression of the form '(type)' or '(expr)' and return its
7331 type */
7332 static void parse_expr_type(CType *type)
7334 int n;
7335 AttributeDef ad;
7337 skip('(');
7338 if (parse_btype(type, &ad)) {
7339 type_decl(type, &ad, &n, TYPE_ABSTRACT);
7340 } else {
7341 expr_type(type);
7343 skip(')');
7346 static void parse_type(CType *type)
7348 AttributeDef ad;
7349 int n;
7351 if (!parse_btype(type, &ad)) {
7352 expect("type");
7354 type_decl(type, &ad, &n, TYPE_ABSTRACT);
7357 static void vpush_tokc(int t)
7359 CType type;
7360 type.t = t;
7361 vsetc(&type, VT_CONST, &tokc);
7364 static void unary(void)
7366 int n, t, align, size, r;
7367 CType type;
7368 Sym *s;
7369 AttributeDef ad;
7371 /* XXX: GCC 2.95.3 does not generate a table although it should be
7372 better here */
7373 tok_next:
7374 switch(tok) {
7375 case TOK_EXTENSION:
7376 next();
7377 goto tok_next;
7378 case TOK_CINT:
7379 case TOK_CCHAR:
7380 case TOK_LCHAR:
7381 vpushi(tokc.i);
7382 next();
7383 break;
7384 case TOK_CUINT:
7385 vpush_tokc(VT_INT | VT_UNSIGNED);
7386 next();
7387 break;
7388 case TOK_CLLONG:
7389 vpush_tokc(VT_LLONG);
7390 next();
7391 break;
7392 case TOK_CULLONG:
7393 vpush_tokc(VT_LLONG | VT_UNSIGNED);
7394 next();
7395 break;
7396 case TOK_CFLOAT:
7397 vpush_tokc(VT_FLOAT);
7398 next();
7399 break;
7400 case TOK_CDOUBLE:
7401 vpush_tokc(VT_DOUBLE);
7402 next();
7403 break;
7404 case TOK_CLDOUBLE:
7405 vpush_tokc(VT_LDOUBLE);
7406 next();
7407 break;
7408 case TOK___FUNCTION__:
7409 if (!gnu_ext)
7410 goto tok_identifier;
7411 /* fall thru */
7412 case TOK___FUNC__:
7414 void *ptr;
7415 int len;
7416 /* special function name identifier */
7417 len = strlen(funcname) + 1;
7418 /* generate char[len] type */
7419 type.t = VT_BYTE;
7420 mk_pointer(&type);
7421 type.t |= VT_ARRAY;
7422 type.ref->c = len;
7423 vpush_ref(&type, data_section, data_section->data_offset, len);
7424 ptr = section_ptr_add(data_section, len);
7425 memcpy(ptr, funcname, len);
7426 next();
7428 break;
7429 case TOK_LSTR:
7430 #ifdef TCC_TARGET_PE
7431 t = VT_SHORT | VT_UNSIGNED;
7432 #else
7433 t = VT_INT;
7434 #endif
7435 goto str_init;
7436 case TOK_STR:
7437 /* string parsing */
7438 t = VT_BYTE;
7439 str_init:
7440 if (tcc_state->warn_write_strings)
7441 t |= VT_CONSTANT;
7442 type.t = t;
7443 mk_pointer(&type);
7444 type.t |= VT_ARRAY;
7445 memset(&ad, 0, sizeof(AttributeDef));
7446 decl_initializer_alloc(&type, &ad, VT_CONST, 2, 0, 0);
7447 break;
7448 case '(':
7449 next();
7450 /* cast ? */
7451 if (parse_btype(&type, &ad)) {
7452 type_decl(&type, &ad, &n, TYPE_ABSTRACT);
7453 skip(')');
7454 /* check ISOC99 compound literal */
7455 if (tok == '{') {
7456 /* data is allocated locally by default */
7457 if (global_expr)
7458 r = VT_CONST;
7459 else
7460 r = VT_LOCAL;
7461 /* all except arrays are lvalues */
7462 if (!(type.t & VT_ARRAY))
7463 r |= lvalue_type(type.t);
7464 memset(&ad, 0, sizeof(AttributeDef));
7465 decl_initializer_alloc(&type, &ad, r, 1, 0, 0);
7466 } else {
7467 unary();
7468 gen_cast(&type);
7470 } else if (tok == '{') {
7471 /* save all registers */
7472 save_regs(0);
7473 /* statement expression : we do not accept break/continue
7474 inside as GCC does */
7475 block(NULL, NULL, NULL, NULL, 0, 1);
7476 skip(')');
7477 } else {
7478 gexpr();
7479 skip(')');
7481 break;
7482 case '*':
7483 next();
7484 unary();
7485 indir();
7486 break;
7487 case '&':
7488 next();
7489 unary();
7490 /* functions names must be treated as function pointers,
7491 except for unary '&' and sizeof. Since we consider that
7492 functions are not lvalues, we only have to handle it
7493 there and in function calls. */
7494 /* arrays can also be used although they are not lvalues */
7495 if ((vtop->type.t & VT_BTYPE) != VT_FUNC &&
7496 !(vtop->type.t & VT_ARRAY) && !(vtop->type.t & VT_LLOCAL))
7497 test_lvalue();
7498 mk_pointer(&vtop->type);
7499 gaddrof();
7500 break;
7501 case '!':
7502 next();
7503 unary();
7504 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST)
7505 vtop->c.i = !vtop->c.i;
7506 else if ((vtop->r & VT_VALMASK) == VT_CMP)
7507 vtop->c.i = vtop->c.i ^ 1;
7508 else {
7509 save_regs(1);
7510 vseti(VT_JMP, gtst(1, 0));
7512 break;
7513 case '~':
7514 next();
7515 unary();
7516 vpushi(-1);
7517 gen_op('^');
7518 break;
7519 case '+':
7520 next();
7521 /* in order to force cast, we add zero */
7522 unary();
7523 if ((vtop->type.t & VT_BTYPE) == VT_PTR)
7524 error("pointer not accepted for unary plus");
7525 vpushi(0);
7526 gen_op('+');
7527 break;
7528 case TOK_SIZEOF:
7529 case TOK_ALIGNOF1:
7530 case TOK_ALIGNOF2:
7531 t = tok;
7532 next();
7533 if (tok == '(') {
7534 parse_expr_type(&type);
7535 } else {
7536 unary_type(&type);
7538 size = type_size(&type, &align);
7539 if (t == TOK_SIZEOF) {
7540 if (size < 0)
7541 error("sizeof applied to an incomplete type");
7542 vpushi(size);
7543 } else {
7544 vpushi(align);
7546 vtop->type.t |= VT_UNSIGNED;
7547 break;
7549 case TOK_builtin_types_compatible_p:
7551 CType type1, type2;
7552 next();
7553 skip('(');
7554 parse_type(&type1);
7555 skip(',');
7556 parse_type(&type2);
7557 skip(')');
7558 type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
7559 type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
7560 vpushi(is_compatible_types(&type1, &type2));
7562 break;
7563 case TOK_builtin_constant_p:
7565 int saved_nocode_wanted, res;
7566 next();
7567 skip('(');
7568 saved_nocode_wanted = nocode_wanted;
7569 nocode_wanted = 1;
7570 gexpr();
7571 res = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
7572 vpop();
7573 nocode_wanted = saved_nocode_wanted;
7574 skip(')');
7575 vpushi(res);
7577 break;
7578 case TOK_INC:
7579 case TOK_DEC:
7580 t = tok;
7581 next();
7582 unary();
7583 inc(0, t);
7584 break;
7585 case '-':
7586 next();
7587 vpushi(0);
7588 unary();
7589 gen_op('-');
7590 break;
7591 case TOK_LAND:
7592 if (!gnu_ext)
7593 goto tok_identifier;
7594 next();
7595 /* allow to take the address of a label */
7596 if (tok < TOK_UIDENT)
7597 expect("label identifier");
7598 s = label_find(tok);
7599 if (!s) {
7600 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
7601 } else {
7602 if (s->r == LABEL_DECLARED)
7603 s->r = LABEL_FORWARD;
7605 if (!s->type.t) {
7606 s->type.t = VT_VOID;
7607 mk_pointer(&s->type);
7608 s->type.t |= VT_STATIC;
7610 vset(&s->type, VT_CONST | VT_SYM, 0);
7611 vtop->sym = s;
7612 next();
7613 break;
7614 default:
7615 tok_identifier:
7616 t = tok;
7617 next();
7618 if (t < TOK_UIDENT)
7619 expect("identifier");
7620 s = sym_find(t);
7621 if (!s) {
7622 if (tok != '(')
7623 error("'%s' undeclared", get_tok_str(t, NULL));
7624 /* for simple function calls, we tolerate undeclared
7625 external reference to int() function */
7626 if (tcc_state->warn_implicit_function_declaration)
7627 warning("implicit declaration of function '%s'",
7628 get_tok_str(t, NULL));
7629 s = external_global_sym(t, &func_old_type, 0);
7631 if ((s->type.t & (VT_STATIC | VT_INLINE | VT_BTYPE)) ==
7632 (VT_STATIC | VT_INLINE | VT_FUNC)) {
7633 /* if referencing an inline function, then we generate a
7634 symbol to it if not already done. It will have the
7635 effect to generate code for it at the end of the
7636 compilation unit. Inline function as always
7637 generated in the text section. */
7638 if (!s->c)
7639 put_extern_sym(s, text_section, 0, 0);
7640 r = VT_SYM | VT_CONST;
7641 } else {
7642 r = s->r;
7644 vset(&s->type, r, s->c);
7645 /* if forward reference, we must point to s */
7646 if (vtop->r & VT_SYM) {
7647 vtop->sym = s;
7648 vtop->c.ul = 0;
7650 break;
7653 /* post operations */
7654 while (1) {
7655 if (tok == TOK_INC || tok == TOK_DEC) {
7656 inc(1, tok);
7657 next();
7658 } else if (tok == '.' || tok == TOK_ARROW) {
7659 /* field */
7660 if (tok == TOK_ARROW)
7661 indir();
7662 test_lvalue();
7663 gaddrof();
7664 next();
7665 /* expect pointer on structure */
7666 if ((vtop->type.t & VT_BTYPE) != VT_STRUCT)
7667 expect("struct or union");
7668 s = vtop->type.ref;
7669 /* find field */
7670 tok |= SYM_FIELD;
7671 while ((s = s->next) != NULL) {
7672 if (s->v == tok)
7673 break;
7675 if (!s)
7676 error("field not found: %s", get_tok_str(tok & ~SYM_FIELD, NULL));
7677 /* add field offset to pointer */
7678 vtop->type = char_pointer_type; /* change type to 'char *' */
7679 vpushi(s->c);
7680 gen_op('+');
7681 /* change type to field type, and set to lvalue */
7682 vtop->type = s->type;
7683 /* an array is never an lvalue */
7684 if (!(vtop->type.t & VT_ARRAY)) {
7685 vtop->r |= lvalue_type(vtop->type.t);
7686 /* if bound checking, the referenced pointer must be checked */
7687 if (do_bounds_check)
7688 vtop->r |= VT_MUSTBOUND;
7690 next();
7691 } else if (tok == '[') {
7692 next();
7693 gexpr();
7694 gen_op('+');
7695 indir();
7696 skip(']');
7697 } else if (tok == '(') {
7698 SValue ret;
7699 Sym *sa;
7700 int nb_args;
7702 /* function call */
7703 if ((vtop->type.t & VT_BTYPE) != VT_FUNC) {
7704 /* pointer test (no array accepted) */
7705 if ((vtop->type.t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
7706 vtop->type = *pointed_type(&vtop->type);
7707 if ((vtop->type.t & VT_BTYPE) != VT_FUNC)
7708 goto error_func;
7709 } else {
7710 error_func:
7711 expect("function pointer");
7713 } else {
7714 vtop->r &= ~VT_LVAL; /* no lvalue */
7716 /* get return type */
7717 s = vtop->type.ref;
7718 next();
7719 sa = s->next; /* first parameter */
7720 nb_args = 0;
7721 ret.r2 = VT_CONST;
7722 /* compute first implicit argument if a structure is returned */
7723 if ((s->type.t & VT_BTYPE) == VT_STRUCT) {
7724 /* get some space for the returned structure */
7725 size = type_size(&s->type, &align);
7726 loc = (loc - size) & -align;
7727 ret.type = s->type;
7728 ret.r = VT_LOCAL | VT_LVAL;
7729 /* pass it as 'int' to avoid structure arg passing
7730 problems */
7731 vseti(VT_LOCAL, loc);
7732 ret.c = vtop->c;
7733 nb_args++;
7734 } else {
7735 ret.type = s->type;
7736 /* return in register */
7737 if (is_float(ret.type.t)) {
7738 ret.r = REG_FRET;
7739 } else {
7740 if ((ret.type.t & VT_BTYPE) == VT_LLONG)
7741 ret.r2 = REG_LRET;
7742 ret.r = REG_IRET;
7744 ret.c.i = 0;
7746 if (tok != ')') {
7747 for(;;) {
7748 expr_eq();
7749 gfunc_param_typed(s, sa);
7750 nb_args++;
7751 if (sa)
7752 sa = sa->next;
7753 if (tok == ')')
7754 break;
7755 skip(',');
7758 if (sa)
7759 error("too few arguments to function");
7760 skip(')');
7761 if (!nocode_wanted) {
7762 gfunc_call(nb_args);
7763 } else {
7764 vtop -= (nb_args + 1);
7766 /* return value */
7767 vsetc(&ret.type, ret.r, &ret.c);
7768 vtop->r2 = ret.r2;
7769 } else {
7770 break;
7775 static void uneq(void)
7777 int t;
7779 unary();
7780 if (tok == '=' ||
7781 (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
7782 tok == TOK_A_XOR || tok == TOK_A_OR ||
7783 tok == TOK_A_SHL || tok == TOK_A_SAR) {
7784 test_lvalue();
7785 t = tok;
7786 next();
7787 if (t == '=') {
7788 expr_eq();
7789 } else {
7790 vdup();
7791 expr_eq();
7792 gen_op(t & 0x7f);
7794 vstore();
7798 static void expr_prod(void)
7800 int t;
7802 uneq();
7803 while (tok == '*' || tok == '/' || tok == '%') {
7804 t = tok;
7805 next();
7806 uneq();
7807 gen_op(t);
7811 static void expr_sum(void)
7813 int t;
7815 expr_prod();
7816 while (tok == '+' || tok == '-') {
7817 t = tok;
7818 next();
7819 expr_prod();
7820 gen_op(t);
7824 static void expr_shift(void)
7826 int t;
7828 expr_sum();
7829 while (tok == TOK_SHL || tok == TOK_SAR) {
7830 t = tok;
7831 next();
7832 expr_sum();
7833 gen_op(t);
7837 static void expr_cmp(void)
7839 int t;
7841 expr_shift();
7842 while ((tok >= TOK_ULE && tok <= TOK_GT) ||
7843 tok == TOK_ULT || tok == TOK_UGE) {
7844 t = tok;
7845 next();
7846 expr_shift();
7847 gen_op(t);
7851 static void expr_cmpeq(void)
7853 int t;
7855 expr_cmp();
7856 while (tok == TOK_EQ || tok == TOK_NE) {
7857 t = tok;
7858 next();
7859 expr_cmp();
7860 gen_op(t);
7864 static void expr_and(void)
7866 expr_cmpeq();
7867 while (tok == '&') {
7868 next();
7869 expr_cmpeq();
7870 gen_op('&');
7874 static void expr_xor(void)
7876 expr_and();
7877 while (tok == '^') {
7878 next();
7879 expr_and();
7880 gen_op('^');
7884 static void expr_or(void)
7886 expr_xor();
7887 while (tok == '|') {
7888 next();
7889 expr_xor();
7890 gen_op('|');
7894 /* XXX: fix this mess */
7895 static void expr_land_const(void)
7897 expr_or();
7898 while (tok == TOK_LAND) {
7899 next();
7900 expr_or();
7901 gen_op(TOK_LAND);
7905 /* XXX: fix this mess */
7906 static void expr_lor_const(void)
7908 expr_land_const();
7909 while (tok == TOK_LOR) {
7910 next();
7911 expr_land_const();
7912 gen_op(TOK_LOR);
7916 /* only used if non constant */
7917 static void expr_land(void)
7919 int t;
7921 expr_or();
7922 if (tok == TOK_LAND) {
7923 t = 0;
7924 save_regs(1);
7925 for(;;) {
7926 t = gtst(1, t);
7927 if (tok != TOK_LAND) {
7928 vseti(VT_JMPI, t);
7929 break;
7931 next();
7932 expr_or();
7937 static void expr_lor(void)
7939 int t;
7941 expr_land();
7942 if (tok == TOK_LOR) {
7943 t = 0;
7944 save_regs(1);
7945 for(;;) {
7946 t = gtst(0, t);
7947 if (tok != TOK_LOR) {
7948 vseti(VT_JMP, t);
7949 break;
7951 next();
7952 expr_land();
7957 /* XXX: better constant handling */
7958 static void expr_eq(void)
7960 int tt, u, r1, r2, rc, t1, t2, bt1, bt2;
7961 SValue sv;
7962 CType type, type1, type2;
7964 if (const_wanted) {
7965 int c1, c;
7966 expr_lor_const();
7967 if (tok == '?') {
7968 c = vtop->c.i;
7969 vpop();
7970 next();
7971 if (tok == ':' && gnu_ext) {
7972 c1 = c;
7973 } else {
7974 gexpr();
7975 c1 = vtop->c.i;
7976 vpop();
7978 skip(':');
7979 expr_eq();
7980 if (c)
7981 vtop->c.i = c1;
7983 } else {
7984 expr_lor();
7985 if (tok == '?') {
7986 next();
7987 if (vtop != vstack) {
7988 /* needed to avoid having different registers saved in
7989 each branch */
7990 if (is_float(vtop->type.t))
7991 rc = RC_FLOAT;
7992 else
7993 rc = RC_INT;
7994 gv(rc);
7995 save_regs(1);
7997 if (tok == ':' && gnu_ext) {
7998 gv_dup();
7999 tt = gtst(1, 0);
8000 } else {
8001 tt = gtst(1, 0);
8002 gexpr();
8004 type1 = vtop->type;
8005 sv = *vtop; /* save value to handle it later */
8006 vtop--; /* no vpop so that FP stack is not flushed */
8007 skip(':');
8008 u = gjmp(0);
8009 gsym(tt);
8010 expr_eq();
8011 type2 = vtop->type;
8013 t1 = type1.t;
8014 bt1 = t1 & VT_BTYPE;
8015 t2 = type2.t;
8016 bt2 = t2 & VT_BTYPE;
8017 /* cast operands to correct type according to ISOC rules */
8018 if (is_float(bt1) || is_float(bt2)) {
8019 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
8020 type.t = VT_LDOUBLE;
8021 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
8022 type.t = VT_DOUBLE;
8023 } else {
8024 type.t = VT_FLOAT;
8026 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
8027 /* cast to biggest op */
8028 type.t = VT_LLONG;
8029 /* convert to unsigned if it does not fit in a long long */
8030 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
8031 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
8032 type.t |= VT_UNSIGNED;
8033 } else if (bt1 == VT_PTR || bt2 == VT_PTR) {
8034 /* XXX: test pointer compatibility */
8035 type = type1;
8036 } else if (bt1 == VT_FUNC || bt2 == VT_FUNC) {
8037 /* XXX: test function pointer compatibility */
8038 type = type1;
8039 } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
8040 /* XXX: test structure compatibility */
8041 type = type1;
8042 } else if (bt1 == VT_VOID || bt2 == VT_VOID) {
8043 /* NOTE: as an extension, we accept void on only one side */
8044 type.t = VT_VOID;
8045 } else {
8046 /* integer operations */
8047 type.t = VT_INT;
8048 /* convert to unsigned if it does not fit in an integer */
8049 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
8050 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
8051 type.t |= VT_UNSIGNED;
8054 /* now we convert second operand */
8055 gen_cast(&type);
8056 if (VT_STRUCT == (vtop->type.t & VT_BTYPE))
8057 gaddrof();
8058 rc = RC_INT;
8059 if (is_float(type.t)) {
8060 rc = RC_FLOAT;
8061 } else if ((type.t & VT_BTYPE) == VT_LLONG) {
8062 /* for long longs, we use fixed registers to avoid having
8063 to handle a complicated move */
8064 rc = RC_IRET;
8067 r2 = gv(rc);
8068 /* this is horrible, but we must also convert first
8069 operand */
8070 tt = gjmp(0);
8071 gsym(u);
8072 /* put again first value and cast it */
8073 *vtop = sv;
8074 gen_cast(&type);
8075 if (VT_STRUCT == (vtop->type.t & VT_BTYPE))
8076 gaddrof();
8077 r1 = gv(rc);
8078 move_reg(r2, r1);
8079 vtop->r = r2;
8080 gsym(tt);
8085 static void gexpr(void)
8087 while (1) {
8088 expr_eq();
8089 if (tok != ',')
8090 break;
8091 vpop();
8092 next();
8096 /* parse an expression and return its type without any side effect. */
8097 static void expr_type(CType *type)
8099 int saved_nocode_wanted;
8101 saved_nocode_wanted = nocode_wanted;
8102 nocode_wanted = 1;
8103 gexpr();
8104 *type = vtop->type;
8105 vpop();
8106 nocode_wanted = saved_nocode_wanted;
8109 /* parse a unary expression and return its type without any side
8110 effect. */
8111 static void unary_type(CType *type)
8113 int a;
8115 a = nocode_wanted;
8116 nocode_wanted = 1;
8117 unary();
8118 *type = vtop->type;
8119 vpop();
8120 nocode_wanted = a;
8123 /* parse a constant expression and return value in vtop. */
8124 static void expr_const1(void)
8126 int a;
8127 a = const_wanted;
8128 const_wanted = 1;
8129 expr_eq();
8130 const_wanted = a;
8133 /* parse an integer constant and return its value. */
8134 static int expr_const(void)
8136 int c;
8137 expr_const1();
8138 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
8139 expect("constant expression");
8140 c = vtop->c.i;
8141 vpop();
8142 return c;
8145 /* return the label token if current token is a label, otherwise
8146 return zero */
8147 static int is_label(void)
8149 int last_tok;
8151 /* fast test first */
8152 if (tok < TOK_UIDENT)
8153 return 0;
8154 /* no need to save tokc because tok is an identifier */
8155 last_tok = tok;
8156 next();
8157 if (tok == ':') {
8158 next();
8159 return last_tok;
8160 } else {
8161 unget_tok(last_tok);
8162 return 0;
8166 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
8167 int case_reg, int is_expr)
8169 int a, b, c, d;
8170 Sym *s;
8172 /* generate line number info */
8173 if (do_debug &&
8174 (last_line_num != file->line_num || last_ind != ind)) {
8175 put_stabn(N_SLINE, 0, file->line_num, ind - func_ind);
8176 last_ind = ind;
8177 last_line_num = file->line_num;
8180 if (is_expr) {
8181 /* default return value is (void) */
8182 vpushi(0);
8183 vtop->type.t = VT_VOID;
8186 if (tok == TOK_IF) {
8187 /* if test */
8188 next();
8189 skip('(');
8190 gexpr();
8191 skip(')');
8192 a = gtst(1, 0);
8193 block(bsym, csym, case_sym, def_sym, case_reg, 0);
8194 c = tok;
8195 if (c == TOK_ELSE) {
8196 next();
8197 d = gjmp(0);
8198 gsym(a);
8199 block(bsym, csym, case_sym, def_sym, case_reg, 0);
8200 gsym(d); /* patch else jmp */
8201 } else
8202 gsym(a);
8203 } else if (tok == TOK_WHILE) {
8204 next();
8205 d = ind;
8206 skip('(');
8207 gexpr();
8208 skip(')');
8209 a = gtst(1, 0);
8210 b = 0;
8211 block(&a, &b, case_sym, def_sym, case_reg, 0);
8212 gjmp_addr(d);
8213 gsym(a);
8214 gsym_addr(b, d);
8215 } else if (tok == '{') {
8216 Sym *llabel;
8218 next();
8219 /* record local declaration stack position */
8220 s = local_stack;
8221 llabel = local_label_stack;
8222 /* handle local labels declarations */
8223 if (tok == TOK_LABEL) {
8224 next();
8225 for(;;) {
8226 if (tok < TOK_UIDENT)
8227 expect("label identifier");
8228 label_push(&local_label_stack, tok, LABEL_DECLARED);
8229 next();
8230 if (tok == ',') {
8231 next();
8232 } else {
8233 skip(';');
8234 break;
8238 while (tok != '}') {
8239 decl(VT_LOCAL);
8240 if (tok != '}') {
8241 if (is_expr)
8242 vpop();
8243 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
8246 /* pop locally defined labels */
8247 label_pop(&local_label_stack, llabel);
8248 /* pop locally defined symbols */
8249 sym_pop(&local_stack, s);
8250 next();
8251 } else if (tok == TOK_RETURN) {
8252 next();
8253 if (tok != ';') {
8254 gexpr();
8255 gen_assign_cast(&func_vt);
8256 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
8257 CType type;
8258 /* if returning structure, must copy it to implicit
8259 first pointer arg location */
8260 #ifdef TCC_ARM_EABI
8261 int align, size;
8262 size = type_size(&func_vt,&align);
8263 if(size <= 4)
8265 if((vtop->r != (VT_LOCAL | VT_LVAL) || (vtop->c.i & 3))
8266 && (align & 3))
8268 int addr;
8269 loc = (loc - size) & -4;
8270 addr = loc;
8271 type = func_vt;
8272 vset(&type, VT_LOCAL | VT_LVAL, addr);
8273 vswap();
8274 vstore();
8275 vset(&int_type, VT_LOCAL | VT_LVAL, addr);
8277 vtop->type = int_type;
8278 gv(RC_IRET);
8279 } else {
8280 #endif
8281 type = func_vt;
8282 mk_pointer(&type);
8283 vset(&type, VT_LOCAL | VT_LVAL, func_vc);
8284 indir();
8285 vswap();
8286 /* copy structure value to pointer */
8287 vstore();
8288 #ifdef TCC_ARM_EABI
8290 #endif
8291 } else if (is_float(func_vt.t)) {
8292 gv(RC_FRET);
8293 } else {
8294 gv(RC_IRET);
8296 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
8298 skip(';');
8299 rsym = gjmp(rsym); /* jmp */
8300 } else if (tok == TOK_BREAK) {
8301 /* compute jump */
8302 if (!bsym)
8303 error("cannot break");
8304 *bsym = gjmp(*bsym);
8305 next();
8306 skip(';');
8307 } else if (tok == TOK_CONTINUE) {
8308 /* compute jump */
8309 if (!csym)
8310 error("cannot continue");
8311 *csym = gjmp(*csym);
8312 next();
8313 skip(';');
8314 } else if (tok == TOK_FOR) {
8315 int e;
8316 next();
8317 skip('(');
8318 if (tok != ';') {
8319 gexpr();
8320 vpop();
8322 skip(';');
8323 d = ind;
8324 c = ind;
8325 a = 0;
8326 b = 0;
8327 if (tok != ';') {
8328 gexpr();
8329 a = gtst(1, 0);
8331 skip(';');
8332 if (tok != ')') {
8333 e = gjmp(0);
8334 c = ind;
8335 gexpr();
8336 vpop();
8337 gjmp_addr(d);
8338 gsym(e);
8340 skip(')');
8341 block(&a, &b, case_sym, def_sym, case_reg, 0);
8342 gjmp_addr(c);
8343 gsym(a);
8344 gsym_addr(b, c);
8345 } else
8346 if (tok == TOK_DO) {
8347 next();
8348 a = 0;
8349 b = 0;
8350 d = ind;
8351 block(&a, &b, case_sym, def_sym, case_reg, 0);
8352 skip(TOK_WHILE);
8353 skip('(');
8354 gsym(b);
8355 gexpr();
8356 c = gtst(0, 0);
8357 gsym_addr(c, d);
8358 skip(')');
8359 gsym(a);
8360 skip(';');
8361 } else
8362 if (tok == TOK_SWITCH) {
8363 next();
8364 skip('(');
8365 gexpr();
8366 /* XXX: other types than integer */
8367 case_reg = gv(RC_INT);
8368 vpop();
8369 skip(')');
8370 a = 0;
8371 b = gjmp(0); /* jump to first case */
8372 c = 0;
8373 block(&a, csym, &b, &c, case_reg, 0);
8374 /* if no default, jmp after switch */
8375 if (c == 0)
8376 c = ind;
8377 /* default label */
8378 gsym_addr(b, c);
8379 /* break label */
8380 gsym(a);
8381 } else
8382 if (tok == TOK_CASE) {
8383 int v1, v2;
8384 if (!case_sym)
8385 expect("switch");
8386 next();
8387 v1 = expr_const();
8388 v2 = v1;
8389 if (gnu_ext && tok == TOK_DOTS) {
8390 next();
8391 v2 = expr_const();
8392 if (v2 < v1)
8393 warning("empty case range");
8395 /* since a case is like a label, we must skip it with a jmp */
8396 b = gjmp(0);
8397 gsym(*case_sym);
8398 vseti(case_reg, 0);
8399 vpushi(v1);
8400 if (v1 == v2) {
8401 gen_op(TOK_EQ);
8402 *case_sym = gtst(1, 0);
8403 } else {
8404 gen_op(TOK_GE);
8405 *case_sym = gtst(1, 0);
8406 vseti(case_reg, 0);
8407 vpushi(v2);
8408 gen_op(TOK_LE);
8409 *case_sym = gtst(1, *case_sym);
8411 gsym(b);
8412 skip(':');
8413 is_expr = 0;
8414 goto block_after_label;
8415 } else
8416 if (tok == TOK_DEFAULT) {
8417 next();
8418 skip(':');
8419 if (!def_sym)
8420 expect("switch");
8421 if (*def_sym)
8422 error("too many 'default'");
8423 *def_sym = ind;
8424 is_expr = 0;
8425 goto block_after_label;
8426 } else
8427 if (tok == TOK_GOTO) {
8428 next();
8429 if (tok == '*' && gnu_ext) {
8430 /* computed goto */
8431 next();
8432 gexpr();
8433 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
8434 expect("pointer");
8435 ggoto();
8436 } else if (tok >= TOK_UIDENT) {
8437 s = label_find(tok);
8438 /* put forward definition if needed */
8439 if (!s) {
8440 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
8441 } else {
8442 if (s->r == LABEL_DECLARED)
8443 s->r = LABEL_FORWARD;
8445 /* label already defined */
8446 if (s->r & LABEL_FORWARD)
8447 s->next = (void *)gjmp((long)s->next);
8448 else
8449 gjmp_addr((long)s->next);
8450 next();
8451 } else {
8452 expect("label identifier");
8454 skip(';');
8455 } else if (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3) {
8456 asm_instr();
8457 } else {
8458 b = is_label();
8459 if (b) {
8460 /* label case */
8461 s = label_find(b);
8462 if (s) {
8463 if (s->r == LABEL_DEFINED)
8464 error("duplicate label '%s'", get_tok_str(s->v, NULL));
8465 gsym((long)s->next);
8466 s->r = LABEL_DEFINED;
8467 } else {
8468 s = label_push(&global_label_stack, b, LABEL_DEFINED);
8470 s->next = (void *)ind;
8471 /* we accept this, but it is a mistake */
8472 block_after_label:
8473 if (tok == '}') {
8474 warning("deprecated use of label at end of compound statement");
8475 } else {
8476 if (is_expr)
8477 vpop();
8478 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
8480 } else {
8481 /* expression case */
8482 if (tok != ';') {
8483 if (is_expr) {
8484 vpop();
8485 gexpr();
8486 } else {
8487 gexpr();
8488 vpop();
8491 skip(';');
8496 /* t is the array or struct type. c is the array or struct
8497 address. cur_index/cur_field is the pointer to the current
8498 value. 'size_only' is true if only size info is needed (only used
8499 in arrays) */
8500 static void decl_designator(CType *type, Section *sec, unsigned long c,
8501 int *cur_index, Sym **cur_field,
8502 int size_only)
8504 Sym *s, *f;
8505 int notfirst, index, index_last, align, l, nb_elems, elem_size;
8506 CType type1;
8508 notfirst = 0;
8509 elem_size = 0;
8510 nb_elems = 1;
8511 if (gnu_ext && (l = is_label()) != 0)
8512 goto struct_field;
8513 while (tok == '[' || tok == '.') {
8514 if (tok == '[') {
8515 if (!(type->t & VT_ARRAY))
8516 expect("array type");
8517 s = type->ref;
8518 next();
8519 index = expr_const();
8520 if (index < 0 || (s->c >= 0 && index >= s->c))
8521 expect("invalid index");
8522 if (tok == TOK_DOTS && gnu_ext) {
8523 next();
8524 index_last = expr_const();
8525 if (index_last < 0 ||
8526 (s->c >= 0 && index_last >= s->c) ||
8527 index_last < index)
8528 expect("invalid index");
8529 } else {
8530 index_last = index;
8532 skip(']');
8533 if (!notfirst)
8534 *cur_index = index_last;
8535 type = pointed_type(type);
8536 elem_size = type_size(type, &align);
8537 c += index * elem_size;
8538 /* NOTE: we only support ranges for last designator */
8539 nb_elems = index_last - index + 1;
8540 if (nb_elems != 1) {
8541 notfirst = 1;
8542 break;
8544 } else {
8545 next();
8546 l = tok;
8547 next();
8548 struct_field:
8549 if ((type->t & VT_BTYPE) != VT_STRUCT)
8550 expect("struct/union type");
8551 s = type->ref;
8552 l |= SYM_FIELD;
8553 f = s->next;
8554 while (f) {
8555 if (f->v == l)
8556 break;
8557 f = f->next;
8559 if (!f)
8560 expect("field");
8561 if (!notfirst)
8562 *cur_field = f;
8563 /* XXX: fix this mess by using explicit storage field */
8564 type1 = f->type;
8565 type1.t |= (type->t & ~VT_TYPE);
8566 type = &type1;
8567 c += f->c;
8569 notfirst = 1;
8571 if (notfirst) {
8572 if (tok == '=') {
8573 next();
8574 } else {
8575 if (!gnu_ext)
8576 expect("=");
8578 } else {
8579 if (type->t & VT_ARRAY) {
8580 index = *cur_index;
8581 type = pointed_type(type);
8582 c += index * type_size(type, &align);
8583 } else {
8584 f = *cur_field;
8585 if (!f)
8586 error("too many field init");
8587 /* XXX: fix this mess by using explicit storage field */
8588 type1 = f->type;
8589 type1.t |= (type->t & ~VT_TYPE);
8590 type = &type1;
8591 c += f->c;
8594 decl_initializer(type, sec, c, 0, size_only);
8596 /* XXX: make it more general */
8597 if (!size_only && nb_elems > 1) {
8598 unsigned long c_end;
8599 uint8_t *src, *dst;
8600 int i;
8602 if (!sec)
8603 error("range init not supported yet for dynamic storage");
8604 c_end = c + nb_elems * elem_size;
8605 if (c_end > sec->data_allocated)
8606 section_realloc(sec, c_end);
8607 src = sec->data + c;
8608 dst = src;
8609 for(i = 1; i < nb_elems; i++) {
8610 dst += elem_size;
8611 memcpy(dst, src, elem_size);
8616 #define EXPR_VAL 0
8617 #define EXPR_CONST 1
8618 #define EXPR_ANY 2
8620 /* store a value or an expression directly in global data or in local array */
8621 static void init_putv(CType *type, Section *sec, unsigned long c,
8622 int v, int expr_type)
8624 int saved_global_expr, bt, bit_pos, bit_size;
8625 void *ptr;
8626 unsigned long long bit_mask;
8627 CType dtype;
8629 switch(expr_type) {
8630 case EXPR_VAL:
8631 vpushi(v);
8632 break;
8633 case EXPR_CONST:
8634 /* compound literals must be allocated globally in this case */
8635 saved_global_expr = global_expr;
8636 global_expr = 1;
8637 expr_const1();
8638 global_expr = saved_global_expr;
8639 /* NOTE: symbols are accepted */
8640 if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST)
8641 error("initializer element is not constant");
8642 break;
8643 case EXPR_ANY:
8644 expr_eq();
8645 break;
8648 dtype = *type;
8649 dtype.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
8651 if (sec) {
8652 /* XXX: not portable */
8653 /* XXX: generate error if incorrect relocation */
8654 gen_assign_cast(&dtype);
8655 bt = type->t & VT_BTYPE;
8656 ptr = sec->data + c;
8657 /* XXX: make code faster ? */
8658 if (!(type->t & VT_BITFIELD)) {
8659 bit_pos = 0;
8660 bit_size = 32;
8661 bit_mask = -1LL;
8662 } else {
8663 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
8664 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
8665 bit_mask = (1LL << bit_size) - 1;
8667 if ((vtop->r & VT_SYM) &&
8668 (bt == VT_BYTE ||
8669 bt == VT_SHORT ||
8670 bt == VT_DOUBLE ||
8671 bt == VT_LDOUBLE ||
8672 bt == VT_LLONG ||
8673 (bt == VT_INT && bit_size != 32)))
8674 error("initializer element is not computable at load time");
8675 switch(bt) {
8676 case VT_BYTE:
8677 *(char *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8678 break;
8679 case VT_SHORT:
8680 *(short *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8681 break;
8682 case VT_DOUBLE:
8683 *(double *)ptr = vtop->c.d;
8684 break;
8685 case VT_LDOUBLE:
8686 *(long double *)ptr = vtop->c.ld;
8687 break;
8688 case VT_LLONG:
8689 *(long long *)ptr |= (vtop->c.ll & bit_mask) << bit_pos;
8690 break;
8691 default:
8692 if (vtop->r & VT_SYM) {
8693 greloc(sec, vtop->sym, c, R_DATA_32);
8695 *(int *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8696 break;
8698 vtop--;
8699 } else {
8700 vset(&dtype, VT_LOCAL|VT_LVAL, c);
8701 vswap();
8702 vstore();
8703 vpop();
8707 /* put zeros for variable based init */
8708 static void init_putz(CType *t, Section *sec, unsigned long c, int size)
8710 if (sec) {
8711 /* nothing to do because globals are already set to zero */
8712 } else {
8713 vpush_global_sym(&func_old_type, TOK_memset);
8714 vseti(VT_LOCAL, c);
8715 vpushi(0);
8716 vpushi(size);
8717 gfunc_call(3);
8721 /* 't' contains the type and storage info. 'c' is the offset of the
8722 object in section 'sec'. If 'sec' is NULL, it means stack based
8723 allocation. 'first' is true if array '{' must be read (multi
8724 dimension implicit array init handling). 'size_only' is true if
8725 size only evaluation is wanted (only for arrays). */
8726 static void decl_initializer(CType *type, Section *sec, unsigned long c,
8727 int first, int size_only)
8729 int index, array_length, n, no_oblock, nb, parlevel, i;
8730 int size1, align1, expr_type;
8731 Sym *s, *f;
8732 CType *t1;
8734 if (type->t & VT_ARRAY) {
8735 s = type->ref;
8736 n = s->c;
8737 array_length = 0;
8738 t1 = pointed_type(type);
8739 size1 = type_size(t1, &align1);
8741 no_oblock = 1;
8742 if ((first && tok != TOK_LSTR && tok != TOK_STR) ||
8743 tok == '{') {
8744 skip('{');
8745 no_oblock = 0;
8748 /* only parse strings here if correct type (otherwise: handle
8749 them as ((w)char *) expressions */
8750 if ((tok == TOK_LSTR &&
8751 #ifdef TCC_TARGET_PE
8752 (t1->t & VT_BTYPE) == VT_SHORT && (t1->t & VT_UNSIGNED)
8753 #else
8754 (t1->t & VT_BTYPE) == VT_INT
8755 #endif
8756 ) || (tok == TOK_STR && (t1->t & VT_BTYPE) == VT_BYTE)) {
8757 while (tok == TOK_STR || tok == TOK_LSTR) {
8758 int cstr_len, ch;
8759 CString *cstr;
8761 cstr = tokc.cstr;
8762 /* compute maximum number of chars wanted */
8763 if (tok == TOK_STR)
8764 cstr_len = cstr->size;
8765 else
8766 cstr_len = cstr->size / sizeof(nwchar_t);
8767 cstr_len--;
8768 nb = cstr_len;
8769 if (n >= 0 && nb > (n - array_length))
8770 nb = n - array_length;
8771 if (!size_only) {
8772 if (cstr_len > nb)
8773 warning("initializer-string for array is too long");
8774 /* in order to go faster for common case (char
8775 string in global variable, we handle it
8776 specifically */
8777 if (sec && tok == TOK_STR && size1 == 1) {
8778 memcpy(sec->data + c + array_length, cstr->data, nb);
8779 } else {
8780 for(i=0;i<nb;i++) {
8781 if (tok == TOK_STR)
8782 ch = ((unsigned char *)cstr->data)[i];
8783 else
8784 ch = ((nwchar_t *)cstr->data)[i];
8785 init_putv(t1, sec, c + (array_length + i) * size1,
8786 ch, EXPR_VAL);
8790 array_length += nb;
8791 next();
8793 /* only add trailing zero if enough storage (no
8794 warning in this case since it is standard) */
8795 if (n < 0 || array_length < n) {
8796 if (!size_only) {
8797 init_putv(t1, sec, c + (array_length * size1), 0, EXPR_VAL);
8799 array_length++;
8801 } else {
8802 index = 0;
8803 while (tok != '}') {
8804 decl_designator(type, sec, c, &index, NULL, size_only);
8805 if (n >= 0 && index >= n)
8806 error("index too large");
8807 /* must put zero in holes (note that doing it that way
8808 ensures that it even works with designators) */
8809 if (!size_only && array_length < index) {
8810 init_putz(t1, sec, c + array_length * size1,
8811 (index - array_length) * size1);
8813 index++;
8814 if (index > array_length)
8815 array_length = index;
8816 /* special test for multi dimensional arrays (may not
8817 be strictly correct if designators are used at the
8818 same time) */
8819 if (index >= n && no_oblock)
8820 break;
8821 if (tok == '}')
8822 break;
8823 skip(',');
8826 if (!no_oblock)
8827 skip('}');
8828 /* put zeros at the end */
8829 if (!size_only && n >= 0 && array_length < n) {
8830 init_putz(t1, sec, c + array_length * size1,
8831 (n - array_length) * size1);
8833 /* patch type size if needed */
8834 if (n < 0)
8835 s->c = array_length;
8836 } else if ((type->t & VT_BTYPE) == VT_STRUCT &&
8837 (sec || !first || tok == '{')) {
8838 int par_count;
8840 /* NOTE: the previous test is a specific case for automatic
8841 struct/union init */
8842 /* XXX: union needs only one init */
8844 /* XXX: this test is incorrect for local initializers
8845 beginning with ( without {. It would be much more difficult
8846 to do it correctly (ideally, the expression parser should
8847 be used in all cases) */
8848 par_count = 0;
8849 if (tok == '(') {
8850 AttributeDef ad1;
8851 CType type1;
8852 next();
8853 while (tok == '(') {
8854 par_count++;
8855 next();
8857 if (!parse_btype(&type1, &ad1))
8858 expect("cast");
8859 type_decl(&type1, &ad1, &n, TYPE_ABSTRACT);
8860 #if 0
8861 if (!is_assignable_types(type, &type1))
8862 error("invalid type for cast");
8863 #endif
8864 skip(')');
8866 no_oblock = 1;
8867 if (first || tok == '{') {
8868 skip('{');
8869 no_oblock = 0;
8871 s = type->ref;
8872 f = s->next;
8873 array_length = 0;
8874 index = 0;
8875 n = s->c;
8876 while (tok != '}') {
8877 decl_designator(type, sec, c, NULL, &f, size_only);
8878 index = f->c;
8879 if (!size_only && array_length < index) {
8880 init_putz(type, sec, c + array_length,
8881 index - array_length);
8883 index = index + type_size(&f->type, &align1);
8884 if (index > array_length)
8885 array_length = index;
8886 f = f->next;
8887 if (no_oblock && f == NULL)
8888 break;
8889 if (tok == '}')
8890 break;
8891 skip(',');
8893 /* put zeros at the end */
8894 if (!size_only && array_length < n) {
8895 init_putz(type, sec, c + array_length,
8896 n - array_length);
8898 if (!no_oblock)
8899 skip('}');
8900 while (par_count) {
8901 skip(')');
8902 par_count--;
8904 } else if (tok == '{') {
8905 next();
8906 decl_initializer(type, sec, c, first, size_only);
8907 skip('}');
8908 } else if (size_only) {
8909 /* just skip expression */
8910 parlevel = 0;
8911 while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
8912 tok != -1) {
8913 if (tok == '(')
8914 parlevel++;
8915 else if (tok == ')')
8916 parlevel--;
8917 next();
8919 } else {
8920 /* currently, we always use constant expression for globals
8921 (may change for scripting case) */
8922 expr_type = EXPR_CONST;
8923 if (!sec)
8924 expr_type = EXPR_ANY;
8925 init_putv(type, sec, c, 0, expr_type);
8929 /* parse an initializer for type 't' if 'has_init' is non zero, and
8930 allocate space in local or global data space ('r' is either
8931 VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
8932 variable 'v' of scope 'scope' is declared before initializers are
8933 parsed. If 'v' is zero, then a reference to the new object is put
8934 in the value stack. If 'has_init' is 2, a special parsing is done
8935 to handle string constants. */
8936 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
8937 int has_init, int v, int scope)
8939 int size, align, addr, data_offset;
8940 int level;
8941 ParseState saved_parse_state;
8942 TokenString init_str;
8943 Section *sec;
8945 size = type_size(type, &align);
8946 /* If unknown size, we must evaluate it before
8947 evaluating initializers because
8948 initializers can generate global data too
8949 (e.g. string pointers or ISOC99 compound
8950 literals). It also simplifies local
8951 initializers handling */
8952 tok_str_new(&init_str);
8953 if (size < 0) {
8954 if (!has_init)
8955 error("unknown type size");
8956 /* get all init string */
8957 if (has_init == 2) {
8958 /* only get strings */
8959 while (tok == TOK_STR || tok == TOK_LSTR) {
8960 tok_str_add_tok(&init_str);
8961 next();
8963 } else {
8964 level = 0;
8965 while (level > 0 || (tok != ',' && tok != ';')) {
8966 if (tok < 0)
8967 error("unexpected end of file in initializer");
8968 tok_str_add_tok(&init_str);
8969 if (tok == '{')
8970 level++;
8971 else if (tok == '}') {
8972 if (level == 0)
8973 break;
8974 level--;
8976 next();
8979 tok_str_add(&init_str, -1);
8980 tok_str_add(&init_str, 0);
8982 /* compute size */
8983 save_parse_state(&saved_parse_state);
8985 macro_ptr = init_str.str;
8986 next();
8987 decl_initializer(type, NULL, 0, 1, 1);
8988 /* prepare second initializer parsing */
8989 macro_ptr = init_str.str;
8990 next();
8992 /* if still unknown size, error */
8993 size = type_size(type, &align);
8994 if (size < 0)
8995 error("unknown type size");
8997 /* take into account specified alignment if bigger */
8998 if (ad->aligned) {
8999 if (ad->aligned > align)
9000 align = ad->aligned;
9001 } else if (ad->packed) {
9002 align = 1;
9004 if ((r & VT_VALMASK) == VT_LOCAL) {
9005 sec = NULL;
9006 if (do_bounds_check && (type->t & VT_ARRAY))
9007 loc--;
9008 loc = (loc - size) & -align;
9009 addr = loc;
9010 /* handles bounds */
9011 /* XXX: currently, since we do only one pass, we cannot track
9012 '&' operators, so we add only arrays */
9013 if (do_bounds_check && (type->t & VT_ARRAY)) {
9014 unsigned long *bounds_ptr;
9015 /* add padding between regions */
9016 loc--;
9017 /* then add local bound info */
9018 bounds_ptr = section_ptr_add(lbounds_section, 2 * sizeof(unsigned long));
9019 bounds_ptr[0] = addr;
9020 bounds_ptr[1] = size;
9022 if (v) {
9023 /* local variable */
9024 sym_push(v, type, r, addr);
9025 } else {
9026 /* push local reference */
9027 vset(type, r, addr);
9029 } else {
9030 Sym *sym;
9032 sym = NULL;
9033 if (v && scope == VT_CONST) {
9034 /* see if the symbol was already defined */
9035 sym = sym_find(v);
9036 if (sym) {
9037 if (!is_compatible_types(&sym->type, type))
9038 error("incompatible types for redefinition of '%s'",
9039 get_tok_str(v, NULL));
9040 if (sym->type.t & VT_EXTERN) {
9041 /* if the variable is extern, it was not allocated */
9042 sym->type.t &= ~VT_EXTERN;
9043 /* set array size if it was ommited in extern
9044 declaration */
9045 if ((sym->type.t & VT_ARRAY) &&
9046 sym->type.ref->c < 0 &&
9047 type->ref->c >= 0)
9048 sym->type.ref->c = type->ref->c;
9049 } else {
9050 /* we accept several definitions of the same
9051 global variable. this is tricky, because we
9052 must play with the SHN_COMMON type of the symbol */
9053 /* XXX: should check if the variable was already
9054 initialized. It is incorrect to initialized it
9055 twice */
9056 /* no init data, we won't add more to the symbol */
9057 if (!has_init)
9058 goto no_alloc;
9063 /* allocate symbol in corresponding section */
9064 sec = ad->section;
9065 if (!sec) {
9066 if (has_init)
9067 sec = data_section;
9068 else if (tcc_state->nocommon)
9069 sec = bss_section;
9071 if (sec) {
9072 data_offset = sec->data_offset;
9073 data_offset = (data_offset + align - 1) & -align;
9074 addr = data_offset;
9075 /* very important to increment global pointer at this time
9076 because initializers themselves can create new initializers */
9077 data_offset += size;
9078 /* add padding if bound check */
9079 if (do_bounds_check)
9080 data_offset++;
9081 sec->data_offset = data_offset;
9082 /* allocate section space to put the data */
9083 if (sec->sh_type != SHT_NOBITS &&
9084 data_offset > sec->data_allocated)
9085 section_realloc(sec, data_offset);
9086 /* align section if needed */
9087 if (align > sec->sh_addralign)
9088 sec->sh_addralign = align;
9089 } else {
9090 addr = 0; /* avoid warning */
9093 if (v) {
9094 if (scope != VT_CONST || !sym) {
9095 sym = sym_push(v, type, r | VT_SYM, 0);
9097 /* update symbol definition */
9098 if (sec) {
9099 put_extern_sym(sym, sec, addr, size);
9100 } else {
9101 Elf32_Sym *esym;
9102 /* put a common area */
9103 put_extern_sym(sym, NULL, align, size);
9104 /* XXX: find a nicer way */
9105 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
9106 esym->st_shndx = SHN_COMMON;
9108 } else {
9109 CValue cval;
9111 /* push global reference */
9112 sym = get_sym_ref(type, sec, addr, size);
9113 cval.ul = 0;
9114 vsetc(type, VT_CONST | VT_SYM, &cval);
9115 vtop->sym = sym;
9118 /* handles bounds now because the symbol must be defined
9119 before for the relocation */
9120 if (do_bounds_check) {
9121 unsigned long *bounds_ptr;
9123 greloc(bounds_section, sym, bounds_section->data_offset, R_DATA_32);
9124 /* then add global bound info */
9125 bounds_ptr = section_ptr_add(bounds_section, 2 * sizeof(long));
9126 bounds_ptr[0] = 0; /* relocated */
9127 bounds_ptr[1] = size;
9130 if (has_init) {
9131 decl_initializer(type, sec, addr, 1, 0);
9132 /* restore parse state if needed */
9133 if (init_str.str) {
9134 tok_str_free(init_str.str);
9135 restore_parse_state(&saved_parse_state);
9138 no_alloc: ;
9141 void put_func_debug(Sym *sym)
9143 char buf[512];
9145 /* stabs info */
9146 /* XXX: we put here a dummy type */
9147 snprintf(buf, sizeof(buf), "%s:%c1",
9148 funcname, sym->type.t & VT_STATIC ? 'f' : 'F');
9149 put_stabs_r(buf, N_FUN, 0, file->line_num, 0,
9150 cur_text_section, sym->c);
9151 last_ind = 0;
9152 last_line_num = 0;
9155 /* parse an old style function declaration list */
9156 /* XXX: check multiple parameter */
9157 static void func_decl_list(Sym *func_sym)
9159 AttributeDef ad;
9160 int v;
9161 Sym *s;
9162 CType btype, type;
9164 /* parse each declaration */
9165 while (tok != '{' && tok != ';' && tok != ',' && tok != TOK_EOF) {
9166 if (!parse_btype(&btype, &ad))
9167 expect("declaration list");
9168 if (((btype.t & VT_BTYPE) == VT_ENUM ||
9169 (btype.t & VT_BTYPE) == VT_STRUCT) &&
9170 tok == ';') {
9171 /* we accept no variable after */
9172 } else {
9173 for(;;) {
9174 type = btype;
9175 type_decl(&type, &ad, &v, TYPE_DIRECT);
9176 /* find parameter in function parameter list */
9177 s = func_sym->next;
9178 while (s != NULL) {
9179 if ((s->v & ~SYM_FIELD) == v)
9180 goto found;
9181 s = s->next;
9183 error("declaration for parameter '%s' but no such parameter",
9184 get_tok_str(v, NULL));
9185 found:
9186 /* check that no storage specifier except 'register' was given */
9187 if (type.t & VT_STORAGE)
9188 error("storage class specified for '%s'", get_tok_str(v, NULL));
9189 convert_parameter_type(&type);
9190 /* we can add the type (NOTE: it could be local to the function) */
9191 s->type = type;
9192 /* accept other parameters */
9193 if (tok == ',')
9194 next();
9195 else
9196 break;
9199 skip(';');
9203 /* parse a function defined by symbol 'sym' and generate its code in
9204 'cur_text_section' */
9205 static void gen_function(Sym *sym)
9207 int saved_nocode_wanted = nocode_wanted;
9208 nocode_wanted = 0;
9209 ind = cur_text_section->data_offset;
9210 /* NOTE: we patch the symbol size later */
9211 put_extern_sym(sym, cur_text_section, ind, 0);
9212 funcname = get_tok_str(sym->v, NULL);
9213 func_ind = ind;
9214 /* put debug symbol */
9215 if (do_debug)
9216 put_func_debug(sym);
9217 /* push a dummy symbol to enable local sym storage */
9218 sym_push2(&local_stack, SYM_FIELD, 0, 0);
9219 gfunc_prolog(&sym->type);
9220 rsym = 0;
9221 block(NULL, NULL, NULL, NULL, 0, 0);
9222 gsym(rsym);
9223 gfunc_epilog();
9224 cur_text_section->data_offset = ind;
9225 label_pop(&global_label_stack, NULL);
9226 sym_pop(&local_stack, NULL); /* reset local stack */
9227 /* end of function */
9228 /* patch symbol size */
9229 ((Elf32_Sym *)symtab_section->data)[sym->c].st_size =
9230 ind - func_ind;
9231 if (do_debug) {
9232 put_stabn(N_FUN, 0, 0, ind - func_ind);
9234 funcname = ""; /* for safety */
9235 func_vt.t = VT_VOID; /* for safety */
9236 ind = 0; /* for safety */
9237 nocode_wanted = saved_nocode_wanted;
9240 static void gen_inline_functions(void)
9242 Sym *sym;
9243 CType *type;
9244 int *str, inline_generated;
9246 /* iterate while inline function are referenced */
9247 for(;;) {
9248 inline_generated = 0;
9249 for(sym = global_stack; sym != NULL; sym = sym->prev) {
9250 type = &sym->type;
9251 if (((type->t & VT_BTYPE) == VT_FUNC) &&
9252 (type->t & (VT_STATIC | VT_INLINE)) ==
9253 (VT_STATIC | VT_INLINE) &&
9254 sym->c != 0) {
9255 /* the function was used: generate its code and
9256 convert it to a normal function */
9257 str = INLINE_DEF(sym->r);
9258 sym->r = VT_SYM | VT_CONST;
9259 sym->type.t &= ~VT_INLINE;
9261 macro_ptr = str;
9262 next();
9263 cur_text_section = text_section;
9264 gen_function(sym);
9265 macro_ptr = NULL; /* fail safe */
9267 tok_str_free(str);
9268 inline_generated = 1;
9271 if (!inline_generated)
9272 break;
9275 /* free all remaining inline function tokens */
9276 for(sym = global_stack; sym != NULL; sym = sym->prev) {
9277 type = &sym->type;
9278 if (((type->t & VT_BTYPE) == VT_FUNC) &&
9279 (type->t & (VT_STATIC | VT_INLINE)) ==
9280 (VT_STATIC | VT_INLINE)) {
9281 //gr printf("sym %d %s\n", sym->r, get_tok_str(sym->v, NULL));
9282 if (sym->r == (VT_SYM | VT_CONST)) //gr beware!
9283 continue;
9284 str = INLINE_DEF(sym->r);
9285 tok_str_free(str);
9286 sym->r = 0; /* fail safe */
9291 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
9292 static void decl(int l)
9294 int v, has_init, r;
9295 CType type, btype;
9296 Sym *sym;
9297 AttributeDef ad;
9299 while (1) {
9300 if (!parse_btype(&btype, &ad)) {
9301 /* skip redundant ';' */
9302 /* XXX: find more elegant solution */
9303 if (tok == ';') {
9304 next();
9305 continue;
9307 if (l == VT_CONST &&
9308 (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3)) {
9309 /* global asm block */
9310 asm_global_instr();
9311 continue;
9313 /* special test for old K&R protos without explicit int
9314 type. Only accepted when defining global data */
9315 if (l == VT_LOCAL || tok < TOK_DEFINE)
9316 break;
9317 btype.t = VT_INT;
9319 if (((btype.t & VT_BTYPE) == VT_ENUM ||
9320 (btype.t & VT_BTYPE) == VT_STRUCT) &&
9321 tok == ';') {
9322 /* we accept no variable after */
9323 next();
9324 continue;
9326 while (1) { /* iterate thru each declaration */
9327 type = btype;
9328 type_decl(&type, &ad, &v, TYPE_DIRECT);
9329 #if 0
9331 char buf[500];
9332 type_to_str(buf, sizeof(buf), t, get_tok_str(v, NULL));
9333 printf("type = '%s'\n", buf);
9335 #endif
9336 if ((type.t & VT_BTYPE) == VT_FUNC) {
9337 /* if old style function prototype, we accept a
9338 declaration list */
9339 sym = type.ref;
9340 if (sym->c == FUNC_OLD)
9341 func_decl_list(sym);
9344 if (tok == '{') {
9345 if (l == VT_LOCAL)
9346 error("cannot use local functions");
9347 if ((type.t & VT_BTYPE) != VT_FUNC)
9348 expect("function definition");
9350 /* reject abstract declarators in function definition */
9351 sym = type.ref;
9352 while ((sym = sym->next) != NULL)
9353 if (!(sym->v & ~SYM_FIELD))
9354 expect("identifier");
9356 /* XXX: cannot do better now: convert extern line to static inline */
9357 if ((type.t & (VT_EXTERN | VT_INLINE)) == (VT_EXTERN | VT_INLINE))
9358 type.t = (type.t & ~VT_EXTERN) | VT_STATIC;
9360 sym = sym_find(v);
9361 if (sym) {
9362 if ((sym->type.t & VT_BTYPE) != VT_FUNC)
9363 goto func_error1;
9364 /* specific case: if not func_call defined, we put
9365 the one of the prototype */
9366 /* XXX: should have default value */
9367 r = sym->type.ref->r;
9368 if (FUNC_CALL(r) != FUNC_CDECL
9369 && FUNC_CALL(type.ref->r) == FUNC_CDECL)
9370 FUNC_CALL(type.ref->r) = FUNC_CALL(r);
9371 if (FUNC_EXPORT(r))
9372 FUNC_EXPORT(type.ref->r) = 1;
9374 if (!is_compatible_types(&sym->type, &type)) {
9375 func_error1:
9376 error("incompatible types for redefinition of '%s'",
9377 get_tok_str(v, NULL));
9379 /* if symbol is already defined, then put complete type */
9380 sym->type = type;
9381 } else {
9382 /* put function symbol */
9383 sym = global_identifier_push(v, type.t, 0);
9384 sym->type.ref = type.ref;
9387 /* static inline functions are just recorded as a kind
9388 of macro. Their code will be emitted at the end of
9389 the compilation unit only if they are used */
9390 if ((type.t & (VT_INLINE | VT_STATIC)) ==
9391 (VT_INLINE | VT_STATIC)) {
9392 TokenString func_str;
9393 int block_level;
9395 tok_str_new(&func_str);
9397 block_level = 0;
9398 for(;;) {
9399 int t;
9400 if (tok == TOK_EOF)
9401 error("unexpected end of file");
9402 tok_str_add_tok(&func_str);
9403 t = tok;
9404 next();
9405 if (t == '{') {
9406 block_level++;
9407 } else if (t == '}') {
9408 block_level--;
9409 if (block_level == 0)
9410 break;
9413 tok_str_add(&func_str, -1);
9414 tok_str_add(&func_str, 0);
9415 INLINE_DEF(sym->r) = func_str.str;
9416 } else {
9417 /* compute text section */
9418 cur_text_section = ad.section;
9419 if (!cur_text_section)
9420 cur_text_section = text_section;
9421 sym->r = VT_SYM | VT_CONST;
9422 gen_function(sym);
9424 break;
9425 } else {
9426 if (btype.t & VT_TYPEDEF) {
9427 /* save typedefed type */
9428 /* XXX: test storage specifiers ? */
9429 sym = sym_push(v, &type, 0, 0);
9430 sym->type.t |= VT_TYPEDEF;
9431 } else if ((type.t & VT_BTYPE) == VT_FUNC) {
9432 /* external function definition */
9433 /* specific case for func_call attribute */
9434 if (ad.func_attr)
9435 type.ref->r = ad.func_attr;
9436 external_sym(v, &type, 0);
9437 } else {
9438 /* not lvalue if array */
9439 r = 0;
9440 if (!(type.t & VT_ARRAY))
9441 r |= lvalue_type(type.t);
9442 has_init = (tok == '=');
9443 if ((btype.t & VT_EXTERN) ||
9444 ((type.t & VT_ARRAY) && (type.t & VT_STATIC) &&
9445 !has_init && l == VT_CONST && type.ref->c < 0)) {
9446 /* external variable */
9447 /* NOTE: as GCC, uninitialized global static
9448 arrays of null size are considered as
9449 extern */
9450 external_sym(v, &type, r);
9451 } else {
9452 type.t |= (btype.t & VT_STATIC); /* Retain "static". */
9453 if (type.t & VT_STATIC)
9454 r |= VT_CONST;
9455 else
9456 r |= l;
9457 if (has_init)
9458 next();
9459 decl_initializer_alloc(&type, &ad, r,
9460 has_init, v, l);
9463 if (tok != ',') {
9464 skip(';');
9465 break;
9467 next();
9473 /* better than nothing, but needs extension to handle '-E' option
9474 correctly too */
9475 static void preprocess_init(TCCState *s1)
9477 s1->include_stack_ptr = s1->include_stack;
9478 /* XXX: move that before to avoid having to initialize
9479 file->ifdef_stack_ptr ? */
9480 s1->ifdef_stack_ptr = s1->ifdef_stack;
9481 file->ifdef_stack_ptr = s1->ifdef_stack_ptr;
9483 /* XXX: not ANSI compliant: bound checking says error */
9484 vtop = vstack - 1;
9485 s1->pack_stack[0] = 0;
9486 s1->pack_stack_ptr = s1->pack_stack;
9488 macro_ptr = NULL;
9491 /* compile the C file opened in 'file'. Return non zero if errors. */
9492 static int tcc_compile(TCCState *s1)
9494 Sym *define_start;
9495 char buf[512];
9496 volatile int section_sym;
9498 #ifdef INC_DEBUG
9499 printf("%s: **** new file\n", file->filename);
9500 #endif
9501 preprocess_init(s1);
9503 funcname = "";
9504 anon_sym = SYM_FIRST_ANOM;
9506 /* file info: full path + filename */
9507 section_sym = 0; /* avoid warning */
9508 if (do_debug) {
9509 section_sym = put_elf_sym(symtab_section, 0, 0,
9510 ELF32_ST_INFO(STB_LOCAL, STT_SECTION), 0,
9511 text_section->sh_num, NULL);
9512 getcwd(buf, sizeof(buf));
9513 #ifdef _WIN32
9514 normalize_slashes(buf);
9515 #endif
9516 pstrcat(buf, sizeof(buf), "/");
9517 put_stabs_r(buf, N_SO, 0, 0,
9518 text_section->data_offset, text_section, section_sym);
9519 put_stabs_r(file->filename, N_SO, 0, 0,
9520 text_section->data_offset, text_section, section_sym);
9522 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
9523 symbols can be safely used */
9524 put_elf_sym(symtab_section, 0, 0,
9525 ELF32_ST_INFO(STB_LOCAL, STT_FILE), 0,
9526 SHN_ABS, file->filename);
9528 /* define some often used types */
9529 int_type.t = VT_INT;
9531 char_pointer_type.t = VT_BYTE;
9532 mk_pointer(&char_pointer_type);
9534 func_old_type.t = VT_FUNC;
9535 func_old_type.ref = sym_push(SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD);
9537 #if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)
9538 float_type.t = VT_FLOAT;
9539 double_type.t = VT_DOUBLE;
9541 func_float_type.t = VT_FUNC;
9542 func_float_type.ref = sym_push(SYM_FIELD, &float_type, FUNC_CDECL, FUNC_OLD);
9543 func_double_type.t = VT_FUNC;
9544 func_double_type.ref = sym_push(SYM_FIELD, &double_type, FUNC_CDECL, FUNC_OLD);
9545 #endif
9547 #if 0
9548 /* define 'void *alloca(unsigned int)' builtin function */
9550 Sym *s1;
9552 p = anon_sym++;
9553 sym = sym_push(p, mk_pointer(VT_VOID), FUNC_CDECL, FUNC_NEW);
9554 s1 = sym_push(SYM_FIELD, VT_UNSIGNED | VT_INT, 0, 0);
9555 s1->next = NULL;
9556 sym->next = s1;
9557 sym_push(TOK_alloca, VT_FUNC | (p << VT_STRUCT_SHIFT), VT_CONST, 0);
9559 #endif
9561 define_start = define_stack;
9562 nocode_wanted = 1;
9564 if (setjmp(s1->error_jmp_buf) == 0) {
9565 s1->nb_errors = 0;
9566 s1->error_set_jmp_enabled = 1;
9568 ch = file->buf_ptr[0];
9569 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
9570 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM;
9571 next();
9572 decl(VT_CONST);
9573 if (tok != TOK_EOF)
9574 expect("declaration");
9576 /* end of translation unit info */
9577 if (do_debug) {
9578 put_stabs_r(NULL, N_SO, 0, 0,
9579 text_section->data_offset, text_section, section_sym);
9582 s1->error_set_jmp_enabled = 0;
9584 /* reset define stack, but leave -Dsymbols (may be incorrect if
9585 they are undefined) */
9586 free_defines(define_start);
9588 gen_inline_functions();
9590 sym_pop(&global_stack, NULL);
9591 sym_pop(&local_stack, NULL);
9593 return s1->nb_errors != 0 ? -1 : 0;
9596 /* Preprocess the current file */
9597 /* XXX: add line and file infos, add options to preserve spaces */
9598 static int tcc_preprocess(TCCState *s1)
9600 Sym *define_start;
9601 int last_is_space;
9603 preprocess_init(s1);
9605 define_start = define_stack;
9607 ch = file->buf_ptr[0];
9608 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
9609 parse_flags = PARSE_FLAG_ASM_COMMENTS | PARSE_FLAG_PREPROCESS |
9610 PARSE_FLAG_LINEFEED;
9611 last_is_space = 1;
9612 next();
9613 for(;;) {
9614 if (tok == TOK_EOF) {
9615 break;
9616 } else if (tok == TOK_LINEFEED) {
9617 last_is_space = 1;
9618 } else {
9619 if (!last_is_space)
9620 fputc(' ', s1->outfile);
9621 last_is_space = 0;
9623 fputs(get_tok_str(tok, &tokc), s1->outfile);
9624 next();
9626 free_defines(define_start);
9627 return 0;
9630 #ifdef LIBTCC
9631 int tcc_compile_string(TCCState *s, const char *str)
9633 BufferedFile bf1, *bf = &bf1;
9634 int ret, len;
9635 char *buf;
9637 /* init file structure */
9638 bf->fd = -1;
9639 /* XXX: avoid copying */
9640 len = strlen(str);
9641 buf = tcc_malloc(len + 1);
9642 if (!buf)
9643 return -1;
9644 memcpy(buf, str, len);
9645 buf[len] = CH_EOB;
9646 bf->buf_ptr = buf;
9647 bf->buf_end = buf + len;
9648 pstrcpy(bf->filename, sizeof(bf->filename), "<string>");
9649 bf->line_num = 1;
9650 file = bf;
9651 ret = tcc_compile(s);
9652 file = NULL;
9653 tcc_free(buf);
9655 /* currently, no need to close */
9656 return ret;
9658 #endif
9660 /* define a preprocessor symbol. A value can also be provided with the '=' operator */
9661 void tcc_define_symbol(TCCState *s1, const char *sym, const char *value)
9663 BufferedFile bf1, *bf = &bf1;
9665 pstrcpy(bf->buffer, IO_BUF_SIZE, sym);
9666 pstrcat(bf->buffer, IO_BUF_SIZE, " ");
9667 /* default value */
9668 if (!value)
9669 value = "1";
9670 pstrcat(bf->buffer, IO_BUF_SIZE, value);
9672 /* init file structure */
9673 bf->fd = -1;
9674 bf->buf_ptr = bf->buffer;
9675 bf->buf_end = bf->buffer + strlen(bf->buffer);
9676 *bf->buf_end = CH_EOB;
9677 bf->filename[0] = '\0';
9678 bf->line_num = 1;
9679 file = bf;
9681 s1->include_stack_ptr = s1->include_stack;
9683 /* parse with define parser */
9684 ch = file->buf_ptr[0];
9685 next_nomacro();
9686 parse_define();
9687 file = NULL;
9690 /* undefine a preprocessor symbol */
9691 void tcc_undefine_symbol(TCCState *s1, const char *sym)
9693 TokenSym *ts;
9694 Sym *s;
9695 ts = tok_alloc(sym, strlen(sym));
9696 s = define_find(ts->tok);
9697 /* undefine symbol by putting an invalid name */
9698 if (s)
9699 define_undef(s);
9702 #ifdef CONFIG_TCC_ASM
9704 #ifdef TCC_TARGET_I386
9705 #include "i386-asm.c"
9706 #endif
9707 #include "tccasm.c"
9709 #else
9710 static void asm_instr(void)
9712 error("inline asm() not supported");
9714 static void asm_global_instr(void)
9716 error("inline asm() not supported");
9718 #endif
9720 #include "tccelf.c"
9722 #ifdef TCC_TARGET_COFF
9723 #include "tcccoff.c"
9724 #endif
9726 #ifdef TCC_TARGET_PE
9727 #include "tccpe.c"
9728 #endif
9730 /* print the position in the source file of PC value 'pc' by reading
9731 the stabs debug information */
9732 static void rt_printline(unsigned long wanted_pc)
9734 Stab_Sym *sym, *sym_end;
9735 char func_name[128], last_func_name[128];
9736 unsigned long func_addr, last_pc, pc;
9737 const char *incl_files[INCLUDE_STACK_SIZE];
9738 int incl_index, len, last_line_num, i;
9739 const char *str, *p;
9741 fprintf(stderr, "0x%08lx:", wanted_pc);
9743 func_name[0] = '\0';
9744 func_addr = 0;
9745 incl_index = 0;
9746 last_func_name[0] = '\0';
9747 last_pc = 0xffffffff;
9748 last_line_num = 1;
9749 sym = (Stab_Sym *)stab_section->data + 1;
9750 sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset);
9751 while (sym < sym_end) {
9752 switch(sym->n_type) {
9753 /* function start or end */
9754 case N_FUN:
9755 if (sym->n_strx == 0) {
9756 /* we test if between last line and end of function */
9757 pc = sym->n_value + func_addr;
9758 if (wanted_pc >= last_pc && wanted_pc < pc)
9759 goto found;
9760 func_name[0] = '\0';
9761 func_addr = 0;
9762 } else {
9763 str = stabstr_section->data + sym->n_strx;
9764 p = strchr(str, ':');
9765 if (!p) {
9766 pstrcpy(func_name, sizeof(func_name), str);
9767 } else {
9768 len = p - str;
9769 if (len > sizeof(func_name) - 1)
9770 len = sizeof(func_name) - 1;
9771 memcpy(func_name, str, len);
9772 func_name[len] = '\0';
9774 func_addr = sym->n_value;
9776 break;
9777 /* line number info */
9778 case N_SLINE:
9779 pc = sym->n_value + func_addr;
9780 if (wanted_pc >= last_pc && wanted_pc < pc)
9781 goto found;
9782 last_pc = pc;
9783 last_line_num = sym->n_desc;
9784 /* XXX: slow! */
9785 strcpy(last_func_name, func_name);
9786 break;
9787 /* include files */
9788 case N_BINCL:
9789 str = stabstr_section->data + sym->n_strx;
9790 add_incl:
9791 if (incl_index < INCLUDE_STACK_SIZE) {
9792 incl_files[incl_index++] = str;
9794 break;
9795 case N_EINCL:
9796 if (incl_index > 1)
9797 incl_index--;
9798 break;
9799 case N_SO:
9800 if (sym->n_strx == 0) {
9801 incl_index = 0; /* end of translation unit */
9802 } else {
9803 str = stabstr_section->data + sym->n_strx;
9804 /* do not add path */
9805 len = strlen(str);
9806 if (len > 0 && str[len - 1] != '/')
9807 goto add_incl;
9809 break;
9811 sym++;
9814 /* second pass: we try symtab symbols (no line number info) */
9815 incl_index = 0;
9817 Elf32_Sym *sym, *sym_end;
9818 int type;
9820 sym_end = (Elf32_Sym *)(symtab_section->data + symtab_section->data_offset);
9821 for(sym = (Elf32_Sym *)symtab_section->data + 1;
9822 sym < sym_end;
9823 sym++) {
9824 type = ELF32_ST_TYPE(sym->st_info);
9825 if (type == STT_FUNC) {
9826 if (wanted_pc >= sym->st_value &&
9827 wanted_pc < sym->st_value + sym->st_size) {
9828 pstrcpy(last_func_name, sizeof(last_func_name),
9829 strtab_section->data + sym->st_name);
9830 goto found;
9835 /* did not find any info: */
9836 fprintf(stderr, " ???\n");
9837 return;
9838 found:
9839 if (last_func_name[0] != '\0') {
9840 fprintf(stderr, " %s()", last_func_name);
9842 if (incl_index > 0) {
9843 fprintf(stderr, " (%s:%d",
9844 incl_files[incl_index - 1], last_line_num);
9845 for(i = incl_index - 2; i >= 0; i--)
9846 fprintf(stderr, ", included from %s", incl_files[i]);
9847 fprintf(stderr, ")");
9849 fprintf(stderr, "\n");
9852 #if !defined(_WIN32) && !defined(CONFIG_TCCBOOT)
9854 #ifdef __i386__
9856 /* fix for glibc 2.1 */
9857 #ifndef REG_EIP
9858 #define REG_EIP EIP
9859 #define REG_EBP EBP
9860 #endif
9862 /* return the PC at frame level 'level'. Return non zero if not found */
9863 static int rt_get_caller_pc(unsigned long *paddr,
9864 ucontext_t *uc, int level)
9866 unsigned long fp;
9867 int i;
9869 if (level == 0) {
9870 #if defined(__FreeBSD__)
9871 *paddr = uc->uc_mcontext.mc_eip;
9872 #elif defined(__dietlibc__)
9873 *paddr = uc->uc_mcontext.eip;
9874 #else
9875 *paddr = uc->uc_mcontext.gregs[REG_EIP];
9876 #endif
9877 return 0;
9878 } else {
9879 #if defined(__FreeBSD__)
9880 fp = uc->uc_mcontext.mc_ebp;
9881 #elif defined(__dietlibc__)
9882 fp = uc->uc_mcontext.ebp;
9883 #else
9884 fp = uc->uc_mcontext.gregs[REG_EBP];
9885 #endif
9886 for(i=1;i<level;i++) {
9887 /* XXX: check address validity with program info */
9888 if (fp <= 0x1000 || fp >= 0xc0000000)
9889 return -1;
9890 fp = ((unsigned long *)fp)[0];
9892 *paddr = ((unsigned long *)fp)[1];
9893 return 0;
9896 #else
9898 #warning add arch specific rt_get_caller_pc()
9900 static int rt_get_caller_pc(unsigned long *paddr,
9901 ucontext_t *uc, int level)
9903 return -1;
9905 #endif
9907 /* emit a run time error at position 'pc' */
9908 void rt_error(ucontext_t *uc, const char *fmt, ...)
9910 va_list ap;
9911 unsigned long pc;
9912 int i;
9914 va_start(ap, fmt);
9915 fprintf(stderr, "Runtime error: ");
9916 vfprintf(stderr, fmt, ap);
9917 fprintf(stderr, "\n");
9918 for(i=0;i<num_callers;i++) {
9919 if (rt_get_caller_pc(&pc, uc, i) < 0)
9920 break;
9921 if (i == 0)
9922 fprintf(stderr, "at ");
9923 else
9924 fprintf(stderr, "by ");
9925 rt_printline(pc);
9927 exit(255);
9928 va_end(ap);
9931 /* signal handler for fatal errors */
9932 static void sig_error(int signum, siginfo_t *siginf, void *puc)
9934 ucontext_t *uc = puc;
9936 switch(signum) {
9937 case SIGFPE:
9938 switch(siginf->si_code) {
9939 case FPE_INTDIV:
9940 case FPE_FLTDIV:
9941 rt_error(uc, "division by zero");
9942 break;
9943 default:
9944 rt_error(uc, "floating point exception");
9945 break;
9947 break;
9948 case SIGBUS:
9949 case SIGSEGV:
9950 if (rt_bound_error_msg && *rt_bound_error_msg)
9951 rt_error(uc, *rt_bound_error_msg);
9952 else
9953 rt_error(uc, "dereferencing invalid pointer");
9954 break;
9955 case SIGILL:
9956 rt_error(uc, "illegal instruction");
9957 break;
9958 case SIGABRT:
9959 rt_error(uc, "abort() called");
9960 break;
9961 default:
9962 rt_error(uc, "caught signal %d", signum);
9963 break;
9965 exit(255);
9967 #endif
9969 /* do all relocations (needed before using tcc_get_symbol()) */
9970 int tcc_relocate(TCCState *s1)
9972 Section *s;
9973 int i;
9975 s1->nb_errors = 0;
9977 #ifdef TCC_TARGET_PE
9978 pe_add_runtime(s1);
9979 #else
9980 tcc_add_runtime(s1);
9981 #endif
9983 relocate_common_syms();
9985 tcc_add_linker_symbols(s1);
9986 #ifndef TCC_TARGET_PE
9987 build_got_entries(s1);
9988 #endif
9989 /* compute relocation address : section are relocated in place. We
9990 also alloc the bss space */
9991 for(i = 1; i < s1->nb_sections; i++) {
9992 s = s1->sections[i];
9993 if (s->sh_flags & SHF_ALLOC) {
9994 if (s->sh_type == SHT_NOBITS)
9995 s->data = tcc_mallocz(s->data_offset);
9996 s->sh_addr = (unsigned long)s->data;
10000 relocate_syms(s1, 1);
10002 if (s1->nb_errors != 0)
10003 return -1;
10005 /* relocate each section */
10006 for(i = 1; i < s1->nb_sections; i++) {
10007 s = s1->sections[i];
10008 if (s->reloc)
10009 relocate_section(s1, s);
10012 /* mark executable sections as executable in memory */
10013 for(i = 1; i < s1->nb_sections; i++) {
10014 s = s1->sections[i];
10015 if ((s->sh_flags & (SHF_ALLOC | SHF_EXECINSTR)) ==
10016 (SHF_ALLOC | SHF_EXECINSTR))
10017 set_pages_executable(s->data, s->data_offset);
10019 return 0;
10022 /* launch the compiled program with the given arguments */
10023 int tcc_run(TCCState *s1, int argc, char **argv)
10025 int (*prog_main)(int, char **);
10027 if (tcc_relocate(s1) < 0)
10028 return -1;
10030 prog_main = tcc_get_symbol_err(s1, "main");
10032 if (do_debug) {
10033 #if defined(_WIN32) || defined(CONFIG_TCCBOOT)
10034 error("debug mode currently not available for Windows");
10035 #else
10036 struct sigaction sigact;
10037 /* install TCC signal handlers to print debug info on fatal
10038 runtime errors */
10039 sigact.sa_flags = SA_SIGINFO | SA_RESETHAND;
10040 sigact.sa_sigaction = sig_error;
10041 sigemptyset(&sigact.sa_mask);
10042 sigaction(SIGFPE, &sigact, NULL);
10043 sigaction(SIGILL, &sigact, NULL);
10044 sigaction(SIGSEGV, &sigact, NULL);
10045 sigaction(SIGBUS, &sigact, NULL);
10046 sigaction(SIGABRT, &sigact, NULL);
10047 #endif
10050 #ifdef CONFIG_TCC_BCHECK
10051 if (do_bounds_check) {
10052 void (*bound_init)(void);
10054 /* set error function */
10055 rt_bound_error_msg = (void *)tcc_get_symbol_err(s1,
10056 "__bound_error_msg");
10058 /* XXX: use .init section so that it also work in binary ? */
10059 bound_init = (void *)tcc_get_symbol_err(s1, "__bound_init");
10060 bound_init();
10062 #endif
10063 return (*prog_main)(argc, argv);
10066 void tcc_memstats(void)
10068 #ifdef MEM_DEBUG
10069 printf("memory in use: %d\n", mem_cur_size);
10070 #endif
10073 static void tcc_cleanup(void)
10075 int i, n;
10077 if (NULL == tcc_state)
10078 return;
10079 tcc_state = NULL;
10081 /* free -D defines */
10082 free_defines(NULL);
10084 /* free tokens */
10085 n = tok_ident - TOK_IDENT;
10086 for(i = 0; i < n; i++)
10087 tcc_free(table_ident[i]);
10088 tcc_free(table_ident);
10090 /* free sym_pools */
10091 dynarray_reset(&sym_pools, &nb_sym_pools);
10092 /* string buffer */
10093 cstr_free(&tokcstr);
10094 /* reset symbol stack */
10095 sym_free_first = NULL;
10098 TCCState *tcc_new(void)
10100 const char *p, *r;
10101 TCCState *s;
10102 TokenSym *ts;
10103 int i, c;
10105 tcc_cleanup();
10107 s = tcc_mallocz(sizeof(TCCState));
10108 if (!s)
10109 return NULL;
10110 tcc_state = s;
10111 s->output_type = TCC_OUTPUT_MEMORY;
10113 /* init isid table */
10114 for(i=0;i<256;i++)
10115 isidnum_table[i] = isid(i) || isnum(i);
10117 /* add all tokens */
10118 table_ident = NULL;
10119 memset(hash_ident, 0, TOK_HASH_SIZE * sizeof(TokenSym *));
10121 tok_ident = TOK_IDENT;
10122 p = tcc_keywords;
10123 while (*p) {
10124 r = p;
10125 for(;;) {
10126 c = *r++;
10127 if (c == '\0')
10128 break;
10130 ts = tok_alloc(p, r - p - 1);
10131 p = r;
10134 /* we add dummy defines for some special macros to speed up tests
10135 and to have working defined() */
10136 define_push(TOK___LINE__, MACRO_OBJ, NULL, NULL);
10137 define_push(TOK___FILE__, MACRO_OBJ, NULL, NULL);
10138 define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL);
10139 define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL);
10141 /* standard defines */
10142 tcc_define_symbol(s, "__STDC__", NULL);
10143 tcc_define_symbol(s, "__STDC_VERSION__", "199901L");
10144 #if defined(TCC_TARGET_I386)
10145 tcc_define_symbol(s, "__i386__", NULL);
10146 #endif
10147 #if defined(TCC_TARGET_ARM)
10148 tcc_define_symbol(s, "__ARM_ARCH_4__", NULL);
10149 tcc_define_symbol(s, "__arm_elf__", NULL);
10150 tcc_define_symbol(s, "__arm_elf", NULL);
10151 tcc_define_symbol(s, "arm_elf", NULL);
10152 tcc_define_symbol(s, "__arm__", NULL);
10153 tcc_define_symbol(s, "__arm", NULL);
10154 tcc_define_symbol(s, "arm", NULL);
10155 tcc_define_symbol(s, "__APCS_32__", NULL);
10156 #endif
10157 #ifdef TCC_TARGET_PE
10158 tcc_define_symbol(s, "_WIN32", NULL);
10159 #else
10160 tcc_define_symbol(s, "__unix__", NULL);
10161 tcc_define_symbol(s, "__unix", NULL);
10162 #if defined(__linux)
10163 tcc_define_symbol(s, "__linux__", NULL);
10164 tcc_define_symbol(s, "__linux", NULL);
10165 #endif
10166 #endif
10167 /* tiny C specific defines */
10168 tcc_define_symbol(s, "__TINYC__", NULL);
10170 /* tiny C & gcc defines */
10171 tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned int");
10172 tcc_define_symbol(s, "__PTRDIFF_TYPE__", "int");
10173 #ifdef TCC_TARGET_PE
10174 tcc_define_symbol(s, "__WCHAR_TYPE__", "unsigned short");
10175 #else
10176 tcc_define_symbol(s, "__WCHAR_TYPE__", "int");
10177 #endif
10179 #ifndef TCC_TARGET_PE
10180 /* default library paths */
10181 tcc_add_library_path(s, "/usr/local/lib");
10182 tcc_add_library_path(s, "/usr/lib");
10183 tcc_add_library_path(s, "/lib");
10184 #endif
10186 /* no section zero */
10187 dynarray_add((void ***)&s->sections, &s->nb_sections, NULL);
10189 /* create standard sections */
10190 text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
10191 data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
10192 bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
10194 /* symbols are always generated for linking stage */
10195 symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0,
10196 ".strtab",
10197 ".hashtab", SHF_PRIVATE);
10198 strtab_section = symtab_section->link;
10200 /* private symbol table for dynamic symbols */
10201 s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE,
10202 ".dynstrtab",
10203 ".dynhashtab", SHF_PRIVATE);
10204 s->alacarte_link = 1;
10206 #ifdef CHAR_IS_UNSIGNED
10207 s->char_is_unsigned = 1;
10208 #endif
10209 #if defined(TCC_TARGET_PE) && 0
10210 /* XXX: currently the PE linker is not ready to support that */
10211 s->leading_underscore = 1;
10212 #endif
10213 return s;
10216 void tcc_delete(TCCState *s1)
10218 int i;
10220 tcc_cleanup();
10222 /* free all sections */
10223 free_section(s1->dynsymtab_section);
10225 for(i = 1; i < s1->nb_sections; i++)
10226 free_section(s1->sections[i]);
10227 tcc_free(s1->sections);
10229 /* free loaded dlls array */
10230 dynarray_reset(&s1->loaded_dlls, &s1->nb_loaded_dlls);
10232 /* free library paths */
10233 dynarray_reset(&s1->library_paths, &s1->nb_library_paths);
10235 /* free include paths */
10236 dynarray_reset(&s1->cached_includes, &s1->nb_cached_includes);
10237 dynarray_reset(&s1->include_paths, &s1->nb_include_paths);
10238 dynarray_reset(&s1->sysinclude_paths, &s1->nb_sysinclude_paths);
10240 tcc_free(s1);
10243 int tcc_add_include_path(TCCState *s1, const char *pathname)
10245 char *pathname1;
10247 pathname1 = tcc_strdup(pathname);
10248 dynarray_add((void ***)&s1->include_paths, &s1->nb_include_paths, pathname1);
10249 return 0;
10252 int tcc_add_sysinclude_path(TCCState *s1, const char *pathname)
10254 char *pathname1;
10256 pathname1 = tcc_strdup(pathname);
10257 dynarray_add((void ***)&s1->sysinclude_paths, &s1->nb_sysinclude_paths, pathname1);
10258 return 0;
10261 static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
10263 const char *ext;
10264 Elf32_Ehdr ehdr;
10265 int fd, ret;
10266 BufferedFile *saved_file;
10268 /* find source file type with extension */
10269 ext = tcc_fileextension(filename);
10270 if (ext[0])
10271 ext++;
10273 /* open the file */
10274 saved_file = file;
10275 file = tcc_open(s1, filename);
10276 if (!file) {
10277 if (flags & AFF_PRINT_ERROR) {
10278 error_noabort("file '%s' not found", filename);
10280 ret = -1;
10281 goto fail1;
10284 if (flags & AFF_PREPROCESS) {
10285 ret = tcc_preprocess(s1);
10286 } else if (!ext[0] || !strcmp(ext, "c")) {
10287 /* C file assumed */
10288 ret = tcc_compile(s1);
10289 } else
10290 #ifdef CONFIG_TCC_ASM
10291 if (!strcmp(ext, "S")) {
10292 /* preprocessed assembler */
10293 ret = tcc_assemble(s1, 1);
10294 } else if (!strcmp(ext, "s")) {
10295 /* non preprocessed assembler */
10296 ret = tcc_assemble(s1, 0);
10297 } else
10298 #endif
10299 #ifdef TCC_TARGET_PE
10300 if (!strcmp(ext, "def")) {
10301 ret = pe_load_def_file(s1, file->fd);
10302 } else
10303 #endif
10305 fd = file->fd;
10306 /* assume executable format: auto guess file type */
10307 ret = read(fd, &ehdr, sizeof(ehdr));
10308 lseek(fd, 0, SEEK_SET);
10309 if (ret <= 0) {
10310 error_noabort("could not read header");
10311 goto fail;
10312 } else if (ret != sizeof(ehdr)) {
10313 goto try_load_script;
10316 if (ehdr.e_ident[0] == ELFMAG0 &&
10317 ehdr.e_ident[1] == ELFMAG1 &&
10318 ehdr.e_ident[2] == ELFMAG2 &&
10319 ehdr.e_ident[3] == ELFMAG3) {
10320 file->line_num = 0; /* do not display line number if error */
10321 if (ehdr.e_type == ET_REL) {
10322 ret = tcc_load_object_file(s1, fd, 0);
10323 } else if (ehdr.e_type == ET_DYN) {
10324 if (s1->output_type == TCC_OUTPUT_MEMORY) {
10325 #ifdef TCC_TARGET_PE
10326 ret = -1;
10327 #else
10328 void *h;
10329 h = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY);
10330 if (h)
10331 ret = 0;
10332 else
10333 ret = -1;
10334 #endif
10335 } else {
10336 ret = tcc_load_dll(s1, fd, filename,
10337 (flags & AFF_REFERENCED_DLL) != 0);
10339 } else {
10340 error_noabort("unrecognized ELF file");
10341 goto fail;
10343 } else if (memcmp((char *)&ehdr, ARMAG, 8) == 0) {
10344 file->line_num = 0; /* do not display line number if error */
10345 ret = tcc_load_archive(s1, fd);
10346 } else
10347 #ifdef TCC_TARGET_COFF
10348 if (*(uint16_t *)(&ehdr) == COFF_C67_MAGIC) {
10349 ret = tcc_load_coff(s1, fd);
10350 } else
10351 #endif
10352 #ifdef TCC_TARGET_PE
10353 if (pe_test_res_file(&ehdr, ret)) {
10354 ret = pe_load_res_file(s1, fd);
10355 } else
10356 #endif
10358 /* as GNU ld, consider it is an ld script if not recognized */
10359 try_load_script:
10360 ret = tcc_load_ldscript(s1);
10361 if (ret < 0) {
10362 error_noabort("unrecognized file type");
10363 goto fail;
10367 the_end:
10368 tcc_close(file);
10369 fail1:
10370 file = saved_file;
10371 return ret;
10372 fail:
10373 ret = -1;
10374 goto the_end;
10377 int tcc_add_file(TCCState *s, const char *filename)
10379 return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR);
10382 int tcc_add_library_path(TCCState *s, const char *pathname)
10384 char *pathname1;
10386 pathname1 = tcc_strdup(pathname);
10387 dynarray_add((void ***)&s->library_paths, &s->nb_library_paths, pathname1);
10388 return 0;
10391 /* find and load a dll. Return non zero if not found */
10392 /* XXX: add '-rpath' option support ? */
10393 static int tcc_add_dll(TCCState *s, const char *filename, int flags)
10395 char buf[1024];
10396 int i;
10398 for(i = 0; i < s->nb_library_paths; i++) {
10399 snprintf(buf, sizeof(buf), "%s/%s",
10400 s->library_paths[i], filename);
10401 if (tcc_add_file_internal(s, buf, flags) == 0)
10402 return 0;
10404 return -1;
10407 /* the library name is the same as the argument of the '-l' option */
10408 int tcc_add_library(TCCState *s, const char *libraryname)
10410 char buf[1024];
10411 int i;
10413 /* first we look for the dynamic library if not static linking */
10414 if (!s->static_link) {
10415 #ifdef TCC_TARGET_PE
10416 snprintf(buf, sizeof(buf), "%s.def", libraryname);
10417 #else
10418 snprintf(buf, sizeof(buf), "lib%s.so", libraryname);
10419 #endif
10420 if (tcc_add_dll(s, buf, 0) == 0)
10421 return 0;
10424 /* then we look for the static library */
10425 for(i = 0; i < s->nb_library_paths; i++) {
10426 snprintf(buf, sizeof(buf), "%s/lib%s.a",
10427 s->library_paths[i], libraryname);
10428 if (tcc_add_file_internal(s, buf, 0) == 0)
10429 return 0;
10431 return -1;
10434 int tcc_add_symbol(TCCState *s, const char *name, unsigned long val)
10436 add_elf_sym(symtab_section, val, 0,
10437 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
10438 SHN_ABS, name);
10439 return 0;
10442 int tcc_set_output_type(TCCState *s, int output_type)
10444 char buf[1024];
10446 s->output_type = output_type;
10448 if (!s->nostdinc) {
10449 /* default include paths */
10450 /* XXX: reverse order needed if -isystem support */
10451 #ifndef TCC_TARGET_PE
10452 tcc_add_sysinclude_path(s, "/usr/local/include");
10453 tcc_add_sysinclude_path(s, "/usr/include");
10454 #endif
10455 snprintf(buf, sizeof(buf), "%s/include", tcc_lib_path);
10456 tcc_add_sysinclude_path(s, buf);
10457 #ifdef TCC_TARGET_PE
10458 snprintf(buf, sizeof(buf), "%s/include/winapi", tcc_lib_path);
10459 tcc_add_sysinclude_path(s, buf);
10460 #endif
10463 /* if bound checking, then add corresponding sections */
10464 #ifdef CONFIG_TCC_BCHECK
10465 if (do_bounds_check) {
10466 /* define symbol */
10467 tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL);
10468 /* create bounds sections */
10469 bounds_section = new_section(s, ".bounds",
10470 SHT_PROGBITS, SHF_ALLOC);
10471 lbounds_section = new_section(s, ".lbounds",
10472 SHT_PROGBITS, SHF_ALLOC);
10474 #endif
10476 if (s->char_is_unsigned) {
10477 tcc_define_symbol(s, "__CHAR_UNSIGNED__", NULL);
10480 /* add debug sections */
10481 if (do_debug) {
10482 /* stab symbols */
10483 stab_section = new_section(s, ".stab", SHT_PROGBITS, 0);
10484 stab_section->sh_entsize = sizeof(Stab_Sym);
10485 stabstr_section = new_section(s, ".stabstr", SHT_STRTAB, 0);
10486 put_elf_str(stabstr_section, "");
10487 stab_section->link = stabstr_section;
10488 /* put first entry */
10489 put_stabs("", 0, 0, 0, 0);
10492 /* add libc crt1/crti objects */
10493 #ifndef TCC_TARGET_PE
10494 if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) &&
10495 !s->nostdlib) {
10496 if (output_type != TCC_OUTPUT_DLL)
10497 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crt1.o");
10498 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crti.o");
10500 #endif
10502 #ifdef TCC_TARGET_PE
10503 snprintf(buf, sizeof(buf), "%s/lib", tcc_lib_path);
10504 tcc_add_library_path(s, buf);
10505 #endif
10507 return 0;
10510 #define WD_ALL 0x0001 /* warning is activated when using -Wall */
10511 #define FD_INVERT 0x0002 /* invert value before storing */
10513 typedef struct FlagDef {
10514 uint16_t offset;
10515 uint16_t flags;
10516 const char *name;
10517 } FlagDef;
10519 static const FlagDef warning_defs[] = {
10520 { offsetof(TCCState, warn_unsupported), 0, "unsupported" },
10521 { offsetof(TCCState, warn_write_strings), 0, "write-strings" },
10522 { offsetof(TCCState, warn_error), 0, "error" },
10523 { offsetof(TCCState, warn_implicit_function_declaration), WD_ALL,
10524 "implicit-function-declaration" },
10527 static int set_flag(TCCState *s, const FlagDef *flags, int nb_flags,
10528 const char *name, int value)
10530 int i;
10531 const FlagDef *p;
10532 const char *r;
10534 r = name;
10535 if (r[0] == 'n' && r[1] == 'o' && r[2] == '-') {
10536 r += 3;
10537 value = !value;
10539 for(i = 0, p = flags; i < nb_flags; i++, p++) {
10540 if (!strcmp(r, p->name))
10541 goto found;
10543 return -1;
10544 found:
10545 if (p->flags & FD_INVERT)
10546 value = !value;
10547 *(int *)((uint8_t *)s + p->offset) = value;
10548 return 0;
10552 /* set/reset a warning */
10553 int tcc_set_warning(TCCState *s, const char *warning_name, int value)
10555 int i;
10556 const FlagDef *p;
10558 if (!strcmp(warning_name, "all")) {
10559 for(i = 0, p = warning_defs; i < countof(warning_defs); i++, p++) {
10560 if (p->flags & WD_ALL)
10561 *(int *)((uint8_t *)s + p->offset) = 1;
10563 return 0;
10564 } else {
10565 return set_flag(s, warning_defs, countof(warning_defs),
10566 warning_name, value);
10570 static const FlagDef flag_defs[] = {
10571 { offsetof(TCCState, char_is_unsigned), 0, "unsigned-char" },
10572 { offsetof(TCCState, char_is_unsigned), FD_INVERT, "signed-char" },
10573 { offsetof(TCCState, nocommon), FD_INVERT, "common" },
10574 { offsetof(TCCState, leading_underscore), 0, "leading-underscore" },
10577 /* set/reset a flag */
10578 int tcc_set_flag(TCCState *s, const char *flag_name, int value)
10580 return set_flag(s, flag_defs, countof(flag_defs),
10581 flag_name, value);
10584 #if !defined(LIBTCC)
10586 static int64_t getclock_us(void)
10588 #ifdef _WIN32
10589 struct _timeb tb;
10590 _ftime(&tb);
10591 return (tb.time * 1000LL + tb.millitm) * 1000LL;
10592 #else
10593 struct timeval tv;
10594 gettimeofday(&tv, NULL);
10595 return tv.tv_sec * 1000000LL + tv.tv_usec;
10596 #endif
10599 void help(void)
10601 printf("tcc version " TCC_VERSION " - Tiny C Compiler - Copyright (C) 2001-2006 Fabrice Bellard\n"
10602 "usage: tcc [-v] [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
10603 " [-Wwarn] [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-soname name]\n"
10604 " [-static] [infile1 infile2...] [-run infile args...]\n"
10605 "\n"
10606 "General options:\n"
10607 " -v display current version, increase verbosity\n"
10608 " -c compile only - generate an object file\n"
10609 " -o outfile set output filename\n"
10610 " -Bdir set tcc internal library path\n"
10611 " -bench output compilation statistics\n"
10612 " -run run compiled source\n"
10613 " -fflag set or reset (with 'no-' prefix) 'flag' (see man page)\n"
10614 " -Wwarning set or reset (with 'no-' prefix) 'warning' (see man page)\n"
10615 " -w disable all warnings\n"
10616 "Preprocessor options:\n"
10617 " -E preprocess only\n"
10618 " -Idir add include path 'dir'\n"
10619 " -Dsym[=val] define 'sym' with value 'val'\n"
10620 " -Usym undefine 'sym'\n"
10621 "Linker options:\n"
10622 " -Ldir add library path 'dir'\n"
10623 " -llib link with dynamic or static library 'lib'\n"
10624 " -shared generate a shared library\n"
10625 " -soname set name for shared library to be used at runtime\n"
10626 " -static static linking\n"
10627 " -rdynamic export all global symbols to dynamic linker\n"
10628 " -r generate (relocatable) object file\n"
10629 "Debugger options:\n"
10630 " -g generate runtime debug info\n"
10631 #ifdef CONFIG_TCC_BCHECK
10632 " -b compile with built-in memory and bounds checker (implies -g)\n"
10633 #endif
10634 " -bt N show N callers in stack traces\n"
10638 #define TCC_OPTION_HAS_ARG 0x0001
10639 #define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
10641 typedef struct TCCOption {
10642 const char *name;
10643 uint16_t index;
10644 uint16_t flags;
10645 } TCCOption;
10647 enum {
10648 TCC_OPTION_HELP,
10649 TCC_OPTION_I,
10650 TCC_OPTION_D,
10651 TCC_OPTION_U,
10652 TCC_OPTION_L,
10653 TCC_OPTION_B,
10654 TCC_OPTION_l,
10655 TCC_OPTION_bench,
10656 TCC_OPTION_bt,
10657 TCC_OPTION_b,
10658 TCC_OPTION_g,
10659 TCC_OPTION_c,
10660 TCC_OPTION_static,
10661 TCC_OPTION_shared,
10662 TCC_OPTION_soname,
10663 TCC_OPTION_o,
10664 TCC_OPTION_r,
10665 TCC_OPTION_Wl,
10666 TCC_OPTION_W,
10667 TCC_OPTION_O,
10668 TCC_OPTION_m,
10669 TCC_OPTION_f,
10670 TCC_OPTION_nostdinc,
10671 TCC_OPTION_nostdlib,
10672 TCC_OPTION_print_search_dirs,
10673 TCC_OPTION_rdynamic,
10674 TCC_OPTION_run,
10675 TCC_OPTION_v,
10676 TCC_OPTION_w,
10677 TCC_OPTION_pipe,
10678 TCC_OPTION_E,
10681 static const TCCOption tcc_options[] = {
10682 { "h", TCC_OPTION_HELP, 0 },
10683 { "?", TCC_OPTION_HELP, 0 },
10684 { "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG },
10685 { "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG },
10686 { "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG },
10687 { "L", TCC_OPTION_L, TCC_OPTION_HAS_ARG },
10688 { "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG },
10689 { "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10690 { "bench", TCC_OPTION_bench, 0 },
10691 { "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG },
10692 #ifdef CONFIG_TCC_BCHECK
10693 { "b", TCC_OPTION_b, 0 },
10694 #endif
10695 { "g", TCC_OPTION_g, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10696 { "c", TCC_OPTION_c, 0 },
10697 { "static", TCC_OPTION_static, 0 },
10698 { "shared", TCC_OPTION_shared, 0 },
10699 { "soname", TCC_OPTION_soname, TCC_OPTION_HAS_ARG },
10700 { "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG },
10701 { "run", TCC_OPTION_run, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10702 { "rdynamic", TCC_OPTION_rdynamic, 0 },
10703 { "r", TCC_OPTION_r, 0 },
10704 { "Wl,", TCC_OPTION_Wl, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10705 { "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10706 { "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10707 { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG },
10708 { "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10709 { "nostdinc", TCC_OPTION_nostdinc, 0 },
10710 { "nostdlib", TCC_OPTION_nostdlib, 0 },
10711 { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 },
10712 { "v", TCC_OPTION_v, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10713 { "w", TCC_OPTION_w, 0 },
10714 { "pipe", TCC_OPTION_pipe, 0},
10715 { "E", TCC_OPTION_E, 0},
10716 { NULL },
10719 /* convert 'str' into an array of space separated strings */
10720 static int expand_args(char ***pargv, const char *str)
10722 const char *s1;
10723 char **argv, *arg;
10724 int argc, len;
10726 argc = 0;
10727 argv = NULL;
10728 for(;;) {
10729 while (is_space(*str))
10730 str++;
10731 if (*str == '\0')
10732 break;
10733 s1 = str;
10734 while (*str != '\0' && !is_space(*str))
10735 str++;
10736 len = str - s1;
10737 arg = tcc_malloc(len + 1);
10738 memcpy(arg, s1, len);
10739 arg[len] = '\0';
10740 dynarray_add((void ***)&argv, &argc, arg);
10742 *pargv = argv;
10743 return argc;
10746 static char **files;
10747 static int nb_files, nb_libraries;
10748 static int multiple_files;
10749 static int print_search_dirs;
10750 static int output_type;
10751 static int reloc_output;
10752 static const char *outfile;
10754 int parse_args(TCCState *s, int argc, char **argv)
10756 int optind;
10757 const TCCOption *popt;
10758 const char *optarg, *p1, *r1;
10759 char *r;
10761 optind = 0;
10762 while (1) {
10763 if (optind >= argc) {
10764 if (nb_files == 0 && !print_search_dirs) {
10765 if (verbose)
10766 exit(0);
10767 goto show_help;
10769 break;
10771 r = argv[optind++];
10772 if (r[0] != '-' || r[1] == '\0') {
10773 /* add a new file */
10774 dynarray_add((void ***)&files, &nb_files, r);
10775 if (!multiple_files) {
10776 optind--;
10777 /* argv[0] will be this file */
10778 break;
10780 } else {
10781 /* find option in table (match only the first chars */
10782 popt = tcc_options;
10783 for(;;) {
10784 p1 = popt->name;
10785 if (p1 == NULL)
10786 error("invalid option -- '%s'", r);
10787 r1 = r + 1;
10788 for(;;) {
10789 if (*p1 == '\0')
10790 goto option_found;
10791 if (*r1 != *p1)
10792 break;
10793 p1++;
10794 r1++;
10796 popt++;
10798 option_found:
10799 if (popt->flags & TCC_OPTION_HAS_ARG) {
10800 if (*r1 != '\0' || (popt->flags & TCC_OPTION_NOSEP)) {
10801 optarg = r1;
10802 } else {
10803 if (optind >= argc)
10804 error("argument to '%s' is missing", r);
10805 optarg = argv[optind++];
10807 } else {
10808 if (*r1 != '\0')
10809 goto show_help;
10810 optarg = NULL;
10813 switch(popt->index) {
10814 case TCC_OPTION_HELP:
10815 show_help:
10816 help();
10817 exit(1);
10818 case TCC_OPTION_I:
10819 if (tcc_add_include_path(s, optarg) < 0)
10820 error("too many include paths");
10821 break;
10822 case TCC_OPTION_D:
10824 char *sym, *value;
10825 sym = (char *)optarg;
10826 value = strchr(sym, '=');
10827 if (value) {
10828 *value = '\0';
10829 value++;
10831 tcc_define_symbol(s, sym, value);
10833 break;
10834 case TCC_OPTION_U:
10835 tcc_undefine_symbol(s, optarg);
10836 break;
10837 case TCC_OPTION_L:
10838 tcc_add_library_path(s, optarg);
10839 break;
10840 case TCC_OPTION_B:
10841 /* set tcc utilities path (mainly for tcc development) */
10842 tcc_lib_path = optarg;
10843 break;
10844 case TCC_OPTION_l:
10845 dynarray_add((void ***)&files, &nb_files, r);
10846 nb_libraries++;
10847 break;
10848 case TCC_OPTION_bench:
10849 do_bench = 1;
10850 break;
10851 case TCC_OPTION_bt:
10852 num_callers = atoi(optarg);
10853 break;
10854 #ifdef CONFIG_TCC_BCHECK
10855 case TCC_OPTION_b:
10856 do_bounds_check = 1;
10857 do_debug = 1;
10858 break;
10859 #endif
10860 case TCC_OPTION_g:
10861 do_debug = 1;
10862 break;
10863 case TCC_OPTION_c:
10864 multiple_files = 1;
10865 output_type = TCC_OUTPUT_OBJ;
10866 break;
10867 case TCC_OPTION_static:
10868 s->static_link = 1;
10869 break;
10870 case TCC_OPTION_shared:
10871 output_type = TCC_OUTPUT_DLL;
10872 break;
10873 case TCC_OPTION_soname:
10874 s->soname = optarg;
10875 break;
10876 case TCC_OPTION_o:
10877 multiple_files = 1;
10878 outfile = optarg;
10879 break;
10880 case TCC_OPTION_r:
10881 /* generate a .o merging several output files */
10882 reloc_output = 1;
10883 output_type = TCC_OUTPUT_OBJ;
10884 break;
10885 case TCC_OPTION_nostdinc:
10886 s->nostdinc = 1;
10887 break;
10888 case TCC_OPTION_nostdlib:
10889 s->nostdlib = 1;
10890 break;
10891 case TCC_OPTION_print_search_dirs:
10892 print_search_dirs = 1;
10893 break;
10894 case TCC_OPTION_run:
10896 int argc1;
10897 char **argv1;
10898 argc1 = expand_args(&argv1, optarg);
10899 if (argc1 > 0) {
10900 parse_args(s, argc1, argv1);
10902 multiple_files = 0;
10903 output_type = TCC_OUTPUT_MEMORY;
10905 break;
10906 case TCC_OPTION_v:
10907 do {
10908 if (0 == verbose++)
10909 printf("tcc version %s\n", TCC_VERSION);
10910 } while (*optarg++ == 'v');
10911 break;
10912 case TCC_OPTION_f:
10913 if (tcc_set_flag(s, optarg, 1) < 0 && s->warn_unsupported)
10914 goto unsupported_option;
10915 break;
10916 case TCC_OPTION_W:
10917 if (tcc_set_warning(s, optarg, 1) < 0 &&
10918 s->warn_unsupported)
10919 goto unsupported_option;
10920 break;
10921 case TCC_OPTION_w:
10922 s->warn_none = 1;
10923 break;
10924 case TCC_OPTION_rdynamic:
10925 s->rdynamic = 1;
10926 break;
10927 case TCC_OPTION_Wl:
10929 const char *p;
10930 if (strstart(optarg, "-Ttext,", &p)) {
10931 s->text_addr = strtoul(p, NULL, 16);
10932 s->has_text_addr = 1;
10933 } else if (strstart(optarg, "--oformat,", &p)) {
10934 if (strstart(p, "elf32-", NULL)) {
10935 s->output_format = TCC_OUTPUT_FORMAT_ELF;
10936 } else if (!strcmp(p, "binary")) {
10937 s->output_format = TCC_OUTPUT_FORMAT_BINARY;
10938 } else
10939 #ifdef TCC_TARGET_COFF
10940 if (!strcmp(p, "coff")) {
10941 s->output_format = TCC_OUTPUT_FORMAT_COFF;
10942 } else
10943 #endif
10945 error("target %s not found", p);
10947 } else {
10948 error("unsupported linker option '%s'", optarg);
10951 break;
10952 case TCC_OPTION_E:
10953 output_type = TCC_OUTPUT_PREPROCESS;
10954 break;
10955 default:
10956 if (s->warn_unsupported) {
10957 unsupported_option:
10958 warning("unsupported option '%s'", r);
10960 break;
10964 return optind;
10967 int main(int argc, char **argv)
10969 int i;
10970 TCCState *s;
10971 int nb_objfiles, ret, optind;
10972 char objfilename[1024];
10973 int64_t start_time = 0;
10975 #ifdef _WIN32
10976 tcc_lib_path = w32_tcc_lib_path();
10977 #endif
10979 s = tcc_new();
10980 output_type = TCC_OUTPUT_EXE;
10981 outfile = NULL;
10982 multiple_files = 1;
10983 files = NULL;
10984 nb_files = 0;
10985 nb_libraries = 0;
10986 reloc_output = 0;
10987 print_search_dirs = 0;
10988 ret = 0;
10990 optind = parse_args(s, argc - 1, argv + 1) + 1;
10992 if (print_search_dirs) {
10993 /* enough for Linux kernel */
10994 printf("install: %s/\n", tcc_lib_path);
10995 return 0;
10998 nb_objfiles = nb_files - nb_libraries;
11000 /* if outfile provided without other options, we output an
11001 executable */
11002 if (outfile && output_type == TCC_OUTPUT_MEMORY)
11003 output_type = TCC_OUTPUT_EXE;
11005 /* check -c consistency : only single file handled. XXX: checks file type */
11006 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
11007 /* accepts only a single input file */
11008 if (nb_objfiles != 1)
11009 error("cannot specify multiple files with -c");
11010 if (nb_libraries != 0)
11011 error("cannot specify libraries with -c");
11015 if (output_type == TCC_OUTPUT_PREPROCESS) {
11016 if (!outfile) {
11017 s->outfile = stdout;
11018 } else {
11019 s->outfile = fopen(outfile, "w");
11020 if (!s->outfile)
11021 error("could not open '%s", outfile);
11023 } else if (output_type != TCC_OUTPUT_MEMORY) {
11024 if (!outfile) {
11025 /* compute default outfile name */
11026 char *ext;
11027 const char *name =
11028 strcmp(files[0], "-") == 0 ? "a" : tcc_basename(files[0]);
11029 pstrcpy(objfilename, sizeof(objfilename), name);
11030 ext = tcc_fileextension(objfilename);
11031 #ifdef TCC_TARGET_PE
11032 if (output_type == TCC_OUTPUT_DLL)
11033 strcpy(ext, ".dll");
11034 else
11035 if (output_type == TCC_OUTPUT_EXE)
11036 strcpy(ext, ".exe");
11037 else
11038 #endif
11039 if (output_type == TCC_OUTPUT_OBJ && !reloc_output && *ext)
11040 strcpy(ext, ".o");
11041 else
11042 pstrcpy(objfilename, sizeof(objfilename), "a.out");
11043 outfile = objfilename;
11047 if (do_bench) {
11048 start_time = getclock_us();
11051 tcc_set_output_type(s, output_type);
11053 /* compile or add each files or library */
11054 for(i = 0; i < nb_files && ret == 0; i++) {
11055 const char *filename;
11057 filename = files[i];
11058 if (output_type == TCC_OUTPUT_PREPROCESS) {
11059 if (tcc_add_file_internal(s, filename,
11060 AFF_PRINT_ERROR | AFF_PREPROCESS) < 0)
11061 ret = 1;
11062 } else if (filename[0] == '-' && filename[1]) {
11063 if (tcc_add_library(s, filename + 2) < 0)
11064 error("cannot find %s", filename);
11065 } else {
11066 if (1 == verbose)
11067 printf("-> %s\n", filename);
11068 if (tcc_add_file(s, filename) < 0)
11069 ret = 1;
11073 /* free all files */
11074 tcc_free(files);
11076 if (ret)
11077 goto the_end;
11079 if (do_bench) {
11080 double total_time;
11081 total_time = (double)(getclock_us() - start_time) / 1000000.0;
11082 if (total_time < 0.001)
11083 total_time = 0.001;
11084 if (total_bytes < 1)
11085 total_bytes = 1;
11086 printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
11087 tok_ident - TOK_IDENT, total_lines, total_bytes,
11088 total_time, (int)(total_lines / total_time),
11089 total_bytes / total_time / 1000000.0);
11092 if (s->output_type == TCC_OUTPUT_PREPROCESS) {
11093 if (outfile)
11094 fclose(s->outfile);
11095 } else if (s->output_type == TCC_OUTPUT_MEMORY) {
11096 ret = tcc_run(s, argc - optind, argv + optind);
11097 } else
11098 #ifdef TCC_TARGET_PE
11099 if (s->output_type != TCC_OUTPUT_OBJ) {
11100 ret = pe_output_file(s, outfile);
11101 } else
11102 #endif
11104 ret = tcc_output_file(s, outfile) ? 1 : 0;
11106 the_end:
11107 /* XXX: cannot do it with bound checking because of the malloc hooks */
11108 if (!do_bounds_check)
11109 tcc_delete(s);
11111 #ifdef MEM_DEBUG
11112 if (do_bench) {
11113 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size, mem_max_size);
11115 #endif
11116 return ret;
11119 #endif