Add -soname linker option (Marc Andre Tanner)
[tinycc/daniel.git] / tcc.c
blob64a8d51a7f18c6117c91806b3be4917c0985925e
1 /*
2 * TCC - Tiny C Compiler
3 *
4 * Copyright (c) 2001-2004 Fabrice Bellard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #define _GNU_SOURCE
21 #include "config.h"
23 #ifdef CONFIG_TCCBOOT
25 #include "tccboot.h"
26 #define CONFIG_TCC_STATIC
28 #else
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <stdarg.h>
33 #include <string.h>
34 #include <errno.h>
35 #include <math.h>
36 #include <unistd.h>
37 #include <signal.h>
38 #include <fcntl.h>
39 #include <setjmp.h>
40 #include <time.h>
41 #ifdef _WIN32
42 #include <sys/timeb.h>
43 #include <windows.h>
44 #endif
45 #ifndef _WIN32
46 #include <sys/time.h>
47 #include <sys/ucontext.h>
48 #include <sys/mman.h>
49 #endif
51 #endif /* !CONFIG_TCCBOOT */
53 #ifndef PAGESIZE
54 #define PAGESIZE 4096
55 #endif
57 #include "elf.h"
58 #include "stab.h"
60 #ifndef O_BINARY
61 #define O_BINARY 0
62 #endif
64 #include "libtcc.h"
66 /* parser debug */
67 //#define PARSE_DEBUG
68 /* preprocessor debug */
69 //#define PP_DEBUG
70 /* include file debug */
71 //#define INC_DEBUG
73 //#define MEM_DEBUG
75 /* assembler debug */
76 //#define ASM_DEBUG
78 /* target selection */
79 //#define TCC_TARGET_I386 /* i386 code generator */
80 //#define TCC_TARGET_ARM /* ARMv4 code generator */
81 //#define TCC_TARGET_C67 /* TMS320C67xx code generator */
83 /* default target is I386 */
84 #if !defined(TCC_TARGET_I386) && !defined(TCC_TARGET_ARM) && \
85 !defined(TCC_TARGET_C67)
86 #define TCC_TARGET_I386
87 #endif
89 #if !defined(_WIN32) && !defined(TCC_UCLIBC) && !defined(TCC_TARGET_ARM) && \
90 !defined(TCC_TARGET_C67)
91 #define CONFIG_TCC_BCHECK /* enable bound checking code */
92 #endif
94 #if defined(_WIN32) && !defined(TCC_TARGET_PE)
95 #define CONFIG_TCC_STATIC
96 #endif
98 /* define it to include assembler support */
99 #if !defined(TCC_TARGET_ARM) && !defined(TCC_TARGET_C67)
100 #define CONFIG_TCC_ASM
101 #endif
103 /* object format selection */
104 #if defined(TCC_TARGET_C67)
105 #define TCC_TARGET_COFF
106 #endif
108 #define FALSE 0
109 #define false 0
110 #define TRUE 1
111 #define true 1
112 typedef int BOOL;
114 /* path to find crt1.o, crti.o and crtn.o. Only needed when generating
115 executables or dlls */
116 #define CONFIG_TCC_CRT_PREFIX "/usr/lib"
118 #define INCLUDE_STACK_SIZE 32
119 #define IFDEF_STACK_SIZE 64
120 #define VSTACK_SIZE 256
121 #define STRING_MAX_SIZE 1024
122 #define PACK_STACK_SIZE 8
124 #define TOK_HASH_SIZE 8192 /* must be a power of two */
125 #define TOK_ALLOC_INCR 512 /* must be a power of two */
126 #define TOK_MAX_SIZE 4 /* token max size in int unit when stored in string */
128 /* token symbol management */
129 typedef struct TokenSym {
130 struct TokenSym *hash_next;
131 struct Sym *sym_define; /* direct pointer to define */
132 struct Sym *sym_label; /* direct pointer to label */
133 struct Sym *sym_struct; /* direct pointer to structure */
134 struct Sym *sym_identifier; /* direct pointer to identifier */
135 int tok; /* token number */
136 int len;
137 char str[1];
138 } TokenSym;
140 #ifdef TCC_TARGET_PE
141 typedef unsigned short nwchar_t;
142 #else
143 typedef int nwchar_t;
144 #endif
146 typedef struct CString {
147 int size; /* size in bytes */
148 void *data; /* either 'char *' or 'nwchar_t *' */
149 int size_allocated;
150 void *data_allocated; /* if non NULL, data has been malloced */
151 } CString;
153 /* type definition */
154 typedef struct CType {
155 int t;
156 struct Sym *ref;
157 } CType;
159 /* constant value */
160 typedef union CValue {
161 long double ld;
162 double d;
163 float f;
164 int i;
165 unsigned int ui;
166 unsigned int ul; /* address (should be unsigned long on 64 bit cpu) */
167 long long ll;
168 unsigned long long ull;
169 struct CString *cstr;
170 void *ptr;
171 int tab[1];
172 } CValue;
174 /* value on stack */
175 typedef struct SValue {
176 CType type; /* type */
177 unsigned short r; /* register + flags */
178 unsigned short r2; /* second register, used for 'long long'
179 type. If not used, set to VT_CONST */
180 CValue c; /* constant, if VT_CONST */
181 struct Sym *sym; /* symbol, if (VT_SYM | VT_CONST) */
182 } SValue;
184 /* symbol management */
185 typedef struct Sym {
186 int v; /* symbol token */
187 int r; /* associated register */
188 int c; /* associated number */
189 CType type; /* associated type */
190 struct Sym *next; /* next related symbol */
191 struct Sym *prev; /* prev symbol in stack */
192 struct Sym *prev_tok; /* previous symbol for this token */
193 } Sym;
195 /* section definition */
196 /* XXX: use directly ELF structure for parameters ? */
197 /* special flag to indicate that the section should not be linked to
198 the other ones */
199 #define SHF_PRIVATE 0x80000000
201 typedef struct Section {
202 unsigned long data_offset; /* current data offset */
203 unsigned char *data; /* section data */
204 unsigned long data_allocated; /* used for realloc() handling */
205 int sh_name; /* elf section name (only used during output) */
206 int sh_num; /* elf section number */
207 int sh_type; /* elf section type */
208 int sh_flags; /* elf section flags */
209 int sh_info; /* elf section info */
210 int sh_addralign; /* elf section alignment */
211 int sh_entsize; /* elf entry size */
212 unsigned long sh_size; /* section size (only used during output) */
213 unsigned long sh_addr; /* address at which the section is relocated */
214 unsigned long sh_offset; /* file offset */
215 int nb_hashed_syms; /* used to resize the hash table */
216 struct Section *link; /* link to another section */
217 struct Section *reloc; /* corresponding section for relocation, if any */
218 struct Section *hash; /* hash table for symbols */
219 struct Section *next;
220 char name[1]; /* section name */
221 } Section;
223 typedef struct DLLReference {
224 int level;
225 char name[1];
226 } DLLReference;
228 /* GNUC attribute definition */
229 typedef struct AttributeDef {
230 int aligned;
231 int packed;
232 Section *section;
233 int func_attr; /* calling convention, exports, ... */
234 } AttributeDef;
236 /* -------------------------------------------------- */
237 /* gr: wrappers for casting sym->r for other purposes */
238 typedef struct {
239 unsigned
240 func_call : 8,
241 func_args : 8,
242 func_export : 1;
243 } func_attr_t;
245 #define FUNC_CALL(r) (((func_attr_t*)&(r))->func_call)
246 #define FUNC_EXPORT(r) (((func_attr_t*)&(r))->func_export)
247 #define FUNC_ARGS(r) (((func_attr_t*)&(r))->func_args)
248 #define INLINE_DEF(r) (*(int **)&(r))
249 /* -------------------------------------------------- */
251 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
252 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
253 #define SYM_FIRST_ANOM 0x10000000 /* first anonymous sym */
255 /* stored in 'Sym.c' field */
256 #define FUNC_NEW 1 /* ansi function prototype */
257 #define FUNC_OLD 2 /* old function prototype */
258 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
260 /* stored in 'Sym.r' field */
261 #define FUNC_CDECL 0 /* standard c call */
262 #define FUNC_STDCALL 1 /* pascal c call */
263 #define FUNC_FASTCALL1 2 /* first param in %eax */
264 #define FUNC_FASTCALL2 3 /* first parameters in %eax, %edx */
265 #define FUNC_FASTCALL3 4 /* first parameter in %eax, %edx, %ecx */
266 #define FUNC_FASTCALLW 5 /* first parameter in %ecx, %edx */
268 /* field 'Sym.t' for macros */
269 #define MACRO_OBJ 0 /* object like macro */
270 #define MACRO_FUNC 1 /* function like macro */
272 /* field 'Sym.r' for C labels */
273 #define LABEL_DEFINED 0 /* label is defined */
274 #define LABEL_FORWARD 1 /* label is forward defined */
275 #define LABEL_DECLARED 2 /* label is declared but never used */
277 /* type_decl() types */
278 #define TYPE_ABSTRACT 1 /* type without variable */
279 #define TYPE_DIRECT 2 /* type with variable */
281 #define IO_BUF_SIZE 8192
283 typedef struct BufferedFile {
284 uint8_t *buf_ptr;
285 uint8_t *buf_end;
286 int fd;
287 int line_num; /* current line number - here to simplify code */
288 int ifndef_macro; /* #ifndef macro / #endif search */
289 int ifndef_macro_saved; /* saved ifndef_macro */
290 int *ifdef_stack_ptr; /* ifdef_stack value at the start of the file */
291 char inc_type; /* type of include */
292 char inc_filename[512]; /* filename specified by the user */
293 char filename[1024]; /* current filename - here to simplify code */
294 unsigned char buffer[IO_BUF_SIZE + 1]; /* extra size for CH_EOB char */
295 } BufferedFile;
297 #define CH_EOB '\\' /* end of buffer or '\0' char in file */
298 #define CH_EOF (-1) /* end of file */
300 /* parsing state (used to save parser state to reparse part of the
301 source several times) */
302 typedef struct ParseState {
303 int *macro_ptr;
304 int line_num;
305 int tok;
306 CValue tokc;
307 } ParseState;
309 /* used to record tokens */
310 typedef struct TokenString {
311 int *str;
312 int len;
313 int allocated_len;
314 int last_line_num;
315 } TokenString;
317 /* include file cache, used to find files faster and also to eliminate
318 inclusion if the include file is protected by #ifndef ... #endif */
319 typedef struct CachedInclude {
320 int ifndef_macro;
321 int hash_next; /* -1 if none */
322 char type; /* '"' or '>' to give include type */
323 char filename[1]; /* path specified in #include */
324 } CachedInclude;
326 #define CACHED_INCLUDES_HASH_SIZE 512
328 /* parser */
329 static struct BufferedFile *file;
330 static int ch, tok;
331 static CValue tokc;
332 static CString tokcstr; /* current parsed string, if any */
333 /* additional informations about token */
334 static int tok_flags;
335 #define TOK_FLAG_BOL 0x0001 /* beginning of line before */
336 #define TOK_FLAG_BOF 0x0002 /* beginning of file before */
337 #define TOK_FLAG_ENDIF 0x0004 /* a endif was found matching starting #ifdef */
338 #define TOK_FLAG_EOF 0x0008 /* end of file */
340 static int *macro_ptr, *macro_ptr_allocated;
341 static int *unget_saved_macro_ptr;
342 static int unget_saved_buffer[TOK_MAX_SIZE + 1];
343 static int unget_buffer_enabled;
344 static int parse_flags;
345 #define PARSE_FLAG_PREPROCESS 0x0001 /* activate preprocessing */
346 #define PARSE_FLAG_TOK_NUM 0x0002 /* return numbers instead of TOK_PPNUM */
347 #define PARSE_FLAG_LINEFEED 0x0004 /* line feed is returned as a
348 token. line feed is also
349 returned at eof */
350 #define PARSE_FLAG_ASM_COMMENTS 0x0008 /* '#' can be used for line comment */
352 static Section *text_section, *data_section, *bss_section; /* predefined sections */
353 static Section *cur_text_section; /* current section where function code is
354 generated */
355 #ifdef CONFIG_TCC_ASM
356 static Section *last_text_section; /* to handle .previous asm directive */
357 #endif
358 /* bound check related sections */
359 static Section *bounds_section; /* contains global data bound description */
360 static Section *lbounds_section; /* contains local data bound description */
361 /* symbol sections */
362 static Section *symtab_section, *strtab_section;
364 /* debug sections */
365 static Section *stab_section, *stabstr_section;
367 /* loc : local variable index
368 ind : output code index
369 rsym: return symbol
370 anon_sym: anonymous symbol index
372 static int rsym, anon_sym, ind, loc;
373 /* expression generation modifiers */
374 static int const_wanted; /* true if constant wanted */
375 static int nocode_wanted; /* true if no code generation wanted for an expression */
376 static int global_expr; /* true if compound literals must be allocated
377 globally (used during initializers parsing */
378 static CType func_vt; /* current function return type (used by return
379 instruction) */
380 static int func_vc;
381 static int last_line_num, last_ind, func_ind; /* debug last line number and pc */
382 static int tok_ident;
383 static TokenSym **table_ident;
384 static TokenSym *hash_ident[TOK_HASH_SIZE];
385 static char token_buf[STRING_MAX_SIZE + 1];
386 static char *funcname;
387 static Sym *global_stack, *local_stack;
388 static Sym *define_stack;
389 static Sym *global_label_stack, *local_label_stack;
390 /* symbol allocator */
391 #define SYM_POOL_NB (8192 / sizeof(Sym))
392 static Sym *sym_free_first;
394 static SValue vstack[VSTACK_SIZE], *vtop;
395 /* some predefined types */
396 static CType char_pointer_type, func_old_type, int_type;
397 /* true if isid(c) || isnum(c) */
398 static unsigned char isidnum_table[256];
400 /* display some information during compilation */
401 static int verbose = 0;
403 /* compile with debug symbol (and use them if error during execution) */
404 static int do_debug = 0;
406 /* compile with built-in memory and bounds checker */
407 static int do_bounds_check = 0;
409 /* display benchmark infos */
410 #if !defined(LIBTCC)
411 static int do_bench = 0;
412 #endif
413 static int total_lines;
414 static int total_bytes;
416 /* use GNU C extensions */
417 static int gnu_ext = 1;
419 /* use Tiny C extensions */
420 static int tcc_ext = 1;
422 /* max number of callers shown if error */
423 static int num_callers = 6;
424 static const char **rt_bound_error_msg;
426 /* XXX: get rid of this ASAP */
427 static struct TCCState *tcc_state;
429 /* give the path of the tcc libraries */
430 static const char *tcc_lib_path = CONFIG_TCCDIR;
432 struct TCCState {
433 int output_type;
435 BufferedFile **include_stack_ptr;
436 int *ifdef_stack_ptr;
438 /* include file handling */
439 char **include_paths;
440 int nb_include_paths;
441 char **sysinclude_paths;
442 int nb_sysinclude_paths;
443 CachedInclude **cached_includes;
444 int nb_cached_includes;
446 char **library_paths;
447 int nb_library_paths;
449 /* array of all loaded dlls (including those referenced by loaded
450 dlls) */
451 DLLReference **loaded_dlls;
452 int nb_loaded_dlls;
454 /* sections */
455 Section **sections;
456 int nb_sections; /* number of sections, including first dummy section */
458 /* got handling */
459 Section *got;
460 Section *plt;
461 unsigned long *got_offsets;
462 int nb_got_offsets;
463 /* give the correspondance from symtab indexes to dynsym indexes */
464 int *symtab_to_dynsym;
466 /* temporary dynamic symbol sections (for dll loading) */
467 Section *dynsymtab_section;
468 /* exported dynamic symbol section */
469 Section *dynsym;
471 int nostdinc; /* if true, no standard headers are added */
472 int nostdlib; /* if true, no standard libraries are added */
474 int nocommon; /* if true, do not use common symbols for .bss data */
476 /* if true, static linking is performed */
477 int static_link;
479 /* soname as specified on the command line (-soname) */
480 const char *soname;
482 /* if true, all symbols are exported */
483 int rdynamic;
485 /* if true, only link in referenced objects from archive */
486 int alacarte_link;
488 /* address of text section */
489 unsigned long text_addr;
490 int has_text_addr;
492 /* output format, see TCC_OUTPUT_FORMAT_xxx */
493 int output_format;
495 /* C language options */
496 int char_is_unsigned;
497 int leading_underscore;
499 /* warning switches */
500 int warn_write_strings;
501 int warn_unsupported;
502 int warn_error;
503 int warn_none;
504 int warn_implicit_function_declaration;
506 /* error handling */
507 void *error_opaque;
508 void (*error_func)(void *opaque, const char *msg);
509 int error_set_jmp_enabled;
510 jmp_buf error_jmp_buf;
511 int nb_errors;
513 /* tiny assembler state */
514 Sym *asm_labels;
516 /* see include_stack_ptr */
517 BufferedFile *include_stack[INCLUDE_STACK_SIZE];
519 /* see ifdef_stack_ptr */
520 int ifdef_stack[IFDEF_STACK_SIZE];
522 /* see cached_includes */
523 int cached_includes_hash[CACHED_INCLUDES_HASH_SIZE];
525 /* pack stack */
526 int pack_stack[PACK_STACK_SIZE];
527 int *pack_stack_ptr;
529 /* output file for preprocessing */
530 FILE *outfile;
533 /* The current value can be: */
534 #define VT_VALMASK 0x00ff
535 #define VT_CONST 0x00f0 /* constant in vc
536 (must be first non register value) */
537 #define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */
538 #define VT_LOCAL 0x00f2 /* offset on stack */
539 #define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */
540 #define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */
541 #define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */
542 #define VT_LVAL 0x0100 /* var is an lvalue */
543 #define VT_SYM 0x0200 /* a symbol value is added */
544 #define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for
545 char/short stored in integer registers) */
546 #define VT_MUSTBOUND 0x0800 /* bound checking must be done before
547 dereferencing value */
548 #define VT_BOUNDED 0x8000 /* value is bounded. The address of the
549 bounding function call point is in vc */
550 #define VT_LVAL_BYTE 0x1000 /* lvalue is a byte */
551 #define VT_LVAL_SHORT 0x2000 /* lvalue is a short */
552 #define VT_LVAL_UNSIGNED 0x4000 /* lvalue is unsigned */
553 #define VT_LVAL_TYPE (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)
555 /* types */
556 #define VT_INT 0 /* integer type */
557 #define VT_BYTE 1 /* signed byte type */
558 #define VT_SHORT 2 /* short type */
559 #define VT_VOID 3 /* void type */
560 #define VT_PTR 4 /* pointer */
561 #define VT_ENUM 5 /* enum definition */
562 #define VT_FUNC 6 /* function type */
563 #define VT_STRUCT 7 /* struct/union definition */
564 #define VT_FLOAT 8 /* IEEE float */
565 #define VT_DOUBLE 9 /* IEEE double */
566 #define VT_LDOUBLE 10 /* IEEE long double */
567 #define VT_BOOL 11 /* ISOC99 boolean type */
568 #define VT_LLONG 12 /* 64 bit integer */
569 #define VT_LONG 13 /* long integer (NEVER USED as type, only
570 during parsing) */
571 #define VT_BTYPE 0x000f /* mask for basic type */
572 #define VT_UNSIGNED 0x0010 /* unsigned type */
573 #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
574 #define VT_BITFIELD 0x0040 /* bitfield modifier */
575 #define VT_CONSTANT 0x0800 /* const modifier */
576 #define VT_VOLATILE 0x1000 /* volatile modifier */
577 #define VT_SIGNED 0x2000 /* signed type */
579 /* storage */
580 #define VT_EXTERN 0x00000080 /* extern definition */
581 #define VT_STATIC 0x00000100 /* static variable */
582 #define VT_TYPEDEF 0x00000200 /* typedef definition */
583 #define VT_INLINE 0x00000400 /* inline definition */
585 #define VT_STRUCT_SHIFT 16 /* shift for bitfield shift values */
587 /* type mask (except storage) */
588 #define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE)
589 #define VT_TYPE (~(VT_STORAGE))
591 /* token values */
593 /* warning: the following compare tokens depend on i386 asm code */
594 #define TOK_ULT 0x92
595 #define TOK_UGE 0x93
596 #define TOK_EQ 0x94
597 #define TOK_NE 0x95
598 #define TOK_ULE 0x96
599 #define TOK_UGT 0x97
600 #define TOK_Nset 0x98
601 #define TOK_Nclear 0x99
602 #define TOK_LT 0x9c
603 #define TOK_GE 0x9d
604 #define TOK_LE 0x9e
605 #define TOK_GT 0x9f
607 #define TOK_LAND 0xa0
608 #define TOK_LOR 0xa1
610 #define TOK_DEC 0xa2
611 #define TOK_MID 0xa3 /* inc/dec, to void constant */
612 #define TOK_INC 0xa4
613 #define TOK_UDIV 0xb0 /* unsigned division */
614 #define TOK_UMOD 0xb1 /* unsigned modulo */
615 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
616 #define TOK_CINT 0xb3 /* number in tokc */
617 #define TOK_CCHAR 0xb4 /* char constant in tokc */
618 #define TOK_STR 0xb5 /* pointer to string in tokc */
619 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
620 #define TOK_LCHAR 0xb7
621 #define TOK_LSTR 0xb8
622 #define TOK_CFLOAT 0xb9 /* float constant */
623 #define TOK_LINENUM 0xba /* line number info */
624 #define TOK_CDOUBLE 0xc0 /* double constant */
625 #define TOK_CLDOUBLE 0xc1 /* long double constant */
626 #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
627 #define TOK_ADDC1 0xc3 /* add with carry generation */
628 #define TOK_ADDC2 0xc4 /* add with carry use */
629 #define TOK_SUBC1 0xc5 /* add with carry generation */
630 #define TOK_SUBC2 0xc6 /* add with carry use */
631 #define TOK_CUINT 0xc8 /* unsigned int constant */
632 #define TOK_CLLONG 0xc9 /* long long constant */
633 #define TOK_CULLONG 0xca /* unsigned long long constant */
634 #define TOK_ARROW 0xcb
635 #define TOK_DOTS 0xcc /* three dots */
636 #define TOK_SHR 0xcd /* unsigned shift right */
637 #define TOK_PPNUM 0xce /* preprocessor number */
639 #define TOK_SHL 0x01 /* shift left */
640 #define TOK_SAR 0x02 /* signed shift right */
642 /* assignement operators : normal operator or 0x80 */
643 #define TOK_A_MOD 0xa5
644 #define TOK_A_AND 0xa6
645 #define TOK_A_MUL 0xaa
646 #define TOK_A_ADD 0xab
647 #define TOK_A_SUB 0xad
648 #define TOK_A_DIV 0xaf
649 #define TOK_A_XOR 0xde
650 #define TOK_A_OR 0xfc
651 #define TOK_A_SHL 0x81
652 #define TOK_A_SAR 0x82
654 #ifndef offsetof
655 #define offsetof(type, field) ((size_t) &((type *)0)->field)
656 #endif
658 #ifndef countof
659 #define countof(tab) (sizeof(tab) / sizeof((tab)[0]))
660 #endif
662 /* WARNING: the content of this string encodes token numbers */
663 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";
665 #define TOK_EOF (-1) /* end of file */
666 #define TOK_LINEFEED 10 /* line feed */
668 /* all identificators and strings have token above that */
669 #define TOK_IDENT 256
671 /* only used for i386 asm opcodes definitions */
672 #define DEF_ASM(x) DEF(TOK_ASM_ ## x, #x)
674 #define DEF_BWL(x) \
675 DEF(TOK_ASM_ ## x ## b, #x "b") \
676 DEF(TOK_ASM_ ## x ## w, #x "w") \
677 DEF(TOK_ASM_ ## x ## l, #x "l") \
678 DEF(TOK_ASM_ ## x, #x)
680 #define DEF_WL(x) \
681 DEF(TOK_ASM_ ## x ## w, #x "w") \
682 DEF(TOK_ASM_ ## x ## l, #x "l") \
683 DEF(TOK_ASM_ ## x, #x)
685 #define DEF_FP1(x) \
686 DEF(TOK_ASM_ ## f ## x ## s, "f" #x "s") \
687 DEF(TOK_ASM_ ## fi ## x ## l, "fi" #x "l") \
688 DEF(TOK_ASM_ ## f ## x ## l, "f" #x "l") \
689 DEF(TOK_ASM_ ## fi ## x ## s, "fi" #x "s")
691 #define DEF_FP(x) \
692 DEF(TOK_ASM_ ## f ## x, "f" #x ) \
693 DEF(TOK_ASM_ ## f ## x ## p, "f" #x "p") \
694 DEF_FP1(x)
696 #define DEF_ASMTEST(x) \
697 DEF_ASM(x ## o) \
698 DEF_ASM(x ## no) \
699 DEF_ASM(x ## b) \
700 DEF_ASM(x ## c) \
701 DEF_ASM(x ## nae) \
702 DEF_ASM(x ## nb) \
703 DEF_ASM(x ## nc) \
704 DEF_ASM(x ## ae) \
705 DEF_ASM(x ## e) \
706 DEF_ASM(x ## z) \
707 DEF_ASM(x ## ne) \
708 DEF_ASM(x ## nz) \
709 DEF_ASM(x ## be) \
710 DEF_ASM(x ## na) \
711 DEF_ASM(x ## nbe) \
712 DEF_ASM(x ## a) \
713 DEF_ASM(x ## s) \
714 DEF_ASM(x ## ns) \
715 DEF_ASM(x ## p) \
716 DEF_ASM(x ## pe) \
717 DEF_ASM(x ## np) \
718 DEF_ASM(x ## po) \
719 DEF_ASM(x ## l) \
720 DEF_ASM(x ## nge) \
721 DEF_ASM(x ## nl) \
722 DEF_ASM(x ## ge) \
723 DEF_ASM(x ## le) \
724 DEF_ASM(x ## ng) \
725 DEF_ASM(x ## nle) \
726 DEF_ASM(x ## g)
728 #define TOK_ASM_int TOK_INT
730 enum tcc_token {
731 TOK_LAST = TOK_IDENT - 1,
732 #define DEF(id, str) id,
733 #include "tcctok.h"
734 #undef DEF
737 static const char tcc_keywords[] =
738 #define DEF(id, str) str "\0"
739 #include "tcctok.h"
740 #undef DEF
743 #define TOK_UIDENT TOK_DEFINE
745 #ifdef _WIN32
746 #define snprintf _snprintf
747 #define vsnprintf _vsnprintf
748 #ifndef __GNUC__
749 #define strtold (long double)strtod
750 #define strtof (float)strtod
751 #define strtoll (long long)strtol
752 #endif
753 #elif defined(TCC_UCLIBC) || defined(__FreeBSD__) || defined(__DragonFly__) \
754 || defined(__OpenBSD__)
755 /* currently incorrect */
756 long double strtold(const char *nptr, char **endptr)
758 return (long double)strtod(nptr, endptr);
760 float strtof(const char *nptr, char **endptr)
762 return (float)strtod(nptr, endptr);
764 #else
765 /* XXX: need to define this to use them in non ISOC99 context */
766 extern float strtof (const char *__nptr, char **__endptr);
767 extern long double strtold (const char *__nptr, char **__endptr);
768 #endif
770 static char *pstrcpy(char *buf, int buf_size, const char *s);
771 static char *pstrcat(char *buf, int buf_size, const char *s);
772 static char *tcc_basename(const char *name);
773 static char *tcc_fileextension (const char *p);
775 static void next(void);
776 static void next_nomacro(void);
777 static void parse_expr_type(CType *type);
778 static void expr_type(CType *type);
779 static void unary_type(CType *type);
780 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
781 int case_reg, int is_expr);
782 static int expr_const(void);
783 static void expr_eq(void);
784 static void gexpr(void);
785 static void gen_inline_functions(void);
786 static void decl(int l);
787 static void decl_initializer(CType *type, Section *sec, unsigned long c,
788 int first, int size_only);
789 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
790 int has_init, int v, int scope);
791 int gv(int rc);
792 void gv2(int rc1, int rc2);
793 void move_reg(int r, int s);
794 void save_regs(int n);
795 void save_reg(int r);
796 void vpop(void);
797 void vswap(void);
798 void vdup(void);
799 int get_reg(int rc);
800 int get_reg_ex(int rc,int rc2);
802 struct macro_level {
803 struct macro_level *prev;
804 int *p;
807 static void macro_subst(TokenString *tok_str, Sym **nested_list,
808 const int *macro_str, struct macro_level **can_read_stream);
809 void gen_op(int op);
810 void force_charshort_cast(int t);
811 static void gen_cast(CType *type);
812 void vstore(void);
813 static Sym *sym_find(int v);
814 static Sym *sym_push(int v, CType *type, int r, int c);
816 /* type handling */
817 static int type_size(CType *type, int *a);
818 static inline CType *pointed_type(CType *type);
819 static int pointed_size(CType *type);
820 static int lvalue_type(int t);
821 static int parse_btype(CType *type, AttributeDef *ad);
822 static void type_decl(CType *type, AttributeDef *ad, int *v, int td);
823 static int compare_types(CType *type1, CType *type2, int unqualified);
824 static int is_compatible_types(CType *type1, CType *type2);
825 static int is_compatible_parameter_types(CType *type1, CType *type2);
827 int ieee_finite(double d);
828 void error(const char *fmt, ...);
829 void vpushi(int v);
830 void vrott(int n);
831 void vnrott(int n);
832 void lexpand_nr(void);
833 static void vpush_global_sym(CType *type, int v);
834 void vset(CType *type, int r, int v);
835 void type_to_str(char *buf, int buf_size,
836 CType *type, const char *varstr);
837 char *get_tok_str(int v, CValue *cv);
838 static Sym *get_sym_ref(CType *type, Section *sec,
839 unsigned long offset, unsigned long size);
840 static Sym *external_global_sym(int v, CType *type, int r);
842 /* section generation */
843 static void section_realloc(Section *sec, unsigned long new_size);
844 static void *section_ptr_add(Section *sec, unsigned long size);
845 static void put_extern_sym(Sym *sym, Section *section,
846 unsigned long value, unsigned long size);
847 static void greloc(Section *s, Sym *sym, unsigned long addr, int type);
848 static int put_elf_str(Section *s, const char *sym);
849 static int put_elf_sym(Section *s,
850 unsigned long value, unsigned long size,
851 int info, int other, int shndx, const char *name);
852 static int add_elf_sym(Section *s, unsigned long value, unsigned long size,
853 int info, int other, int sh_num, const char *name);
854 static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
855 int type, int symbol);
856 static void put_stabs(const char *str, int type, int other, int desc,
857 unsigned long value);
858 static void put_stabs_r(const char *str, int type, int other, int desc,
859 unsigned long value, Section *sec, int sym_index);
860 static void put_stabn(int type, int other, int desc, int value);
861 static void put_stabd(int type, int other, int desc);
862 static int tcc_add_dll(TCCState *s, const char *filename, int flags);
864 #define AFF_PRINT_ERROR 0x0001 /* print error if file not found */
865 #define AFF_REFERENCED_DLL 0x0002 /* load a referenced dll from another dll */
866 #define AFF_PREPROCESS 0x0004 /* preprocess file */
867 static int tcc_add_file_internal(TCCState *s, const char *filename, int flags);
869 /* tcccoff.c */
870 int tcc_output_coff(TCCState *s1, FILE *f);
872 /* tccpe.c */
873 void *resolve_sym(TCCState *s1, const char *sym, int type);
874 int pe_load_def_file(struct TCCState *s1, int fd);
875 int pe_test_res_file(void *v, int size);
876 int pe_load_res_file(struct TCCState *s1, int fd);
877 void pe_add_runtime(struct TCCState *s1);
878 void pe_guess_outfile(char *objfilename, int output_type);
879 int pe_output_file(struct TCCState *s1, const char *filename);
881 /* tccasm.c */
883 #ifdef CONFIG_TCC_ASM
885 typedef struct ExprValue {
886 uint32_t v;
887 Sym *sym;
888 } ExprValue;
890 #define MAX_ASM_OPERANDS 30
892 typedef struct ASMOperand {
893 int id; /* GCC 3 optionnal identifier (0 if number only supported */
894 char *constraint;
895 char asm_str[16]; /* computed asm string for operand */
896 SValue *vt; /* C value of the expression */
897 int ref_index; /* if >= 0, gives reference to a output constraint */
898 int input_index; /* if >= 0, gives reference to an input constraint */
899 int priority; /* priority, used to assign registers */
900 int reg; /* if >= 0, register number used for this operand */
901 int is_llong; /* true if double register value */
902 int is_memory; /* true if memory operand */
903 int is_rw; /* for '+' modifier */
904 } ASMOperand;
906 static void asm_expr(TCCState *s1, ExprValue *pe);
907 static int asm_int_expr(TCCState *s1);
908 static int find_constraint(ASMOperand *operands, int nb_operands,
909 const char *name, const char **pp);
911 static int tcc_assemble(TCCState *s1, int do_preprocess);
913 #endif
915 static void asm_instr(void);
916 static void asm_global_instr(void);
918 /* true if float/double/long double type */
919 static inline int is_float(int t)
921 int bt;
922 bt = t & VT_BTYPE;
923 return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT;
926 #ifdef TCC_TARGET_I386
927 #include "i386-gen.c"
928 #endif
930 #ifdef TCC_TARGET_ARM
931 #include "arm-gen.c"
932 #endif
934 #ifdef TCC_TARGET_C67
935 #include "c67-gen.c"
936 #endif
938 #ifdef CONFIG_TCC_STATIC
940 #define RTLD_LAZY 0x001
941 #define RTLD_NOW 0x002
942 #define RTLD_GLOBAL 0x100
943 #define RTLD_DEFAULT NULL
945 /* dummy function for profiling */
946 void *dlopen(const char *filename, int flag)
948 return NULL;
951 const char *dlerror(void)
953 return "error";
956 typedef struct TCCSyms {
957 char *str;
958 void *ptr;
959 } TCCSyms;
961 #define TCCSYM(a) { #a, &a, },
963 /* add the symbol you want here if no dynamic linking is done */
964 static TCCSyms tcc_syms[] = {
965 #if !defined(CONFIG_TCCBOOT)
966 TCCSYM(printf)
967 TCCSYM(fprintf)
968 TCCSYM(fopen)
969 TCCSYM(fclose)
970 #endif
971 { NULL, NULL },
974 void *resolve_sym(TCCState *s1, const char *symbol, int type)
976 TCCSyms *p;
977 p = tcc_syms;
978 while (p->str != NULL) {
979 if (!strcmp(p->str, symbol))
980 return p->ptr;
981 p++;
983 return NULL;
986 #elif !defined(_WIN32)
988 #include <dlfcn.h>
990 void *resolve_sym(TCCState *s1, const char *sym, int type)
992 return dlsym(RTLD_DEFAULT, sym);
995 #endif
997 /********************************************************/
999 /* we use our own 'finite' function to avoid potential problems with
1000 non standard math libs */
1001 /* XXX: endianness dependent */
1002 int ieee_finite(double d)
1004 int *p = (int *)&d;
1005 return ((unsigned)((p[1] | 0x800fffff) + 1)) >> 31;
1008 /* copy a string and truncate it. */
1009 static char *pstrcpy(char *buf, int buf_size, const char *s)
1011 char *q, *q_end;
1012 int c;
1014 if (buf_size > 0) {
1015 q = buf;
1016 q_end = buf + buf_size - 1;
1017 while (q < q_end) {
1018 c = *s++;
1019 if (c == '\0')
1020 break;
1021 *q++ = c;
1023 *q = '\0';
1025 return buf;
1028 /* strcat and truncate. */
1029 static char *pstrcat(char *buf, int buf_size, const char *s)
1031 int len;
1032 len = strlen(buf);
1033 if (len < buf_size)
1034 pstrcpy(buf + len, buf_size - len, s);
1035 return buf;
1038 static int strstart(const char *str, const char *val, const char **ptr)
1040 const char *p, *q;
1041 p = str;
1042 q = val;
1043 while (*q != '\0') {
1044 if (*p != *q)
1045 return 0;
1046 p++;
1047 q++;
1049 if (ptr)
1050 *ptr = p;
1051 return 1;
1054 /* extract the basename of a file */
1055 static char *tcc_basename(const char *name)
1057 char *p = strchr(name, 0);
1058 while (p > name
1059 && p[-1] != '/'
1060 #ifdef _WIN32
1061 && p[-1] != '\\'
1062 #endif
1064 --p;
1065 return p;
1068 static char *tcc_fileextension (const char *name)
1070 char *b = tcc_basename(name);
1071 char *e = strrchr(b, '.');
1072 return e ? e : strchr(b, 0);
1075 #ifdef _WIN32
1076 char *normalize_slashes(char *path)
1078 char *p;
1079 for (p = path; *p; ++p)
1080 if (*p == '\\')
1081 *p = '/';
1082 return path;
1085 char *w32_tcc_lib_path(void)
1087 /* on win32, we suppose the lib and includes are at the location
1088 of 'tcc.exe' */
1089 char path[1024], *p;
1090 GetModuleFileNameA(NULL, path, sizeof path);
1091 p = tcc_basename(normalize_slashes(strlwr(path)));
1092 if (p - 5 > path && 0 == strncmp(p - 5, "/bin/", 5))
1093 p -= 5;
1094 else if (p > path)
1095 p--;
1096 *p = 0;
1097 return strdup(path);
1099 #endif
1101 void set_pages_executable(void *ptr, unsigned long length)
1103 #ifdef _WIN32
1104 unsigned long old_protect;
1105 VirtualProtect(ptr, length, PAGE_EXECUTE_READWRITE, &old_protect);
1106 #else
1107 unsigned long start, end;
1108 start = (unsigned long)ptr & ~(PAGESIZE - 1);
1109 end = (unsigned long)ptr + length;
1110 end = (end + PAGESIZE - 1) & ~(PAGESIZE - 1);
1111 mprotect((void *)start, end - start, PROT_READ | PROT_WRITE | PROT_EXEC);
1112 #endif
1115 /* memory management */
1116 #ifdef MEM_DEBUG
1117 int mem_cur_size;
1118 int mem_max_size;
1119 #endif
1121 static inline void tcc_free(void *ptr)
1123 #ifdef MEM_DEBUG
1124 mem_cur_size -= malloc_usable_size(ptr);
1125 #endif
1126 free(ptr);
1129 static void *tcc_malloc(unsigned long size)
1131 void *ptr;
1132 ptr = malloc(size);
1133 if (!ptr && size)
1134 error("memory full");
1135 #ifdef MEM_DEBUG
1136 mem_cur_size += malloc_usable_size(ptr);
1137 if (mem_cur_size > mem_max_size)
1138 mem_max_size = mem_cur_size;
1139 #endif
1140 return ptr;
1143 static void *tcc_mallocz(unsigned long size)
1145 void *ptr;
1146 ptr = tcc_malloc(size);
1147 memset(ptr, 0, size);
1148 return ptr;
1151 static inline void *tcc_realloc(void *ptr, unsigned long size)
1153 void *ptr1;
1154 #ifdef MEM_DEBUG
1155 mem_cur_size -= malloc_usable_size(ptr);
1156 #endif
1157 ptr1 = realloc(ptr, size);
1158 #ifdef MEM_DEBUG
1159 /* NOTE: count not correct if alloc error, but not critical */
1160 mem_cur_size += malloc_usable_size(ptr1);
1161 if (mem_cur_size > mem_max_size)
1162 mem_max_size = mem_cur_size;
1163 #endif
1164 return ptr1;
1167 static char *tcc_strdup(const char *str)
1169 char *ptr;
1170 ptr = tcc_malloc(strlen(str) + 1);
1171 strcpy(ptr, str);
1172 return ptr;
1175 #define free(p) use_tcc_free(p)
1176 #define malloc(s) use_tcc_malloc(s)
1177 #define realloc(p, s) use_tcc_realloc(p, s)
1179 static void dynarray_add(void ***ptab, int *nb_ptr, void *data)
1181 int nb, nb_alloc;
1182 void **pp;
1184 nb = *nb_ptr;
1185 pp = *ptab;
1186 /* every power of two we double array size */
1187 if ((nb & (nb - 1)) == 0) {
1188 if (!nb)
1189 nb_alloc = 1;
1190 else
1191 nb_alloc = nb * 2;
1192 pp = tcc_realloc(pp, nb_alloc * sizeof(void *));
1193 if (!pp)
1194 error("memory full");
1195 *ptab = pp;
1197 pp[nb++] = data;
1198 *nb_ptr = nb;
1201 static void dynarray_reset(void *pp, int *n)
1203 void **p;
1204 for (p = *(void***)pp; *n; ++p, --*n)
1205 if (*p)
1206 tcc_free(*p);
1207 tcc_free(*(void**)pp);
1208 *(void**)pp = NULL;
1211 /* symbol allocator */
1212 static Sym *__sym_malloc(void)
1214 Sym *sym_pool, *sym, *last_sym;
1215 int i;
1217 sym_pool = tcc_malloc(SYM_POOL_NB * sizeof(Sym));
1219 last_sym = sym_free_first;
1220 sym = sym_pool;
1221 for(i = 0; i < SYM_POOL_NB; i++) {
1222 sym->next = last_sym;
1223 last_sym = sym;
1224 sym++;
1226 sym_free_first = last_sym;
1227 return last_sym;
1230 static inline Sym *sym_malloc(void)
1232 Sym *sym;
1233 sym = sym_free_first;
1234 if (!sym)
1235 sym = __sym_malloc();
1236 sym_free_first = sym->next;
1237 return sym;
1240 static inline void sym_free(Sym *sym)
1242 sym->next = sym_free_first;
1243 sym_free_first = sym;
1246 Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags)
1248 Section *sec;
1250 sec = tcc_mallocz(sizeof(Section) + strlen(name));
1251 strcpy(sec->name, name);
1252 sec->sh_type = sh_type;
1253 sec->sh_flags = sh_flags;
1254 switch(sh_type) {
1255 case SHT_HASH:
1256 case SHT_REL:
1257 case SHT_DYNSYM:
1258 case SHT_SYMTAB:
1259 case SHT_DYNAMIC:
1260 sec->sh_addralign = 4;
1261 break;
1262 case SHT_STRTAB:
1263 sec->sh_addralign = 1;
1264 break;
1265 default:
1266 sec->sh_addralign = 32; /* default conservative alignment */
1267 break;
1270 /* only add section if not private */
1271 if (!(sh_flags & SHF_PRIVATE)) {
1272 sec->sh_num = s1->nb_sections;
1273 dynarray_add((void ***)&s1->sections, &s1->nb_sections, sec);
1275 return sec;
1278 static void free_section(Section *s)
1280 tcc_free(s->data);
1281 tcc_free(s);
1284 /* realloc section and set its content to zero */
1285 static void section_realloc(Section *sec, unsigned long new_size)
1287 unsigned long size;
1288 unsigned char *data;
1290 size = sec->data_allocated;
1291 if (size == 0)
1292 size = 1;
1293 while (size < new_size)
1294 size = size * 2;
1295 data = tcc_realloc(sec->data, size);
1296 if (!data)
1297 error("memory full");
1298 memset(data + sec->data_allocated, 0, size - sec->data_allocated);
1299 sec->data = data;
1300 sec->data_allocated = size;
1303 /* reserve at least 'size' bytes in section 'sec' from
1304 sec->data_offset. */
1305 static void *section_ptr_add(Section *sec, unsigned long size)
1307 unsigned long offset, offset1;
1309 offset = sec->data_offset;
1310 offset1 = offset + size;
1311 if (offset1 > sec->data_allocated)
1312 section_realloc(sec, offset1);
1313 sec->data_offset = offset1;
1314 return sec->data + offset;
1317 /* return a reference to a section, and create it if it does not
1318 exists */
1319 Section *find_section(TCCState *s1, const char *name)
1321 Section *sec;
1322 int i;
1323 for(i = 1; i < s1->nb_sections; i++) {
1324 sec = s1->sections[i];
1325 if (!strcmp(name, sec->name))
1326 return sec;
1328 /* sections are created as PROGBITS */
1329 return new_section(s1, name, SHT_PROGBITS, SHF_ALLOC);
1332 #define SECTION_ABS ((void *)1)
1334 /* update sym->c so that it points to an external symbol in section
1335 'section' with value 'value' */
1336 static void put_extern_sym2(Sym *sym, Section *section,
1337 unsigned long value, unsigned long size,
1338 int can_add_underscore)
1340 int sym_type, sym_bind, sh_num, info, other, attr;
1341 Elf32_Sym *esym;
1342 const char *name;
1343 char buf1[256];
1345 if (section == NULL)
1346 sh_num = SHN_UNDEF;
1347 else if (section == SECTION_ABS)
1348 sh_num = SHN_ABS;
1349 else
1350 sh_num = section->sh_num;
1352 other = attr = 0;
1354 if ((sym->type.t & VT_BTYPE) == VT_FUNC) {
1355 sym_type = STT_FUNC;
1356 #ifdef TCC_TARGET_PE
1357 if (sym->type.ref)
1358 attr = sym->type.ref->r;
1359 if (FUNC_EXPORT(attr))
1360 other |= 1;
1361 if (FUNC_CALL(attr) == FUNC_STDCALL)
1362 other |= 2;
1363 #endif
1364 } else {
1365 sym_type = STT_OBJECT;
1368 if (sym->type.t & VT_STATIC)
1369 sym_bind = STB_LOCAL;
1370 else
1371 sym_bind = STB_GLOBAL;
1373 if (!sym->c) {
1374 name = get_tok_str(sym->v, NULL);
1375 #ifdef CONFIG_TCC_BCHECK
1376 if (do_bounds_check) {
1377 char buf[32];
1379 /* XXX: avoid doing that for statics ? */
1380 /* if bound checking is activated, we change some function
1381 names by adding the "__bound" prefix */
1382 switch(sym->v) {
1383 #if 0
1384 /* XXX: we rely only on malloc hooks */
1385 case TOK_malloc:
1386 case TOK_free:
1387 case TOK_realloc:
1388 case TOK_memalign:
1389 case TOK_calloc:
1390 #endif
1391 case TOK_memcpy:
1392 case TOK_memmove:
1393 case TOK_memset:
1394 case TOK_strlen:
1395 case TOK_strcpy:
1396 case TOK__alloca:
1397 strcpy(buf, "__bound_");
1398 strcat(buf, name);
1399 name = buf;
1400 break;
1403 #endif
1405 #ifdef TCC_TARGET_PE
1406 if ((other & 2) && can_add_underscore) {
1407 sprintf(buf1, "_%s@%d", name, FUNC_ARGS(attr));
1408 name = buf1;
1409 } else
1410 #endif
1411 if (tcc_state->leading_underscore && can_add_underscore) {
1412 buf1[0] = '_';
1413 pstrcpy(buf1 + 1, sizeof(buf1) - 1, name);
1414 name = buf1;
1416 info = ELF32_ST_INFO(sym_bind, sym_type);
1417 sym->c = add_elf_sym(symtab_section, value, size, info, other, sh_num, name);
1418 } else {
1419 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
1420 esym->st_value = value;
1421 esym->st_size = size;
1422 esym->st_shndx = sh_num;
1423 esym->st_other |= other;
1427 static void put_extern_sym(Sym *sym, Section *section,
1428 unsigned long value, unsigned long size)
1430 put_extern_sym2(sym, section, value, size, 1);
1433 /* add a new relocation entry to symbol 'sym' in section 's' */
1434 static void greloc(Section *s, Sym *sym, unsigned long offset, int type)
1436 if (!sym->c)
1437 put_extern_sym(sym, NULL, 0, 0);
1438 /* now we can add ELF relocation info */
1439 put_elf_reloc(symtab_section, s, offset, type, sym->c);
1442 static inline int isid(int c)
1444 return (c >= 'a' && c <= 'z') ||
1445 (c >= 'A' && c <= 'Z') ||
1446 c == '_';
1449 static inline int isnum(int c)
1451 return c >= '0' && c <= '9';
1454 static inline int isoct(int c)
1456 return c >= '0' && c <= '7';
1459 static inline int toup(int c)
1461 if (c >= 'a' && c <= 'z')
1462 return c - 'a' + 'A';
1463 else
1464 return c;
1467 static void strcat_vprintf(char *buf, int buf_size, const char *fmt, va_list ap)
1469 int len;
1470 len = strlen(buf);
1471 vsnprintf(buf + len, buf_size - len, fmt, ap);
1474 static void strcat_printf(char *buf, int buf_size, const char *fmt, ...)
1476 va_list ap;
1477 va_start(ap, fmt);
1478 strcat_vprintf(buf, buf_size, fmt, ap);
1479 va_end(ap);
1482 void error1(TCCState *s1, int is_warning, const char *fmt, va_list ap)
1484 char buf[2048];
1485 BufferedFile **f;
1487 buf[0] = '\0';
1488 if (file) {
1489 for(f = s1->include_stack; f < s1->include_stack_ptr; f++)
1490 strcat_printf(buf, sizeof(buf), "In file included from %s:%d:\n",
1491 (*f)->filename, (*f)->line_num);
1492 if (file->line_num > 0) {
1493 strcat_printf(buf, sizeof(buf),
1494 "%s:%d: ", file->filename, file->line_num);
1495 } else {
1496 strcat_printf(buf, sizeof(buf),
1497 "%s: ", file->filename);
1499 } else {
1500 strcat_printf(buf, sizeof(buf),
1501 "tcc: ");
1503 if (is_warning)
1504 strcat_printf(buf, sizeof(buf), "warning: ");
1505 strcat_vprintf(buf, sizeof(buf), fmt, ap);
1507 if (!s1->error_func) {
1508 /* default case: stderr */
1509 fprintf(stderr, "%s\n", buf);
1510 } else {
1511 s1->error_func(s1->error_opaque, buf);
1513 if (!is_warning || s1->warn_error)
1514 s1->nb_errors++;
1517 #ifdef LIBTCC
1518 void tcc_set_error_func(TCCState *s, void *error_opaque,
1519 void (*error_func)(void *opaque, const char *msg))
1521 s->error_opaque = error_opaque;
1522 s->error_func = error_func;
1524 #endif
1526 /* error without aborting current compilation */
1527 void error_noabort(const char *fmt, ...)
1529 TCCState *s1 = tcc_state;
1530 va_list ap;
1532 va_start(ap, fmt);
1533 error1(s1, 0, fmt, ap);
1534 va_end(ap);
1537 void error(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);
1545 /* better than nothing: in some cases, we accept to handle errors */
1546 if (s1->error_set_jmp_enabled) {
1547 longjmp(s1->error_jmp_buf, 1);
1548 } else {
1549 /* XXX: eliminate this someday */
1550 exit(1);
1554 void expect(const char *msg)
1556 error("%s expected", msg);
1559 void warning(const char *fmt, ...)
1561 TCCState *s1 = tcc_state;
1562 va_list ap;
1564 if (s1->warn_none)
1565 return;
1567 va_start(ap, fmt);
1568 error1(s1, 1, fmt, ap);
1569 va_end(ap);
1572 void skip(int c)
1574 if (tok != c)
1575 error("'%c' expected", c);
1576 next();
1579 static void test_lvalue(void)
1581 if (!(vtop->r & VT_LVAL))
1582 expect("lvalue");
1585 /* allocate a new token */
1586 static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len)
1588 TokenSym *ts, **ptable;
1589 int i;
1591 if (tok_ident >= SYM_FIRST_ANOM)
1592 error("memory full");
1594 /* expand token table if needed */
1595 i = tok_ident - TOK_IDENT;
1596 if ((i % TOK_ALLOC_INCR) == 0) {
1597 ptable = tcc_realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *));
1598 if (!ptable)
1599 error("memory full");
1600 table_ident = ptable;
1603 ts = tcc_malloc(sizeof(TokenSym) + len);
1604 table_ident[i] = ts;
1605 ts->tok = tok_ident++;
1606 ts->sym_define = NULL;
1607 ts->sym_label = NULL;
1608 ts->sym_struct = NULL;
1609 ts->sym_identifier = NULL;
1610 ts->len = len;
1611 ts->hash_next = NULL;
1612 memcpy(ts->str, str, len);
1613 ts->str[len] = '\0';
1614 *pts = ts;
1615 return ts;
1618 #define TOK_HASH_INIT 1
1619 #define TOK_HASH_FUNC(h, c) ((h) * 263 + (c))
1621 /* find a token and add it if not found */
1622 static TokenSym *tok_alloc(const char *str, int len)
1624 TokenSym *ts, **pts;
1625 int i;
1626 unsigned int h;
1628 h = TOK_HASH_INIT;
1629 for(i=0;i<len;i++)
1630 h = TOK_HASH_FUNC(h, ((unsigned char *)str)[i]);
1631 h &= (TOK_HASH_SIZE - 1);
1633 pts = &hash_ident[h];
1634 for(;;) {
1635 ts = *pts;
1636 if (!ts)
1637 break;
1638 if (ts->len == len && !memcmp(ts->str, str, len))
1639 return ts;
1640 pts = &(ts->hash_next);
1642 return tok_alloc_new(pts, str, len);
1645 /* CString handling */
1647 static void cstr_realloc(CString *cstr, int new_size)
1649 int size;
1650 void *data;
1652 size = cstr->size_allocated;
1653 if (size == 0)
1654 size = 8; /* no need to allocate a too small first string */
1655 while (size < new_size)
1656 size = size * 2;
1657 data = tcc_realloc(cstr->data_allocated, size);
1658 if (!data)
1659 error("memory full");
1660 cstr->data_allocated = data;
1661 cstr->size_allocated = size;
1662 cstr->data = data;
1665 /* add a byte */
1666 static inline void cstr_ccat(CString *cstr, int ch)
1668 int size;
1669 size = cstr->size + 1;
1670 if (size > cstr->size_allocated)
1671 cstr_realloc(cstr, size);
1672 ((unsigned char *)cstr->data)[size - 1] = ch;
1673 cstr->size = size;
1676 static void cstr_cat(CString *cstr, const char *str)
1678 int c;
1679 for(;;) {
1680 c = *str;
1681 if (c == '\0')
1682 break;
1683 cstr_ccat(cstr, c);
1684 str++;
1688 /* add a wide char */
1689 static void cstr_wccat(CString *cstr, int ch)
1691 int size;
1692 size = cstr->size + sizeof(nwchar_t);
1693 if (size > cstr->size_allocated)
1694 cstr_realloc(cstr, size);
1695 *(nwchar_t *)(((unsigned char *)cstr->data) + size - sizeof(nwchar_t)) = ch;
1696 cstr->size = size;
1699 static void cstr_new(CString *cstr)
1701 memset(cstr, 0, sizeof(CString));
1704 /* free string and reset it to NULL */
1705 static void cstr_free(CString *cstr)
1707 tcc_free(cstr->data_allocated);
1708 cstr_new(cstr);
1711 #define cstr_reset(cstr) cstr_free(cstr)
1713 /* XXX: unicode ? */
1714 static void add_char(CString *cstr, int c)
1716 if (c == '\'' || c == '\"' || c == '\\') {
1717 /* XXX: could be more precise if char or string */
1718 cstr_ccat(cstr, '\\');
1720 if (c >= 32 && c <= 126) {
1721 cstr_ccat(cstr, c);
1722 } else {
1723 cstr_ccat(cstr, '\\');
1724 if (c == '\n') {
1725 cstr_ccat(cstr, 'n');
1726 } else {
1727 cstr_ccat(cstr, '0' + ((c >> 6) & 7));
1728 cstr_ccat(cstr, '0' + ((c >> 3) & 7));
1729 cstr_ccat(cstr, '0' + (c & 7));
1734 /* XXX: buffer overflow */
1735 /* XXX: float tokens */
1736 char *get_tok_str(int v, CValue *cv)
1738 static char buf[STRING_MAX_SIZE + 1];
1739 static CString cstr_buf;
1740 CString *cstr;
1741 unsigned char *q;
1742 char *p;
1743 int i, len;
1745 /* NOTE: to go faster, we give a fixed buffer for small strings */
1746 cstr_reset(&cstr_buf);
1747 cstr_buf.data = buf;
1748 cstr_buf.size_allocated = sizeof(buf);
1749 p = buf;
1751 switch(v) {
1752 case TOK_CINT:
1753 case TOK_CUINT:
1754 /* XXX: not quite exact, but only useful for testing */
1755 sprintf(p, "%u", cv->ui);
1756 break;
1757 case TOK_CLLONG:
1758 case TOK_CULLONG:
1759 /* XXX: not quite exact, but only useful for testing */
1760 sprintf(p, "%Lu", cv->ull);
1761 break;
1762 case TOK_CCHAR:
1763 case TOK_LCHAR:
1764 cstr_ccat(&cstr_buf, '\'');
1765 add_char(&cstr_buf, cv->i);
1766 cstr_ccat(&cstr_buf, '\'');
1767 cstr_ccat(&cstr_buf, '\0');
1768 break;
1769 case TOK_PPNUM:
1770 cstr = cv->cstr;
1771 len = cstr->size - 1;
1772 for(i=0;i<len;i++)
1773 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1774 cstr_ccat(&cstr_buf, '\0');
1775 break;
1776 case TOK_STR:
1777 case TOK_LSTR:
1778 cstr = cv->cstr;
1779 cstr_ccat(&cstr_buf, '\"');
1780 if (v == TOK_STR) {
1781 len = cstr->size - 1;
1782 for(i=0;i<len;i++)
1783 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1784 } else {
1785 len = (cstr->size / sizeof(nwchar_t)) - 1;
1786 for(i=0;i<len;i++)
1787 add_char(&cstr_buf, ((nwchar_t *)cstr->data)[i]);
1789 cstr_ccat(&cstr_buf, '\"');
1790 cstr_ccat(&cstr_buf, '\0');
1791 break;
1792 case TOK_LT:
1793 v = '<';
1794 goto addv;
1795 case TOK_GT:
1796 v = '>';
1797 goto addv;
1798 case TOK_DOTS:
1799 return strcpy(p, "...");
1800 case TOK_A_SHL:
1801 return strcpy(p, "<<=");
1802 case TOK_A_SAR:
1803 return strcpy(p, ">>=");
1804 default:
1805 if (v < TOK_IDENT) {
1806 /* search in two bytes table */
1807 q = tok_two_chars;
1808 while (*q) {
1809 if (q[2] == v) {
1810 *p++ = q[0];
1811 *p++ = q[1];
1812 *p = '\0';
1813 return buf;
1815 q += 3;
1817 addv:
1818 *p++ = v;
1819 *p = '\0';
1820 } else if (v < tok_ident) {
1821 return table_ident[v - TOK_IDENT]->str;
1822 } else if (v >= SYM_FIRST_ANOM) {
1823 /* special name for anonymous symbol */
1824 sprintf(p, "L.%u", v - SYM_FIRST_ANOM);
1825 } else {
1826 /* should never happen */
1827 return NULL;
1829 break;
1831 return cstr_buf.data;
1834 /* push, without hashing */
1835 static Sym *sym_push2(Sym **ps, int v, int t, int c)
1837 Sym *s;
1838 s = sym_malloc();
1839 s->v = v;
1840 s->type.t = t;
1841 s->c = c;
1842 s->next = NULL;
1843 /* add in stack */
1844 s->prev = *ps;
1845 *ps = s;
1846 return s;
1849 /* find a symbol and return its associated structure. 's' is the top
1850 of the symbol stack */
1851 static Sym *sym_find2(Sym *s, int v)
1853 while (s) {
1854 if (s->v == v)
1855 return s;
1856 s = s->prev;
1858 return NULL;
1861 /* structure lookup */
1862 static inline Sym *struct_find(int v)
1864 v -= TOK_IDENT;
1865 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1866 return NULL;
1867 return table_ident[v]->sym_struct;
1870 /* find an identifier */
1871 static inline Sym *sym_find(int v)
1873 v -= TOK_IDENT;
1874 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1875 return NULL;
1876 return table_ident[v]->sym_identifier;
1879 /* push a given symbol on the symbol stack */
1880 static Sym *sym_push(int v, CType *type, int r, int c)
1882 Sym *s, **ps;
1883 TokenSym *ts;
1885 if (local_stack)
1886 ps = &local_stack;
1887 else
1888 ps = &global_stack;
1889 s = sym_push2(ps, v, type->t, c);
1890 s->type.ref = type->ref;
1891 s->r = r;
1892 /* don't record fields or anonymous symbols */
1893 /* XXX: simplify */
1894 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1895 /* record symbol in token array */
1896 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1897 if (v & SYM_STRUCT)
1898 ps = &ts->sym_struct;
1899 else
1900 ps = &ts->sym_identifier;
1901 s->prev_tok = *ps;
1902 *ps = s;
1904 return s;
1907 /* push a global identifier */
1908 static Sym *global_identifier_push(int v, int t, int c)
1910 Sym *s, **ps;
1911 s = sym_push2(&global_stack, v, t, c);
1912 /* don't record anonymous symbol */
1913 if (v < SYM_FIRST_ANOM) {
1914 ps = &table_ident[v - TOK_IDENT]->sym_identifier;
1915 /* modify the top most local identifier, so that
1916 sym_identifier will point to 's' when popped */
1917 while (*ps != NULL)
1918 ps = &(*ps)->prev_tok;
1919 s->prev_tok = NULL;
1920 *ps = s;
1922 return s;
1925 /* pop symbols until top reaches 'b' */
1926 static void sym_pop(Sym **ptop, Sym *b)
1928 Sym *s, *ss, **ps;
1929 TokenSym *ts;
1930 int v;
1932 s = *ptop;
1933 while(s != b) {
1934 ss = s->prev;
1935 v = s->v;
1936 /* remove symbol in token array */
1937 /* XXX: simplify */
1938 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1939 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1940 if (v & SYM_STRUCT)
1941 ps = &ts->sym_struct;
1942 else
1943 ps = &ts->sym_identifier;
1944 *ps = s->prev_tok;
1946 sym_free(s);
1947 s = ss;
1949 *ptop = b;
1952 /* I/O layer */
1954 BufferedFile *tcc_open(TCCState *s1, const char *filename)
1956 int fd;
1957 BufferedFile *bf;
1959 fd = open(filename, O_RDONLY | O_BINARY);
1960 if (fd < 0)
1961 return NULL;
1962 bf = tcc_malloc(sizeof(BufferedFile));
1963 if (!bf) {
1964 close(fd);
1965 return NULL;
1967 bf->fd = fd;
1968 bf->buf_ptr = bf->buffer;
1969 bf->buf_end = bf->buffer;
1970 bf->buffer[0] = CH_EOB; /* put eob symbol */
1971 pstrcpy(bf->filename, sizeof(bf->filename), filename);
1972 #ifdef _WIN32
1973 normalize_slashes(bf->filename);
1974 #endif
1975 bf->line_num = 1;
1976 bf->ifndef_macro = 0;
1977 bf->ifdef_stack_ptr = s1->ifdef_stack_ptr;
1978 // printf("opening '%s'\n", filename);
1979 return bf;
1982 void tcc_close(BufferedFile *bf)
1984 total_lines += bf->line_num;
1985 close(bf->fd);
1986 tcc_free(bf);
1989 /* fill input buffer and peek next char */
1990 static int tcc_peekc_slow(BufferedFile *bf)
1992 int len;
1993 /* only tries to read if really end of buffer */
1994 if (bf->buf_ptr >= bf->buf_end) {
1995 if (bf->fd != -1) {
1996 #if defined(PARSE_DEBUG)
1997 len = 8;
1998 #else
1999 len = IO_BUF_SIZE;
2000 #endif
2001 len = read(bf->fd, bf->buffer, len);
2002 if (len < 0)
2003 len = 0;
2004 } else {
2005 len = 0;
2007 total_bytes += len;
2008 bf->buf_ptr = bf->buffer;
2009 bf->buf_end = bf->buffer + len;
2010 *bf->buf_end = CH_EOB;
2012 if (bf->buf_ptr < bf->buf_end) {
2013 return bf->buf_ptr[0];
2014 } else {
2015 bf->buf_ptr = bf->buf_end;
2016 return CH_EOF;
2020 /* return the current character, handling end of block if necessary
2021 (but not stray) */
2022 static int handle_eob(void)
2024 return tcc_peekc_slow(file);
2027 /* read next char from current input file and handle end of input buffer */
2028 static inline void inp(void)
2030 ch = *(++(file->buf_ptr));
2031 /* end of buffer/file handling */
2032 if (ch == CH_EOB)
2033 ch = handle_eob();
2036 /* handle '\[\r]\n' */
2037 static int handle_stray_noerror(void)
2039 while (ch == '\\') {
2040 inp();
2041 if (ch == '\n') {
2042 file->line_num++;
2043 inp();
2044 } else if (ch == '\r') {
2045 inp();
2046 if (ch != '\n')
2047 goto fail;
2048 file->line_num++;
2049 inp();
2050 } else {
2051 fail:
2052 return 1;
2055 return 0;
2058 static void handle_stray(void)
2060 if (handle_stray_noerror())
2061 error("stray '\\' in program");
2064 /* skip the stray and handle the \\n case. Output an error if
2065 incorrect char after the stray */
2066 static int handle_stray1(uint8_t *p)
2068 int c;
2070 if (p >= file->buf_end) {
2071 file->buf_ptr = p;
2072 c = handle_eob();
2073 p = file->buf_ptr;
2074 if (c == '\\')
2075 goto parse_stray;
2076 } else {
2077 parse_stray:
2078 file->buf_ptr = p;
2079 ch = *p;
2080 handle_stray();
2081 p = file->buf_ptr;
2082 c = *p;
2084 return c;
2087 /* handle just the EOB case, but not stray */
2088 #define PEEKC_EOB(c, p)\
2090 p++;\
2091 c = *p;\
2092 if (c == '\\') {\
2093 file->buf_ptr = p;\
2094 c = handle_eob();\
2095 p = file->buf_ptr;\
2099 /* handle the complicated stray case */
2100 #define PEEKC(c, p)\
2102 p++;\
2103 c = *p;\
2104 if (c == '\\') {\
2105 c = handle_stray1(p);\
2106 p = file->buf_ptr;\
2110 /* input with '\[\r]\n' handling. Note that this function cannot
2111 handle other characters after '\', so you cannot call it inside
2112 strings or comments */
2113 static void minp(void)
2115 inp();
2116 if (ch == '\\')
2117 handle_stray();
2121 /* single line C++ comments */
2122 static uint8_t *parse_line_comment(uint8_t *p)
2124 int c;
2126 p++;
2127 for(;;) {
2128 c = *p;
2129 redo:
2130 if (c == '\n' || c == CH_EOF) {
2131 break;
2132 } else if (c == '\\') {
2133 file->buf_ptr = p;
2134 c = handle_eob();
2135 p = file->buf_ptr;
2136 if (c == '\\') {
2137 PEEKC_EOB(c, p);
2138 if (c == '\n') {
2139 file->line_num++;
2140 PEEKC_EOB(c, p);
2141 } else if (c == '\r') {
2142 PEEKC_EOB(c, p);
2143 if (c == '\n') {
2144 file->line_num++;
2145 PEEKC_EOB(c, p);
2148 } else {
2149 goto redo;
2151 } else {
2152 p++;
2155 return p;
2158 /* C comments */
2159 static uint8_t *parse_comment(uint8_t *p)
2161 int c;
2163 p++;
2164 for(;;) {
2165 /* fast skip loop */
2166 for(;;) {
2167 c = *p;
2168 if (c == '\n' || c == '*' || c == '\\')
2169 break;
2170 p++;
2171 c = *p;
2172 if (c == '\n' || c == '*' || c == '\\')
2173 break;
2174 p++;
2176 /* now we can handle all the cases */
2177 if (c == '\n') {
2178 file->line_num++;
2179 p++;
2180 } else if (c == '*') {
2181 p++;
2182 for(;;) {
2183 c = *p;
2184 if (c == '*') {
2185 p++;
2186 } else if (c == '/') {
2187 goto end_of_comment;
2188 } else if (c == '\\') {
2189 file->buf_ptr = p;
2190 c = handle_eob();
2191 p = file->buf_ptr;
2192 if (c == '\\') {
2193 /* skip '\[\r]\n', otherwise just skip the stray */
2194 while (c == '\\') {
2195 PEEKC_EOB(c, p);
2196 if (c == '\n') {
2197 file->line_num++;
2198 PEEKC_EOB(c, p);
2199 } else if (c == '\r') {
2200 PEEKC_EOB(c, p);
2201 if (c == '\n') {
2202 file->line_num++;
2203 PEEKC_EOB(c, p);
2205 } else {
2206 goto after_star;
2210 } else {
2211 break;
2214 after_star: ;
2215 } else {
2216 /* stray, eob or eof */
2217 file->buf_ptr = p;
2218 c = handle_eob();
2219 p = file->buf_ptr;
2220 if (c == CH_EOF) {
2221 error("unexpected end of file in comment");
2222 } else if (c == '\\') {
2223 p++;
2227 end_of_comment:
2228 p++;
2229 return p;
2232 #define cinp minp
2234 /* space exlcuding newline */
2235 static inline int is_space(int ch)
2237 return ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f' || ch == '\r';
2240 static inline void skip_spaces(void)
2242 while (is_space(ch))
2243 cinp();
2246 /* parse a string without interpreting escapes */
2247 static uint8_t *parse_pp_string(uint8_t *p,
2248 int sep, CString *str)
2250 int c;
2251 p++;
2252 for(;;) {
2253 c = *p;
2254 if (c == sep) {
2255 break;
2256 } else if (c == '\\') {
2257 file->buf_ptr = p;
2258 c = handle_eob();
2259 p = file->buf_ptr;
2260 if (c == CH_EOF) {
2261 unterminated_string:
2262 /* XXX: indicate line number of start of string */
2263 error("missing terminating %c character", sep);
2264 } else if (c == '\\') {
2265 /* escape : just skip \[\r]\n */
2266 PEEKC_EOB(c, p);
2267 if (c == '\n') {
2268 file->line_num++;
2269 p++;
2270 } else if (c == '\r') {
2271 PEEKC_EOB(c, p);
2272 if (c != '\n')
2273 expect("'\n' after '\r'");
2274 file->line_num++;
2275 p++;
2276 } else if (c == CH_EOF) {
2277 goto unterminated_string;
2278 } else {
2279 if (str) {
2280 cstr_ccat(str, '\\');
2281 cstr_ccat(str, c);
2283 p++;
2286 } else if (c == '\n') {
2287 file->line_num++;
2288 goto add_char;
2289 } else if (c == '\r') {
2290 PEEKC_EOB(c, p);
2291 if (c != '\n') {
2292 if (str)
2293 cstr_ccat(str, '\r');
2294 } else {
2295 file->line_num++;
2296 goto add_char;
2298 } else {
2299 add_char:
2300 if (str)
2301 cstr_ccat(str, c);
2302 p++;
2305 p++;
2306 return p;
2309 /* skip block of text until #else, #elif or #endif. skip also pairs of
2310 #if/#endif */
2311 void preprocess_skip(void)
2313 int a, start_of_line, c, in_warn_or_error;
2314 uint8_t *p;
2316 p = file->buf_ptr;
2317 a = 0;
2318 redo_start:
2319 start_of_line = 1;
2320 in_warn_or_error = 0;
2321 for(;;) {
2322 redo_no_start:
2323 c = *p;
2324 switch(c) {
2325 case ' ':
2326 case '\t':
2327 case '\f':
2328 case '\v':
2329 case '\r':
2330 p++;
2331 goto redo_no_start;
2332 case '\n':
2333 file->line_num++;
2334 p++;
2335 goto redo_start;
2336 case '\\':
2337 file->buf_ptr = p;
2338 c = handle_eob();
2339 if (c == CH_EOF) {
2340 expect("#endif");
2341 } else if (c == '\\') {
2342 ch = file->buf_ptr[0];
2343 handle_stray_noerror();
2345 p = file->buf_ptr;
2346 goto redo_no_start;
2347 /* skip strings */
2348 case '\"':
2349 case '\'':
2350 if (in_warn_or_error)
2351 goto _default;
2352 p = parse_pp_string(p, c, NULL);
2353 break;
2354 /* skip comments */
2355 case '/':
2356 if (in_warn_or_error)
2357 goto _default;
2358 file->buf_ptr = p;
2359 ch = *p;
2360 minp();
2361 p = file->buf_ptr;
2362 if (ch == '*') {
2363 p = parse_comment(p);
2364 } else if (ch == '/') {
2365 p = parse_line_comment(p);
2367 break;
2368 case '#':
2369 p++;
2370 if (start_of_line) {
2371 file->buf_ptr = p;
2372 next_nomacro();
2373 p = file->buf_ptr;
2374 if (a == 0 &&
2375 (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
2376 goto the_end;
2377 if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
2378 a++;
2379 else if (tok == TOK_ENDIF)
2380 a--;
2381 else if( tok == TOK_ERROR || tok == TOK_WARNING)
2382 in_warn_or_error = 1;
2384 break;
2385 _default:
2386 default:
2387 p++;
2388 break;
2390 start_of_line = 0;
2392 the_end: ;
2393 file->buf_ptr = p;
2396 /* ParseState handling */
2398 /* XXX: currently, no include file info is stored. Thus, we cannot display
2399 accurate messages if the function or data definition spans multiple
2400 files */
2402 /* save current parse state in 's' */
2403 void save_parse_state(ParseState *s)
2405 s->line_num = file->line_num;
2406 s->macro_ptr = macro_ptr;
2407 s->tok = tok;
2408 s->tokc = tokc;
2411 /* restore parse state from 's' */
2412 void restore_parse_state(ParseState *s)
2414 file->line_num = s->line_num;
2415 macro_ptr = s->macro_ptr;
2416 tok = s->tok;
2417 tokc = s->tokc;
2420 /* return the number of additional 'ints' necessary to store the
2421 token */
2422 static inline int tok_ext_size(int t)
2424 switch(t) {
2425 /* 4 bytes */
2426 case TOK_CINT:
2427 case TOK_CUINT:
2428 case TOK_CCHAR:
2429 case TOK_LCHAR:
2430 case TOK_CFLOAT:
2431 case TOK_LINENUM:
2432 return 1;
2433 case TOK_STR:
2434 case TOK_LSTR:
2435 case TOK_PPNUM:
2436 error("unsupported token");
2437 return 1;
2438 case TOK_CDOUBLE:
2439 case TOK_CLLONG:
2440 case TOK_CULLONG:
2441 return 2;
2442 case TOK_CLDOUBLE:
2443 return LDOUBLE_SIZE / 4;
2444 default:
2445 return 0;
2449 /* token string handling */
2451 static inline void tok_str_new(TokenString *s)
2453 s->str = NULL;
2454 s->len = 0;
2455 s->allocated_len = 0;
2456 s->last_line_num = -1;
2459 static void tok_str_free(int *str)
2461 tcc_free(str);
2464 static int *tok_str_realloc(TokenString *s)
2466 int *str, len;
2468 if (s->allocated_len == 0) {
2469 len = 8;
2470 } else {
2471 len = s->allocated_len * 2;
2473 str = tcc_realloc(s->str, len * sizeof(int));
2474 if (!str)
2475 error("memory full");
2476 s->allocated_len = len;
2477 s->str = str;
2478 return str;
2481 static void tok_str_add(TokenString *s, int t)
2483 int len, *str;
2485 len = s->len;
2486 str = s->str;
2487 if (len >= s->allocated_len)
2488 str = tok_str_realloc(s);
2489 str[len++] = t;
2490 s->len = len;
2493 static void tok_str_add2(TokenString *s, int t, CValue *cv)
2495 int len, *str;
2497 len = s->len;
2498 str = s->str;
2500 /* allocate space for worst case */
2501 if (len + TOK_MAX_SIZE > s->allocated_len)
2502 str = tok_str_realloc(s);
2503 str[len++] = t;
2504 switch(t) {
2505 case TOK_CINT:
2506 case TOK_CUINT:
2507 case TOK_CCHAR:
2508 case TOK_LCHAR:
2509 case TOK_CFLOAT:
2510 case TOK_LINENUM:
2511 str[len++] = cv->tab[0];
2512 break;
2513 case TOK_PPNUM:
2514 case TOK_STR:
2515 case TOK_LSTR:
2517 int nb_words;
2518 CString *cstr;
2520 nb_words = (sizeof(CString) + cv->cstr->size + 3) >> 2;
2521 while ((len + nb_words) > s->allocated_len)
2522 str = tok_str_realloc(s);
2523 cstr = (CString *)(str + len);
2524 cstr->data = NULL;
2525 cstr->size = cv->cstr->size;
2526 cstr->data_allocated = NULL;
2527 cstr->size_allocated = cstr->size;
2528 memcpy((char *)cstr + sizeof(CString),
2529 cv->cstr->data, cstr->size);
2530 len += nb_words;
2532 break;
2533 case TOK_CDOUBLE:
2534 case TOK_CLLONG:
2535 case TOK_CULLONG:
2536 #if LDOUBLE_SIZE == 8
2537 case TOK_CLDOUBLE:
2538 #endif
2539 str[len++] = cv->tab[0];
2540 str[len++] = cv->tab[1];
2541 break;
2542 #if LDOUBLE_SIZE == 12
2543 case TOK_CLDOUBLE:
2544 str[len++] = cv->tab[0];
2545 str[len++] = cv->tab[1];
2546 str[len++] = cv->tab[2];
2547 #elif LDOUBLE_SIZE != 8
2548 #error add long double size support
2549 #endif
2550 break;
2551 default:
2552 break;
2554 s->len = len;
2557 /* add the current parse token in token string 's' */
2558 static void tok_str_add_tok(TokenString *s)
2560 CValue cval;
2562 /* save line number info */
2563 if (file->line_num != s->last_line_num) {
2564 s->last_line_num = file->line_num;
2565 cval.i = s->last_line_num;
2566 tok_str_add2(s, TOK_LINENUM, &cval);
2568 tok_str_add2(s, tok, &tokc);
2571 #if LDOUBLE_SIZE == 12
2572 #define LDOUBLE_GET(p, cv) \
2573 cv.tab[0] = p[0]; \
2574 cv.tab[1] = p[1]; \
2575 cv.tab[2] = p[2];
2576 #elif LDOUBLE_SIZE == 8
2577 #define LDOUBLE_GET(p, cv) \
2578 cv.tab[0] = p[0]; \
2579 cv.tab[1] = p[1];
2580 #else
2581 #error add long double size support
2582 #endif
2585 /* get a token from an integer array and increment pointer
2586 accordingly. we code it as a macro to avoid pointer aliasing. */
2587 #define TOK_GET(t, p, cv) \
2589 t = *p++; \
2590 switch(t) { \
2591 case TOK_CINT: \
2592 case TOK_CUINT: \
2593 case TOK_CCHAR: \
2594 case TOK_LCHAR: \
2595 case TOK_CFLOAT: \
2596 case TOK_LINENUM: \
2597 cv.tab[0] = *p++; \
2598 break; \
2599 case TOK_STR: \
2600 case TOK_LSTR: \
2601 case TOK_PPNUM: \
2602 cv.cstr = (CString *)p; \
2603 cv.cstr->data = (char *)p + sizeof(CString);\
2604 p += (sizeof(CString) + cv.cstr->size + 3) >> 2;\
2605 break; \
2606 case TOK_CDOUBLE: \
2607 case TOK_CLLONG: \
2608 case TOK_CULLONG: \
2609 cv.tab[0] = p[0]; \
2610 cv.tab[1] = p[1]; \
2611 p += 2; \
2612 break; \
2613 case TOK_CLDOUBLE: \
2614 LDOUBLE_GET(p, cv); \
2615 p += LDOUBLE_SIZE / 4; \
2616 break; \
2617 default: \
2618 break; \
2622 /* defines handling */
2623 static inline void define_push(int v, int macro_type, int *str, Sym *first_arg)
2625 Sym *s;
2627 s = sym_push2(&define_stack, v, macro_type, (int)str);
2628 s->next = first_arg;
2629 table_ident[v - TOK_IDENT]->sym_define = s;
2632 /* undefined a define symbol. Its name is just set to zero */
2633 static void define_undef(Sym *s)
2635 int v;
2636 v = s->v;
2637 if (v >= TOK_IDENT && v < tok_ident)
2638 table_ident[v - TOK_IDENT]->sym_define = NULL;
2639 s->v = 0;
2642 static inline Sym *define_find(int v)
2644 v -= TOK_IDENT;
2645 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2646 return NULL;
2647 return table_ident[v]->sym_define;
2650 /* free define stack until top reaches 'b' */
2651 static void free_defines(Sym *b)
2653 Sym *top, *top1;
2654 int v;
2656 top = define_stack;
2657 while (top != b) {
2658 top1 = top->prev;
2659 /* do not free args or predefined defines */
2660 if (top->c)
2661 tok_str_free((int *)top->c);
2662 v = top->v;
2663 if (v >= TOK_IDENT && v < tok_ident)
2664 table_ident[v - TOK_IDENT]->sym_define = NULL;
2665 sym_free(top);
2666 top = top1;
2668 define_stack = b;
2671 /* label lookup */
2672 static Sym *label_find(int v)
2674 v -= TOK_IDENT;
2675 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2676 return NULL;
2677 return table_ident[v]->sym_label;
2680 static Sym *label_push(Sym **ptop, int v, int flags)
2682 Sym *s, **ps;
2683 s = sym_push2(ptop, v, 0, 0);
2684 s->r = flags;
2685 ps = &table_ident[v - TOK_IDENT]->sym_label;
2686 if (ptop == &global_label_stack) {
2687 /* modify the top most local identifier, so that
2688 sym_identifier will point to 's' when popped */
2689 while (*ps != NULL)
2690 ps = &(*ps)->prev_tok;
2692 s->prev_tok = *ps;
2693 *ps = s;
2694 return s;
2697 /* pop labels until element last is reached. Look if any labels are
2698 undefined. Define symbols if '&&label' was used. */
2699 static void label_pop(Sym **ptop, Sym *slast)
2701 Sym *s, *s1;
2702 for(s = *ptop; s != slast; s = s1) {
2703 s1 = s->prev;
2704 if (s->r == LABEL_DECLARED) {
2705 warning("label '%s' declared but not used", get_tok_str(s->v, NULL));
2706 } else if (s->r == LABEL_FORWARD) {
2707 error("label '%s' used but not defined",
2708 get_tok_str(s->v, NULL));
2709 } else {
2710 if (s->c) {
2711 /* define corresponding symbol. A size of
2712 1 is put. */
2713 put_extern_sym(s, cur_text_section, (long)s->next, 1);
2716 /* remove label */
2717 table_ident[s->v - TOK_IDENT]->sym_label = s->prev_tok;
2718 sym_free(s);
2720 *ptop = slast;
2723 /* eval an expression for #if/#elif */
2724 static int expr_preprocess(void)
2726 int c, t;
2727 TokenString str;
2729 tok_str_new(&str);
2730 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2731 next(); /* do macro subst */
2732 if (tok == TOK_DEFINED) {
2733 next_nomacro();
2734 t = tok;
2735 if (t == '(')
2736 next_nomacro();
2737 c = define_find(tok) != 0;
2738 if (t == '(')
2739 next_nomacro();
2740 tok = TOK_CINT;
2741 tokc.i = c;
2742 } else if (tok >= TOK_IDENT) {
2743 /* if undefined macro */
2744 tok = TOK_CINT;
2745 tokc.i = 0;
2747 tok_str_add_tok(&str);
2749 tok_str_add(&str, -1); /* simulate end of file */
2750 tok_str_add(&str, 0);
2751 /* now evaluate C constant expression */
2752 macro_ptr = str.str;
2753 next();
2754 c = expr_const();
2755 macro_ptr = NULL;
2756 tok_str_free(str.str);
2757 return c != 0;
2760 #if defined(PARSE_DEBUG) || defined(PP_DEBUG)
2761 static void tok_print(int *str)
2763 int t;
2764 CValue cval;
2766 while (1) {
2767 TOK_GET(t, str, cval);
2768 if (!t)
2769 break;
2770 printf(" %s", get_tok_str(t, &cval));
2772 printf("\n");
2774 #endif
2776 /* parse after #define */
2777 static void parse_define(void)
2779 Sym *s, *first, **ps;
2780 int v, t, varg, is_vaargs, c;
2781 TokenString str;
2783 v = tok;
2784 if (v < TOK_IDENT)
2785 error("invalid macro name '%s'", get_tok_str(tok, &tokc));
2786 /* XXX: should check if same macro (ANSI) */
2787 first = NULL;
2788 t = MACRO_OBJ;
2789 /* '(' must be just after macro definition for MACRO_FUNC */
2790 c = file->buf_ptr[0];
2791 if (c == '\\')
2792 c = handle_stray1(file->buf_ptr);
2793 if (c == '(') {
2794 next_nomacro();
2795 next_nomacro();
2796 ps = &first;
2797 while (tok != ')') {
2798 varg = tok;
2799 next_nomacro();
2800 is_vaargs = 0;
2801 if (varg == TOK_DOTS) {
2802 varg = TOK___VA_ARGS__;
2803 is_vaargs = 1;
2804 } else if (tok == TOK_DOTS && gnu_ext) {
2805 is_vaargs = 1;
2806 next_nomacro();
2808 if (varg < TOK_IDENT)
2809 error("badly punctuated parameter list");
2810 s = sym_push2(&define_stack, varg | SYM_FIELD, is_vaargs, 0);
2811 *ps = s;
2812 ps = &s->next;
2813 if (tok != ',')
2814 break;
2815 next_nomacro();
2817 t = MACRO_FUNC;
2819 tok_str_new(&str);
2820 next_nomacro();
2821 /* EOF testing necessary for '-D' handling */
2822 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2823 tok_str_add2(&str, tok, &tokc);
2824 next_nomacro();
2826 tok_str_add(&str, 0);
2827 #ifdef PP_DEBUG
2828 printf("define %s %d: ", get_tok_str(v, NULL), t);
2829 tok_print(str.str);
2830 #endif
2831 define_push(v, t, str.str, first);
2834 static inline int hash_cached_include(int type, const char *filename)
2836 const unsigned char *s;
2837 unsigned int h;
2839 h = TOK_HASH_INIT;
2840 h = TOK_HASH_FUNC(h, type);
2841 s = filename;
2842 while (*s) {
2843 h = TOK_HASH_FUNC(h, *s);
2844 s++;
2846 h &= (CACHED_INCLUDES_HASH_SIZE - 1);
2847 return h;
2850 /* XXX: use a token or a hash table to accelerate matching ? */
2851 static CachedInclude *search_cached_include(TCCState *s1,
2852 int type, const char *filename)
2854 CachedInclude *e;
2855 int i, h;
2856 h = hash_cached_include(type, filename);
2857 i = s1->cached_includes_hash[h];
2858 for(;;) {
2859 if (i == 0)
2860 break;
2861 e = s1->cached_includes[i - 1];
2862 if (e->type == type && !strcmp(e->filename, filename))
2863 return e;
2864 i = e->hash_next;
2866 return NULL;
2869 static inline void add_cached_include(TCCState *s1, int type,
2870 const char *filename, int ifndef_macro)
2872 CachedInclude *e;
2873 int h;
2875 if (search_cached_include(s1, type, filename))
2876 return;
2877 #ifdef INC_DEBUG
2878 printf("adding cached '%s' %s\n", filename, get_tok_str(ifndef_macro, NULL));
2879 #endif
2880 e = tcc_malloc(sizeof(CachedInclude) + strlen(filename));
2881 if (!e)
2882 return;
2883 e->type = type;
2884 strcpy(e->filename, filename);
2885 e->ifndef_macro = ifndef_macro;
2886 dynarray_add((void ***)&s1->cached_includes, &s1->nb_cached_includes, e);
2887 /* add in hash table */
2888 h = hash_cached_include(type, filename);
2889 e->hash_next = s1->cached_includes_hash[h];
2890 s1->cached_includes_hash[h] = s1->nb_cached_includes;
2893 static void pragma_parse(TCCState *s1)
2895 int val;
2897 next();
2898 if (tok == TOK_pack) {
2900 This may be:
2901 #pragma pack(1) // set
2902 #pragma pack() // reset to default
2903 #pragma pack(push,1) // push & set
2904 #pragma pack(pop) // restore previous
2906 next();
2907 skip('(');
2908 if (tok == TOK_ASM_pop) {
2909 next();
2910 if (s1->pack_stack_ptr <= s1->pack_stack) {
2911 stk_error:
2912 error("out of pack stack");
2914 s1->pack_stack_ptr--;
2915 } else {
2916 val = 0;
2917 if (tok != ')') {
2918 if (tok == TOK_ASM_push) {
2919 next();
2920 if (s1->pack_stack_ptr >= s1->pack_stack + PACK_STACK_SIZE - 1)
2921 goto stk_error;
2922 s1->pack_stack_ptr++;
2923 skip(',');
2925 if (tok != TOK_CINT) {
2926 pack_error:
2927 error("invalid pack pragma");
2929 val = tokc.i;
2930 if (val < 1 || val > 16 || (val & (val - 1)) != 0)
2931 goto pack_error;
2932 next();
2934 *s1->pack_stack_ptr = val;
2935 skip(')');
2940 /* is_bof is true if first non space token at beginning of file */
2941 static void preprocess(int is_bof)
2943 TCCState *s1 = tcc_state;
2944 int size, i, c, n, saved_parse_flags;
2945 char buf[1024], *q;
2946 char buf1[1024];
2947 BufferedFile *f;
2948 Sym *s;
2949 CachedInclude *e;
2951 saved_parse_flags = parse_flags;
2952 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM |
2953 PARSE_FLAG_LINEFEED;
2954 next_nomacro();
2955 redo:
2956 switch(tok) {
2957 case TOK_DEFINE:
2958 next_nomacro();
2959 parse_define();
2960 break;
2961 case TOK_UNDEF:
2962 next_nomacro();
2963 s = define_find(tok);
2964 /* undefine symbol by putting an invalid name */
2965 if (s)
2966 define_undef(s);
2967 break;
2968 case TOK_INCLUDE:
2969 case TOK_INCLUDE_NEXT:
2970 ch = file->buf_ptr[0];
2971 /* XXX: incorrect if comments : use next_nomacro with a special mode */
2972 skip_spaces();
2973 if (ch == '<') {
2974 c = '>';
2975 goto read_name;
2976 } else if (ch == '\"') {
2977 c = ch;
2978 read_name:
2979 inp();
2980 q = buf;
2981 while (ch != c && ch != '\n' && ch != CH_EOF) {
2982 if ((q - buf) < sizeof(buf) - 1)
2983 *q++ = ch;
2984 if (ch == '\\') {
2985 if (handle_stray_noerror() == 0)
2986 --q;
2987 } else
2988 inp();
2990 *q = '\0';
2991 minp();
2992 #if 0
2993 /* eat all spaces and comments after include */
2994 /* XXX: slightly incorrect */
2995 while (ch1 != '\n' && ch1 != CH_EOF)
2996 inp();
2997 #endif
2998 } else {
2999 /* computed #include : either we have only strings or
3000 we have anything enclosed in '<>' */
3001 next();
3002 buf[0] = '\0';
3003 if (tok == TOK_STR) {
3004 while (tok != TOK_LINEFEED) {
3005 if (tok != TOK_STR) {
3006 include_syntax:
3007 error("'#include' expects \"FILENAME\" or <FILENAME>");
3009 pstrcat(buf, sizeof(buf), (char *)tokc.cstr->data);
3010 next();
3012 c = '\"';
3013 } else {
3014 int len;
3015 while (tok != TOK_LINEFEED) {
3016 pstrcat(buf, sizeof(buf), get_tok_str(tok, &tokc));
3017 next();
3019 len = strlen(buf);
3020 /* check syntax and remove '<>' */
3021 if (len < 2 || buf[0] != '<' || buf[len - 1] != '>')
3022 goto include_syntax;
3023 memmove(buf, buf + 1, len - 2);
3024 buf[len - 2] = '\0';
3025 c = '>';
3029 e = search_cached_include(s1, c, buf);
3030 if (e && define_find(e->ifndef_macro)) {
3031 /* no need to parse the include because the 'ifndef macro'
3032 is defined */
3033 #ifdef INC_DEBUG
3034 printf("%s: skipping %s\n", file->filename, buf);
3035 #endif
3036 } else {
3037 if (c == '\"') {
3038 /* first search in current dir if "header.h" */
3039 size = tcc_basename(file->filename) - file->filename;
3040 if (size > sizeof(buf1) - 1)
3041 size = sizeof(buf1) - 1;
3042 memcpy(buf1, file->filename, size);
3043 buf1[size] = '\0';
3044 pstrcat(buf1, sizeof(buf1), buf);
3045 f = tcc_open(s1, buf1);
3046 if (f) {
3047 if (tok == TOK_INCLUDE_NEXT)
3048 tok = TOK_INCLUDE;
3049 else
3050 goto found;
3053 if (s1->include_stack_ptr >= s1->include_stack + INCLUDE_STACK_SIZE)
3054 error("#include recursion too deep");
3055 /* now search in all the include paths */
3056 n = s1->nb_include_paths + s1->nb_sysinclude_paths;
3057 for(i = 0; i < n; i++) {
3058 const char *path;
3059 if (i < s1->nb_include_paths)
3060 path = s1->include_paths[i];
3061 else
3062 path = s1->sysinclude_paths[i - s1->nb_include_paths];
3063 pstrcpy(buf1, sizeof(buf1), path);
3064 pstrcat(buf1, sizeof(buf1), "/");
3065 pstrcat(buf1, sizeof(buf1), buf);
3066 f = tcc_open(s1, buf1);
3067 if (f) {
3068 if (tok == TOK_INCLUDE_NEXT)
3069 tok = TOK_INCLUDE;
3070 else
3071 goto found;
3074 error("include file '%s' not found", buf);
3075 f = NULL;
3076 found:
3077 #ifdef INC_DEBUG
3078 printf("%s: including %s\n", file->filename, buf1);
3079 #endif
3080 f->inc_type = c;
3081 pstrcpy(f->inc_filename, sizeof(f->inc_filename), buf);
3082 /* push current file in stack */
3083 /* XXX: fix current line init */
3084 *s1->include_stack_ptr++ = file;
3085 file = f;
3086 /* add include file debug info */
3087 if (do_debug) {
3088 put_stabs(file->filename, N_BINCL, 0, 0, 0);
3090 tok_flags |= TOK_FLAG_BOF | TOK_FLAG_BOL;
3091 ch = file->buf_ptr[0];
3092 goto the_end;
3094 break;
3095 case TOK_IFNDEF:
3096 c = 1;
3097 goto do_ifdef;
3098 case TOK_IF:
3099 c = expr_preprocess();
3100 goto do_if;
3101 case TOK_IFDEF:
3102 c = 0;
3103 do_ifdef:
3104 next_nomacro();
3105 if (tok < TOK_IDENT)
3106 error("invalid argument for '#if%sdef'", c ? "n" : "");
3107 if (is_bof) {
3108 if (c) {
3109 #ifdef INC_DEBUG
3110 printf("#ifndef %s\n", get_tok_str(tok, NULL));
3111 #endif
3112 file->ifndef_macro = tok;
3115 c = (define_find(tok) != 0) ^ c;
3116 do_if:
3117 if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE)
3118 error("memory full");
3119 *s1->ifdef_stack_ptr++ = c;
3120 goto test_skip;
3121 case TOK_ELSE:
3122 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
3123 error("#else without matching #if");
3124 if (s1->ifdef_stack_ptr[-1] & 2)
3125 error("#else after #else");
3126 c = (s1->ifdef_stack_ptr[-1] ^= 3);
3127 goto test_skip;
3128 case TOK_ELIF:
3129 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
3130 error("#elif without matching #if");
3131 c = s1->ifdef_stack_ptr[-1];
3132 if (c > 1)
3133 error("#elif after #else");
3134 /* last #if/#elif expression was true: we skip */
3135 if (c == 1)
3136 goto skip;
3137 c = expr_preprocess();
3138 s1->ifdef_stack_ptr[-1] = c;
3139 test_skip:
3140 if (!(c & 1)) {
3141 skip:
3142 preprocess_skip();
3143 is_bof = 0;
3144 goto redo;
3146 break;
3147 case TOK_ENDIF:
3148 if (s1->ifdef_stack_ptr <= file->ifdef_stack_ptr)
3149 error("#endif without matching #if");
3150 s1->ifdef_stack_ptr--;
3151 /* '#ifndef macro' was at the start of file. Now we check if
3152 an '#endif' is exactly at the end of file */
3153 if (file->ifndef_macro &&
3154 s1->ifdef_stack_ptr == file->ifdef_stack_ptr) {
3155 file->ifndef_macro_saved = file->ifndef_macro;
3156 /* need to set to zero to avoid false matches if another
3157 #ifndef at middle of file */
3158 file->ifndef_macro = 0;
3159 while (tok != TOK_LINEFEED)
3160 next_nomacro();
3161 tok_flags |= TOK_FLAG_ENDIF;
3162 goto the_end;
3164 break;
3165 case TOK_LINE:
3166 next();
3167 if (tok != TOK_CINT)
3168 error("#line");
3169 file->line_num = tokc.i - 1; /* the line number will be incremented after */
3170 next();
3171 if (tok != TOK_LINEFEED) {
3172 if (tok != TOK_STR)
3173 error("#line");
3174 pstrcpy(file->filename, sizeof(file->filename),
3175 (char *)tokc.cstr->data);
3177 break;
3178 case TOK_ERROR:
3179 case TOK_WARNING:
3180 c = tok;
3181 ch = file->buf_ptr[0];
3182 skip_spaces();
3183 q = buf;
3184 while (ch != '\n' && ch != CH_EOF) {
3185 if ((q - buf) < sizeof(buf) - 1)
3186 *q++ = ch;
3187 if (ch == '\\') {
3188 if (handle_stray_noerror() == 0)
3189 --q;
3190 } else
3191 inp();
3193 *q = '\0';
3194 if (c == TOK_ERROR)
3195 error("#error %s", buf);
3196 else
3197 warning("#warning %s", buf);
3198 break;
3199 case TOK_PRAGMA:
3200 pragma_parse(s1);
3201 break;
3202 default:
3203 if (tok == TOK_LINEFEED || tok == '!' || tok == TOK_CINT) {
3204 /* '!' is ignored to allow C scripts. numbers are ignored
3205 to emulate cpp behaviour */
3206 } else {
3207 if (!(saved_parse_flags & PARSE_FLAG_ASM_COMMENTS))
3208 warning("Ignoring unknown preprocessing directive #%s", get_tok_str(tok, &tokc));
3210 break;
3212 /* ignore other preprocess commands or #! for C scripts */
3213 while (tok != TOK_LINEFEED)
3214 next_nomacro();
3215 the_end:
3216 parse_flags = saved_parse_flags;
3219 /* evaluate escape codes in a string. */
3220 static void parse_escape_string(CString *outstr, const uint8_t *buf, int is_long)
3222 int c, n;
3223 const uint8_t *p;
3225 p = buf;
3226 for(;;) {
3227 c = *p;
3228 if (c == '\0')
3229 break;
3230 if (c == '\\') {
3231 p++;
3232 /* escape */
3233 c = *p;
3234 switch(c) {
3235 case '0': case '1': case '2': case '3':
3236 case '4': case '5': case '6': case '7':
3237 /* at most three octal digits */
3238 n = c - '0';
3239 p++;
3240 c = *p;
3241 if (isoct(c)) {
3242 n = n * 8 + c - '0';
3243 p++;
3244 c = *p;
3245 if (isoct(c)) {
3246 n = n * 8 + c - '0';
3247 p++;
3250 c = n;
3251 goto add_char_nonext;
3252 case 'x':
3253 case 'u':
3254 case 'U':
3255 p++;
3256 n = 0;
3257 for(;;) {
3258 c = *p;
3259 if (c >= 'a' && c <= 'f')
3260 c = c - 'a' + 10;
3261 else if (c >= 'A' && c <= 'F')
3262 c = c - 'A' + 10;
3263 else if (isnum(c))
3264 c = c - '0';
3265 else
3266 break;
3267 n = n * 16 + c;
3268 p++;
3270 c = n;
3271 goto add_char_nonext;
3272 case 'a':
3273 c = '\a';
3274 break;
3275 case 'b':
3276 c = '\b';
3277 break;
3278 case 'f':
3279 c = '\f';
3280 break;
3281 case 'n':
3282 c = '\n';
3283 break;
3284 case 'r':
3285 c = '\r';
3286 break;
3287 case 't':
3288 c = '\t';
3289 break;
3290 case 'v':
3291 c = '\v';
3292 break;
3293 case 'e':
3294 if (!gnu_ext)
3295 goto invalid_escape;
3296 c = 27;
3297 break;
3298 case '\'':
3299 case '\"':
3300 case '\\':
3301 case '?':
3302 break;
3303 default:
3304 invalid_escape:
3305 if (c >= '!' && c <= '~')
3306 warning("unknown escape sequence: \'\\%c\'", c);
3307 else
3308 warning("unknown escape sequence: \'\\x%x\'", c);
3309 break;
3312 p++;
3313 add_char_nonext:
3314 if (!is_long)
3315 cstr_ccat(outstr, c);
3316 else
3317 cstr_wccat(outstr, c);
3319 /* add a trailing '\0' */
3320 if (!is_long)
3321 cstr_ccat(outstr, '\0');
3322 else
3323 cstr_wccat(outstr, '\0');
3326 /* we use 64 bit numbers */
3327 #define BN_SIZE 2
3329 /* bn = (bn << shift) | or_val */
3330 void bn_lshift(unsigned int *bn, int shift, int or_val)
3332 int i;
3333 unsigned int v;
3334 for(i=0;i<BN_SIZE;i++) {
3335 v = bn[i];
3336 bn[i] = (v << shift) | or_val;
3337 or_val = v >> (32 - shift);
3341 void bn_zero(unsigned int *bn)
3343 int i;
3344 for(i=0;i<BN_SIZE;i++) {
3345 bn[i] = 0;
3349 /* parse number in null terminated string 'p' and return it in the
3350 current token */
3351 void parse_number(const char *p)
3353 int b, t, shift, frac_bits, s, exp_val, ch;
3354 char *q;
3355 unsigned int bn[BN_SIZE];
3356 double d;
3358 /* number */
3359 q = token_buf;
3360 ch = *p++;
3361 t = ch;
3362 ch = *p++;
3363 *q++ = t;
3364 b = 10;
3365 if (t == '.') {
3366 goto float_frac_parse;
3367 } else if (t == '0') {
3368 if (ch == 'x' || ch == 'X') {
3369 q--;
3370 ch = *p++;
3371 b = 16;
3372 } else if (tcc_ext && (ch == 'b' || ch == 'B')) {
3373 q--;
3374 ch = *p++;
3375 b = 2;
3378 /* parse all digits. cannot check octal numbers at this stage
3379 because of floating point constants */
3380 while (1) {
3381 if (ch >= 'a' && ch <= 'f')
3382 t = ch - 'a' + 10;
3383 else if (ch >= 'A' && ch <= 'F')
3384 t = ch - 'A' + 10;
3385 else if (isnum(ch))
3386 t = ch - '0';
3387 else
3388 break;
3389 if (t >= b)
3390 break;
3391 if (q >= token_buf + STRING_MAX_SIZE) {
3392 num_too_long:
3393 error("number too long");
3395 *q++ = ch;
3396 ch = *p++;
3398 if (ch == '.' ||
3399 ((ch == 'e' || ch == 'E') && b == 10) ||
3400 ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
3401 if (b != 10) {
3402 /* NOTE: strtox should support that for hexa numbers, but
3403 non ISOC99 libcs do not support it, so we prefer to do
3404 it by hand */
3405 /* hexadecimal or binary floats */
3406 /* XXX: handle overflows */
3407 *q = '\0';
3408 if (b == 16)
3409 shift = 4;
3410 else
3411 shift = 2;
3412 bn_zero(bn);
3413 q = token_buf;
3414 while (1) {
3415 t = *q++;
3416 if (t == '\0') {
3417 break;
3418 } else if (t >= 'a') {
3419 t = t - 'a' + 10;
3420 } else if (t >= 'A') {
3421 t = t - 'A' + 10;
3422 } else {
3423 t = t - '0';
3425 bn_lshift(bn, shift, t);
3427 frac_bits = 0;
3428 if (ch == '.') {
3429 ch = *p++;
3430 while (1) {
3431 t = ch;
3432 if (t >= 'a' && t <= 'f') {
3433 t = t - 'a' + 10;
3434 } else if (t >= 'A' && t <= 'F') {
3435 t = t - 'A' + 10;
3436 } else if (t >= '0' && t <= '9') {
3437 t = t - '0';
3438 } else {
3439 break;
3441 if (t >= b)
3442 error("invalid digit");
3443 bn_lshift(bn, shift, t);
3444 frac_bits += shift;
3445 ch = *p++;
3448 if (ch != 'p' && ch != 'P')
3449 expect("exponent");
3450 ch = *p++;
3451 s = 1;
3452 exp_val = 0;
3453 if (ch == '+') {
3454 ch = *p++;
3455 } else if (ch == '-') {
3456 s = -1;
3457 ch = *p++;
3459 if (ch < '0' || ch > '9')
3460 expect("exponent digits");
3461 while (ch >= '0' && ch <= '9') {
3462 exp_val = exp_val * 10 + ch - '0';
3463 ch = *p++;
3465 exp_val = exp_val * s;
3467 /* now we can generate the number */
3468 /* XXX: should patch directly float number */
3469 d = (double)bn[1] * 4294967296.0 + (double)bn[0];
3470 d = ldexp(d, exp_val - frac_bits);
3471 t = toup(ch);
3472 if (t == 'F') {
3473 ch = *p++;
3474 tok = TOK_CFLOAT;
3475 /* float : should handle overflow */
3476 tokc.f = (float)d;
3477 } else if (t == 'L') {
3478 ch = *p++;
3479 tok = TOK_CLDOUBLE;
3480 /* XXX: not large enough */
3481 tokc.ld = (long double)d;
3482 } else {
3483 tok = TOK_CDOUBLE;
3484 tokc.d = d;
3486 } else {
3487 /* decimal floats */
3488 if (ch == '.') {
3489 if (q >= token_buf + STRING_MAX_SIZE)
3490 goto num_too_long;
3491 *q++ = ch;
3492 ch = *p++;
3493 float_frac_parse:
3494 while (ch >= '0' && ch <= '9') {
3495 if (q >= token_buf + STRING_MAX_SIZE)
3496 goto num_too_long;
3497 *q++ = ch;
3498 ch = *p++;
3501 if (ch == 'e' || ch == 'E') {
3502 if (q >= token_buf + STRING_MAX_SIZE)
3503 goto num_too_long;
3504 *q++ = ch;
3505 ch = *p++;
3506 if (ch == '-' || ch == '+') {
3507 if (q >= token_buf + STRING_MAX_SIZE)
3508 goto num_too_long;
3509 *q++ = ch;
3510 ch = *p++;
3512 if (ch < '0' || ch > '9')
3513 expect("exponent digits");
3514 while (ch >= '0' && ch <= '9') {
3515 if (q >= token_buf + STRING_MAX_SIZE)
3516 goto num_too_long;
3517 *q++ = ch;
3518 ch = *p++;
3521 *q = '\0';
3522 t = toup(ch);
3523 errno = 0;
3524 if (t == 'F') {
3525 ch = *p++;
3526 tok = TOK_CFLOAT;
3527 tokc.f = strtof(token_buf, NULL);
3528 } else if (t == 'L') {
3529 ch = *p++;
3530 tok = TOK_CLDOUBLE;
3531 tokc.ld = strtold(token_buf, NULL);
3532 } else {
3533 tok = TOK_CDOUBLE;
3534 tokc.d = strtod(token_buf, NULL);
3537 } else {
3538 unsigned long long n, n1;
3539 int lcount, ucount;
3541 /* integer number */
3542 *q = '\0';
3543 q = token_buf;
3544 if (b == 10 && *q == '0') {
3545 b = 8;
3546 q++;
3548 n = 0;
3549 while(1) {
3550 t = *q++;
3551 /* no need for checks except for base 10 / 8 errors */
3552 if (t == '\0') {
3553 break;
3554 } else if (t >= 'a') {
3555 t = t - 'a' + 10;
3556 } else if (t >= 'A') {
3557 t = t - 'A' + 10;
3558 } else {
3559 t = t - '0';
3560 if (t >= b)
3561 error("invalid digit");
3563 n1 = n;
3564 n = n * b + t;
3565 /* detect overflow */
3566 /* XXX: this test is not reliable */
3567 if (n < n1)
3568 error("integer constant overflow");
3571 /* XXX: not exactly ANSI compliant */
3572 if ((n & 0xffffffff00000000LL) != 0) {
3573 if ((n >> 63) != 0)
3574 tok = TOK_CULLONG;
3575 else
3576 tok = TOK_CLLONG;
3577 } else if (n > 0x7fffffff) {
3578 tok = TOK_CUINT;
3579 } else {
3580 tok = TOK_CINT;
3582 lcount = 0;
3583 ucount = 0;
3584 for(;;) {
3585 t = toup(ch);
3586 if (t == 'L') {
3587 if (lcount >= 2)
3588 error("three 'l's in integer constant");
3589 lcount++;
3590 if (lcount == 2) {
3591 if (tok == TOK_CINT)
3592 tok = TOK_CLLONG;
3593 else if (tok == TOK_CUINT)
3594 tok = TOK_CULLONG;
3596 ch = *p++;
3597 } else if (t == 'U') {
3598 if (ucount >= 1)
3599 error("two 'u's in integer constant");
3600 ucount++;
3601 if (tok == TOK_CINT)
3602 tok = TOK_CUINT;
3603 else if (tok == TOK_CLLONG)
3604 tok = TOK_CULLONG;
3605 ch = *p++;
3606 } else {
3607 break;
3610 if (tok == TOK_CINT || tok == TOK_CUINT)
3611 tokc.ui = n;
3612 else
3613 tokc.ull = n;
3618 #define PARSE2(c1, tok1, c2, tok2) \
3619 case c1: \
3620 PEEKC(c, p); \
3621 if (c == c2) { \
3622 p++; \
3623 tok = tok2; \
3624 } else { \
3625 tok = tok1; \
3627 break;
3629 /* return next token without macro substitution */
3630 static inline void next_nomacro1(void)
3632 int t, c, is_long;
3633 TokenSym *ts;
3634 uint8_t *p, *p1;
3635 unsigned int h;
3637 p = file->buf_ptr;
3638 redo_no_start:
3639 c = *p;
3640 switch(c) {
3641 case ' ':
3642 case '\t':
3643 case '\f':
3644 case '\v':
3645 case '\r':
3646 p++;
3647 goto redo_no_start;
3649 case '\\':
3650 /* first look if it is in fact an end of buffer */
3651 if (p >= file->buf_end) {
3652 file->buf_ptr = p;
3653 handle_eob();
3654 p = file->buf_ptr;
3655 if (p >= file->buf_end)
3656 goto parse_eof;
3657 else
3658 goto redo_no_start;
3659 } else {
3660 file->buf_ptr = p;
3661 ch = *p;
3662 handle_stray();
3663 p = file->buf_ptr;
3664 goto redo_no_start;
3666 parse_eof:
3668 TCCState *s1 = tcc_state;
3669 if ((parse_flags & PARSE_FLAG_LINEFEED)
3670 && !(tok_flags & TOK_FLAG_EOF)) {
3671 tok_flags |= TOK_FLAG_EOF;
3672 tok = TOK_LINEFEED;
3673 goto keep_tok_flags;
3674 } else if (s1->include_stack_ptr == s1->include_stack ||
3675 !(parse_flags & PARSE_FLAG_PREPROCESS)) {
3676 /* no include left : end of file. */
3677 tok = TOK_EOF;
3678 } else {
3679 tok_flags &= ~TOK_FLAG_EOF;
3680 /* pop include file */
3682 /* test if previous '#endif' was after a #ifdef at
3683 start of file */
3684 if (tok_flags & TOK_FLAG_ENDIF) {
3685 #ifdef INC_DEBUG
3686 printf("#endif %s\n", get_tok_str(file->ifndef_macro_saved, NULL));
3687 #endif
3688 add_cached_include(s1, file->inc_type, file->inc_filename,
3689 file->ifndef_macro_saved);
3692 /* add end of include file debug info */
3693 if (do_debug) {
3694 put_stabd(N_EINCL, 0, 0);
3696 /* pop include stack */
3697 tcc_close(file);
3698 s1->include_stack_ptr--;
3699 file = *s1->include_stack_ptr;
3700 p = file->buf_ptr;
3701 goto redo_no_start;
3704 break;
3706 case '\n':
3707 file->line_num++;
3708 tok_flags |= TOK_FLAG_BOL;
3709 p++;
3710 if (0 == (parse_flags & PARSE_FLAG_LINEFEED))
3711 goto redo_no_start;
3712 tok = TOK_LINEFEED;
3713 goto keep_tok_flags;
3715 case '#':
3716 /* XXX: simplify */
3717 PEEKC(c, p);
3718 if ((tok_flags & TOK_FLAG_BOL) &&
3719 (parse_flags & PARSE_FLAG_PREPROCESS)) {
3720 file->buf_ptr = p;
3721 preprocess(tok_flags & TOK_FLAG_BOF);
3722 p = file->buf_ptr;
3723 goto redo_no_start;
3724 } else {
3725 if (c == '#') {
3726 p++;
3727 tok = TOK_TWOSHARPS;
3728 } else {
3729 if (parse_flags & PARSE_FLAG_ASM_COMMENTS) {
3730 p = parse_line_comment(p - 1);
3731 goto redo_no_start;
3732 } else {
3733 tok = '#';
3737 break;
3739 case 'a': case 'b': case 'c': case 'd':
3740 case 'e': case 'f': case 'g': case 'h':
3741 case 'i': case 'j': case 'k': case 'l':
3742 case 'm': case 'n': case 'o': case 'p':
3743 case 'q': case 'r': case 's': case 't':
3744 case 'u': case 'v': case 'w': case 'x':
3745 case 'y': case 'z':
3746 case 'A': case 'B': case 'C': case 'D':
3747 case 'E': case 'F': case 'G': case 'H':
3748 case 'I': case 'J': case 'K':
3749 case 'M': case 'N': case 'O': case 'P':
3750 case 'Q': case 'R': case 'S': case 'T':
3751 case 'U': case 'V': case 'W': case 'X':
3752 case 'Y': case 'Z':
3753 case '_':
3754 parse_ident_fast:
3755 p1 = p;
3756 h = TOK_HASH_INIT;
3757 h = TOK_HASH_FUNC(h, c);
3758 p++;
3759 for(;;) {
3760 c = *p;
3761 if (!isidnum_table[c])
3762 break;
3763 h = TOK_HASH_FUNC(h, c);
3764 p++;
3766 if (c != '\\') {
3767 TokenSym **pts;
3768 int len;
3770 /* fast case : no stray found, so we have the full token
3771 and we have already hashed it */
3772 len = p - p1;
3773 h &= (TOK_HASH_SIZE - 1);
3774 pts = &hash_ident[h];
3775 for(;;) {
3776 ts = *pts;
3777 if (!ts)
3778 break;
3779 if (ts->len == len && !memcmp(ts->str, p1, len))
3780 goto token_found;
3781 pts = &(ts->hash_next);
3783 ts = tok_alloc_new(pts, p1, len);
3784 token_found: ;
3785 } else {
3786 /* slower case */
3787 cstr_reset(&tokcstr);
3789 while (p1 < p) {
3790 cstr_ccat(&tokcstr, *p1);
3791 p1++;
3793 p--;
3794 PEEKC(c, p);
3795 parse_ident_slow:
3796 while (isidnum_table[c]) {
3797 cstr_ccat(&tokcstr, c);
3798 PEEKC(c, p);
3800 ts = tok_alloc(tokcstr.data, tokcstr.size);
3802 tok = ts->tok;
3803 break;
3804 case 'L':
3805 t = p[1];
3806 if (t != '\\' && t != '\'' && t != '\"') {
3807 /* fast case */
3808 goto parse_ident_fast;
3809 } else {
3810 PEEKC(c, p);
3811 if (c == '\'' || c == '\"') {
3812 is_long = 1;
3813 goto str_const;
3814 } else {
3815 cstr_reset(&tokcstr);
3816 cstr_ccat(&tokcstr, 'L');
3817 goto parse_ident_slow;
3820 break;
3821 case '0': case '1': case '2': case '3':
3822 case '4': case '5': case '6': case '7':
3823 case '8': case '9':
3825 cstr_reset(&tokcstr);
3826 /* after the first digit, accept digits, alpha, '.' or sign if
3827 prefixed by 'eEpP' */
3828 parse_num:
3829 for(;;) {
3830 t = c;
3831 cstr_ccat(&tokcstr, c);
3832 PEEKC(c, p);
3833 if (!(isnum(c) || isid(c) || c == '.' ||
3834 ((c == '+' || c == '-') &&
3835 (t == 'e' || t == 'E' || t == 'p' || t == 'P'))))
3836 break;
3838 /* We add a trailing '\0' to ease parsing */
3839 cstr_ccat(&tokcstr, '\0');
3840 tokc.cstr = &tokcstr;
3841 tok = TOK_PPNUM;
3842 break;
3843 case '.':
3844 /* special dot handling because it can also start a number */
3845 PEEKC(c, p);
3846 if (isnum(c)) {
3847 cstr_reset(&tokcstr);
3848 cstr_ccat(&tokcstr, '.');
3849 goto parse_num;
3850 } else if (c == '.') {
3851 PEEKC(c, p);
3852 if (c != '.')
3853 expect("'.'");
3854 PEEKC(c, p);
3855 tok = TOK_DOTS;
3856 } else {
3857 tok = '.';
3859 break;
3860 case '\'':
3861 case '\"':
3862 is_long = 0;
3863 str_const:
3865 CString str;
3866 int sep;
3868 sep = c;
3870 /* parse the string */
3871 cstr_new(&str);
3872 p = parse_pp_string(p, sep, &str);
3873 cstr_ccat(&str, '\0');
3875 /* eval the escape (should be done as TOK_PPNUM) */
3876 cstr_reset(&tokcstr);
3877 parse_escape_string(&tokcstr, str.data, is_long);
3878 cstr_free(&str);
3880 if (sep == '\'') {
3881 int char_size;
3882 /* XXX: make it portable */
3883 if (!is_long)
3884 char_size = 1;
3885 else
3886 char_size = sizeof(nwchar_t);
3887 if (tokcstr.size <= char_size)
3888 error("empty character constant");
3889 if (tokcstr.size > 2 * char_size)
3890 warning("multi-character character constant");
3891 if (!is_long) {
3892 tokc.i = *(int8_t *)tokcstr.data;
3893 tok = TOK_CCHAR;
3894 } else {
3895 tokc.i = *(nwchar_t *)tokcstr.data;
3896 tok = TOK_LCHAR;
3898 } else {
3899 tokc.cstr = &tokcstr;
3900 if (!is_long)
3901 tok = TOK_STR;
3902 else
3903 tok = TOK_LSTR;
3906 break;
3908 case '<':
3909 PEEKC(c, p);
3910 if (c == '=') {
3911 p++;
3912 tok = TOK_LE;
3913 } else if (c == '<') {
3914 PEEKC(c, p);
3915 if (c == '=') {
3916 p++;
3917 tok = TOK_A_SHL;
3918 } else {
3919 tok = TOK_SHL;
3921 } else {
3922 tok = TOK_LT;
3924 break;
3926 case '>':
3927 PEEKC(c, p);
3928 if (c == '=') {
3929 p++;
3930 tok = TOK_GE;
3931 } else if (c == '>') {
3932 PEEKC(c, p);
3933 if (c == '=') {
3934 p++;
3935 tok = TOK_A_SAR;
3936 } else {
3937 tok = TOK_SAR;
3939 } else {
3940 tok = TOK_GT;
3942 break;
3944 case '&':
3945 PEEKC(c, p);
3946 if (c == '&') {
3947 p++;
3948 tok = TOK_LAND;
3949 } else if (c == '=') {
3950 p++;
3951 tok = TOK_A_AND;
3952 } else {
3953 tok = '&';
3955 break;
3957 case '|':
3958 PEEKC(c, p);
3959 if (c == '|') {
3960 p++;
3961 tok = TOK_LOR;
3962 } else if (c == '=') {
3963 p++;
3964 tok = TOK_A_OR;
3965 } else {
3966 tok = '|';
3968 break;
3970 case '+':
3971 PEEKC(c, p);
3972 if (c == '+') {
3973 p++;
3974 tok = TOK_INC;
3975 } else if (c == '=') {
3976 p++;
3977 tok = TOK_A_ADD;
3978 } else {
3979 tok = '+';
3981 break;
3983 case '-':
3984 PEEKC(c, p);
3985 if (c == '-') {
3986 p++;
3987 tok = TOK_DEC;
3988 } else if (c == '=') {
3989 p++;
3990 tok = TOK_A_SUB;
3991 } else if (c == '>') {
3992 p++;
3993 tok = TOK_ARROW;
3994 } else {
3995 tok = '-';
3997 break;
3999 PARSE2('!', '!', '=', TOK_NE)
4000 PARSE2('=', '=', '=', TOK_EQ)
4001 PARSE2('*', '*', '=', TOK_A_MUL)
4002 PARSE2('%', '%', '=', TOK_A_MOD)
4003 PARSE2('^', '^', '=', TOK_A_XOR)
4005 /* comments or operator */
4006 case '/':
4007 PEEKC(c, p);
4008 if (c == '*') {
4009 p = parse_comment(p);
4010 goto redo_no_start;
4011 } else if (c == '/') {
4012 p = parse_line_comment(p);
4013 goto redo_no_start;
4014 } else if (c == '=') {
4015 p++;
4016 tok = TOK_A_DIV;
4017 } else {
4018 tok = '/';
4020 break;
4022 /* simple tokens */
4023 case '(':
4024 case ')':
4025 case '[':
4026 case ']':
4027 case '{':
4028 case '}':
4029 case ',':
4030 case ';':
4031 case ':':
4032 case '?':
4033 case '~':
4034 case '$': /* only used in assembler */
4035 case '@': /* dito */
4036 tok = c;
4037 p++;
4038 break;
4039 default:
4040 error("unrecognized character \\x%02x", c);
4041 break;
4043 tok_flags = 0;
4044 keep_tok_flags:
4045 file->buf_ptr = p;
4046 #if defined(PARSE_DEBUG)
4047 printf("token = %s\n", get_tok_str(tok, &tokc));
4048 #endif
4051 /* return next token without macro substitution. Can read input from
4052 macro_ptr buffer */
4053 static void next_nomacro(void)
4055 if (macro_ptr) {
4056 redo:
4057 tok = *macro_ptr;
4058 if (tok) {
4059 TOK_GET(tok, macro_ptr, tokc);
4060 if (tok == TOK_LINENUM) {
4061 file->line_num = tokc.i;
4062 goto redo;
4065 } else {
4066 next_nomacro1();
4070 /* substitute args in macro_str and return allocated string */
4071 static int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
4073 int *st, last_tok, t, notfirst;
4074 Sym *s;
4075 CValue cval;
4076 TokenString str;
4077 CString cstr;
4079 tok_str_new(&str);
4080 last_tok = 0;
4081 while(1) {
4082 TOK_GET(t, macro_str, cval);
4083 if (!t)
4084 break;
4085 if (t == '#') {
4086 /* stringize */
4087 TOK_GET(t, macro_str, cval);
4088 if (!t)
4089 break;
4090 s = sym_find2(args, t);
4091 if (s) {
4092 cstr_new(&cstr);
4093 st = (int *)s->c;
4094 notfirst = 0;
4095 while (*st) {
4096 if (notfirst)
4097 cstr_ccat(&cstr, ' ');
4098 TOK_GET(t, st, cval);
4099 cstr_cat(&cstr, get_tok_str(t, &cval));
4100 #ifndef PP_NOSPACES
4101 notfirst = 1;
4102 #endif
4104 cstr_ccat(&cstr, '\0');
4105 #ifdef PP_DEBUG
4106 printf("stringize: %s\n", (char *)cstr.data);
4107 #endif
4108 /* add string */
4109 cval.cstr = &cstr;
4110 tok_str_add2(&str, TOK_STR, &cval);
4111 cstr_free(&cstr);
4112 } else {
4113 tok_str_add2(&str, t, &cval);
4115 } else if (t >= TOK_IDENT) {
4116 s = sym_find2(args, t);
4117 if (s) {
4118 st = (int *)s->c;
4119 /* if '##' is present before or after, no arg substitution */
4120 if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) {
4121 /* special case for var arg macros : ## eats the
4122 ',' if empty VA_ARGS variable. */
4123 /* XXX: test of the ',' is not 100%
4124 reliable. should fix it to avoid security
4125 problems */
4126 if (gnu_ext && s->type.t &&
4127 last_tok == TOK_TWOSHARPS &&
4128 str.len >= 2 && str.str[str.len - 2] == ',') {
4129 if (*st == 0) {
4130 /* suppress ',' '##' */
4131 str.len -= 2;
4132 } else {
4133 /* suppress '##' and add variable */
4134 str.len--;
4135 goto add_var;
4137 } else {
4138 int t1;
4139 add_var:
4140 for(;;) {
4141 TOK_GET(t1, st, cval);
4142 if (!t1)
4143 break;
4144 tok_str_add2(&str, t1, &cval);
4147 } else {
4148 /* NOTE: the stream cannot be read when macro
4149 substituing an argument */
4150 macro_subst(&str, nested_list, st, NULL);
4152 } else {
4153 tok_str_add(&str, t);
4155 } else {
4156 tok_str_add2(&str, t, &cval);
4158 last_tok = t;
4160 tok_str_add(&str, 0);
4161 return str.str;
4164 static char const ab_month_name[12][4] =
4166 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
4167 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
4170 /* do macro substitution of current token with macro 's' and add
4171 result to (tok_str,tok_len). 'nested_list' is the list of all
4172 macros we got inside to avoid recursing. Return non zero if no
4173 substitution needs to be done */
4174 static int macro_subst_tok(TokenString *tok_str,
4175 Sym **nested_list, Sym *s, struct macro_level **can_read_stream)
4177 Sym *args, *sa, *sa1;
4178 int mstr_allocated, parlevel, *mstr, t, t1;
4179 TokenString str;
4180 char *cstrval;
4181 CValue cval;
4182 CString cstr;
4183 char buf[32];
4185 /* if symbol is a macro, prepare substitution */
4186 /* special macros */
4187 if (tok == TOK___LINE__) {
4188 snprintf(buf, sizeof(buf), "%d", file->line_num);
4189 cstrval = buf;
4190 t1 = TOK_PPNUM;
4191 goto add_cstr1;
4192 } else if (tok == TOK___FILE__) {
4193 cstrval = file->filename;
4194 goto add_cstr;
4195 } else if (tok == TOK___DATE__ || tok == TOK___TIME__) {
4196 time_t ti;
4197 struct tm *tm;
4199 time(&ti);
4200 tm = localtime(&ti);
4201 if (tok == TOK___DATE__) {
4202 snprintf(buf, sizeof(buf), "%s %2d %d",
4203 ab_month_name[tm->tm_mon], tm->tm_mday, tm->tm_year + 1900);
4204 } else {
4205 snprintf(buf, sizeof(buf), "%02d:%02d:%02d",
4206 tm->tm_hour, tm->tm_min, tm->tm_sec);
4208 cstrval = buf;
4209 add_cstr:
4210 t1 = TOK_STR;
4211 add_cstr1:
4212 cstr_new(&cstr);
4213 cstr_cat(&cstr, cstrval);
4214 cstr_ccat(&cstr, '\0');
4215 cval.cstr = &cstr;
4216 tok_str_add2(tok_str, t1, &cval);
4217 cstr_free(&cstr);
4218 } else {
4219 mstr = (int *)s->c;
4220 mstr_allocated = 0;
4221 if (s->type.t == MACRO_FUNC) {
4222 /* NOTE: we do not use next_nomacro to avoid eating the
4223 next token. XXX: find better solution */
4224 redo:
4225 if (macro_ptr) {
4226 t = *macro_ptr;
4227 if (t == 0 && can_read_stream) {
4228 /* end of macro stream: we must look at the token
4229 after in the file */
4230 struct macro_level *ml = *can_read_stream;
4231 macro_ptr = NULL;
4232 if (ml)
4234 macro_ptr = ml->p;
4235 ml->p = NULL;
4236 *can_read_stream = ml -> prev;
4238 goto redo;
4240 } else {
4241 /* XXX: incorrect with comments */
4242 ch = file->buf_ptr[0];
4243 while (is_space(ch) || ch == '\n')
4244 cinp();
4245 t = ch;
4247 if (t != '(') /* no macro subst */
4248 return -1;
4250 /* argument macro */
4251 next_nomacro();
4252 next_nomacro();
4253 args = NULL;
4254 sa = s->next;
4255 /* NOTE: empty args are allowed, except if no args */
4256 for(;;) {
4257 /* handle '()' case */
4258 if (!args && !sa && tok == ')')
4259 break;
4260 if (!sa)
4261 error("macro '%s' used with too many args",
4262 get_tok_str(s->v, 0));
4263 tok_str_new(&str);
4264 parlevel = 0;
4265 /* NOTE: non zero sa->t indicates VA_ARGS */
4266 while ((parlevel > 0 ||
4267 (tok != ')' &&
4268 (tok != ',' || sa->type.t))) &&
4269 tok != -1) {
4270 if (tok == '(')
4271 parlevel++;
4272 else if (tok == ')')
4273 parlevel--;
4274 if (tok != TOK_LINEFEED)
4275 tok_str_add2(&str, tok, &tokc);
4276 next_nomacro();
4278 tok_str_add(&str, 0);
4279 sym_push2(&args, sa->v & ~SYM_FIELD, sa->type.t, (int)str.str);
4280 sa = sa->next;
4281 if (tok == ')') {
4282 /* special case for gcc var args: add an empty
4283 var arg argument if it is omitted */
4284 if (sa && sa->type.t && gnu_ext)
4285 continue;
4286 else
4287 break;
4289 if (tok != ',')
4290 expect(",");
4291 next_nomacro();
4293 if (sa) {
4294 error("macro '%s' used with too few args",
4295 get_tok_str(s->v, 0));
4298 /* now subst each arg */
4299 mstr = macro_arg_subst(nested_list, mstr, args);
4300 /* free memory */
4301 sa = args;
4302 while (sa) {
4303 sa1 = sa->prev;
4304 tok_str_free((int *)sa->c);
4305 sym_free(sa);
4306 sa = sa1;
4308 mstr_allocated = 1;
4310 sym_push2(nested_list, s->v, 0, 0);
4311 macro_subst(tok_str, nested_list, mstr, can_read_stream);
4312 /* pop nested defined symbol */
4313 sa1 = *nested_list;
4314 *nested_list = sa1->prev;
4315 sym_free(sa1);
4316 if (mstr_allocated)
4317 tok_str_free(mstr);
4319 return 0;
4322 /* handle the '##' operator. Return NULL if no '##' seen. Otherwise
4323 return the resulting string (which must be freed). */
4324 static inline int *macro_twosharps(const int *macro_str)
4326 TokenSym *ts;
4327 const int *macro_ptr1, *start_macro_ptr, *ptr, *saved_macro_ptr;
4328 int t;
4329 const char *p1, *p2;
4330 CValue cval;
4331 TokenString macro_str1;
4332 CString cstr;
4334 start_macro_ptr = macro_str;
4335 /* we search the first '##' */
4336 for(;;) {
4337 macro_ptr1 = macro_str;
4338 TOK_GET(t, macro_str, cval);
4339 /* nothing more to do if end of string */
4340 if (t == 0)
4341 return NULL;
4342 if (*macro_str == TOK_TWOSHARPS)
4343 break;
4346 /* we saw '##', so we need more processing to handle it */
4347 cstr_new(&cstr);
4348 tok_str_new(&macro_str1);
4349 tok = t;
4350 tokc = cval;
4352 /* add all tokens seen so far */
4353 for(ptr = start_macro_ptr; ptr < macro_ptr1;) {
4354 TOK_GET(t, ptr, cval);
4355 tok_str_add2(&macro_str1, t, &cval);
4357 saved_macro_ptr = macro_ptr;
4358 /* XXX: get rid of the use of macro_ptr here */
4359 macro_ptr = (int *)macro_str;
4360 for(;;) {
4361 while (*macro_ptr == TOK_TWOSHARPS) {
4362 macro_ptr++;
4363 macro_ptr1 = macro_ptr;
4364 t = *macro_ptr;
4365 if (t) {
4366 TOK_GET(t, macro_ptr, cval);
4367 /* We concatenate the two tokens if we have an
4368 identifier or a preprocessing number */
4369 cstr_reset(&cstr);
4370 p1 = get_tok_str(tok, &tokc);
4371 cstr_cat(&cstr, p1);
4372 p2 = get_tok_str(t, &cval);
4373 cstr_cat(&cstr, p2);
4374 cstr_ccat(&cstr, '\0');
4376 if ((tok >= TOK_IDENT || tok == TOK_PPNUM) &&
4377 (t >= TOK_IDENT || t == TOK_PPNUM)) {
4378 if (tok == TOK_PPNUM) {
4379 /* if number, then create a number token */
4380 /* NOTE: no need to allocate because
4381 tok_str_add2() does it */
4382 cstr_reset(&tokcstr);
4383 tokcstr = cstr;
4384 cstr_new(&cstr);
4385 tokc.cstr = &tokcstr;
4386 } else {
4387 /* if identifier, we must do a test to
4388 validate we have a correct identifier */
4389 if (t == TOK_PPNUM) {
4390 const char *p;
4391 int c;
4393 p = p2;
4394 for(;;) {
4395 c = *p;
4396 if (c == '\0')
4397 break;
4398 p++;
4399 if (!isnum(c) && !isid(c))
4400 goto error_pasting;
4403 ts = tok_alloc(cstr.data, strlen(cstr.data));
4404 tok = ts->tok; /* modify current token */
4406 } else {
4407 const char *str = cstr.data;
4408 const unsigned char *q;
4410 /* we look for a valid token */
4411 /* XXX: do more extensive checks */
4412 if (!strcmp(str, ">>=")) {
4413 tok = TOK_A_SAR;
4414 } else if (!strcmp(str, "<<=")) {
4415 tok = TOK_A_SHL;
4416 } else if (strlen(str) == 2) {
4417 /* search in two bytes table */
4418 q = tok_two_chars;
4419 for(;;) {
4420 if (!*q)
4421 goto error_pasting;
4422 if (q[0] == str[0] && q[1] == str[1])
4423 break;
4424 q += 3;
4426 tok = q[2];
4427 } else {
4428 error_pasting:
4429 /* NOTE: because get_tok_str use a static buffer,
4430 we must save it */
4431 cstr_reset(&cstr);
4432 p1 = get_tok_str(tok, &tokc);
4433 cstr_cat(&cstr, p1);
4434 cstr_ccat(&cstr, '\0');
4435 p2 = get_tok_str(t, &cval);
4436 warning("pasting \"%s\" and \"%s\" does not give a valid preprocessing token", cstr.data, p2);
4437 /* cannot merge tokens: just add them separately */
4438 tok_str_add2(&macro_str1, tok, &tokc);
4439 /* XXX: free associated memory ? */
4440 tok = t;
4441 tokc = cval;
4446 tok_str_add2(&macro_str1, tok, &tokc);
4447 next_nomacro();
4448 if (tok == 0)
4449 break;
4451 macro_ptr = (int *)saved_macro_ptr;
4452 cstr_free(&cstr);
4453 tok_str_add(&macro_str1, 0);
4454 return macro_str1.str;
4458 /* do macro substitution of macro_str and add result to
4459 (tok_str,tok_len). 'nested_list' is the list of all macros we got
4460 inside to avoid recursing. */
4461 static void macro_subst(TokenString *tok_str, Sym **nested_list,
4462 const int *macro_str, struct macro_level ** can_read_stream)
4464 Sym *s;
4465 int *macro_str1;
4466 const int *ptr;
4467 int t, ret;
4468 CValue cval;
4469 struct macro_level ml;
4471 /* first scan for '##' operator handling */
4472 ptr = macro_str;
4473 macro_str1 = macro_twosharps(ptr);
4474 if (macro_str1)
4475 ptr = macro_str1;
4476 while (1) {
4477 /* NOTE: ptr == NULL can only happen if tokens are read from
4478 file stream due to a macro function call */
4479 if (ptr == NULL)
4480 break;
4481 TOK_GET(t, ptr, cval);
4482 if (t == 0)
4483 break;
4484 s = define_find(t);
4485 if (s != NULL) {
4486 /* if nested substitution, do nothing */
4487 if (sym_find2(*nested_list, t))
4488 goto no_subst;
4489 ml.p = macro_ptr;
4490 if (can_read_stream)
4491 ml.prev = *can_read_stream, *can_read_stream = &ml;
4492 macro_ptr = (int *)ptr;
4493 tok = t;
4494 ret = macro_subst_tok(tok_str, nested_list, s, can_read_stream);
4495 ptr = (int *)macro_ptr;
4496 macro_ptr = ml.p;
4497 if (can_read_stream && *can_read_stream == &ml)
4498 *can_read_stream = ml.prev;
4499 if (ret != 0)
4500 goto no_subst;
4501 } else {
4502 no_subst:
4503 tok_str_add2(tok_str, t, &cval);
4506 if (macro_str1)
4507 tok_str_free(macro_str1);
4510 /* return next token with macro substitution */
4511 static void next(void)
4513 Sym *nested_list, *s;
4514 TokenString str;
4515 struct macro_level *ml;
4517 redo:
4518 next_nomacro();
4519 if (!macro_ptr) {
4520 /* if not reading from macro substituted string, then try
4521 to substitute macros */
4522 if (tok >= TOK_IDENT &&
4523 (parse_flags & PARSE_FLAG_PREPROCESS)) {
4524 s = define_find(tok);
4525 if (s) {
4526 /* we have a macro: we try to substitute */
4527 tok_str_new(&str);
4528 nested_list = NULL;
4529 ml = NULL;
4530 if (macro_subst_tok(&str, &nested_list, s, &ml) == 0) {
4531 /* substitution done, NOTE: maybe empty */
4532 tok_str_add(&str, 0);
4533 macro_ptr = str.str;
4534 macro_ptr_allocated = str.str;
4535 goto redo;
4539 } else {
4540 if (tok == 0) {
4541 /* end of macro or end of unget buffer */
4542 if (unget_buffer_enabled) {
4543 macro_ptr = unget_saved_macro_ptr;
4544 unget_buffer_enabled = 0;
4545 } else {
4546 /* end of macro string: free it */
4547 tok_str_free(macro_ptr_allocated);
4548 macro_ptr = NULL;
4550 goto redo;
4554 /* convert preprocessor tokens into C tokens */
4555 if (tok == TOK_PPNUM &&
4556 (parse_flags & PARSE_FLAG_TOK_NUM)) {
4557 parse_number((char *)tokc.cstr->data);
4561 /* push back current token and set current token to 'last_tok'. Only
4562 identifier case handled for labels. */
4563 static inline void unget_tok(int last_tok)
4565 int i, n;
4566 int *q;
4567 unget_saved_macro_ptr = macro_ptr;
4568 unget_buffer_enabled = 1;
4569 q = unget_saved_buffer;
4570 macro_ptr = q;
4571 *q++ = tok;
4572 n = tok_ext_size(tok) - 1;
4573 for(i=0;i<n;i++)
4574 *q++ = tokc.tab[i];
4575 *q = 0; /* end of token string */
4576 tok = last_tok;
4580 void swap(int *p, int *q)
4582 int t;
4583 t = *p;
4584 *p = *q;
4585 *q = t;
4588 void vsetc(CType *type, int r, CValue *vc)
4590 int v;
4592 if (vtop >= vstack + (VSTACK_SIZE - 1))
4593 error("memory full");
4594 /* cannot let cpu flags if other instruction are generated. Also
4595 avoid leaving VT_JMP anywhere except on the top of the stack
4596 because it would complicate the code generator. */
4597 if (vtop >= vstack) {
4598 v = vtop->r & VT_VALMASK;
4599 if (v == VT_CMP || (v & ~1) == VT_JMP)
4600 gv(RC_INT);
4602 vtop++;
4603 vtop->type = *type;
4604 vtop->r = r;
4605 vtop->r2 = VT_CONST;
4606 vtop->c = *vc;
4609 /* push integer constant */
4610 void vpushi(int v)
4612 CValue cval;
4613 cval.i = v;
4614 vsetc(&int_type, VT_CONST, &cval);
4617 /* Return a static symbol pointing to a section */
4618 static Sym *get_sym_ref(CType *type, Section *sec,
4619 unsigned long offset, unsigned long size)
4621 int v;
4622 Sym *sym;
4624 v = anon_sym++;
4625 sym = global_identifier_push(v, type->t | VT_STATIC, 0);
4626 sym->type.ref = type->ref;
4627 sym->r = VT_CONST | VT_SYM;
4628 put_extern_sym(sym, sec, offset, size);
4629 return sym;
4632 /* push a reference to a section offset by adding a dummy symbol */
4633 static void vpush_ref(CType *type, Section *sec, unsigned long offset, unsigned long size)
4635 CValue cval;
4637 cval.ul = 0;
4638 vsetc(type, VT_CONST | VT_SYM, &cval);
4639 vtop->sym = get_sym_ref(type, sec, offset, size);
4642 /* define a new external reference to a symbol 'v' of type 'u' */
4643 static Sym *external_global_sym(int v, CType *type, int r)
4645 Sym *s;
4647 s = sym_find(v);
4648 if (!s) {
4649 /* push forward reference */
4650 s = global_identifier_push(v, type->t | VT_EXTERN, 0);
4651 s->type.ref = type->ref;
4652 s->r = r | VT_CONST | VT_SYM;
4654 return s;
4657 /* define a new external reference to a symbol 'v' of type 'u' */
4658 static Sym *external_sym(int v, CType *type, int r)
4660 Sym *s;
4662 s = sym_find(v);
4663 if (!s) {
4664 /* push forward reference */
4665 s = sym_push(v, type, r | VT_CONST | VT_SYM, 0);
4666 s->type.t |= VT_EXTERN;
4667 } else {
4668 if (!is_compatible_types(&s->type, type))
4669 error("incompatible types for redefinition of '%s'",
4670 get_tok_str(v, NULL));
4672 return s;
4675 /* push a reference to global symbol v */
4676 static void vpush_global_sym(CType *type, int v)
4678 Sym *sym;
4679 CValue cval;
4681 sym = external_global_sym(v, type, 0);
4682 cval.ul = 0;
4683 vsetc(type, VT_CONST | VT_SYM, &cval);
4684 vtop->sym = sym;
4687 void vset(CType *type, int r, int v)
4689 CValue cval;
4691 cval.i = v;
4692 vsetc(type, r, &cval);
4695 void vseti(int r, int v)
4697 CType type;
4698 type.t = VT_INT;
4699 vset(&type, r, v);
4702 void vswap(void)
4704 SValue tmp;
4706 tmp = vtop[0];
4707 vtop[0] = vtop[-1];
4708 vtop[-1] = tmp;
4711 void vpushv(SValue *v)
4713 if (vtop >= vstack + (VSTACK_SIZE - 1))
4714 error("memory full");
4715 vtop++;
4716 *vtop = *v;
4719 void vdup(void)
4721 vpushv(vtop);
4724 /* save r to the memory stack, and mark it as being free */
4725 void save_reg(int r)
4727 int l, saved, size, align;
4728 SValue *p, sv;
4729 CType *type;
4731 /* modify all stack values */
4732 saved = 0;
4733 l = 0;
4734 for(p=vstack;p<=vtop;p++) {
4735 if ((p->r & VT_VALMASK) == r ||
4736 ((p->type.t & VT_BTYPE) == VT_LLONG && (p->r2 & VT_VALMASK) == r)) {
4737 /* must save value on stack if not already done */
4738 if (!saved) {
4739 /* NOTE: must reload 'r' because r might be equal to r2 */
4740 r = p->r & VT_VALMASK;
4741 /* store register in the stack */
4742 type = &p->type;
4743 if ((p->r & VT_LVAL) ||
4744 (!is_float(type->t) && (type->t & VT_BTYPE) != VT_LLONG))
4745 type = &int_type;
4746 size = type_size(type, &align);
4747 loc = (loc - size) & -align;
4748 sv.type.t = type->t;
4749 sv.r = VT_LOCAL | VT_LVAL;
4750 sv.c.ul = loc;
4751 store(r, &sv);
4752 #ifdef TCC_TARGET_I386
4753 /* x86 specific: need to pop fp register ST0 if saved */
4754 if (r == TREG_ST0) {
4755 o(0xd9dd); /* fstp %st(1) */
4757 #endif
4758 /* special long long case */
4759 if ((type->t & VT_BTYPE) == VT_LLONG) {
4760 sv.c.ul += 4;
4761 store(p->r2, &sv);
4763 l = loc;
4764 saved = 1;
4766 /* mark that stack entry as being saved on the stack */
4767 if (p->r & VT_LVAL) {
4768 /* also clear the bounded flag because the
4769 relocation address of the function was stored in
4770 p->c.ul */
4771 p->r = (p->r & ~(VT_VALMASK | VT_BOUNDED)) | VT_LLOCAL;
4772 } else {
4773 p->r = lvalue_type(p->type.t) | VT_LOCAL;
4775 p->r2 = VT_CONST;
4776 p->c.ul = l;
4781 /* find a register of class 'rc2' with at most one reference on stack.
4782 * If none, call get_reg(rc) */
4783 int get_reg_ex(int rc, int rc2)
4785 int r;
4786 SValue *p;
4788 for(r=0;r<NB_REGS;r++) {
4789 if (reg_classes[r] & rc2) {
4790 int n;
4791 n=0;
4792 for(p = vstack; p <= vtop; p++) {
4793 if ((p->r & VT_VALMASK) == r ||
4794 (p->r2 & VT_VALMASK) == r)
4795 n++;
4797 if (n <= 1)
4798 return r;
4801 return get_reg(rc);
4804 /* find a free register of class 'rc'. If none, save one register */
4805 int get_reg(int rc)
4807 int r;
4808 SValue *p;
4810 /* find a free register */
4811 for(r=0;r<NB_REGS;r++) {
4812 if (reg_classes[r] & rc) {
4813 for(p=vstack;p<=vtop;p++) {
4814 if ((p->r & VT_VALMASK) == r ||
4815 (p->r2 & VT_VALMASK) == r)
4816 goto notfound;
4818 return r;
4820 notfound: ;
4823 /* no register left : free the first one on the stack (VERY
4824 IMPORTANT to start from the bottom to ensure that we don't
4825 spill registers used in gen_opi()) */
4826 for(p=vstack;p<=vtop;p++) {
4827 r = p->r & VT_VALMASK;
4828 if (r < VT_CONST && (reg_classes[r] & rc))
4829 goto save_found;
4830 /* also look at second register (if long long) */
4831 r = p->r2 & VT_VALMASK;
4832 if (r < VT_CONST && (reg_classes[r] & rc)) {
4833 save_found:
4834 save_reg(r);
4835 return r;
4838 /* Should never comes here */
4839 return -1;
4842 /* save registers up to (vtop - n) stack entry */
4843 void save_regs(int n)
4845 int r;
4846 SValue *p, *p1;
4847 p1 = vtop - n;
4848 for(p = vstack;p <= p1; p++) {
4849 r = p->r & VT_VALMASK;
4850 if (r < VT_CONST) {
4851 save_reg(r);
4856 /* move register 's' to 'r', and flush previous value of r to memory
4857 if needed */
4858 void move_reg(int r, int s)
4860 SValue sv;
4862 if (r != s) {
4863 save_reg(r);
4864 sv.type.t = VT_INT;
4865 sv.r = s;
4866 sv.c.ul = 0;
4867 load(r, &sv);
4871 /* get address of vtop (vtop MUST BE an lvalue) */
4872 void gaddrof(void)
4874 vtop->r &= ~VT_LVAL;
4875 /* tricky: if saved lvalue, then we can go back to lvalue */
4876 if ((vtop->r & VT_VALMASK) == VT_LLOCAL)
4877 vtop->r = (vtop->r & ~(VT_VALMASK | VT_LVAL_TYPE)) | VT_LOCAL | VT_LVAL;
4880 #ifdef CONFIG_TCC_BCHECK
4881 /* generate lvalue bound code */
4882 void gbound(void)
4884 int lval_type;
4885 CType type1;
4887 vtop->r &= ~VT_MUSTBOUND;
4888 /* if lvalue, then use checking code before dereferencing */
4889 if (vtop->r & VT_LVAL) {
4890 /* if not VT_BOUNDED value, then make one */
4891 if (!(vtop->r & VT_BOUNDED)) {
4892 lval_type = vtop->r & (VT_LVAL_TYPE | VT_LVAL);
4893 /* must save type because we must set it to int to get pointer */
4894 type1 = vtop->type;
4895 vtop->type.t = VT_INT;
4896 gaddrof();
4897 vpushi(0);
4898 gen_bounded_ptr_add();
4899 vtop->r |= lval_type;
4900 vtop->type = type1;
4902 /* then check for dereferencing */
4903 gen_bounded_ptr_deref();
4906 #endif
4908 /* store vtop a register belonging to class 'rc'. lvalues are
4909 converted to values. Cannot be used if cannot be converted to
4910 register value (such as structures). */
4911 int gv(int rc)
4913 int r, r2, rc2, bit_pos, bit_size, size, align, i;
4914 unsigned long long ll;
4916 /* NOTE: get_reg can modify vstack[] */
4917 if (vtop->type.t & VT_BITFIELD) {
4918 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
4919 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
4920 /* remove bit field info to avoid loops */
4921 vtop->type.t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
4922 /* generate shifts */
4923 vpushi(32 - (bit_pos + bit_size));
4924 gen_op(TOK_SHL);
4925 vpushi(32 - bit_size);
4926 /* NOTE: transformed to SHR if unsigned */
4927 gen_op(TOK_SAR);
4928 r = gv(rc);
4929 } else {
4930 if (is_float(vtop->type.t) &&
4931 (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4932 Sym *sym;
4933 int *ptr;
4934 unsigned long offset;
4935 #if defined(TCC_TARGET_ARM) && !defined(TCC_ARM_VFP)
4936 CValue check;
4937 #endif
4939 /* XXX: unify with initializers handling ? */
4940 /* CPUs usually cannot use float constants, so we store them
4941 generically in data segment */
4942 size = type_size(&vtop->type, &align);
4943 offset = (data_section->data_offset + align - 1) & -align;
4944 data_section->data_offset = offset;
4945 /* XXX: not portable yet */
4946 #ifdef __i386__
4947 /* Zero pad x87 tenbyte long doubles */
4948 if (size == 12)
4949 vtop->c.tab[2] &= 0xffff;
4950 #endif
4951 ptr = section_ptr_add(data_section, size);
4952 size = size >> 2;
4953 #if defined(TCC_TARGET_ARM) && !defined(TCC_ARM_VFP)
4954 check.d = 1;
4955 if(check.tab[0])
4956 for(i=0;i<size;i++)
4957 ptr[i] = vtop->c.tab[size-1-i];
4958 else
4959 #endif
4960 for(i=0;i<size;i++)
4961 ptr[i] = vtop->c.tab[i];
4962 sym = get_sym_ref(&vtop->type, data_section, offset, size << 2);
4963 vtop->r |= VT_LVAL | VT_SYM;
4964 vtop->sym = sym;
4965 vtop->c.ul = 0;
4967 #ifdef CONFIG_TCC_BCHECK
4968 if (vtop->r & VT_MUSTBOUND)
4969 gbound();
4970 #endif
4972 r = vtop->r & VT_VALMASK;
4973 /* need to reload if:
4974 - constant
4975 - lvalue (need to dereference pointer)
4976 - already a register, but not in the right class */
4977 if (r >= VT_CONST ||
4978 (vtop->r & VT_LVAL) ||
4979 !(reg_classes[r] & rc) ||
4980 ((vtop->type.t & VT_BTYPE) == VT_LLONG &&
4981 !(reg_classes[vtop->r2] & rc))) {
4982 r = get_reg(rc);
4983 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
4984 /* two register type load : expand to two words
4985 temporarily */
4986 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4987 /* load constant */
4988 ll = vtop->c.ull;
4989 vtop->c.ui = ll; /* first word */
4990 load(r, vtop);
4991 vtop->r = r; /* save register value */
4992 vpushi(ll >> 32); /* second word */
4993 } else if (r >= VT_CONST || /* XXX: test to VT_CONST incorrect ? */
4994 (vtop->r & VT_LVAL)) {
4995 /* We do not want to modifier the long long
4996 pointer here, so the safest (and less
4997 efficient) is to save all the other registers
4998 in the stack. XXX: totally inefficient. */
4999 save_regs(1);
5000 /* load from memory */
5001 load(r, vtop);
5002 vdup();
5003 vtop[-1].r = r; /* save register value */
5004 /* increment pointer to get second word */
5005 vtop->type.t = VT_INT;
5006 gaddrof();
5007 vpushi(4);
5008 gen_op('+');
5009 vtop->r |= VT_LVAL;
5010 } else {
5011 /* move registers */
5012 load(r, vtop);
5013 vdup();
5014 vtop[-1].r = r; /* save register value */
5015 vtop->r = vtop[-1].r2;
5017 /* allocate second register */
5018 rc2 = RC_INT;
5019 if (rc == RC_IRET)
5020 rc2 = RC_LRET;
5021 r2 = get_reg(rc2);
5022 load(r2, vtop);
5023 vpop();
5024 /* write second register */
5025 vtop->r2 = r2;
5026 } else if ((vtop->r & VT_LVAL) && !is_float(vtop->type.t)) {
5027 int t1, t;
5028 /* lvalue of scalar type : need to use lvalue type
5029 because of possible cast */
5030 t = vtop->type.t;
5031 t1 = t;
5032 /* compute memory access type */
5033 if (vtop->r & VT_LVAL_BYTE)
5034 t = VT_BYTE;
5035 else if (vtop->r & VT_LVAL_SHORT)
5036 t = VT_SHORT;
5037 if (vtop->r & VT_LVAL_UNSIGNED)
5038 t |= VT_UNSIGNED;
5039 vtop->type.t = t;
5040 load(r, vtop);
5041 /* restore wanted type */
5042 vtop->type.t = t1;
5043 } else {
5044 /* one register type load */
5045 load(r, vtop);
5048 vtop->r = r;
5049 #ifdef TCC_TARGET_C67
5050 /* uses register pairs for doubles */
5051 if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE)
5052 vtop->r2 = r+1;
5053 #endif
5055 return r;
5058 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
5059 void gv2(int rc1, int rc2)
5061 int v;
5063 /* generate more generic register first. But VT_JMP or VT_CMP
5064 values must be generated first in all cases to avoid possible
5065 reload errors */
5066 v = vtop[0].r & VT_VALMASK;
5067 if (v != VT_CMP && (v & ~1) != VT_JMP && rc1 <= rc2) {
5068 vswap();
5069 gv(rc1);
5070 vswap();
5071 gv(rc2);
5072 /* test if reload is needed for first register */
5073 if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
5074 vswap();
5075 gv(rc1);
5076 vswap();
5078 } else {
5079 gv(rc2);
5080 vswap();
5081 gv(rc1);
5082 vswap();
5083 /* test if reload is needed for first register */
5084 if ((vtop[0].r & VT_VALMASK) >= VT_CONST) {
5085 gv(rc2);
5090 /* expand long long on stack in two int registers */
5091 void lexpand(void)
5093 int u;
5095 u = vtop->type.t & VT_UNSIGNED;
5096 gv(RC_INT);
5097 vdup();
5098 vtop[0].r = vtop[-1].r2;
5099 vtop[0].r2 = VT_CONST;
5100 vtop[-1].r2 = VT_CONST;
5101 vtop[0].type.t = VT_INT | u;
5102 vtop[-1].type.t = VT_INT | u;
5105 #ifdef TCC_TARGET_ARM
5106 /* expand long long on stack */
5107 void lexpand_nr(void)
5109 int u,v;
5111 u = vtop->type.t & VT_UNSIGNED;
5112 vdup();
5113 vtop->r2 = VT_CONST;
5114 vtop->type.t = VT_INT | u;
5115 v=vtop[-1].r & (VT_VALMASK | VT_LVAL);
5116 if (v == VT_CONST) {
5117 vtop[-1].c.ui = vtop->c.ull;
5118 vtop->c.ui = vtop->c.ull >> 32;
5119 vtop->r = VT_CONST;
5120 } else if (v == (VT_LVAL|VT_CONST) || v == (VT_LVAL|VT_LOCAL)) {
5121 vtop->c.ui += 4;
5122 vtop->r = vtop[-1].r;
5123 } else if (v > VT_CONST) {
5124 vtop--;
5125 lexpand();
5126 } else
5127 vtop->r = vtop[-1].r2;
5128 vtop[-1].r2 = VT_CONST;
5129 vtop[-1].type.t = VT_INT | u;
5131 #endif
5133 /* build a long long from two ints */
5134 void lbuild(int t)
5136 gv2(RC_INT, RC_INT);
5137 vtop[-1].r2 = vtop[0].r;
5138 vtop[-1].type.t = t;
5139 vpop();
5142 /* rotate n first stack elements to the bottom
5143 I1 ... In -> I2 ... In I1 [top is right]
5145 void vrotb(int n)
5147 int i;
5148 SValue tmp;
5150 tmp = vtop[-n + 1];
5151 for(i=-n+1;i!=0;i++)
5152 vtop[i] = vtop[i+1];
5153 vtop[0] = tmp;
5156 /* rotate n first stack elements to the top
5157 I1 ... In -> In I1 ... I(n-1) [top is right]
5159 void vrott(int n)
5161 int i;
5162 SValue tmp;
5164 tmp = vtop[0];
5165 for(i = 0;i < n - 1; i++)
5166 vtop[-i] = vtop[-i - 1];
5167 vtop[-n + 1] = tmp;
5170 #ifdef TCC_TARGET_ARM
5171 /* like vrott but in other direction
5172 In ... I1 -> I(n-1) ... I1 In [top is right]
5174 void vnrott(int n)
5176 int i;
5177 SValue tmp;
5179 tmp = vtop[-n + 1];
5180 for(i = n - 1; i > 0; i--)
5181 vtop[-i] = vtop[-i + 1];
5182 vtop[0] = tmp;
5184 #endif
5186 /* pop stack value */
5187 void vpop(void)
5189 int v;
5190 v = vtop->r & VT_VALMASK;
5191 #ifdef TCC_TARGET_I386
5192 /* for x86, we need to pop the FP stack */
5193 if (v == TREG_ST0 && !nocode_wanted) {
5194 o(0xd9dd); /* fstp %st(1) */
5195 } else
5196 #endif
5197 if (v == VT_JMP || v == VT_JMPI) {
5198 /* need to put correct jump if && or || without test */
5199 gsym(vtop->c.ul);
5201 vtop--;
5204 /* convert stack entry to register and duplicate its value in another
5205 register */
5206 void gv_dup(void)
5208 int rc, t, r, r1;
5209 SValue sv;
5211 t = vtop->type.t;
5212 if ((t & VT_BTYPE) == VT_LLONG) {
5213 lexpand();
5214 gv_dup();
5215 vswap();
5216 vrotb(3);
5217 gv_dup();
5218 vrotb(4);
5219 /* stack: H L L1 H1 */
5220 lbuild(t);
5221 vrotb(3);
5222 vrotb(3);
5223 vswap();
5224 lbuild(t);
5225 vswap();
5226 } else {
5227 /* duplicate value */
5228 rc = RC_INT;
5229 sv.type.t = VT_INT;
5230 if (is_float(t)) {
5231 rc = RC_FLOAT;
5232 sv.type.t = t;
5234 r = gv(rc);
5235 r1 = get_reg(rc);
5236 sv.r = r;
5237 sv.c.ul = 0;
5238 load(r1, &sv); /* move r to r1 */
5239 vdup();
5240 /* duplicates value */
5241 vtop->r = r1;
5245 /* generate CPU independent (unsigned) long long operations */
5246 void gen_opl(int op)
5248 int t, a, b, op1, c, i;
5249 int func;
5250 SValue tmp;
5252 switch(op) {
5253 case '/':
5254 case TOK_PDIV:
5255 func = TOK___divdi3;
5256 goto gen_func;
5257 case TOK_UDIV:
5258 func = TOK___udivdi3;
5259 goto gen_func;
5260 case '%':
5261 func = TOK___moddi3;
5262 goto gen_func;
5263 case TOK_UMOD:
5264 func = TOK___umoddi3;
5265 gen_func:
5266 /* call generic long long function */
5267 vpush_global_sym(&func_old_type, func);
5268 vrott(3);
5269 gfunc_call(2);
5270 vpushi(0);
5271 vtop->r = REG_IRET;
5272 vtop->r2 = REG_LRET;
5273 break;
5274 case '^':
5275 case '&':
5276 case '|':
5277 case '*':
5278 case '+':
5279 case '-':
5280 t = vtop->type.t;
5281 vswap();
5282 lexpand();
5283 vrotb(3);
5284 lexpand();
5285 /* stack: L1 H1 L2 H2 */
5286 tmp = vtop[0];
5287 vtop[0] = vtop[-3];
5288 vtop[-3] = tmp;
5289 tmp = vtop[-2];
5290 vtop[-2] = vtop[-3];
5291 vtop[-3] = tmp;
5292 vswap();
5293 /* stack: H1 H2 L1 L2 */
5294 if (op == '*') {
5295 vpushv(vtop - 1);
5296 vpushv(vtop - 1);
5297 gen_op(TOK_UMULL);
5298 lexpand();
5299 /* stack: H1 H2 L1 L2 ML MH */
5300 for(i=0;i<4;i++)
5301 vrotb(6);
5302 /* stack: ML MH H1 H2 L1 L2 */
5303 tmp = vtop[0];
5304 vtop[0] = vtop[-2];
5305 vtop[-2] = tmp;
5306 /* stack: ML MH H1 L2 H2 L1 */
5307 gen_op('*');
5308 vrotb(3);
5309 vrotb(3);
5310 gen_op('*');
5311 /* stack: ML MH M1 M2 */
5312 gen_op('+');
5313 gen_op('+');
5314 } else if (op == '+' || op == '-') {
5315 /* XXX: add non carry method too (for MIPS or alpha) */
5316 if (op == '+')
5317 op1 = TOK_ADDC1;
5318 else
5319 op1 = TOK_SUBC1;
5320 gen_op(op1);
5321 /* stack: H1 H2 (L1 op L2) */
5322 vrotb(3);
5323 vrotb(3);
5324 gen_op(op1 + 1); /* TOK_xxxC2 */
5325 } else {
5326 gen_op(op);
5327 /* stack: H1 H2 (L1 op L2) */
5328 vrotb(3);
5329 vrotb(3);
5330 /* stack: (L1 op L2) H1 H2 */
5331 gen_op(op);
5332 /* stack: (L1 op L2) (H1 op H2) */
5334 /* stack: L H */
5335 lbuild(t);
5336 break;
5337 case TOK_SAR:
5338 case TOK_SHR:
5339 case TOK_SHL:
5340 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
5341 t = vtop[-1].type.t;
5342 vswap();
5343 lexpand();
5344 vrotb(3);
5345 /* stack: L H shift */
5346 c = (int)vtop->c.i;
5347 /* constant: simpler */
5348 /* NOTE: all comments are for SHL. the other cases are
5349 done by swaping words */
5350 vpop();
5351 if (op != TOK_SHL)
5352 vswap();
5353 if (c >= 32) {
5354 /* stack: L H */
5355 vpop();
5356 if (c > 32) {
5357 vpushi(c - 32);
5358 gen_op(op);
5360 if (op != TOK_SAR) {
5361 vpushi(0);
5362 } else {
5363 gv_dup();
5364 vpushi(31);
5365 gen_op(TOK_SAR);
5367 vswap();
5368 } else {
5369 vswap();
5370 gv_dup();
5371 /* stack: H L L */
5372 vpushi(c);
5373 gen_op(op);
5374 vswap();
5375 vpushi(32 - c);
5376 if (op == TOK_SHL)
5377 gen_op(TOK_SHR);
5378 else
5379 gen_op(TOK_SHL);
5380 vrotb(3);
5381 /* stack: L L H */
5382 vpushi(c);
5383 if (op == TOK_SHL)
5384 gen_op(TOK_SHL);
5385 else
5386 gen_op(TOK_SHR);
5387 gen_op('|');
5389 if (op != TOK_SHL)
5390 vswap();
5391 lbuild(t);
5392 } else {
5393 /* XXX: should provide a faster fallback on x86 ? */
5394 switch(op) {
5395 case TOK_SAR:
5396 func = TOK___sardi3;
5397 goto gen_func;
5398 case TOK_SHR:
5399 func = TOK___shrdi3;
5400 goto gen_func;
5401 case TOK_SHL:
5402 func = TOK___shldi3;
5403 goto gen_func;
5406 break;
5407 default:
5408 /* compare operations */
5409 t = vtop->type.t;
5410 vswap();
5411 lexpand();
5412 vrotb(3);
5413 lexpand();
5414 /* stack: L1 H1 L2 H2 */
5415 tmp = vtop[-1];
5416 vtop[-1] = vtop[-2];
5417 vtop[-2] = tmp;
5418 /* stack: L1 L2 H1 H2 */
5419 /* compare high */
5420 op1 = op;
5421 /* when values are equal, we need to compare low words. since
5422 the jump is inverted, we invert the test too. */
5423 if (op1 == TOK_LT)
5424 op1 = TOK_LE;
5425 else if (op1 == TOK_GT)
5426 op1 = TOK_GE;
5427 else if (op1 == TOK_ULT)
5428 op1 = TOK_ULE;
5429 else if (op1 == TOK_UGT)
5430 op1 = TOK_UGE;
5431 a = 0;
5432 b = 0;
5433 gen_op(op1);
5434 if (op1 != TOK_NE) {
5435 a = gtst(1, 0);
5437 if (op != TOK_EQ) {
5438 /* generate non equal test */
5439 /* XXX: NOT PORTABLE yet */
5440 if (a == 0) {
5441 b = gtst(0, 0);
5442 } else {
5443 #if defined(TCC_TARGET_I386)
5444 b = psym(0x850f, 0);
5445 #elif defined(TCC_TARGET_ARM)
5446 b = ind;
5447 o(0x1A000000 | encbranch(ind, 0, 1));
5448 #elif defined(TCC_TARGET_C67)
5449 error("not implemented");
5450 #else
5451 #error not supported
5452 #endif
5455 /* compare low. Always unsigned */
5456 op1 = op;
5457 if (op1 == TOK_LT)
5458 op1 = TOK_ULT;
5459 else if (op1 == TOK_LE)
5460 op1 = TOK_ULE;
5461 else if (op1 == TOK_GT)
5462 op1 = TOK_UGT;
5463 else if (op1 == TOK_GE)
5464 op1 = TOK_UGE;
5465 gen_op(op1);
5466 a = gtst(1, a);
5467 gsym(b);
5468 vseti(VT_JMPI, a);
5469 break;
5473 /* handle integer constant optimizations and various machine
5474 independent opt */
5475 void gen_opic(int op)
5477 int c1, c2, t1, t2, n;
5478 SValue *v1, *v2;
5479 long long l1, l2;
5480 typedef unsigned long long U;
5482 v1 = vtop - 1;
5483 v2 = vtop;
5484 t1 = v1->type.t & VT_BTYPE;
5485 t2 = v2->type.t & VT_BTYPE;
5486 l1 = (t1 == VT_LLONG) ? v1->c.ll : v1->c.i;
5487 l2 = (t2 == VT_LLONG) ? v2->c.ll : v2->c.i;
5489 /* currently, we cannot do computations with forward symbols */
5490 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5491 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5492 if (c1 && c2) {
5493 switch(op) {
5494 case '+': l1 += l2; break;
5495 case '-': l1 -= l2; break;
5496 case '&': l1 &= l2; break;
5497 case '^': l1 ^= l2; break;
5498 case '|': l1 |= l2; break;
5499 case '*': l1 *= l2; break;
5501 case TOK_PDIV:
5502 case '/':
5503 case '%':
5504 case TOK_UDIV:
5505 case TOK_UMOD:
5506 /* if division by zero, generate explicit division */
5507 if (l2 == 0) {
5508 if (const_wanted)
5509 error("division by zero in constant");
5510 goto general_case;
5512 switch(op) {
5513 default: l1 /= l2; break;
5514 case '%': l1 %= l2; break;
5515 case TOK_UDIV: l1 = (U)l1 / l2; break;
5516 case TOK_UMOD: l1 = (U)l1 % l2; break;
5518 break;
5519 case TOK_SHL: l1 <<= l2; break;
5520 case TOK_SHR: l1 = (U)l1 >> l2; break;
5521 case TOK_SAR: l1 >>= l2; break;
5522 /* tests */
5523 case TOK_ULT: l1 = (U)l1 < (U)l2; break;
5524 case TOK_UGE: l1 = (U)l1 >= (U)l2; break;
5525 case TOK_EQ: l1 = l1 == l2; break;
5526 case TOK_NE: l1 = l1 != l2; break;
5527 case TOK_ULE: l1 = (U)l1 <= (U)l2; break;
5528 case TOK_UGT: l1 = (U)l1 > (U)l2; break;
5529 case TOK_LT: l1 = l1 < l2; break;
5530 case TOK_GE: l1 = l1 >= l2; break;
5531 case TOK_LE: l1 = l1 <= l2; break;
5532 case TOK_GT: l1 = l1 > l2; break;
5533 /* logical */
5534 case TOK_LAND: l1 = l1 && l2; break;
5535 case TOK_LOR: l1 = l1 || l2; break;
5536 default:
5537 goto general_case;
5539 v1->c.ll = l1;
5540 vtop--;
5541 } else {
5542 /* if commutative ops, put c2 as constant */
5543 if (c1 && (op == '+' || op == '&' || op == '^' ||
5544 op == '|' || op == '*')) {
5545 vswap();
5546 c2 = c1; //c = c1, c1 = c2, c2 = c;
5547 l2 = l1; //l = l1, l1 = l2, l2 = l;
5549 /* Filter out NOP operations like x*1, x-0, x&-1... */
5550 if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
5551 op == TOK_PDIV) &&
5552 l2 == 1) ||
5553 ((op == '+' || op == '-' || op == '|' || op == '^' ||
5554 op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
5555 l2 == 0) ||
5556 (op == '&' &&
5557 l2 == -1))) {
5558 /* nothing to do */
5559 vtop--;
5560 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
5561 /* try to use shifts instead of muls or divs */
5562 if (l2 > 0 && (l2 & (l2 - 1)) == 0) {
5563 n = -1;
5564 while (l2) {
5565 l2 >>= 1;
5566 n++;
5568 vtop->c.ll = n;
5569 if (op == '*')
5570 op = TOK_SHL;
5571 else if (op == TOK_PDIV)
5572 op = TOK_SAR;
5573 else
5574 op = TOK_SHR;
5576 goto general_case;
5577 } else if (c2 && (op == '+' || op == '-') &&
5578 (vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) ==
5579 (VT_CONST | VT_SYM)) {
5580 /* symbol + constant case */
5581 if (op == '-')
5582 l2 = -l2;
5583 vtop--;
5584 vtop->c.ll += l2;
5585 } else {
5586 general_case:
5587 if (!nocode_wanted) {
5588 /* call low level op generator */
5589 if (t1 == VT_LLONG || t2 == VT_LLONG)
5590 gen_opl(op);
5591 else
5592 gen_opi(op);
5593 } else {
5594 vtop--;
5600 /* generate a floating point operation with constant propagation */
5601 void gen_opif(int op)
5603 int c1, c2;
5604 SValue *v1, *v2;
5605 long double f1, f2;
5607 v1 = vtop - 1;
5608 v2 = vtop;
5609 /* currently, we cannot do computations with forward symbols */
5610 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5611 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5612 if (c1 && c2) {
5613 if (v1->type.t == VT_FLOAT) {
5614 f1 = v1->c.f;
5615 f2 = v2->c.f;
5616 } else if (v1->type.t == VT_DOUBLE) {
5617 f1 = v1->c.d;
5618 f2 = v2->c.d;
5619 } else {
5620 f1 = v1->c.ld;
5621 f2 = v2->c.ld;
5624 /* NOTE: we only do constant propagation if finite number (not
5625 NaN or infinity) (ANSI spec) */
5626 if (!ieee_finite(f1) || !ieee_finite(f2))
5627 goto general_case;
5629 switch(op) {
5630 case '+': f1 += f2; break;
5631 case '-': f1 -= f2; break;
5632 case '*': f1 *= f2; break;
5633 case '/':
5634 if (f2 == 0.0) {
5635 if (const_wanted)
5636 error("division by zero in constant");
5637 goto general_case;
5639 f1 /= f2;
5640 break;
5641 /* XXX: also handles tests ? */
5642 default:
5643 goto general_case;
5645 /* XXX: overflow test ? */
5646 if (v1->type.t == VT_FLOAT) {
5647 v1->c.f = f1;
5648 } else if (v1->type.t == VT_DOUBLE) {
5649 v1->c.d = f1;
5650 } else {
5651 v1->c.ld = f1;
5653 vtop--;
5654 } else {
5655 general_case:
5656 if (!nocode_wanted) {
5657 gen_opf(op);
5658 } else {
5659 vtop--;
5664 static int pointed_size(CType *type)
5666 int align;
5667 return type_size(pointed_type(type), &align);
5670 static inline int is_null_pointer(SValue *p)
5672 if ((p->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
5673 return 0;
5674 return ((p->type.t & VT_BTYPE) == VT_INT && p->c.i == 0) ||
5675 ((p->type.t & VT_BTYPE) == VT_LLONG && p->c.ll == 0);
5678 static inline int is_integer_btype(int bt)
5680 return (bt == VT_BYTE || bt == VT_SHORT ||
5681 bt == VT_INT || bt == VT_LLONG);
5684 /* check types for comparison or substraction of pointers */
5685 static void check_comparison_pointer_types(SValue *p1, SValue *p2, int op)
5687 CType *type1, *type2, tmp_type1, tmp_type2;
5688 int bt1, bt2;
5690 /* null pointers are accepted for all comparisons as gcc */
5691 if (is_null_pointer(p1) || is_null_pointer(p2))
5692 return;
5693 type1 = &p1->type;
5694 type2 = &p2->type;
5695 bt1 = type1->t & VT_BTYPE;
5696 bt2 = type2->t & VT_BTYPE;
5697 /* accept comparison between pointer and integer with a warning */
5698 if ((is_integer_btype(bt1) || is_integer_btype(bt2)) && op != '-') {
5699 if (op != TOK_LOR && op != TOK_LAND )
5700 warning("comparison between pointer and integer");
5701 return;
5704 /* both must be pointers or implicit function pointers */
5705 if (bt1 == VT_PTR) {
5706 type1 = pointed_type(type1);
5707 } else if (bt1 != VT_FUNC)
5708 goto invalid_operands;
5710 if (bt2 == VT_PTR) {
5711 type2 = pointed_type(type2);
5712 } else if (bt2 != VT_FUNC) {
5713 invalid_operands:
5714 error("invalid operands to binary %s", get_tok_str(op, NULL));
5716 if ((type1->t & VT_BTYPE) == VT_VOID ||
5717 (type2->t & VT_BTYPE) == VT_VOID)
5718 return;
5719 tmp_type1 = *type1;
5720 tmp_type2 = *type2;
5721 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5722 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5723 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
5724 /* gcc-like error if '-' is used */
5725 if (op == '-')
5726 goto invalid_operands;
5727 else
5728 warning("comparison of distinct pointer types lacks a cast");
5732 /* generic gen_op: handles types problems */
5733 void gen_op(int op)
5735 int u, t1, t2, bt1, bt2, t;
5736 CType type1;
5738 t1 = vtop[-1].type.t;
5739 t2 = vtop[0].type.t;
5740 bt1 = t1 & VT_BTYPE;
5741 bt2 = t2 & VT_BTYPE;
5743 if (bt1 == VT_PTR || bt2 == VT_PTR) {
5744 /* at least one operand is a pointer */
5745 /* relationnal op: must be both pointers */
5746 if (op >= TOK_ULT && op <= TOK_LOR) {
5747 check_comparison_pointer_types(vtop - 1, vtop, op);
5748 /* pointers are handled are unsigned */
5749 t = VT_INT | VT_UNSIGNED;
5750 goto std_op;
5752 /* if both pointers, then it must be the '-' op */
5753 if (bt1 == VT_PTR && bt2 == VT_PTR) {
5754 if (op != '-')
5755 error("cannot use pointers here");
5756 check_comparison_pointer_types(vtop - 1, vtop, op);
5757 /* XXX: check that types are compatible */
5758 u = pointed_size(&vtop[-1].type);
5759 gen_opic(op);
5760 /* set to integer type */
5761 vtop->type.t = VT_INT;
5762 vpushi(u);
5763 gen_op(TOK_PDIV);
5764 } else {
5765 /* exactly one pointer : must be '+' or '-'. */
5766 if (op != '-' && op != '+')
5767 error("cannot use pointers here");
5768 /* Put pointer as first operand */
5769 if (bt2 == VT_PTR) {
5770 vswap();
5771 swap(&t1, &t2);
5773 type1 = vtop[-1].type;
5774 /* XXX: cast to int ? (long long case) */
5775 vpushi(pointed_size(&vtop[-1].type));
5776 gen_op('*');
5777 #ifdef CONFIG_TCC_BCHECK
5778 /* if evaluating constant expression, no code should be
5779 generated, so no bound check */
5780 if (do_bounds_check && !const_wanted) {
5781 /* if bounded pointers, we generate a special code to
5782 test bounds */
5783 if (op == '-') {
5784 vpushi(0);
5785 vswap();
5786 gen_op('-');
5788 gen_bounded_ptr_add();
5789 } else
5790 #endif
5792 gen_opic(op);
5794 /* put again type if gen_opic() swaped operands */
5795 vtop->type = type1;
5797 } else if (is_float(bt1) || is_float(bt2)) {
5798 /* compute bigger type and do implicit casts */
5799 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
5800 t = VT_LDOUBLE;
5801 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
5802 t = VT_DOUBLE;
5803 } else {
5804 t = VT_FLOAT;
5806 /* floats can only be used for a few operations */
5807 if (op != '+' && op != '-' && op != '*' && op != '/' &&
5808 (op < TOK_ULT || op > TOK_GT))
5809 error("invalid operands for binary operation");
5810 goto std_op;
5811 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
5812 /* cast to biggest op */
5813 t = VT_LLONG;
5814 /* convert to unsigned if it does not fit in a long long */
5815 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
5816 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
5817 t |= VT_UNSIGNED;
5818 goto std_op;
5819 } else {
5820 /* integer operations */
5821 t = VT_INT;
5822 /* convert to unsigned if it does not fit in an integer */
5823 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
5824 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
5825 t |= VT_UNSIGNED;
5826 std_op:
5827 /* XXX: currently, some unsigned operations are explicit, so
5828 we modify them here */
5829 if (t & VT_UNSIGNED) {
5830 if (op == TOK_SAR)
5831 op = TOK_SHR;
5832 else if (op == '/')
5833 op = TOK_UDIV;
5834 else if (op == '%')
5835 op = TOK_UMOD;
5836 else if (op == TOK_LT)
5837 op = TOK_ULT;
5838 else if (op == TOK_GT)
5839 op = TOK_UGT;
5840 else if (op == TOK_LE)
5841 op = TOK_ULE;
5842 else if (op == TOK_GE)
5843 op = TOK_UGE;
5845 vswap();
5846 type1.t = t;
5847 gen_cast(&type1);
5848 vswap();
5849 /* special case for shifts and long long: we keep the shift as
5850 an integer */
5851 if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL)
5852 type1.t = VT_INT;
5853 gen_cast(&type1);
5854 if (is_float(t))
5855 gen_opif(op);
5856 else
5857 gen_opic(op);
5858 if (op >= TOK_ULT && op <= TOK_GT) {
5859 /* relationnal op: the result is an int */
5860 vtop->type.t = VT_INT;
5861 } else {
5862 vtop->type.t = t;
5867 /* generic itof for unsigned long long case */
5868 void gen_cvt_itof1(int t)
5870 if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
5871 (VT_LLONG | VT_UNSIGNED)) {
5873 if (t == VT_FLOAT)
5874 vpush_global_sym(&func_old_type, TOK___ulltof);
5875 else if (t == VT_DOUBLE)
5876 vpush_global_sym(&func_old_type, TOK___ulltod);
5877 else
5878 vpush_global_sym(&func_old_type, TOK___ulltold);
5879 vrott(2);
5880 gfunc_call(1);
5881 vpushi(0);
5882 vtop->r = REG_FRET;
5883 } else {
5884 gen_cvt_itof(t);
5888 /* generic ftoi for unsigned long long case */
5889 void gen_cvt_ftoi1(int t)
5891 int st;
5893 if (t == (VT_LLONG | VT_UNSIGNED)) {
5894 /* not handled natively */
5895 st = vtop->type.t & VT_BTYPE;
5896 if (st == VT_FLOAT)
5897 vpush_global_sym(&func_old_type, TOK___fixunssfdi);
5898 else if (st == VT_DOUBLE)
5899 vpush_global_sym(&func_old_type, TOK___fixunsdfdi);
5900 else
5901 vpush_global_sym(&func_old_type, TOK___fixunsxfdi);
5902 vrott(2);
5903 gfunc_call(1);
5904 vpushi(0);
5905 vtop->r = REG_IRET;
5906 vtop->r2 = REG_LRET;
5907 } else {
5908 gen_cvt_ftoi(t);
5912 /* force char or short cast */
5913 void force_charshort_cast(int t)
5915 int bits, dbt;
5916 dbt = t & VT_BTYPE;
5917 /* XXX: add optimization if lvalue : just change type and offset */
5918 if (dbt == VT_BYTE)
5919 bits = 8;
5920 else
5921 bits = 16;
5922 if (t & VT_UNSIGNED) {
5923 vpushi((1 << bits) - 1);
5924 gen_op('&');
5925 } else {
5926 bits = 32 - bits;
5927 vpushi(bits);
5928 gen_op(TOK_SHL);
5929 /* result must be signed or the SAR is converted to an SHL
5930 This was not the case when "t" was a signed short
5931 and the last value on the stack was an unsigned int */
5932 vtop->type.t &= ~VT_UNSIGNED;
5933 vpushi(bits);
5934 gen_op(TOK_SAR);
5938 /* cast 'vtop' to 'type'. Casting to bitfields is forbidden. */
5939 static void gen_cast(CType *type)
5941 int sbt, dbt, sf, df, c;
5943 /* special delayed cast for char/short */
5944 /* XXX: in some cases (multiple cascaded casts), it may still
5945 be incorrect */
5946 if (vtop->r & VT_MUSTCAST) {
5947 vtop->r &= ~VT_MUSTCAST;
5948 force_charshort_cast(vtop->type.t);
5951 /* bitfields first get cast to ints */
5952 if (vtop->type.t & VT_BITFIELD) {
5953 gv(RC_INT);
5956 dbt = type->t & (VT_BTYPE | VT_UNSIGNED);
5957 sbt = vtop->type.t & (VT_BTYPE | VT_UNSIGNED);
5959 if (sbt != dbt && !nocode_wanted) {
5960 sf = is_float(sbt);
5961 df = is_float(dbt);
5962 c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5963 if (sf && df) {
5964 /* convert from fp to fp */
5965 if (c) {
5966 /* constant case: we can do it now */
5967 /* XXX: in ISOC, cannot do it if error in convert */
5968 if (dbt == VT_FLOAT && sbt == VT_DOUBLE)
5969 vtop->c.f = (float)vtop->c.d;
5970 else if (dbt == VT_FLOAT && sbt == VT_LDOUBLE)
5971 vtop->c.f = (float)vtop->c.ld;
5972 else if (dbt == VT_DOUBLE && sbt == VT_FLOAT)
5973 vtop->c.d = (double)vtop->c.f;
5974 else if (dbt == VT_DOUBLE && sbt == VT_LDOUBLE)
5975 vtop->c.d = (double)vtop->c.ld;
5976 else if (dbt == VT_LDOUBLE && sbt == VT_FLOAT)
5977 vtop->c.ld = (long double)vtop->c.f;
5978 else if (dbt == VT_LDOUBLE && sbt == VT_DOUBLE)
5979 vtop->c.ld = (long double)vtop->c.d;
5980 } else {
5981 /* non constant case: generate code */
5982 gen_cvt_ftof(dbt);
5984 } else if (df) {
5985 /* convert int to fp */
5986 if (c) {
5987 switch(sbt) {
5988 case VT_LLONG | VT_UNSIGNED:
5989 case VT_LLONG:
5990 /* XXX: add const cases for long long */
5991 goto do_itof;
5992 case VT_INT | VT_UNSIGNED:
5993 switch(dbt) {
5994 case VT_FLOAT: vtop->c.f = (float)vtop->c.ui; break;
5995 case VT_DOUBLE: vtop->c.d = (double)vtop->c.ui; break;
5996 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.ui; break;
5998 break;
5999 default:
6000 switch(dbt) {
6001 case VT_FLOAT: vtop->c.f = (float)vtop->c.i; break;
6002 case VT_DOUBLE: vtop->c.d = (double)vtop->c.i; break;
6003 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.i; break;
6005 break;
6007 } else {
6008 do_itof:
6009 #if !defined(TCC_TARGET_ARM)
6010 gen_cvt_itof1(dbt);
6011 #else
6012 gen_cvt_itof(dbt);
6013 #endif
6015 } else if (sf) {
6016 /* convert fp to int */
6017 if (dbt == VT_BOOL) {
6018 vpushi(0);
6019 gen_op(TOK_NE);
6020 } else {
6021 /* we handle char/short/etc... with generic code */
6022 if (dbt != (VT_INT | VT_UNSIGNED) &&
6023 dbt != (VT_LLONG | VT_UNSIGNED) &&
6024 dbt != VT_LLONG)
6025 dbt = VT_INT;
6026 if (c) {
6027 switch(dbt) {
6028 case VT_LLONG | VT_UNSIGNED:
6029 case VT_LLONG:
6030 /* XXX: add const cases for long long */
6031 goto do_ftoi;
6032 case VT_INT | VT_UNSIGNED:
6033 switch(sbt) {
6034 case VT_FLOAT: vtop->c.ui = (unsigned int)vtop->c.d; break;
6035 case VT_DOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
6036 case VT_LDOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
6038 break;
6039 default:
6040 /* int case */
6041 switch(sbt) {
6042 case VT_FLOAT: vtop->c.i = (int)vtop->c.d; break;
6043 case VT_DOUBLE: vtop->c.i = (int)vtop->c.d; break;
6044 case VT_LDOUBLE: vtop->c.i = (int)vtop->c.d; break;
6046 break;
6048 } else {
6049 do_ftoi:
6050 gen_cvt_ftoi1(dbt);
6052 if (dbt == VT_INT && (type->t & (VT_BTYPE | VT_UNSIGNED)) != dbt) {
6053 /* additional cast for char/short... */
6054 vtop->type.t = dbt;
6055 gen_cast(type);
6058 } else if ((dbt & VT_BTYPE) == VT_LLONG) {
6059 if ((sbt & VT_BTYPE) != VT_LLONG) {
6060 /* scalar to long long */
6061 if (c) {
6062 if (sbt == (VT_INT | VT_UNSIGNED))
6063 vtop->c.ll = vtop->c.ui;
6064 else
6065 vtop->c.ll = vtop->c.i;
6066 } else {
6067 /* machine independent conversion */
6068 gv(RC_INT);
6069 /* generate high word */
6070 if (sbt == (VT_INT | VT_UNSIGNED)) {
6071 vpushi(0);
6072 gv(RC_INT);
6073 } else {
6074 gv_dup();
6075 vpushi(31);
6076 gen_op(TOK_SAR);
6078 /* patch second register */
6079 vtop[-1].r2 = vtop->r;
6080 vpop();
6083 } else if (dbt == VT_BOOL) {
6084 /* scalar to bool */
6085 vpushi(0);
6086 gen_op(TOK_NE);
6087 } else if ((dbt & VT_BTYPE) == VT_BYTE ||
6088 (dbt & VT_BTYPE) == VT_SHORT) {
6089 if (sbt == VT_PTR) {
6090 vtop->type.t = VT_INT;
6091 warning("nonportable conversion from pointer to char/short");
6093 force_charshort_cast(dbt);
6094 } else if ((dbt & VT_BTYPE) == VT_INT) {
6095 /* scalar to int */
6096 if (sbt == VT_LLONG) {
6097 /* from long long: just take low order word */
6098 lexpand();
6099 vpop();
6101 /* if lvalue and single word type, nothing to do because
6102 the lvalue already contains the real type size (see
6103 VT_LVAL_xxx constants) */
6105 } else if ((dbt & VT_BTYPE) == VT_PTR && !(vtop->r & VT_LVAL)) {
6106 /* if we are casting between pointer types,
6107 we must update the VT_LVAL_xxx size */
6108 vtop->r = (vtop->r & ~VT_LVAL_TYPE)
6109 | (lvalue_type(type->ref->type.t) & VT_LVAL_TYPE);
6111 vtop->type = *type;
6114 /* return type size. Put alignment at 'a' */
6115 static int type_size(CType *type, int *a)
6117 Sym *s;
6118 int bt;
6120 bt = type->t & VT_BTYPE;
6121 if (bt == VT_STRUCT) {
6122 /* struct/union */
6123 s = type->ref;
6124 *a = s->r;
6125 return s->c;
6126 } else if (bt == VT_PTR) {
6127 if (type->t & VT_ARRAY) {
6128 s = type->ref;
6129 return type_size(&s->type, a) * s->c;
6130 } else {
6131 *a = PTR_SIZE;
6132 return PTR_SIZE;
6134 } else if (bt == VT_LDOUBLE) {
6135 *a = LDOUBLE_ALIGN;
6136 return LDOUBLE_SIZE;
6137 } else if (bt == VT_DOUBLE || bt == VT_LLONG) {
6138 #ifdef TCC_TARGET_I386
6139 *a = 4;
6140 #elif defined(TCC_TARGET_ARM)
6141 #ifdef TCC_ARM_EABI
6142 *a = 8;
6143 #else
6144 *a = 4;
6145 #endif
6146 #else
6147 *a = 8;
6148 #endif
6149 return 8;
6150 } else if (bt == VT_INT || bt == VT_ENUM || bt == VT_FLOAT) {
6151 *a = 4;
6152 return 4;
6153 } else if (bt == VT_SHORT) {
6154 *a = 2;
6155 return 2;
6156 } else {
6157 /* char, void, function, _Bool */
6158 *a = 1;
6159 return 1;
6163 /* return the pointed type of t */
6164 static inline CType *pointed_type(CType *type)
6166 return &type->ref->type;
6169 /* modify type so that its it is a pointer to type. */
6170 static void mk_pointer(CType *type)
6172 Sym *s;
6173 s = sym_push(SYM_FIELD, type, 0, -1);
6174 type->t = VT_PTR | (type->t & ~VT_TYPE);
6175 type->ref = s;
6178 /* compare function types. OLD functions match any new functions */
6179 static int is_compatible_func(CType *type1, CType *type2)
6181 Sym *s1, *s2;
6183 s1 = type1->ref;
6184 s2 = type2->ref;
6185 if (!is_compatible_types(&s1->type, &s2->type))
6186 return 0;
6187 /* check func_call */
6188 if (FUNC_CALL(s1->r) != FUNC_CALL(s2->r))
6189 return 0;
6190 /* XXX: not complete */
6191 if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
6192 return 1;
6193 if (s1->c != s2->c)
6194 return 0;
6195 while (s1 != NULL) {
6196 if (s2 == NULL)
6197 return 0;
6198 if (!is_compatible_parameter_types(&s1->type, &s2->type))
6199 return 0;
6200 s1 = s1->next;
6201 s2 = s2->next;
6203 if (s2)
6204 return 0;
6205 return 1;
6208 /* return true if type1 and type2 are the same. If unqualified is
6209 true, qualifiers on the types are ignored.
6211 - enums are not checked as gcc __builtin_types_compatible_p ()
6213 static int compare_types(CType *type1, CType *type2, int unqualified)
6215 int bt1, t1, t2;
6217 t1 = type1->t & VT_TYPE;
6218 t2 = type2->t & VT_TYPE;
6219 if (unqualified) {
6220 /* strip qualifiers before comparing */
6221 t1 &= ~(VT_CONSTANT | VT_VOLATILE);
6222 t2 &= ~(VT_CONSTANT | VT_VOLATILE);
6224 /* XXX: bitfields ? */
6225 if (t1 != t2)
6226 return 0;
6227 /* test more complicated cases */
6228 bt1 = t1 & VT_BTYPE;
6229 if (bt1 == VT_PTR) {
6230 type1 = pointed_type(type1);
6231 type2 = pointed_type(type2);
6232 return is_compatible_types(type1, type2);
6233 } else if (bt1 == VT_STRUCT) {
6234 return (type1->ref == type2->ref);
6235 } else if (bt1 == VT_FUNC) {
6236 return is_compatible_func(type1, type2);
6237 } else {
6238 return 1;
6242 /* return true if type1 and type2 are exactly the same (including
6243 qualifiers).
6245 static int is_compatible_types(CType *type1, CType *type2)
6247 return compare_types(type1,type2,0);
6250 /* return true if type1 and type2 are the same (ignoring qualifiers).
6252 static int is_compatible_parameter_types(CType *type1, CType *type2)
6254 return compare_types(type1,type2,1);
6257 /* print a type. If 'varstr' is not NULL, then the variable is also
6258 printed in the type */
6259 /* XXX: union */
6260 /* XXX: add array and function pointers */
6261 void type_to_str(char *buf, int buf_size,
6262 CType *type, const char *varstr)
6264 int bt, v, t;
6265 Sym *s, *sa;
6266 char buf1[256];
6267 const char *tstr;
6269 t = type->t & VT_TYPE;
6270 bt = t & VT_BTYPE;
6271 buf[0] = '\0';
6272 if (t & VT_CONSTANT)
6273 pstrcat(buf, buf_size, "const ");
6274 if (t & VT_VOLATILE)
6275 pstrcat(buf, buf_size, "volatile ");
6276 if (t & VT_UNSIGNED)
6277 pstrcat(buf, buf_size, "unsigned ");
6278 switch(bt) {
6279 case VT_VOID:
6280 tstr = "void";
6281 goto add_tstr;
6282 case VT_BOOL:
6283 tstr = "_Bool";
6284 goto add_tstr;
6285 case VT_BYTE:
6286 tstr = "char";
6287 goto add_tstr;
6288 case VT_SHORT:
6289 tstr = "short";
6290 goto add_tstr;
6291 case VT_INT:
6292 tstr = "int";
6293 goto add_tstr;
6294 case VT_LONG:
6295 tstr = "long";
6296 goto add_tstr;
6297 case VT_LLONG:
6298 tstr = "long long";
6299 goto add_tstr;
6300 case VT_FLOAT:
6301 tstr = "float";
6302 goto add_tstr;
6303 case VT_DOUBLE:
6304 tstr = "double";
6305 goto add_tstr;
6306 case VT_LDOUBLE:
6307 tstr = "long double";
6308 add_tstr:
6309 pstrcat(buf, buf_size, tstr);
6310 break;
6311 case VT_ENUM:
6312 case VT_STRUCT:
6313 if (bt == VT_STRUCT)
6314 tstr = "struct ";
6315 else
6316 tstr = "enum ";
6317 pstrcat(buf, buf_size, tstr);
6318 v = type->ref->v & ~SYM_STRUCT;
6319 if (v >= SYM_FIRST_ANOM)
6320 pstrcat(buf, buf_size, "<anonymous>");
6321 else
6322 pstrcat(buf, buf_size, get_tok_str(v, NULL));
6323 break;
6324 case VT_FUNC:
6325 s = type->ref;
6326 type_to_str(buf, buf_size, &s->type, varstr);
6327 pstrcat(buf, buf_size, "(");
6328 sa = s->next;
6329 while (sa != NULL) {
6330 type_to_str(buf1, sizeof(buf1), &sa->type, NULL);
6331 pstrcat(buf, buf_size, buf1);
6332 sa = sa->next;
6333 if (sa)
6334 pstrcat(buf, buf_size, ", ");
6336 pstrcat(buf, buf_size, ")");
6337 goto no_var;
6338 case VT_PTR:
6339 s = type->ref;
6340 pstrcpy(buf1, sizeof(buf1), "*");
6341 if (varstr)
6342 pstrcat(buf1, sizeof(buf1), varstr);
6343 type_to_str(buf, buf_size, &s->type, buf1);
6344 goto no_var;
6346 if (varstr) {
6347 pstrcat(buf, buf_size, " ");
6348 pstrcat(buf, buf_size, varstr);
6350 no_var: ;
6353 /* verify type compatibility to store vtop in 'dt' type, and generate
6354 casts if needed. */
6355 static void gen_assign_cast(CType *dt)
6357 CType *st, *type1, *type2, tmp_type1, tmp_type2;
6358 char buf1[256], buf2[256];
6359 int dbt, sbt;
6361 st = &vtop->type; /* source type */
6362 dbt = dt->t & VT_BTYPE;
6363 sbt = st->t & VT_BTYPE;
6364 if (dt->t & VT_CONSTANT)
6365 warning("assignment of read-only location");
6366 switch(dbt) {
6367 case VT_PTR:
6368 /* special cases for pointers */
6369 /* '0' can also be a pointer */
6370 if (is_null_pointer(vtop))
6371 goto type_ok;
6372 /* accept implicit pointer to integer cast with warning */
6373 if (is_integer_btype(sbt)) {
6374 warning("assignment makes pointer from integer without a cast");
6375 goto type_ok;
6377 type1 = pointed_type(dt);
6378 /* a function is implicitely a function pointer */
6379 if (sbt == VT_FUNC) {
6380 if ((type1->t & VT_BTYPE) != VT_VOID &&
6381 !is_compatible_types(pointed_type(dt), st))
6382 goto error;
6383 else
6384 goto type_ok;
6386 if (sbt != VT_PTR)
6387 goto error;
6388 type2 = pointed_type(st);
6389 if ((type1->t & VT_BTYPE) == VT_VOID ||
6390 (type2->t & VT_BTYPE) == VT_VOID) {
6391 /* void * can match anything */
6392 } else {
6393 /* exact type match, except for unsigned */
6394 tmp_type1 = *type1;
6395 tmp_type2 = *type2;
6396 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
6397 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
6398 if (!is_compatible_types(&tmp_type1, &tmp_type2))
6399 warning("assignment from incompatible pointer type");
6401 /* check const and volatile */
6402 if ((!(type1->t & VT_CONSTANT) && (type2->t & VT_CONSTANT)) ||
6403 (!(type1->t & VT_VOLATILE) && (type2->t & VT_VOLATILE)))
6404 warning("assignment discards qualifiers from pointer target type");
6405 break;
6406 case VT_BYTE:
6407 case VT_SHORT:
6408 case VT_INT:
6409 case VT_LLONG:
6410 if (sbt == VT_PTR || sbt == VT_FUNC) {
6411 warning("assignment makes integer from pointer without a cast");
6413 /* XXX: more tests */
6414 break;
6415 case VT_STRUCT:
6416 tmp_type1 = *dt;
6417 tmp_type2 = *st;
6418 tmp_type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
6419 tmp_type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
6420 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
6421 error:
6422 type_to_str(buf1, sizeof(buf1), st, NULL);
6423 type_to_str(buf2, sizeof(buf2), dt, NULL);
6424 error("cannot cast '%s' to '%s'", buf1, buf2);
6426 break;
6428 type_ok:
6429 gen_cast(dt);
6432 /* store vtop in lvalue pushed on stack */
6433 void vstore(void)
6435 int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
6437 ft = vtop[-1].type.t;
6438 sbt = vtop->type.t & VT_BTYPE;
6439 dbt = ft & VT_BTYPE;
6440 if (((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
6441 (sbt == VT_INT && dbt == VT_SHORT)) {
6442 /* optimize char/short casts */
6443 delayed_cast = VT_MUSTCAST;
6444 vtop->type.t = ft & VT_TYPE;
6445 /* XXX: factorize */
6446 if (ft & VT_CONSTANT)
6447 warning("assignment of read-only location");
6448 } else {
6449 delayed_cast = 0;
6450 if (!(ft & VT_BITFIELD))
6451 gen_assign_cast(&vtop[-1].type);
6454 if (sbt == VT_STRUCT) {
6455 /* if structure, only generate pointer */
6456 /* structure assignment : generate memcpy */
6457 /* XXX: optimize if small size */
6458 if (!nocode_wanted) {
6459 size = type_size(&vtop->type, &align);
6461 #ifdef TCC_ARM_EABI
6462 if(!(align & 7))
6463 vpush_global_sym(&func_old_type, TOK_memcpy8);
6464 else if(!(align & 3))
6465 vpush_global_sym(&func_old_type, TOK_memcpy4);
6466 else
6467 #endif
6468 vpush_global_sym(&func_old_type, TOK_memcpy);
6470 /* destination */
6471 vpushv(vtop - 2);
6472 vtop->type.t = VT_INT;
6473 gaddrof();
6474 /* source */
6475 vpushv(vtop - 2);
6476 vtop->type.t = VT_INT;
6477 gaddrof();
6478 /* type size */
6479 vpushi(size);
6480 gfunc_call(3);
6482 vswap();
6483 vpop();
6484 } else {
6485 vswap();
6486 vpop();
6488 /* leave source on stack */
6489 } else if (ft & VT_BITFIELD) {
6490 /* bitfield store handling */
6491 bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
6492 bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
6493 /* remove bit field info to avoid loops */
6494 vtop[-1].type.t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
6496 /* duplicate source into other register */
6497 gv_dup();
6498 vswap();
6499 vrott(3);
6501 /* duplicate destination */
6502 vdup();
6503 vtop[-1] = vtop[-2];
6505 /* mask and shift source */
6506 vpushi((1 << bit_size) - 1);
6507 gen_op('&');
6508 vpushi(bit_pos);
6509 gen_op(TOK_SHL);
6510 /* load destination, mask and or with source */
6511 vswap();
6512 vpushi(~(((1 << bit_size) - 1) << bit_pos));
6513 gen_op('&');
6514 gen_op('|');
6515 /* store result */
6516 vstore();
6518 /* pop off shifted source from "duplicate source..." above */
6519 vpop();
6521 } else {
6522 #ifdef CONFIG_TCC_BCHECK
6523 /* bound check case */
6524 if (vtop[-1].r & VT_MUSTBOUND) {
6525 vswap();
6526 gbound();
6527 vswap();
6529 #endif
6530 if (!nocode_wanted) {
6531 rc = RC_INT;
6532 if (is_float(ft))
6533 rc = RC_FLOAT;
6534 r = gv(rc); /* generate value */
6535 /* if lvalue was saved on stack, must read it */
6536 if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
6537 SValue sv;
6538 t = get_reg(RC_INT);
6539 sv.type.t = VT_INT;
6540 sv.r = VT_LOCAL | VT_LVAL;
6541 sv.c.ul = vtop[-1].c.ul;
6542 load(t, &sv);
6543 vtop[-1].r = t | VT_LVAL;
6545 store(r, vtop - 1);
6546 /* two word case handling : store second register at word + 4 */
6547 if ((ft & VT_BTYPE) == VT_LLONG) {
6548 vswap();
6549 /* convert to int to increment easily */
6550 vtop->type.t = VT_INT;
6551 gaddrof();
6552 vpushi(4);
6553 gen_op('+');
6554 vtop->r |= VT_LVAL;
6555 vswap();
6556 /* XXX: it works because r2 is spilled last ! */
6557 store(vtop->r2, vtop - 1);
6560 vswap();
6561 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
6562 vtop->r |= delayed_cast;
6566 /* post defines POST/PRE add. c is the token ++ or -- */
6567 void inc(int post, int c)
6569 test_lvalue();
6570 vdup(); /* save lvalue */
6571 if (post) {
6572 gv_dup(); /* duplicate value */
6573 vrotb(3);
6574 vrotb(3);
6576 /* add constant */
6577 vpushi(c - TOK_MID);
6578 gen_op('+');
6579 vstore(); /* store value */
6580 if (post)
6581 vpop(); /* if post op, return saved value */
6584 /* Parse GNUC __attribute__ extension. Currently, the following
6585 extensions are recognized:
6586 - aligned(n) : set data/function alignment.
6587 - packed : force data alignment to 1
6588 - section(x) : generate data/code in this section.
6589 - unused : currently ignored, but may be used someday.
6590 - regparm(n) : pass function parameters in registers (i386 only)
6592 static void parse_attribute(AttributeDef *ad)
6594 int t, n;
6596 while (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) {
6597 next();
6598 skip('(');
6599 skip('(');
6600 while (tok != ')') {
6601 if (tok < TOK_IDENT)
6602 expect("attribute name");
6603 t = tok;
6604 next();
6605 switch(t) {
6606 case TOK_SECTION1:
6607 case TOK_SECTION2:
6608 skip('(');
6609 if (tok != TOK_STR)
6610 expect("section name");
6611 ad->section = find_section(tcc_state, (char *)tokc.cstr->data);
6612 next();
6613 skip(')');
6614 break;
6615 case TOK_ALIGNED1:
6616 case TOK_ALIGNED2:
6617 if (tok == '(') {
6618 next();
6619 n = expr_const();
6620 if (n <= 0 || (n & (n - 1)) != 0)
6621 error("alignment must be a positive power of two");
6622 skip(')');
6623 } else {
6624 n = MAX_ALIGN;
6626 ad->aligned = n;
6627 break;
6628 case TOK_PACKED1:
6629 case TOK_PACKED2:
6630 ad->packed = 1;
6631 break;
6632 case TOK_UNUSED1:
6633 case TOK_UNUSED2:
6634 /* currently, no need to handle it because tcc does not
6635 track unused objects */
6636 break;
6637 case TOK_NORETURN1:
6638 case TOK_NORETURN2:
6639 /* currently, no need to handle it because tcc does not
6640 track unused objects */
6641 break;
6642 case TOK_CDECL1:
6643 case TOK_CDECL2:
6644 case TOK_CDECL3:
6645 FUNC_CALL(ad->func_attr) = FUNC_CDECL;
6646 break;
6647 case TOK_STDCALL1:
6648 case TOK_STDCALL2:
6649 case TOK_STDCALL3:
6650 FUNC_CALL(ad->func_attr) = FUNC_STDCALL;
6651 break;
6652 #ifdef TCC_TARGET_I386
6653 case TOK_REGPARM1:
6654 case TOK_REGPARM2:
6655 skip('(');
6656 n = expr_const();
6657 if (n > 3)
6658 n = 3;
6659 else if (n < 0)
6660 n = 0;
6661 if (n > 0)
6662 FUNC_CALL(ad->func_attr) = FUNC_FASTCALL1 + n - 1;
6663 skip(')');
6664 break;
6665 case TOK_FASTCALL1:
6666 case TOK_FASTCALL2:
6667 case TOK_FASTCALL3:
6668 FUNC_CALL(ad->func_attr) = FUNC_FASTCALLW;
6669 break;
6670 #endif
6671 case TOK_DLLEXPORT:
6672 FUNC_EXPORT(ad->func_attr) = 1;
6673 break;
6674 default:
6675 if (tcc_state->warn_unsupported)
6676 warning("'%s' attribute ignored", get_tok_str(t, NULL));
6677 /* skip parameters */
6678 if (tok == '(') {
6679 int parenthesis = 0;
6680 do {
6681 if (tok == '(')
6682 parenthesis++;
6683 else if (tok == ')')
6684 parenthesis--;
6685 next();
6686 } while (parenthesis && tok != -1);
6688 break;
6690 if (tok != ',')
6691 break;
6692 next();
6694 skip(')');
6695 skip(')');
6699 /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
6700 static void struct_decl(CType *type, int u)
6702 int a, v, size, align, maxalign, c, offset;
6703 int bit_size, bit_pos, bsize, bt, lbit_pos;
6704 Sym *s, *ss, *ass, **ps;
6705 AttributeDef ad;
6706 CType type1, btype;
6708 a = tok; /* save decl type */
6709 next();
6710 if (tok != '{') {
6711 v = tok;
6712 next();
6713 /* struct already defined ? return it */
6714 if (v < TOK_IDENT)
6715 expect("struct/union/enum name");
6716 s = struct_find(v);
6717 if (s) {
6718 if (s->type.t != a)
6719 error("invalid type");
6720 goto do_decl;
6722 } else {
6723 v = anon_sym++;
6725 type1.t = a;
6726 /* we put an undefined size for struct/union */
6727 s = sym_push(v | SYM_STRUCT, &type1, 0, -1);
6728 s->r = 0; /* default alignment is zero as gcc */
6729 /* put struct/union/enum name in type */
6730 do_decl:
6731 type->t = u;
6732 type->ref = s;
6734 if (tok == '{') {
6735 next();
6736 if (s->c != -1)
6737 error("struct/union/enum already defined");
6738 /* cannot be empty */
6739 c = 0;
6740 /* non empty enums are not allowed */
6741 if (a == TOK_ENUM) {
6742 for(;;) {
6743 v = tok;
6744 if (v < TOK_UIDENT)
6745 expect("identifier");
6746 next();
6747 if (tok == '=') {
6748 next();
6749 c = expr_const();
6751 /* enum symbols have static storage */
6752 ss = sym_push(v, &int_type, VT_CONST, c);
6753 ss->type.t |= VT_STATIC;
6754 if (tok != ',')
6755 break;
6756 next();
6757 c++;
6758 /* NOTE: we accept a trailing comma */
6759 if (tok == '}')
6760 break;
6762 skip('}');
6763 } else {
6764 maxalign = 1;
6765 ps = &s->next;
6766 bit_pos = 0;
6767 offset = 0;
6768 while (tok != '}') {
6769 parse_btype(&btype, &ad);
6770 while (1) {
6771 bit_size = -1;
6772 v = 0;
6773 type1 = btype;
6774 if (tok != ':') {
6775 type_decl(&type1, &ad, &v, TYPE_DIRECT | TYPE_ABSTRACT);
6776 if (v == 0 && (type1.t & VT_BTYPE) != VT_STRUCT)
6777 expect("identifier");
6778 if ((type1.t & VT_BTYPE) == VT_FUNC ||
6779 (type1.t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN | VT_INLINE)))
6780 error("invalid type for '%s'",
6781 get_tok_str(v, NULL));
6783 if (tok == ':') {
6784 next();
6785 bit_size = expr_const();
6786 /* XXX: handle v = 0 case for messages */
6787 if (bit_size < 0)
6788 error("negative width in bit-field '%s'",
6789 get_tok_str(v, NULL));
6790 if (v && bit_size == 0)
6791 error("zero width for bit-field '%s'",
6792 get_tok_str(v, NULL));
6794 size = type_size(&type1, &align);
6795 if (ad.aligned) {
6796 if (align < ad.aligned)
6797 align = ad.aligned;
6798 } else if (ad.packed) {
6799 align = 1;
6800 } else if (*tcc_state->pack_stack_ptr) {
6801 if (align > *tcc_state->pack_stack_ptr)
6802 align = *tcc_state->pack_stack_ptr;
6804 lbit_pos = 0;
6805 if (bit_size >= 0) {
6806 bt = type1.t & VT_BTYPE;
6807 if (bt != VT_INT &&
6808 bt != VT_BYTE &&
6809 bt != VT_SHORT &&
6810 bt != VT_BOOL &&
6811 bt != VT_ENUM)
6812 error("bitfields must have scalar type");
6813 bsize = size * 8;
6814 if (bit_size > bsize) {
6815 error("width of '%s' exceeds its type",
6816 get_tok_str(v, NULL));
6817 } else if (bit_size == bsize) {
6818 /* no need for bit fields */
6819 bit_pos = 0;
6820 } else if (bit_size == 0) {
6821 /* XXX: what to do if only padding in a
6822 structure ? */
6823 /* zero size: means to pad */
6824 if (bit_pos > 0)
6825 bit_pos = bsize;
6826 } else {
6827 /* we do not have enough room ? */
6828 if ((bit_pos + bit_size) > bsize)
6829 bit_pos = 0;
6830 lbit_pos = bit_pos;
6831 /* XXX: handle LSB first */
6832 type1.t |= VT_BITFIELD |
6833 (bit_pos << VT_STRUCT_SHIFT) |
6834 (bit_size << (VT_STRUCT_SHIFT + 6));
6835 bit_pos += bit_size;
6837 } else {
6838 bit_pos = 0;
6840 if (v != 0 || (type1.t & VT_BTYPE) == VT_STRUCT) {
6841 /* add new memory data only if starting
6842 bit field */
6843 if (lbit_pos == 0) {
6844 if (a == TOK_STRUCT) {
6845 c = (c + align - 1) & -align;
6846 offset = c;
6847 if (size > 0)
6848 c += size;
6849 } else {
6850 offset = 0;
6851 if (size > c)
6852 c = size;
6854 if (align > maxalign)
6855 maxalign = align;
6857 #if 0
6858 printf("add field %s offset=%d",
6859 get_tok_str(v, NULL), offset);
6860 if (type1.t & VT_BITFIELD) {
6861 printf(" pos=%d size=%d",
6862 (type1.t >> VT_STRUCT_SHIFT) & 0x3f,
6863 (type1.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
6865 printf("\n");
6866 #endif
6868 if (v == 0 && (type1.t & VT_BTYPE) == VT_STRUCT) {
6869 ass = type1.ref;
6870 while ((ass = ass->next) != NULL) {
6871 ss = sym_push(ass->v, &ass->type, 0, offset + ass->c);
6872 *ps = ss;
6873 ps = &ss->next;
6875 } else if (v) {
6876 ss = sym_push(v | SYM_FIELD, &type1, 0, offset);
6877 *ps = ss;
6878 ps = &ss->next;
6880 if (tok == ';' || tok == TOK_EOF)
6881 break;
6882 skip(',');
6884 skip(';');
6886 skip('}');
6887 /* store size and alignment */
6888 s->c = (c + maxalign - 1) & -maxalign;
6889 s->r = maxalign;
6894 /* return 0 if no type declaration. otherwise, return the basic type
6895 and skip it.
6897 static int parse_btype(CType *type, AttributeDef *ad)
6899 int t, u, type_found, typespec_found, typedef_found;
6900 Sym *s;
6901 CType type1;
6903 memset(ad, 0, sizeof(AttributeDef));
6904 type_found = 0;
6905 typespec_found = 0;
6906 typedef_found = 0;
6907 t = 0;
6908 while(1) {
6909 switch(tok) {
6910 case TOK_EXTENSION:
6911 /* currently, we really ignore extension */
6912 next();
6913 continue;
6915 /* basic types */
6916 case TOK_CHAR:
6917 u = VT_BYTE;
6918 basic_type:
6919 next();
6920 basic_type1:
6921 if ((t & VT_BTYPE) != 0)
6922 error("too many basic types");
6923 t |= u;
6924 typespec_found = 1;
6925 break;
6926 case TOK_VOID:
6927 u = VT_VOID;
6928 goto basic_type;
6929 case TOK_SHORT:
6930 u = VT_SHORT;
6931 goto basic_type;
6932 case TOK_INT:
6933 next();
6934 typespec_found = 1;
6935 break;
6936 case TOK_LONG:
6937 next();
6938 if ((t & VT_BTYPE) == VT_DOUBLE) {
6939 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6940 } else if ((t & VT_BTYPE) == VT_LONG) {
6941 t = (t & ~VT_BTYPE) | VT_LLONG;
6942 } else {
6943 u = VT_LONG;
6944 goto basic_type1;
6946 break;
6947 case TOK_BOOL:
6948 u = VT_BOOL;
6949 goto basic_type;
6950 case TOK_FLOAT:
6951 u = VT_FLOAT;
6952 goto basic_type;
6953 case TOK_DOUBLE:
6954 next();
6955 if ((t & VT_BTYPE) == VT_LONG) {
6956 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6957 } else {
6958 u = VT_DOUBLE;
6959 goto basic_type1;
6961 break;
6962 case TOK_ENUM:
6963 struct_decl(&type1, VT_ENUM);
6964 basic_type2:
6965 u = type1.t;
6966 type->ref = type1.ref;
6967 goto basic_type1;
6968 case TOK_STRUCT:
6969 case TOK_UNION:
6970 struct_decl(&type1, VT_STRUCT);
6971 goto basic_type2;
6973 /* type modifiers */
6974 case TOK_CONST1:
6975 case TOK_CONST2:
6976 case TOK_CONST3:
6977 t |= VT_CONSTANT;
6978 next();
6979 break;
6980 case TOK_VOLATILE1:
6981 case TOK_VOLATILE2:
6982 case TOK_VOLATILE3:
6983 t |= VT_VOLATILE;
6984 next();
6985 break;
6986 case TOK_SIGNED1:
6987 case TOK_SIGNED2:
6988 case TOK_SIGNED3:
6989 typespec_found = 1;
6990 t |= VT_SIGNED;
6991 next();
6992 break;
6993 case TOK_REGISTER:
6994 case TOK_AUTO:
6995 case TOK_RESTRICT1:
6996 case TOK_RESTRICT2:
6997 case TOK_RESTRICT3:
6998 next();
6999 break;
7000 case TOK_UNSIGNED:
7001 t |= VT_UNSIGNED;
7002 next();
7003 typespec_found = 1;
7004 break;
7006 /* storage */
7007 case TOK_EXTERN:
7008 t |= VT_EXTERN;
7009 next();
7010 break;
7011 case TOK_STATIC:
7012 t |= VT_STATIC;
7013 next();
7014 break;
7015 case TOK_TYPEDEF:
7016 t |= VT_TYPEDEF;
7017 next();
7018 break;
7019 case TOK_INLINE1:
7020 case TOK_INLINE2:
7021 case TOK_INLINE3:
7022 t |= VT_INLINE;
7023 next();
7024 break;
7026 /* GNUC attribute */
7027 case TOK_ATTRIBUTE1:
7028 case TOK_ATTRIBUTE2:
7029 parse_attribute(ad);
7030 break;
7031 /* GNUC typeof */
7032 case TOK_TYPEOF1:
7033 case TOK_TYPEOF2:
7034 case TOK_TYPEOF3:
7035 next();
7036 parse_expr_type(&type1);
7037 goto basic_type2;
7038 default:
7039 if (typespec_found || typedef_found)
7040 goto the_end;
7041 s = sym_find(tok);
7042 if (!s || !(s->type.t & VT_TYPEDEF))
7043 goto the_end;
7044 typedef_found = 1;
7045 t |= (s->type.t & ~VT_TYPEDEF);
7046 type->ref = s->type.ref;
7047 next();
7048 typespec_found = 1;
7049 break;
7051 type_found = 1;
7053 the_end:
7054 if ((t & (VT_SIGNED|VT_UNSIGNED)) == (VT_SIGNED|VT_UNSIGNED))
7055 error("signed and unsigned modifier");
7056 if (tcc_state->char_is_unsigned) {
7057 if ((t & (VT_SIGNED|VT_UNSIGNED|VT_BTYPE)) == VT_BYTE)
7058 t |= VT_UNSIGNED;
7060 t &= ~VT_SIGNED;
7062 /* long is never used as type */
7063 if ((t & VT_BTYPE) == VT_LONG)
7064 t = (t & ~VT_BTYPE) | VT_INT;
7065 type->t = t;
7066 return type_found;
7069 /* convert a function parameter type (array to pointer and function to
7070 function pointer) */
7071 static inline void convert_parameter_type(CType *pt)
7073 /* remove const and volatile qualifiers (XXX: const could be used
7074 to indicate a const function parameter */
7075 pt->t &= ~(VT_CONSTANT | VT_VOLATILE);
7076 /* array must be transformed to pointer according to ANSI C */
7077 pt->t &= ~VT_ARRAY;
7078 if ((pt->t & VT_BTYPE) == VT_FUNC) {
7079 mk_pointer(pt);
7083 static void post_type(CType *type, AttributeDef *ad)
7085 int n, l, t1, arg_size, align;
7086 Sym **plast, *s, *first;
7087 AttributeDef ad1;
7088 CType pt;
7090 if (tok == '(') {
7091 /* function declaration */
7092 next();
7093 l = 0;
7094 first = NULL;
7095 plast = &first;
7096 arg_size = 0;
7097 if (tok != ')') {
7098 for(;;) {
7099 /* read param name and compute offset */
7100 if (l != FUNC_OLD) {
7101 if (!parse_btype(&pt, &ad1)) {
7102 if (l) {
7103 error("invalid type");
7104 } else {
7105 l = FUNC_OLD;
7106 goto old_proto;
7109 l = FUNC_NEW;
7110 if ((pt.t & VT_BTYPE) == VT_VOID && tok == ')')
7111 break;
7112 type_decl(&pt, &ad1, &n, TYPE_DIRECT | TYPE_ABSTRACT);
7113 if ((pt.t & VT_BTYPE) == VT_VOID)
7114 error("parameter declared as void");
7115 arg_size += (type_size(&pt, &align) + 3) & ~3;
7116 } else {
7117 old_proto:
7118 n = tok;
7119 if (n < TOK_UIDENT)
7120 expect("identifier");
7121 pt.t = VT_INT;
7122 next();
7124 convert_parameter_type(&pt);
7125 s = sym_push(n | SYM_FIELD, &pt, 0, 0);
7126 *plast = s;
7127 plast = &s->next;
7128 if (tok == ')')
7129 break;
7130 skip(',');
7131 if (l == FUNC_NEW && tok == TOK_DOTS) {
7132 l = FUNC_ELLIPSIS;
7133 next();
7134 break;
7138 /* if no parameters, then old type prototype */
7139 if (l == 0)
7140 l = FUNC_OLD;
7141 skip(')');
7142 t1 = type->t & VT_STORAGE;
7143 /* NOTE: const is ignored in returned type as it has a special
7144 meaning in gcc / C++ */
7145 type->t &= ~(VT_STORAGE | VT_CONSTANT);
7146 post_type(type, ad);
7147 /* we push a anonymous symbol which will contain the function prototype */
7148 FUNC_ARGS(ad->func_attr) = arg_size;
7149 s = sym_push(SYM_FIELD, type, ad->func_attr, l);
7150 s->next = first;
7151 type->t = t1 | VT_FUNC;
7152 type->ref = s;
7153 } else if (tok == '[') {
7154 /* array definition */
7155 next();
7156 n = -1;
7157 if (tok != ']') {
7158 n = expr_const();
7159 if (n < 0)
7160 error("invalid array size");
7162 skip(']');
7163 /* parse next post type */
7164 t1 = type->t & VT_STORAGE;
7165 type->t &= ~VT_STORAGE;
7166 post_type(type, ad);
7168 /* we push a anonymous symbol which will contain the array
7169 element type */
7170 s = sym_push(SYM_FIELD, type, 0, n);
7171 type->t = t1 | VT_ARRAY | VT_PTR;
7172 type->ref = s;
7176 /* Parse a type declaration (except basic type), and return the type
7177 in 'type'. 'td' is a bitmask indicating which kind of type decl is
7178 expected. 'type' should contain the basic type. 'ad' is the
7179 attribute definition of the basic type. It can be modified by
7180 type_decl().
7182 static void type_decl(CType *type, AttributeDef *ad, int *v, int td)
7184 Sym *s;
7185 CType type1, *type2;
7186 int qualifiers;
7188 while (tok == '*') {
7189 qualifiers = 0;
7190 redo:
7191 next();
7192 switch(tok) {
7193 case TOK_CONST1:
7194 case TOK_CONST2:
7195 case TOK_CONST3:
7196 qualifiers |= VT_CONSTANT;
7197 goto redo;
7198 case TOK_VOLATILE1:
7199 case TOK_VOLATILE2:
7200 case TOK_VOLATILE3:
7201 qualifiers |= VT_VOLATILE;
7202 goto redo;
7203 case TOK_RESTRICT1:
7204 case TOK_RESTRICT2:
7205 case TOK_RESTRICT3:
7206 goto redo;
7208 mk_pointer(type);
7209 type->t |= qualifiers;
7212 /* XXX: clarify attribute handling */
7213 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
7214 parse_attribute(ad);
7216 /* recursive type */
7217 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
7218 type1.t = 0; /* XXX: same as int */
7219 if (tok == '(') {
7220 next();
7221 /* XXX: this is not correct to modify 'ad' at this point, but
7222 the syntax is not clear */
7223 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
7224 parse_attribute(ad);
7225 type_decl(&type1, ad, v, td);
7226 skip(')');
7227 } else {
7228 /* type identifier */
7229 if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
7230 *v = tok;
7231 next();
7232 } else {
7233 if (!(td & TYPE_ABSTRACT))
7234 expect("identifier");
7235 *v = 0;
7238 post_type(type, ad);
7239 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
7240 parse_attribute(ad);
7241 if (!type1.t)
7242 return;
7243 /* append type at the end of type1 */
7244 type2 = &type1;
7245 for(;;) {
7246 s = type2->ref;
7247 type2 = &s->type;
7248 if (!type2->t) {
7249 *type2 = *type;
7250 break;
7253 *type = type1;
7256 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
7257 static int lvalue_type(int t)
7259 int bt, r;
7260 r = VT_LVAL;
7261 bt = t & VT_BTYPE;
7262 if (bt == VT_BYTE || bt == VT_BOOL)
7263 r |= VT_LVAL_BYTE;
7264 else if (bt == VT_SHORT)
7265 r |= VT_LVAL_SHORT;
7266 else
7267 return r;
7268 if (t & VT_UNSIGNED)
7269 r |= VT_LVAL_UNSIGNED;
7270 return r;
7273 /* indirection with full error checking and bound check */
7274 static void indir(void)
7276 if ((vtop->type.t & VT_BTYPE) != VT_PTR) {
7277 if ((vtop->type.t & VT_BTYPE) == VT_FUNC)
7278 return;
7279 expect("pointer");
7281 if ((vtop->r & VT_LVAL) && !nocode_wanted)
7282 gv(RC_INT);
7283 vtop->type = *pointed_type(&vtop->type);
7284 /* Arrays and functions are never lvalues */
7285 if (!(vtop->type.t & VT_ARRAY)
7286 && (vtop->type.t & VT_BTYPE) != VT_FUNC) {
7287 vtop->r |= lvalue_type(vtop->type.t);
7288 /* if bound checking, the referenced pointer must be checked */
7289 if (do_bounds_check)
7290 vtop->r |= VT_MUSTBOUND;
7294 /* pass a parameter to a function and do type checking and casting */
7295 static void gfunc_param_typed(Sym *func, Sym *arg)
7297 int func_type;
7298 CType type;
7300 func_type = func->c;
7301 if (func_type == FUNC_OLD ||
7302 (func_type == FUNC_ELLIPSIS && arg == NULL)) {
7303 /* default casting : only need to convert float to double */
7304 if ((vtop->type.t & VT_BTYPE) == VT_FLOAT) {
7305 type.t = VT_DOUBLE;
7306 gen_cast(&type);
7308 } else if (arg == NULL) {
7309 error("too many arguments to function");
7310 } else {
7311 type = arg->type;
7312 type.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
7313 gen_assign_cast(&type);
7317 /* parse an expression of the form '(type)' or '(expr)' and return its
7318 type */
7319 static void parse_expr_type(CType *type)
7321 int n;
7322 AttributeDef ad;
7324 skip('(');
7325 if (parse_btype(type, &ad)) {
7326 type_decl(type, &ad, &n, TYPE_ABSTRACT);
7327 } else {
7328 expr_type(type);
7330 skip(')');
7333 static void parse_type(CType *type)
7335 AttributeDef ad;
7336 int n;
7338 if (!parse_btype(type, &ad)) {
7339 expect("type");
7341 type_decl(type, &ad, &n, TYPE_ABSTRACT);
7344 static void vpush_tokc(int t)
7346 CType type;
7347 type.t = t;
7348 vsetc(&type, VT_CONST, &tokc);
7351 static void unary(void)
7353 int n, t, align, size, r;
7354 CType type;
7355 Sym *s;
7356 AttributeDef ad;
7358 /* XXX: GCC 2.95.3 does not generate a table although it should be
7359 better here */
7360 tok_next:
7361 switch(tok) {
7362 case TOK_EXTENSION:
7363 next();
7364 goto tok_next;
7365 case TOK_CINT:
7366 case TOK_CCHAR:
7367 case TOK_LCHAR:
7368 vpushi(tokc.i);
7369 next();
7370 break;
7371 case TOK_CUINT:
7372 vpush_tokc(VT_INT | VT_UNSIGNED);
7373 next();
7374 break;
7375 case TOK_CLLONG:
7376 vpush_tokc(VT_LLONG);
7377 next();
7378 break;
7379 case TOK_CULLONG:
7380 vpush_tokc(VT_LLONG | VT_UNSIGNED);
7381 next();
7382 break;
7383 case TOK_CFLOAT:
7384 vpush_tokc(VT_FLOAT);
7385 next();
7386 break;
7387 case TOK_CDOUBLE:
7388 vpush_tokc(VT_DOUBLE);
7389 next();
7390 break;
7391 case TOK_CLDOUBLE:
7392 vpush_tokc(VT_LDOUBLE);
7393 next();
7394 break;
7395 case TOK___FUNCTION__:
7396 if (!gnu_ext)
7397 goto tok_identifier;
7398 /* fall thru */
7399 case TOK___FUNC__:
7401 void *ptr;
7402 int len;
7403 /* special function name identifier */
7404 len = strlen(funcname) + 1;
7405 /* generate char[len] type */
7406 type.t = VT_BYTE;
7407 mk_pointer(&type);
7408 type.t |= VT_ARRAY;
7409 type.ref->c = len;
7410 vpush_ref(&type, data_section, data_section->data_offset, len);
7411 ptr = section_ptr_add(data_section, len);
7412 memcpy(ptr, funcname, len);
7413 next();
7415 break;
7416 case TOK_LSTR:
7417 #ifdef TCC_TARGET_PE
7418 t = VT_SHORT | VT_UNSIGNED;
7419 #else
7420 t = VT_INT;
7421 #endif
7422 goto str_init;
7423 case TOK_STR:
7424 /* string parsing */
7425 t = VT_BYTE;
7426 str_init:
7427 if (tcc_state->warn_write_strings)
7428 t |= VT_CONSTANT;
7429 type.t = t;
7430 mk_pointer(&type);
7431 type.t |= VT_ARRAY;
7432 memset(&ad, 0, sizeof(AttributeDef));
7433 decl_initializer_alloc(&type, &ad, VT_CONST, 2, 0, 0);
7434 break;
7435 case '(':
7436 next();
7437 /* cast ? */
7438 if (parse_btype(&type, &ad)) {
7439 type_decl(&type, &ad, &n, TYPE_ABSTRACT);
7440 skip(')');
7441 /* check ISOC99 compound literal */
7442 if (tok == '{') {
7443 /* data is allocated locally by default */
7444 if (global_expr)
7445 r = VT_CONST;
7446 else
7447 r = VT_LOCAL;
7448 /* all except arrays are lvalues */
7449 if (!(type.t & VT_ARRAY))
7450 r |= lvalue_type(type.t);
7451 memset(&ad, 0, sizeof(AttributeDef));
7452 decl_initializer_alloc(&type, &ad, r, 1, 0, 0);
7453 } else {
7454 unary();
7455 gen_cast(&type);
7457 } else if (tok == '{') {
7458 /* save all registers */
7459 save_regs(0);
7460 /* statement expression : we do not accept break/continue
7461 inside as GCC does */
7462 block(NULL, NULL, NULL, NULL, 0, 1);
7463 skip(')');
7464 } else {
7465 gexpr();
7466 skip(')');
7468 break;
7469 case '*':
7470 next();
7471 unary();
7472 indir();
7473 break;
7474 case '&':
7475 next();
7476 unary();
7477 /* functions names must be treated as function pointers,
7478 except for unary '&' and sizeof. Since we consider that
7479 functions are not lvalues, we only have to handle it
7480 there and in function calls. */
7481 /* arrays can also be used although they are not lvalues */
7482 if ((vtop->type.t & VT_BTYPE) != VT_FUNC &&
7483 !(vtop->type.t & VT_ARRAY) && !(vtop->type.t & VT_LLOCAL))
7484 test_lvalue();
7485 mk_pointer(&vtop->type);
7486 gaddrof();
7487 break;
7488 case '!':
7489 next();
7490 unary();
7491 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST)
7492 vtop->c.i = !vtop->c.i;
7493 else if ((vtop->r & VT_VALMASK) == VT_CMP)
7494 vtop->c.i = vtop->c.i ^ 1;
7495 else {
7496 save_regs(1);
7497 vseti(VT_JMP, gtst(1, 0));
7499 break;
7500 case '~':
7501 next();
7502 unary();
7503 vpushi(-1);
7504 gen_op('^');
7505 break;
7506 case '+':
7507 next();
7508 /* in order to force cast, we add zero */
7509 unary();
7510 if ((vtop->type.t & VT_BTYPE) == VT_PTR)
7511 error("pointer not accepted for unary plus");
7512 vpushi(0);
7513 gen_op('+');
7514 break;
7515 case TOK_SIZEOF:
7516 case TOK_ALIGNOF1:
7517 case TOK_ALIGNOF2:
7518 t = tok;
7519 next();
7520 if (tok == '(') {
7521 parse_expr_type(&type);
7522 } else {
7523 unary_type(&type);
7525 size = type_size(&type, &align);
7526 if (t == TOK_SIZEOF) {
7527 if (size < 0)
7528 error("sizeof applied to an incomplete type");
7529 vpushi(size);
7530 } else {
7531 vpushi(align);
7533 vtop->type.t |= VT_UNSIGNED;
7534 break;
7536 case TOK_builtin_types_compatible_p:
7538 CType type1, type2;
7539 next();
7540 skip('(');
7541 parse_type(&type1);
7542 skip(',');
7543 parse_type(&type2);
7544 skip(')');
7545 type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
7546 type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
7547 vpushi(is_compatible_types(&type1, &type2));
7549 break;
7550 case TOK_builtin_constant_p:
7552 int saved_nocode_wanted, res;
7553 next();
7554 skip('(');
7555 saved_nocode_wanted = nocode_wanted;
7556 nocode_wanted = 1;
7557 gexpr();
7558 res = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
7559 vpop();
7560 nocode_wanted = saved_nocode_wanted;
7561 skip(')');
7562 vpushi(res);
7564 break;
7565 case TOK_INC:
7566 case TOK_DEC:
7567 t = tok;
7568 next();
7569 unary();
7570 inc(0, t);
7571 break;
7572 case '-':
7573 next();
7574 vpushi(0);
7575 unary();
7576 gen_op('-');
7577 break;
7578 case TOK_LAND:
7579 if (!gnu_ext)
7580 goto tok_identifier;
7581 next();
7582 /* allow to take the address of a label */
7583 if (tok < TOK_UIDENT)
7584 expect("label identifier");
7585 s = label_find(tok);
7586 if (!s) {
7587 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
7588 } else {
7589 if (s->r == LABEL_DECLARED)
7590 s->r = LABEL_FORWARD;
7592 if (!s->type.t) {
7593 s->type.t = VT_VOID;
7594 mk_pointer(&s->type);
7595 s->type.t |= VT_STATIC;
7597 vset(&s->type, VT_CONST | VT_SYM, 0);
7598 vtop->sym = s;
7599 next();
7600 break;
7601 default:
7602 tok_identifier:
7603 t = tok;
7604 next();
7605 if (t < TOK_UIDENT)
7606 expect("identifier");
7607 s = sym_find(t);
7608 if (!s) {
7609 if (tok != '(')
7610 error("'%s' undeclared", get_tok_str(t, NULL));
7611 /* for simple function calls, we tolerate undeclared
7612 external reference to int() function */
7613 if (tcc_state->warn_implicit_function_declaration)
7614 warning("implicit declaration of function '%s'",
7615 get_tok_str(t, NULL));
7616 s = external_global_sym(t, &func_old_type, 0);
7618 if ((s->type.t & (VT_STATIC | VT_INLINE | VT_BTYPE)) ==
7619 (VT_STATIC | VT_INLINE | VT_FUNC)) {
7620 /* if referencing an inline function, then we generate a
7621 symbol to it if not already done. It will have the
7622 effect to generate code for it at the end of the
7623 compilation unit. Inline function as always
7624 generated in the text section. */
7625 if (!s->c)
7626 put_extern_sym(s, text_section, 0, 0);
7627 r = VT_SYM | VT_CONST;
7628 } else {
7629 r = s->r;
7631 vset(&s->type, r, s->c);
7632 /* if forward reference, we must point to s */
7633 if (vtop->r & VT_SYM) {
7634 vtop->sym = s;
7635 vtop->c.ul = 0;
7637 break;
7640 /* post operations */
7641 while (1) {
7642 if (tok == TOK_INC || tok == TOK_DEC) {
7643 inc(1, tok);
7644 next();
7645 } else if (tok == '.' || tok == TOK_ARROW) {
7646 /* field */
7647 if (tok == TOK_ARROW)
7648 indir();
7649 test_lvalue();
7650 gaddrof();
7651 next();
7652 /* expect pointer on structure */
7653 if ((vtop->type.t & VT_BTYPE) != VT_STRUCT)
7654 expect("struct or union");
7655 s = vtop->type.ref;
7656 /* find field */
7657 tok |= SYM_FIELD;
7658 while ((s = s->next) != NULL) {
7659 if (s->v == tok)
7660 break;
7662 if (!s)
7663 error("field not found: %s", get_tok_str(tok & ~SYM_FIELD, NULL));
7664 /* add field offset to pointer */
7665 vtop->type = char_pointer_type; /* change type to 'char *' */
7666 vpushi(s->c);
7667 gen_op('+');
7668 /* change type to field type, and set to lvalue */
7669 vtop->type = s->type;
7670 /* an array is never an lvalue */
7671 if (!(vtop->type.t & VT_ARRAY)) {
7672 vtop->r |= lvalue_type(vtop->type.t);
7673 /* if bound checking, the referenced pointer must be checked */
7674 if (do_bounds_check)
7675 vtop->r |= VT_MUSTBOUND;
7677 next();
7678 } else if (tok == '[') {
7679 next();
7680 gexpr();
7681 gen_op('+');
7682 indir();
7683 skip(']');
7684 } else if (tok == '(') {
7685 SValue ret;
7686 Sym *sa;
7687 int nb_args;
7689 /* function call */
7690 if ((vtop->type.t & VT_BTYPE) != VT_FUNC) {
7691 /* pointer test (no array accepted) */
7692 if ((vtop->type.t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
7693 vtop->type = *pointed_type(&vtop->type);
7694 if ((vtop->type.t & VT_BTYPE) != VT_FUNC)
7695 goto error_func;
7696 } else {
7697 error_func:
7698 expect("function pointer");
7700 } else {
7701 vtop->r &= ~VT_LVAL; /* no lvalue */
7703 /* get return type */
7704 s = vtop->type.ref;
7705 next();
7706 sa = s->next; /* first parameter */
7707 nb_args = 0;
7708 ret.r2 = VT_CONST;
7709 /* compute first implicit argument if a structure is returned */
7710 if ((s->type.t & VT_BTYPE) == VT_STRUCT) {
7711 /* get some space for the returned structure */
7712 size = type_size(&s->type, &align);
7713 loc = (loc - size) & -align;
7714 ret.type = s->type;
7715 ret.r = VT_LOCAL | VT_LVAL;
7716 /* pass it as 'int' to avoid structure arg passing
7717 problems */
7718 vseti(VT_LOCAL, loc);
7719 ret.c = vtop->c;
7720 nb_args++;
7721 } else {
7722 ret.type = s->type;
7723 /* return in register */
7724 if (is_float(ret.type.t)) {
7725 ret.r = REG_FRET;
7726 } else {
7727 if ((ret.type.t & VT_BTYPE) == VT_LLONG)
7728 ret.r2 = REG_LRET;
7729 ret.r = REG_IRET;
7731 ret.c.i = 0;
7733 if (tok != ')') {
7734 for(;;) {
7735 expr_eq();
7736 gfunc_param_typed(s, sa);
7737 nb_args++;
7738 if (sa)
7739 sa = sa->next;
7740 if (tok == ')')
7741 break;
7742 skip(',');
7745 if (sa)
7746 error("too few arguments to function");
7747 skip(')');
7748 if (!nocode_wanted) {
7749 gfunc_call(nb_args);
7750 } else {
7751 vtop -= (nb_args + 1);
7753 /* return value */
7754 vsetc(&ret.type, ret.r, &ret.c);
7755 vtop->r2 = ret.r2;
7756 } else {
7757 break;
7762 static void uneq(void)
7764 int t;
7766 unary();
7767 if (tok == '=' ||
7768 (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
7769 tok == TOK_A_XOR || tok == TOK_A_OR ||
7770 tok == TOK_A_SHL || tok == TOK_A_SAR) {
7771 test_lvalue();
7772 t = tok;
7773 next();
7774 if (t == '=') {
7775 expr_eq();
7776 } else {
7777 vdup();
7778 expr_eq();
7779 gen_op(t & 0x7f);
7781 vstore();
7785 static void expr_prod(void)
7787 int t;
7789 uneq();
7790 while (tok == '*' || tok == '/' || tok == '%') {
7791 t = tok;
7792 next();
7793 uneq();
7794 gen_op(t);
7798 static void expr_sum(void)
7800 int t;
7802 expr_prod();
7803 while (tok == '+' || tok == '-') {
7804 t = tok;
7805 next();
7806 expr_prod();
7807 gen_op(t);
7811 static void expr_shift(void)
7813 int t;
7815 expr_sum();
7816 while (tok == TOK_SHL || tok == TOK_SAR) {
7817 t = tok;
7818 next();
7819 expr_sum();
7820 gen_op(t);
7824 static void expr_cmp(void)
7826 int t;
7828 expr_shift();
7829 while ((tok >= TOK_ULE && tok <= TOK_GT) ||
7830 tok == TOK_ULT || tok == TOK_UGE) {
7831 t = tok;
7832 next();
7833 expr_shift();
7834 gen_op(t);
7838 static void expr_cmpeq(void)
7840 int t;
7842 expr_cmp();
7843 while (tok == TOK_EQ || tok == TOK_NE) {
7844 t = tok;
7845 next();
7846 expr_cmp();
7847 gen_op(t);
7851 static void expr_and(void)
7853 expr_cmpeq();
7854 while (tok == '&') {
7855 next();
7856 expr_cmpeq();
7857 gen_op('&');
7861 static void expr_xor(void)
7863 expr_and();
7864 while (tok == '^') {
7865 next();
7866 expr_and();
7867 gen_op('^');
7871 static void expr_or(void)
7873 expr_xor();
7874 while (tok == '|') {
7875 next();
7876 expr_xor();
7877 gen_op('|');
7881 /* XXX: fix this mess */
7882 static void expr_land_const(void)
7884 expr_or();
7885 while (tok == TOK_LAND) {
7886 next();
7887 expr_or();
7888 gen_op(TOK_LAND);
7892 /* XXX: fix this mess */
7893 static void expr_lor_const(void)
7895 expr_land_const();
7896 while (tok == TOK_LOR) {
7897 next();
7898 expr_land_const();
7899 gen_op(TOK_LOR);
7903 /* only used if non constant */
7904 static void expr_land(void)
7906 int t;
7908 expr_or();
7909 if (tok == TOK_LAND) {
7910 t = 0;
7911 save_regs(1);
7912 for(;;) {
7913 t = gtst(1, t);
7914 if (tok != TOK_LAND) {
7915 vseti(VT_JMPI, t);
7916 break;
7918 next();
7919 expr_or();
7924 static void expr_lor(void)
7926 int t;
7928 expr_land();
7929 if (tok == TOK_LOR) {
7930 t = 0;
7931 save_regs(1);
7932 for(;;) {
7933 t = gtst(0, t);
7934 if (tok != TOK_LOR) {
7935 vseti(VT_JMP, t);
7936 break;
7938 next();
7939 expr_land();
7944 /* XXX: better constant handling */
7945 static void expr_eq(void)
7947 int tt, u, r1, r2, rc, t1, t2, bt1, bt2;
7948 SValue sv;
7949 CType type, type1, type2;
7951 if (const_wanted) {
7952 int c1, c;
7953 expr_lor_const();
7954 if (tok == '?') {
7955 c = vtop->c.i;
7956 vpop();
7957 next();
7958 if (tok == ':' && gnu_ext) {
7959 c1 = c;
7960 } else {
7961 gexpr();
7962 c1 = vtop->c.i;
7963 vpop();
7965 skip(':');
7966 expr_eq();
7967 if (c)
7968 vtop->c.i = c1;
7970 } else {
7971 expr_lor();
7972 if (tok == '?') {
7973 next();
7974 if (vtop != vstack) {
7975 /* needed to avoid having different registers saved in
7976 each branch */
7977 if (is_float(vtop->type.t))
7978 rc = RC_FLOAT;
7979 else
7980 rc = RC_INT;
7981 gv(rc);
7982 save_regs(1);
7984 if (tok == ':' && gnu_ext) {
7985 gv_dup();
7986 tt = gtst(1, 0);
7987 } else {
7988 tt = gtst(1, 0);
7989 gexpr();
7991 type1 = vtop->type;
7992 sv = *vtop; /* save value to handle it later */
7993 vtop--; /* no vpop so that FP stack is not flushed */
7994 skip(':');
7995 u = gjmp(0);
7996 gsym(tt);
7997 expr_eq();
7998 type2 = vtop->type;
8000 t1 = type1.t;
8001 bt1 = t1 & VT_BTYPE;
8002 t2 = type2.t;
8003 bt2 = t2 & VT_BTYPE;
8004 /* cast operands to correct type according to ISOC rules */
8005 if (is_float(bt1) || is_float(bt2)) {
8006 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
8007 type.t = VT_LDOUBLE;
8008 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
8009 type.t = VT_DOUBLE;
8010 } else {
8011 type.t = VT_FLOAT;
8013 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
8014 /* cast to biggest op */
8015 type.t = VT_LLONG;
8016 /* convert to unsigned if it does not fit in a long long */
8017 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
8018 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
8019 type.t |= VT_UNSIGNED;
8020 } else if (bt1 == VT_PTR || bt2 == VT_PTR) {
8021 /* XXX: test pointer compatibility */
8022 type = type1;
8023 } else if (bt1 == VT_FUNC || bt2 == VT_FUNC) {
8024 /* XXX: test function pointer compatibility */
8025 type = type1;
8026 } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
8027 /* XXX: test structure compatibility */
8028 type = type1;
8029 } else if (bt1 == VT_VOID || bt2 == VT_VOID) {
8030 /* NOTE: as an extension, we accept void on only one side */
8031 type.t = VT_VOID;
8032 } else {
8033 /* integer operations */
8034 type.t = VT_INT;
8035 /* convert to unsigned if it does not fit in an integer */
8036 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
8037 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
8038 type.t |= VT_UNSIGNED;
8041 /* now we convert second operand */
8042 gen_cast(&type);
8043 if (VT_STRUCT == (vtop->type.t & VT_BTYPE))
8044 gaddrof();
8045 rc = RC_INT;
8046 if (is_float(type.t)) {
8047 rc = RC_FLOAT;
8048 } else if ((type.t & VT_BTYPE) == VT_LLONG) {
8049 /* for long longs, we use fixed registers to avoid having
8050 to handle a complicated move */
8051 rc = RC_IRET;
8054 r2 = gv(rc);
8055 /* this is horrible, but we must also convert first
8056 operand */
8057 tt = gjmp(0);
8058 gsym(u);
8059 /* put again first value and cast it */
8060 *vtop = sv;
8061 gen_cast(&type);
8062 if (VT_STRUCT == (vtop->type.t & VT_BTYPE))
8063 gaddrof();
8064 r1 = gv(rc);
8065 move_reg(r2, r1);
8066 vtop->r = r2;
8067 gsym(tt);
8072 static void gexpr(void)
8074 while (1) {
8075 expr_eq();
8076 if (tok != ',')
8077 break;
8078 vpop();
8079 next();
8083 /* parse an expression and return its type without any side effect. */
8084 static void expr_type(CType *type)
8086 int saved_nocode_wanted;
8088 saved_nocode_wanted = nocode_wanted;
8089 nocode_wanted = 1;
8090 gexpr();
8091 *type = vtop->type;
8092 vpop();
8093 nocode_wanted = saved_nocode_wanted;
8096 /* parse a unary expression and return its type without any side
8097 effect. */
8098 static void unary_type(CType *type)
8100 int a;
8102 a = nocode_wanted;
8103 nocode_wanted = 1;
8104 unary();
8105 *type = vtop->type;
8106 vpop();
8107 nocode_wanted = a;
8110 /* parse a constant expression and return value in vtop. */
8111 static void expr_const1(void)
8113 int a;
8114 a = const_wanted;
8115 const_wanted = 1;
8116 expr_eq();
8117 const_wanted = a;
8120 /* parse an integer constant and return its value. */
8121 static int expr_const(void)
8123 int c;
8124 expr_const1();
8125 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
8126 expect("constant expression");
8127 c = vtop->c.i;
8128 vpop();
8129 return c;
8132 /* return the label token if current token is a label, otherwise
8133 return zero */
8134 static int is_label(void)
8136 int last_tok;
8138 /* fast test first */
8139 if (tok < TOK_UIDENT)
8140 return 0;
8141 /* no need to save tokc because tok is an identifier */
8142 last_tok = tok;
8143 next();
8144 if (tok == ':') {
8145 next();
8146 return last_tok;
8147 } else {
8148 unget_tok(last_tok);
8149 return 0;
8153 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
8154 int case_reg, int is_expr)
8156 int a, b, c, d;
8157 Sym *s;
8159 /* generate line number info */
8160 if (do_debug &&
8161 (last_line_num != file->line_num || last_ind != ind)) {
8162 put_stabn(N_SLINE, 0, file->line_num, ind - func_ind);
8163 last_ind = ind;
8164 last_line_num = file->line_num;
8167 if (is_expr) {
8168 /* default return value is (void) */
8169 vpushi(0);
8170 vtop->type.t = VT_VOID;
8173 if (tok == TOK_IF) {
8174 /* if test */
8175 next();
8176 skip('(');
8177 gexpr();
8178 skip(')');
8179 a = gtst(1, 0);
8180 block(bsym, csym, case_sym, def_sym, case_reg, 0);
8181 c = tok;
8182 if (c == TOK_ELSE) {
8183 next();
8184 d = gjmp(0);
8185 gsym(a);
8186 block(bsym, csym, case_sym, def_sym, case_reg, 0);
8187 gsym(d); /* patch else jmp */
8188 } else
8189 gsym(a);
8190 } else if (tok == TOK_WHILE) {
8191 next();
8192 d = ind;
8193 skip('(');
8194 gexpr();
8195 skip(')');
8196 a = gtst(1, 0);
8197 b = 0;
8198 block(&a, &b, case_sym, def_sym, case_reg, 0);
8199 gjmp_addr(d);
8200 gsym(a);
8201 gsym_addr(b, d);
8202 } else if (tok == '{') {
8203 Sym *llabel;
8205 next();
8206 /* record local declaration stack position */
8207 s = local_stack;
8208 llabel = local_label_stack;
8209 /* handle local labels declarations */
8210 if (tok == TOK_LABEL) {
8211 next();
8212 for(;;) {
8213 if (tok < TOK_UIDENT)
8214 expect("label identifier");
8215 label_push(&local_label_stack, tok, LABEL_DECLARED);
8216 next();
8217 if (tok == ',') {
8218 next();
8219 } else {
8220 skip(';');
8221 break;
8225 while (tok != '}') {
8226 decl(VT_LOCAL);
8227 if (tok != '}') {
8228 if (is_expr)
8229 vpop();
8230 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
8233 /* pop locally defined labels */
8234 label_pop(&local_label_stack, llabel);
8235 /* pop locally defined symbols */
8236 sym_pop(&local_stack, s);
8237 next();
8238 } else if (tok == TOK_RETURN) {
8239 next();
8240 if (tok != ';') {
8241 gexpr();
8242 gen_assign_cast(&func_vt);
8243 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
8244 CType type;
8245 /* if returning structure, must copy it to implicit
8246 first pointer arg location */
8247 #ifdef TCC_ARM_EABI
8248 int align, size;
8249 size = type_size(&func_vt,&align);
8250 if(size <= 4)
8252 if((vtop->r != (VT_LOCAL | VT_LVAL) || (vtop->c.i & 3))
8253 && (align & 3))
8255 int addr;
8256 loc = (loc - size) & -4;
8257 addr = loc;
8258 type = func_vt;
8259 vset(&type, VT_LOCAL | VT_LVAL, addr);
8260 vswap();
8261 vstore();
8262 vset(&int_type, VT_LOCAL | VT_LVAL, addr);
8264 vtop->type = int_type;
8265 gv(RC_IRET);
8266 } else {
8267 #endif
8268 type = func_vt;
8269 mk_pointer(&type);
8270 vset(&type, VT_LOCAL | VT_LVAL, func_vc);
8271 indir();
8272 vswap();
8273 /* copy structure value to pointer */
8274 vstore();
8275 #ifdef TCC_ARM_EABI
8277 #endif
8278 } else if (is_float(func_vt.t)) {
8279 gv(RC_FRET);
8280 } else {
8281 gv(RC_IRET);
8283 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
8285 skip(';');
8286 rsym = gjmp(rsym); /* jmp */
8287 } else if (tok == TOK_BREAK) {
8288 /* compute jump */
8289 if (!bsym)
8290 error("cannot break");
8291 *bsym = gjmp(*bsym);
8292 next();
8293 skip(';');
8294 } else if (tok == TOK_CONTINUE) {
8295 /* compute jump */
8296 if (!csym)
8297 error("cannot continue");
8298 *csym = gjmp(*csym);
8299 next();
8300 skip(';');
8301 } else if (tok == TOK_FOR) {
8302 int e;
8303 next();
8304 skip('(');
8305 if (tok != ';') {
8306 gexpr();
8307 vpop();
8309 skip(';');
8310 d = ind;
8311 c = ind;
8312 a = 0;
8313 b = 0;
8314 if (tok != ';') {
8315 gexpr();
8316 a = gtst(1, 0);
8318 skip(';');
8319 if (tok != ')') {
8320 e = gjmp(0);
8321 c = ind;
8322 gexpr();
8323 vpop();
8324 gjmp_addr(d);
8325 gsym(e);
8327 skip(')');
8328 block(&a, &b, case_sym, def_sym, case_reg, 0);
8329 gjmp_addr(c);
8330 gsym(a);
8331 gsym_addr(b, c);
8332 } else
8333 if (tok == TOK_DO) {
8334 next();
8335 a = 0;
8336 b = 0;
8337 d = ind;
8338 block(&a, &b, case_sym, def_sym, case_reg, 0);
8339 skip(TOK_WHILE);
8340 skip('(');
8341 gsym(b);
8342 gexpr();
8343 c = gtst(0, 0);
8344 gsym_addr(c, d);
8345 skip(')');
8346 gsym(a);
8347 skip(';');
8348 } else
8349 if (tok == TOK_SWITCH) {
8350 next();
8351 skip('(');
8352 gexpr();
8353 /* XXX: other types than integer */
8354 case_reg = gv(RC_INT);
8355 vpop();
8356 skip(')');
8357 a = 0;
8358 b = gjmp(0); /* jump to first case */
8359 c = 0;
8360 block(&a, csym, &b, &c, case_reg, 0);
8361 /* if no default, jmp after switch */
8362 if (c == 0)
8363 c = ind;
8364 /* default label */
8365 gsym_addr(b, c);
8366 /* break label */
8367 gsym(a);
8368 } else
8369 if (tok == TOK_CASE) {
8370 int v1, v2;
8371 if (!case_sym)
8372 expect("switch");
8373 next();
8374 v1 = expr_const();
8375 v2 = v1;
8376 if (gnu_ext && tok == TOK_DOTS) {
8377 next();
8378 v2 = expr_const();
8379 if (v2 < v1)
8380 warning("empty case range");
8382 /* since a case is like a label, we must skip it with a jmp */
8383 b = gjmp(0);
8384 gsym(*case_sym);
8385 vseti(case_reg, 0);
8386 vpushi(v1);
8387 if (v1 == v2) {
8388 gen_op(TOK_EQ);
8389 *case_sym = gtst(1, 0);
8390 } else {
8391 gen_op(TOK_GE);
8392 *case_sym = gtst(1, 0);
8393 vseti(case_reg, 0);
8394 vpushi(v2);
8395 gen_op(TOK_LE);
8396 *case_sym = gtst(1, *case_sym);
8398 gsym(b);
8399 skip(':');
8400 is_expr = 0;
8401 goto block_after_label;
8402 } else
8403 if (tok == TOK_DEFAULT) {
8404 next();
8405 skip(':');
8406 if (!def_sym)
8407 expect("switch");
8408 if (*def_sym)
8409 error("too many 'default'");
8410 *def_sym = ind;
8411 is_expr = 0;
8412 goto block_after_label;
8413 } else
8414 if (tok == TOK_GOTO) {
8415 next();
8416 if (tok == '*' && gnu_ext) {
8417 /* computed goto */
8418 next();
8419 gexpr();
8420 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
8421 expect("pointer");
8422 ggoto();
8423 } else if (tok >= TOK_UIDENT) {
8424 s = label_find(tok);
8425 /* put forward definition if needed */
8426 if (!s) {
8427 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
8428 } else {
8429 if (s->r == LABEL_DECLARED)
8430 s->r = LABEL_FORWARD;
8432 /* label already defined */
8433 if (s->r & LABEL_FORWARD)
8434 s->next = (void *)gjmp((long)s->next);
8435 else
8436 gjmp_addr((long)s->next);
8437 next();
8438 } else {
8439 expect("label identifier");
8441 skip(';');
8442 } else if (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3) {
8443 asm_instr();
8444 } else {
8445 b = is_label();
8446 if (b) {
8447 /* label case */
8448 s = label_find(b);
8449 if (s) {
8450 if (s->r == LABEL_DEFINED)
8451 error("duplicate label '%s'", get_tok_str(s->v, NULL));
8452 gsym((long)s->next);
8453 s->r = LABEL_DEFINED;
8454 } else {
8455 s = label_push(&global_label_stack, b, LABEL_DEFINED);
8457 s->next = (void *)ind;
8458 /* we accept this, but it is a mistake */
8459 block_after_label:
8460 if (tok == '}') {
8461 warning("deprecated use of label at end of compound statement");
8462 } else {
8463 if (is_expr)
8464 vpop();
8465 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
8467 } else {
8468 /* expression case */
8469 if (tok != ';') {
8470 if (is_expr) {
8471 vpop();
8472 gexpr();
8473 } else {
8474 gexpr();
8475 vpop();
8478 skip(';');
8483 /* t is the array or struct type. c is the array or struct
8484 address. cur_index/cur_field is the pointer to the current
8485 value. 'size_only' is true if only size info is needed (only used
8486 in arrays) */
8487 static void decl_designator(CType *type, Section *sec, unsigned long c,
8488 int *cur_index, Sym **cur_field,
8489 int size_only)
8491 Sym *s, *f;
8492 int notfirst, index, index_last, align, l, nb_elems, elem_size;
8493 CType type1;
8495 notfirst = 0;
8496 elem_size = 0;
8497 nb_elems = 1;
8498 if (gnu_ext && (l = is_label()) != 0)
8499 goto struct_field;
8500 while (tok == '[' || tok == '.') {
8501 if (tok == '[') {
8502 if (!(type->t & VT_ARRAY))
8503 expect("array type");
8504 s = type->ref;
8505 next();
8506 index = expr_const();
8507 if (index < 0 || (s->c >= 0 && index >= s->c))
8508 expect("invalid index");
8509 if (tok == TOK_DOTS && gnu_ext) {
8510 next();
8511 index_last = expr_const();
8512 if (index_last < 0 ||
8513 (s->c >= 0 && index_last >= s->c) ||
8514 index_last < index)
8515 expect("invalid index");
8516 } else {
8517 index_last = index;
8519 skip(']');
8520 if (!notfirst)
8521 *cur_index = index_last;
8522 type = pointed_type(type);
8523 elem_size = type_size(type, &align);
8524 c += index * elem_size;
8525 /* NOTE: we only support ranges for last designator */
8526 nb_elems = index_last - index + 1;
8527 if (nb_elems != 1) {
8528 notfirst = 1;
8529 break;
8531 } else {
8532 next();
8533 l = tok;
8534 next();
8535 struct_field:
8536 if ((type->t & VT_BTYPE) != VT_STRUCT)
8537 expect("struct/union type");
8538 s = type->ref;
8539 l |= SYM_FIELD;
8540 f = s->next;
8541 while (f) {
8542 if (f->v == l)
8543 break;
8544 f = f->next;
8546 if (!f)
8547 expect("field");
8548 if (!notfirst)
8549 *cur_field = f;
8550 /* XXX: fix this mess by using explicit storage field */
8551 type1 = f->type;
8552 type1.t |= (type->t & ~VT_TYPE);
8553 type = &type1;
8554 c += f->c;
8556 notfirst = 1;
8558 if (notfirst) {
8559 if (tok == '=') {
8560 next();
8561 } else {
8562 if (!gnu_ext)
8563 expect("=");
8565 } else {
8566 if (type->t & VT_ARRAY) {
8567 index = *cur_index;
8568 type = pointed_type(type);
8569 c += index * type_size(type, &align);
8570 } else {
8571 f = *cur_field;
8572 if (!f)
8573 error("too many field init");
8574 /* XXX: fix this mess by using explicit storage field */
8575 type1 = f->type;
8576 type1.t |= (type->t & ~VT_TYPE);
8577 type = &type1;
8578 c += f->c;
8581 decl_initializer(type, sec, c, 0, size_only);
8583 /* XXX: make it more general */
8584 if (!size_only && nb_elems > 1) {
8585 unsigned long c_end;
8586 uint8_t *src, *dst;
8587 int i;
8589 if (!sec)
8590 error("range init not supported yet for dynamic storage");
8591 c_end = c + nb_elems * elem_size;
8592 if (c_end > sec->data_allocated)
8593 section_realloc(sec, c_end);
8594 src = sec->data + c;
8595 dst = src;
8596 for(i = 1; i < nb_elems; i++) {
8597 dst += elem_size;
8598 memcpy(dst, src, elem_size);
8603 #define EXPR_VAL 0
8604 #define EXPR_CONST 1
8605 #define EXPR_ANY 2
8607 /* store a value or an expression directly in global data or in local array */
8608 static void init_putv(CType *type, Section *sec, unsigned long c,
8609 int v, int expr_type)
8611 int saved_global_expr, bt, bit_pos, bit_size;
8612 void *ptr;
8613 unsigned long long bit_mask;
8614 CType dtype;
8616 switch(expr_type) {
8617 case EXPR_VAL:
8618 vpushi(v);
8619 break;
8620 case EXPR_CONST:
8621 /* compound literals must be allocated globally in this case */
8622 saved_global_expr = global_expr;
8623 global_expr = 1;
8624 expr_const1();
8625 global_expr = saved_global_expr;
8626 /* NOTE: symbols are accepted */
8627 if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST)
8628 error("initializer element is not constant");
8629 break;
8630 case EXPR_ANY:
8631 expr_eq();
8632 break;
8635 dtype = *type;
8636 dtype.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
8638 if (sec) {
8639 /* XXX: not portable */
8640 /* XXX: generate error if incorrect relocation */
8641 gen_assign_cast(&dtype);
8642 bt = type->t & VT_BTYPE;
8643 ptr = sec->data + c;
8644 /* XXX: make code faster ? */
8645 if (!(type->t & VT_BITFIELD)) {
8646 bit_pos = 0;
8647 bit_size = 32;
8648 bit_mask = -1LL;
8649 } else {
8650 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
8651 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
8652 bit_mask = (1LL << bit_size) - 1;
8654 if ((vtop->r & VT_SYM) &&
8655 (bt == VT_BYTE ||
8656 bt == VT_SHORT ||
8657 bt == VT_DOUBLE ||
8658 bt == VT_LDOUBLE ||
8659 bt == VT_LLONG ||
8660 (bt == VT_INT && bit_size != 32)))
8661 error("initializer element is not computable at load time");
8662 switch(bt) {
8663 case VT_BYTE:
8664 *(char *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8665 break;
8666 case VT_SHORT:
8667 *(short *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8668 break;
8669 case VT_DOUBLE:
8670 *(double *)ptr = vtop->c.d;
8671 break;
8672 case VT_LDOUBLE:
8673 *(long double *)ptr = vtop->c.ld;
8674 break;
8675 case VT_LLONG:
8676 *(long long *)ptr |= (vtop->c.ll & bit_mask) << bit_pos;
8677 break;
8678 default:
8679 if (vtop->r & VT_SYM) {
8680 greloc(sec, vtop->sym, c, R_DATA_32);
8682 *(int *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8683 break;
8685 vtop--;
8686 } else {
8687 vset(&dtype, VT_LOCAL|VT_LVAL, c);
8688 vswap();
8689 vstore();
8690 vpop();
8694 /* put zeros for variable based init */
8695 static void init_putz(CType *t, Section *sec, unsigned long c, int size)
8697 if (sec) {
8698 /* nothing to do because globals are already set to zero */
8699 } else {
8700 vpush_global_sym(&func_old_type, TOK_memset);
8701 vseti(VT_LOCAL, c);
8702 vpushi(0);
8703 vpushi(size);
8704 gfunc_call(3);
8708 /* 't' contains the type and storage info. 'c' is the offset of the
8709 object in section 'sec'. If 'sec' is NULL, it means stack based
8710 allocation. 'first' is true if array '{' must be read (multi
8711 dimension implicit array init handling). 'size_only' is true if
8712 size only evaluation is wanted (only for arrays). */
8713 static void decl_initializer(CType *type, Section *sec, unsigned long c,
8714 int first, int size_only)
8716 int index, array_length, n, no_oblock, nb, parlevel, i;
8717 int size1, align1, expr_type;
8718 Sym *s, *f;
8719 CType *t1;
8721 if (type->t & VT_ARRAY) {
8722 s = type->ref;
8723 n = s->c;
8724 array_length = 0;
8725 t1 = pointed_type(type);
8726 size1 = type_size(t1, &align1);
8728 no_oblock = 1;
8729 if ((first && tok != TOK_LSTR && tok != TOK_STR) ||
8730 tok == '{') {
8731 skip('{');
8732 no_oblock = 0;
8735 /* only parse strings here if correct type (otherwise: handle
8736 them as ((w)char *) expressions */
8737 if ((tok == TOK_LSTR &&
8738 #ifdef TCC_TARGET_PE
8739 (t1->t & VT_BTYPE) == VT_SHORT && (t1->t & VT_UNSIGNED)
8740 #else
8741 (t1->t & VT_BTYPE) == VT_INT
8742 #endif
8743 ) || (tok == TOK_STR && (t1->t & VT_BTYPE) == VT_BYTE)) {
8744 while (tok == TOK_STR || tok == TOK_LSTR) {
8745 int cstr_len, ch;
8746 CString *cstr;
8748 cstr = tokc.cstr;
8749 /* compute maximum number of chars wanted */
8750 if (tok == TOK_STR)
8751 cstr_len = cstr->size;
8752 else
8753 cstr_len = cstr->size / sizeof(nwchar_t);
8754 cstr_len--;
8755 nb = cstr_len;
8756 if (n >= 0 && nb > (n - array_length))
8757 nb = n - array_length;
8758 if (!size_only) {
8759 if (cstr_len > nb)
8760 warning("initializer-string for array is too long");
8761 /* in order to go faster for common case (char
8762 string in global variable, we handle it
8763 specifically */
8764 if (sec && tok == TOK_STR && size1 == 1) {
8765 memcpy(sec->data + c + array_length, cstr->data, nb);
8766 } else {
8767 for(i=0;i<nb;i++) {
8768 if (tok == TOK_STR)
8769 ch = ((unsigned char *)cstr->data)[i];
8770 else
8771 ch = ((nwchar_t *)cstr->data)[i];
8772 init_putv(t1, sec, c + (array_length + i) * size1,
8773 ch, EXPR_VAL);
8777 array_length += nb;
8778 next();
8780 /* only add trailing zero if enough storage (no
8781 warning in this case since it is standard) */
8782 if (n < 0 || array_length < n) {
8783 if (!size_only) {
8784 init_putv(t1, sec, c + (array_length * size1), 0, EXPR_VAL);
8786 array_length++;
8788 } else {
8789 index = 0;
8790 while (tok != '}') {
8791 decl_designator(type, sec, c, &index, NULL, size_only);
8792 if (n >= 0 && index >= n)
8793 error("index too large");
8794 /* must put zero in holes (note that doing it that way
8795 ensures that it even works with designators) */
8796 if (!size_only && array_length < index) {
8797 init_putz(t1, sec, c + array_length * size1,
8798 (index - array_length) * size1);
8800 index++;
8801 if (index > array_length)
8802 array_length = index;
8803 /* special test for multi dimensional arrays (may not
8804 be strictly correct if designators are used at the
8805 same time) */
8806 if (index >= n && no_oblock)
8807 break;
8808 if (tok == '}')
8809 break;
8810 skip(',');
8813 if (!no_oblock)
8814 skip('}');
8815 /* put zeros at the end */
8816 if (!size_only && n >= 0 && array_length < n) {
8817 init_putz(t1, sec, c + array_length * size1,
8818 (n - array_length) * size1);
8820 /* patch type size if needed */
8821 if (n < 0)
8822 s->c = array_length;
8823 } else if ((type->t & VT_BTYPE) == VT_STRUCT &&
8824 (sec || !first || tok == '{')) {
8825 int par_count;
8827 /* NOTE: the previous test is a specific case for automatic
8828 struct/union init */
8829 /* XXX: union needs only one init */
8831 /* XXX: this test is incorrect for local initializers
8832 beginning with ( without {. It would be much more difficult
8833 to do it correctly (ideally, the expression parser should
8834 be used in all cases) */
8835 par_count = 0;
8836 if (tok == '(') {
8837 AttributeDef ad1;
8838 CType type1;
8839 next();
8840 while (tok == '(') {
8841 par_count++;
8842 next();
8844 if (!parse_btype(&type1, &ad1))
8845 expect("cast");
8846 type_decl(&type1, &ad1, &n, TYPE_ABSTRACT);
8847 #if 0
8848 if (!is_assignable_types(type, &type1))
8849 error("invalid type for cast");
8850 #endif
8851 skip(')');
8853 no_oblock = 1;
8854 if (first || tok == '{') {
8855 skip('{');
8856 no_oblock = 0;
8858 s = type->ref;
8859 f = s->next;
8860 array_length = 0;
8861 index = 0;
8862 n = s->c;
8863 while (tok != '}') {
8864 decl_designator(type, sec, c, NULL, &f, size_only);
8865 index = f->c;
8866 if (!size_only && array_length < index) {
8867 init_putz(type, sec, c + array_length,
8868 index - array_length);
8870 index = index + type_size(&f->type, &align1);
8871 if (index > array_length)
8872 array_length = index;
8873 f = f->next;
8874 if (no_oblock && f == NULL)
8875 break;
8876 if (tok == '}')
8877 break;
8878 skip(',');
8880 /* put zeros at the end */
8881 if (!size_only && array_length < n) {
8882 init_putz(type, sec, c + array_length,
8883 n - array_length);
8885 if (!no_oblock)
8886 skip('}');
8887 while (par_count) {
8888 skip(')');
8889 par_count--;
8891 } else if (tok == '{') {
8892 next();
8893 decl_initializer(type, sec, c, first, size_only);
8894 skip('}');
8895 } else if (size_only) {
8896 /* just skip expression */
8897 parlevel = 0;
8898 while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
8899 tok != -1) {
8900 if (tok == '(')
8901 parlevel++;
8902 else if (tok == ')')
8903 parlevel--;
8904 next();
8906 } else {
8907 /* currently, we always use constant expression for globals
8908 (may change for scripting case) */
8909 expr_type = EXPR_CONST;
8910 if (!sec)
8911 expr_type = EXPR_ANY;
8912 init_putv(type, sec, c, 0, expr_type);
8916 /* parse an initializer for type 't' if 'has_init' is non zero, and
8917 allocate space in local or global data space ('r' is either
8918 VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
8919 variable 'v' of scope 'scope' is declared before initializers are
8920 parsed. If 'v' is zero, then a reference to the new object is put
8921 in the value stack. If 'has_init' is 2, a special parsing is done
8922 to handle string constants. */
8923 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
8924 int has_init, int v, int scope)
8926 int size, align, addr, data_offset;
8927 int level;
8928 ParseState saved_parse_state;
8929 TokenString init_str;
8930 Section *sec;
8932 size = type_size(type, &align);
8933 /* If unknown size, we must evaluate it before
8934 evaluating initializers because
8935 initializers can generate global data too
8936 (e.g. string pointers or ISOC99 compound
8937 literals). It also simplifies local
8938 initializers handling */
8939 tok_str_new(&init_str);
8940 if (size < 0) {
8941 if (!has_init)
8942 error("unknown type size");
8943 /* get all init string */
8944 if (has_init == 2) {
8945 /* only get strings */
8946 while (tok == TOK_STR || tok == TOK_LSTR) {
8947 tok_str_add_tok(&init_str);
8948 next();
8950 } else {
8951 level = 0;
8952 while (level > 0 || (tok != ',' && tok != ';')) {
8953 if (tok < 0)
8954 error("unexpected end of file in initializer");
8955 tok_str_add_tok(&init_str);
8956 if (tok == '{')
8957 level++;
8958 else if (tok == '}') {
8959 if (level == 0)
8960 break;
8961 level--;
8963 next();
8966 tok_str_add(&init_str, -1);
8967 tok_str_add(&init_str, 0);
8969 /* compute size */
8970 save_parse_state(&saved_parse_state);
8972 macro_ptr = init_str.str;
8973 next();
8974 decl_initializer(type, NULL, 0, 1, 1);
8975 /* prepare second initializer parsing */
8976 macro_ptr = init_str.str;
8977 next();
8979 /* if still unknown size, error */
8980 size = type_size(type, &align);
8981 if (size < 0)
8982 error("unknown type size");
8984 /* take into account specified alignment if bigger */
8985 if (ad->aligned) {
8986 if (ad->aligned > align)
8987 align = ad->aligned;
8988 } else if (ad->packed) {
8989 align = 1;
8991 if ((r & VT_VALMASK) == VT_LOCAL) {
8992 sec = NULL;
8993 if (do_bounds_check && (type->t & VT_ARRAY))
8994 loc--;
8995 loc = (loc - size) & -align;
8996 addr = loc;
8997 /* handles bounds */
8998 /* XXX: currently, since we do only one pass, we cannot track
8999 '&' operators, so we add only arrays */
9000 if (do_bounds_check && (type->t & VT_ARRAY)) {
9001 unsigned long *bounds_ptr;
9002 /* add padding between regions */
9003 loc--;
9004 /* then add local bound info */
9005 bounds_ptr = section_ptr_add(lbounds_section, 2 * sizeof(unsigned long));
9006 bounds_ptr[0] = addr;
9007 bounds_ptr[1] = size;
9009 if (v) {
9010 /* local variable */
9011 sym_push(v, type, r, addr);
9012 } else {
9013 /* push local reference */
9014 vset(type, r, addr);
9016 } else {
9017 Sym *sym;
9019 sym = NULL;
9020 if (v && scope == VT_CONST) {
9021 /* see if the symbol was already defined */
9022 sym = sym_find(v);
9023 if (sym) {
9024 if (!is_compatible_types(&sym->type, type))
9025 error("incompatible types for redefinition of '%s'",
9026 get_tok_str(v, NULL));
9027 if (sym->type.t & VT_EXTERN) {
9028 /* if the variable is extern, it was not allocated */
9029 sym->type.t &= ~VT_EXTERN;
9030 /* set array size if it was ommited in extern
9031 declaration */
9032 if ((sym->type.t & VT_ARRAY) &&
9033 sym->type.ref->c < 0 &&
9034 type->ref->c >= 0)
9035 sym->type.ref->c = type->ref->c;
9036 } else {
9037 /* we accept several definitions of the same
9038 global variable. this is tricky, because we
9039 must play with the SHN_COMMON type of the symbol */
9040 /* XXX: should check if the variable was already
9041 initialized. It is incorrect to initialized it
9042 twice */
9043 /* no init data, we won't add more to the symbol */
9044 if (!has_init)
9045 goto no_alloc;
9050 /* allocate symbol in corresponding section */
9051 sec = ad->section;
9052 if (!sec) {
9053 if (has_init)
9054 sec = data_section;
9055 else if (tcc_state->nocommon)
9056 sec = bss_section;
9058 if (sec) {
9059 data_offset = sec->data_offset;
9060 data_offset = (data_offset + align - 1) & -align;
9061 addr = data_offset;
9062 /* very important to increment global pointer at this time
9063 because initializers themselves can create new initializers */
9064 data_offset += size;
9065 /* add padding if bound check */
9066 if (do_bounds_check)
9067 data_offset++;
9068 sec->data_offset = data_offset;
9069 /* allocate section space to put the data */
9070 if (sec->sh_type != SHT_NOBITS &&
9071 data_offset > sec->data_allocated)
9072 section_realloc(sec, data_offset);
9073 /* align section if needed */
9074 if (align > sec->sh_addralign)
9075 sec->sh_addralign = align;
9076 } else {
9077 addr = 0; /* avoid warning */
9080 if (v) {
9081 if (scope != VT_CONST || !sym) {
9082 sym = sym_push(v, type, r | VT_SYM, 0);
9084 /* update symbol definition */
9085 if (sec) {
9086 put_extern_sym(sym, sec, addr, size);
9087 } else {
9088 Elf32_Sym *esym;
9089 /* put a common area */
9090 put_extern_sym(sym, NULL, align, size);
9091 /* XXX: find a nicer way */
9092 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
9093 esym->st_shndx = SHN_COMMON;
9095 } else {
9096 CValue cval;
9098 /* push global reference */
9099 sym = get_sym_ref(type, sec, addr, size);
9100 cval.ul = 0;
9101 vsetc(type, VT_CONST | VT_SYM, &cval);
9102 vtop->sym = sym;
9105 /* handles bounds now because the symbol must be defined
9106 before for the relocation */
9107 if (do_bounds_check) {
9108 unsigned long *bounds_ptr;
9110 greloc(bounds_section, sym, bounds_section->data_offset, R_DATA_32);
9111 /* then add global bound info */
9112 bounds_ptr = section_ptr_add(bounds_section, 2 * sizeof(long));
9113 bounds_ptr[0] = 0; /* relocated */
9114 bounds_ptr[1] = size;
9117 if (has_init) {
9118 decl_initializer(type, sec, addr, 1, 0);
9119 /* restore parse state if needed */
9120 if (init_str.str) {
9121 tok_str_free(init_str.str);
9122 restore_parse_state(&saved_parse_state);
9125 no_alloc: ;
9128 void put_func_debug(Sym *sym)
9130 char buf[512];
9132 /* stabs info */
9133 /* XXX: we put here a dummy type */
9134 snprintf(buf, sizeof(buf), "%s:%c1",
9135 funcname, sym->type.t & VT_STATIC ? 'f' : 'F');
9136 put_stabs_r(buf, N_FUN, 0, file->line_num, 0,
9137 cur_text_section, sym->c);
9138 last_ind = 0;
9139 last_line_num = 0;
9142 /* parse an old style function declaration list */
9143 /* XXX: check multiple parameter */
9144 static void func_decl_list(Sym *func_sym)
9146 AttributeDef ad;
9147 int v;
9148 Sym *s;
9149 CType btype, type;
9151 /* parse each declaration */
9152 while (tok != '{' && tok != ';' && tok != ',' && tok != TOK_EOF) {
9153 if (!parse_btype(&btype, &ad))
9154 expect("declaration list");
9155 if (((btype.t & VT_BTYPE) == VT_ENUM ||
9156 (btype.t & VT_BTYPE) == VT_STRUCT) &&
9157 tok == ';') {
9158 /* we accept no variable after */
9159 } else {
9160 for(;;) {
9161 type = btype;
9162 type_decl(&type, &ad, &v, TYPE_DIRECT);
9163 /* find parameter in function parameter list */
9164 s = func_sym->next;
9165 while (s != NULL) {
9166 if ((s->v & ~SYM_FIELD) == v)
9167 goto found;
9168 s = s->next;
9170 error("declaration for parameter '%s' but no such parameter",
9171 get_tok_str(v, NULL));
9172 found:
9173 /* check that no storage specifier except 'register' was given */
9174 if (type.t & VT_STORAGE)
9175 error("storage class specified for '%s'", get_tok_str(v, NULL));
9176 convert_parameter_type(&type);
9177 /* we can add the type (NOTE: it could be local to the function) */
9178 s->type = type;
9179 /* accept other parameters */
9180 if (tok == ',')
9181 next();
9182 else
9183 break;
9186 skip(';');
9190 /* parse a function defined by symbol 'sym' and generate its code in
9191 'cur_text_section' */
9192 static void gen_function(Sym *sym)
9194 int saved_nocode_wanted = nocode_wanted;
9195 nocode_wanted = 0;
9196 ind = cur_text_section->data_offset;
9197 /* NOTE: we patch the symbol size later */
9198 put_extern_sym(sym, cur_text_section, ind, 0);
9199 funcname = get_tok_str(sym->v, NULL);
9200 func_ind = ind;
9201 /* put debug symbol */
9202 if (do_debug)
9203 put_func_debug(sym);
9204 /* push a dummy symbol to enable local sym storage */
9205 sym_push2(&local_stack, SYM_FIELD, 0, 0);
9206 gfunc_prolog(&sym->type);
9207 rsym = 0;
9208 block(NULL, NULL, NULL, NULL, 0, 0);
9209 gsym(rsym);
9210 gfunc_epilog();
9211 cur_text_section->data_offset = ind;
9212 label_pop(&global_label_stack, NULL);
9213 sym_pop(&local_stack, NULL); /* reset local stack */
9214 /* end of function */
9215 /* patch symbol size */
9216 ((Elf32_Sym *)symtab_section->data)[sym->c].st_size =
9217 ind - func_ind;
9218 if (do_debug) {
9219 put_stabn(N_FUN, 0, 0, ind - func_ind);
9221 funcname = ""; /* for safety */
9222 func_vt.t = VT_VOID; /* for safety */
9223 ind = 0; /* for safety */
9224 nocode_wanted = saved_nocode_wanted;
9227 static void gen_inline_functions(void)
9229 Sym *sym;
9230 CType *type;
9231 int *str, inline_generated;
9233 /* iterate while inline function are referenced */
9234 for(;;) {
9235 inline_generated = 0;
9236 for(sym = global_stack; sym != NULL; sym = sym->prev) {
9237 type = &sym->type;
9238 if (((type->t & VT_BTYPE) == VT_FUNC) &&
9239 (type->t & (VT_STATIC | VT_INLINE)) ==
9240 (VT_STATIC | VT_INLINE) &&
9241 sym->c != 0) {
9242 /* the function was used: generate its code and
9243 convert it to a normal function */
9244 str = INLINE_DEF(sym->r);
9245 sym->r = VT_SYM | VT_CONST;
9246 sym->type.t &= ~VT_INLINE;
9248 macro_ptr = str;
9249 next();
9250 cur_text_section = text_section;
9251 gen_function(sym);
9252 macro_ptr = NULL; /* fail safe */
9254 tok_str_free(str);
9255 inline_generated = 1;
9258 if (!inline_generated)
9259 break;
9262 /* free all remaining inline function tokens */
9263 for(sym = global_stack; sym != NULL; sym = sym->prev) {
9264 type = &sym->type;
9265 if (((type->t & VT_BTYPE) == VT_FUNC) &&
9266 (type->t & (VT_STATIC | VT_INLINE)) ==
9267 (VT_STATIC | VT_INLINE)) {
9268 //gr printf("sym %d %s\n", sym->r, get_tok_str(sym->v, NULL));
9269 if (sym->r == (VT_SYM | VT_CONST)) //gr beware!
9270 continue;
9271 str = INLINE_DEF(sym->r);
9272 tok_str_free(str);
9273 sym->r = 0; /* fail safe */
9278 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
9279 static void decl(int l)
9281 int v, has_init, r;
9282 CType type, btype;
9283 Sym *sym;
9284 AttributeDef ad;
9286 while (1) {
9287 if (!parse_btype(&btype, &ad)) {
9288 /* skip redundant ';' */
9289 /* XXX: find more elegant solution */
9290 if (tok == ';') {
9291 next();
9292 continue;
9294 if (l == VT_CONST &&
9295 (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3)) {
9296 /* global asm block */
9297 asm_global_instr();
9298 continue;
9300 /* special test for old K&R protos without explicit int
9301 type. Only accepted when defining global data */
9302 if (l == VT_LOCAL || tok < TOK_DEFINE)
9303 break;
9304 btype.t = VT_INT;
9306 if (((btype.t & VT_BTYPE) == VT_ENUM ||
9307 (btype.t & VT_BTYPE) == VT_STRUCT) &&
9308 tok == ';') {
9309 /* we accept no variable after */
9310 next();
9311 continue;
9313 while (1) { /* iterate thru each declaration */
9314 type = btype;
9315 type_decl(&type, &ad, &v, TYPE_DIRECT);
9316 #if 0
9318 char buf[500];
9319 type_to_str(buf, sizeof(buf), t, get_tok_str(v, NULL));
9320 printf("type = '%s'\n", buf);
9322 #endif
9323 if ((type.t & VT_BTYPE) == VT_FUNC) {
9324 /* if old style function prototype, we accept a
9325 declaration list */
9326 sym = type.ref;
9327 if (sym->c == FUNC_OLD)
9328 func_decl_list(sym);
9331 if (tok == '{') {
9332 if (l == VT_LOCAL)
9333 error("cannot use local functions");
9334 if ((type.t & VT_BTYPE) != VT_FUNC)
9335 expect("function definition");
9337 /* reject abstract declarators in function definition */
9338 sym = type.ref;
9339 while ((sym = sym->next) != NULL)
9340 if (!(sym->v & ~SYM_FIELD))
9341 expect("identifier");
9343 /* XXX: cannot do better now: convert extern line to static inline */
9344 if ((type.t & (VT_EXTERN | VT_INLINE)) == (VT_EXTERN | VT_INLINE))
9345 type.t = (type.t & ~VT_EXTERN) | VT_STATIC;
9347 sym = sym_find(v);
9348 if (sym) {
9349 if ((sym->type.t & VT_BTYPE) != VT_FUNC)
9350 goto func_error1;
9351 /* specific case: if not func_call defined, we put
9352 the one of the prototype */
9353 /* XXX: should have default value */
9354 r = sym->type.ref->r;
9355 if (FUNC_CALL(r) != FUNC_CDECL
9356 && FUNC_CALL(type.ref->r) == FUNC_CDECL)
9357 FUNC_CALL(type.ref->r) = FUNC_CALL(r);
9358 if (FUNC_EXPORT(r))
9359 FUNC_EXPORT(type.ref->r) = 1;
9361 if (!is_compatible_types(&sym->type, &type)) {
9362 func_error1:
9363 error("incompatible types for redefinition of '%s'",
9364 get_tok_str(v, NULL));
9366 /* if symbol is already defined, then put complete type */
9367 sym->type = type;
9368 } else {
9369 /* put function symbol */
9370 sym = global_identifier_push(v, type.t, 0);
9371 sym->type.ref = type.ref;
9374 /* static inline functions are just recorded as a kind
9375 of macro. Their code will be emitted at the end of
9376 the compilation unit only if they are used */
9377 if ((type.t & (VT_INLINE | VT_STATIC)) ==
9378 (VT_INLINE | VT_STATIC)) {
9379 TokenString func_str;
9380 int block_level;
9382 tok_str_new(&func_str);
9384 block_level = 0;
9385 for(;;) {
9386 int t;
9387 if (tok == TOK_EOF)
9388 error("unexpected end of file");
9389 tok_str_add_tok(&func_str);
9390 t = tok;
9391 next();
9392 if (t == '{') {
9393 block_level++;
9394 } else if (t == '}') {
9395 block_level--;
9396 if (block_level == 0)
9397 break;
9400 tok_str_add(&func_str, -1);
9401 tok_str_add(&func_str, 0);
9402 INLINE_DEF(sym->r) = func_str.str;
9403 } else {
9404 /* compute text section */
9405 cur_text_section = ad.section;
9406 if (!cur_text_section)
9407 cur_text_section = text_section;
9408 sym->r = VT_SYM | VT_CONST;
9409 gen_function(sym);
9411 break;
9412 } else {
9413 if (btype.t & VT_TYPEDEF) {
9414 /* save typedefed type */
9415 /* XXX: test storage specifiers ? */
9416 sym = sym_push(v, &type, 0, 0);
9417 sym->type.t |= VT_TYPEDEF;
9418 } else if ((type.t & VT_BTYPE) == VT_FUNC) {
9419 /* external function definition */
9420 /* specific case for func_call attribute */
9421 if (ad.func_attr)
9422 type.ref->r = ad.func_attr;
9423 external_sym(v, &type, 0);
9424 } else {
9425 /* not lvalue if array */
9426 r = 0;
9427 if (!(type.t & VT_ARRAY))
9428 r |= lvalue_type(type.t);
9429 has_init = (tok == '=');
9430 if ((btype.t & VT_EXTERN) ||
9431 ((type.t & VT_ARRAY) && (type.t & VT_STATIC) &&
9432 !has_init && l == VT_CONST && type.ref->c < 0)) {
9433 /* external variable */
9434 /* NOTE: as GCC, uninitialized global static
9435 arrays of null size are considered as
9436 extern */
9437 external_sym(v, &type, r);
9438 } else {
9439 type.t |= (btype.t & VT_STATIC); /* Retain "static". */
9440 if (type.t & VT_STATIC)
9441 r |= VT_CONST;
9442 else
9443 r |= l;
9444 if (has_init)
9445 next();
9446 decl_initializer_alloc(&type, &ad, r,
9447 has_init, v, l);
9450 if (tok != ',') {
9451 skip(';');
9452 break;
9454 next();
9460 /* better than nothing, but needs extension to handle '-E' option
9461 correctly too */
9462 static void preprocess_init(TCCState *s1)
9464 s1->include_stack_ptr = s1->include_stack;
9465 /* XXX: move that before to avoid having to initialize
9466 file->ifdef_stack_ptr ? */
9467 s1->ifdef_stack_ptr = s1->ifdef_stack;
9468 file->ifdef_stack_ptr = s1->ifdef_stack_ptr;
9470 /* XXX: not ANSI compliant: bound checking says error */
9471 vtop = vstack - 1;
9472 s1->pack_stack[0] = 0;
9473 s1->pack_stack_ptr = s1->pack_stack;
9476 /* compile the C file opened in 'file'. Return non zero if errors. */
9477 static int tcc_compile(TCCState *s1)
9479 Sym *define_start;
9480 char buf[512];
9481 volatile int section_sym;
9483 #ifdef INC_DEBUG
9484 printf("%s: **** new file\n", file->filename);
9485 #endif
9486 preprocess_init(s1);
9488 funcname = "";
9489 anon_sym = SYM_FIRST_ANOM;
9491 /* file info: full path + filename */
9492 section_sym = 0; /* avoid warning */
9493 if (do_debug) {
9494 section_sym = put_elf_sym(symtab_section, 0, 0,
9495 ELF32_ST_INFO(STB_LOCAL, STT_SECTION), 0,
9496 text_section->sh_num, NULL);
9497 getcwd(buf, sizeof(buf));
9498 #ifdef _WIN32
9499 normalize_slashes(buf);
9500 #endif
9501 pstrcat(buf, sizeof(buf), "/");
9502 put_stabs_r(buf, N_SO, 0, 0,
9503 text_section->data_offset, text_section, section_sym);
9504 put_stabs_r(file->filename, N_SO, 0, 0,
9505 text_section->data_offset, text_section, section_sym);
9507 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
9508 symbols can be safely used */
9509 put_elf_sym(symtab_section, 0, 0,
9510 ELF32_ST_INFO(STB_LOCAL, STT_FILE), 0,
9511 SHN_ABS, file->filename);
9513 /* define some often used types */
9514 int_type.t = VT_INT;
9516 char_pointer_type.t = VT_BYTE;
9517 mk_pointer(&char_pointer_type);
9519 func_old_type.t = VT_FUNC;
9520 func_old_type.ref = sym_push(SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD);
9522 #if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)
9523 float_type.t = VT_FLOAT;
9524 double_type.t = VT_DOUBLE;
9526 func_float_type.t = VT_FUNC;
9527 func_float_type.ref = sym_push(SYM_FIELD, &float_type, FUNC_CDECL, FUNC_OLD);
9528 func_double_type.t = VT_FUNC;
9529 func_double_type.ref = sym_push(SYM_FIELD, &double_type, FUNC_CDECL, FUNC_OLD);
9530 #endif
9532 #if 0
9533 /* define 'void *alloca(unsigned int)' builtin function */
9535 Sym *s1;
9537 p = anon_sym++;
9538 sym = sym_push(p, mk_pointer(VT_VOID), FUNC_CDECL, FUNC_NEW);
9539 s1 = sym_push(SYM_FIELD, VT_UNSIGNED | VT_INT, 0, 0);
9540 s1->next = NULL;
9541 sym->next = s1;
9542 sym_push(TOK_alloca, VT_FUNC | (p << VT_STRUCT_SHIFT), VT_CONST, 0);
9544 #endif
9546 define_start = define_stack;
9547 nocode_wanted = 1;
9549 if (setjmp(s1->error_jmp_buf) == 0) {
9550 s1->nb_errors = 0;
9551 s1->error_set_jmp_enabled = 1;
9553 ch = file->buf_ptr[0];
9554 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
9555 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM;
9556 next();
9557 decl(VT_CONST);
9558 if (tok != TOK_EOF)
9559 expect("declaration");
9561 /* end of translation unit info */
9562 if (do_debug) {
9563 put_stabs_r(NULL, N_SO, 0, 0,
9564 text_section->data_offset, text_section, section_sym);
9567 s1->error_set_jmp_enabled = 0;
9569 /* reset define stack, but leave -Dsymbols (may be incorrect if
9570 they are undefined) */
9571 free_defines(define_start);
9573 gen_inline_functions();
9575 sym_pop(&global_stack, NULL);
9577 return s1->nb_errors != 0 ? -1 : 0;
9580 /* Preprocess the current file */
9581 /* XXX: add line and file infos, add options to preserve spaces */
9582 static int tcc_preprocess(TCCState *s1)
9584 Sym *define_start;
9585 int last_is_space;
9587 preprocess_init(s1);
9589 define_start = define_stack;
9591 ch = file->buf_ptr[0];
9592 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
9593 parse_flags = PARSE_FLAG_ASM_COMMENTS | PARSE_FLAG_PREPROCESS |
9594 PARSE_FLAG_LINEFEED;
9595 last_is_space = 1;
9596 next();
9597 for(;;) {
9598 if (tok == TOK_EOF) {
9599 break;
9600 } else if (tok == TOK_LINEFEED) {
9601 last_is_space = 1;
9602 } else {
9603 if (!last_is_space)
9604 fputc(' ', s1->outfile);
9605 last_is_space = 0;
9607 fputs(get_tok_str(tok, &tokc), s1->outfile);
9608 next();
9610 free_defines(define_start);
9611 return 0;
9614 #ifdef LIBTCC
9615 int tcc_compile_string(TCCState *s, const char *str)
9617 BufferedFile bf1, *bf = &bf1;
9618 int ret, len;
9619 char *buf;
9621 /* init file structure */
9622 bf->fd = -1;
9623 /* XXX: avoid copying */
9624 len = strlen(str);
9625 buf = tcc_malloc(len + 1);
9626 if (!buf)
9627 return -1;
9628 memcpy(buf, str, len);
9629 buf[len] = CH_EOB;
9630 bf->buf_ptr = buf;
9631 bf->buf_end = buf + len;
9632 pstrcpy(bf->filename, sizeof(bf->filename), "<string>");
9633 bf->line_num = 1;
9634 file = bf;
9636 ret = tcc_compile(s);
9638 tcc_free(buf);
9640 /* currently, no need to close */
9641 return ret;
9643 #endif
9645 /* define a preprocessor symbol. A value can also be provided with the '=' operator */
9646 void tcc_define_symbol(TCCState *s1, const char *sym, const char *value)
9648 BufferedFile bf1, *bf = &bf1;
9650 pstrcpy(bf->buffer, IO_BUF_SIZE, sym);
9651 pstrcat(bf->buffer, IO_BUF_SIZE, " ");
9652 /* default value */
9653 if (!value)
9654 value = "1";
9655 pstrcat(bf->buffer, IO_BUF_SIZE, value);
9657 /* init file structure */
9658 bf->fd = -1;
9659 bf->buf_ptr = bf->buffer;
9660 bf->buf_end = bf->buffer + strlen(bf->buffer);
9661 *bf->buf_end = CH_EOB;
9662 bf->filename[0] = '\0';
9663 bf->line_num = 1;
9664 file = bf;
9666 s1->include_stack_ptr = s1->include_stack;
9668 /* parse with define parser */
9669 ch = file->buf_ptr[0];
9670 next_nomacro();
9671 parse_define();
9672 file = NULL;
9675 /* undefine a preprocessor symbol */
9676 void tcc_undefine_symbol(TCCState *s1, const char *sym)
9678 TokenSym *ts;
9679 Sym *s;
9680 ts = tok_alloc(sym, strlen(sym));
9681 s = define_find(ts->tok);
9682 /* undefine symbol by putting an invalid name */
9683 if (s)
9684 define_undef(s);
9687 #ifdef CONFIG_TCC_ASM
9689 #ifdef TCC_TARGET_I386
9690 #include "i386-asm.c"
9691 #endif
9692 #include "tccasm.c"
9694 #else
9695 static void asm_instr(void)
9697 error("inline asm() not supported");
9699 static void asm_global_instr(void)
9701 error("inline asm() not supported");
9703 #endif
9705 #include "tccelf.c"
9707 #ifdef TCC_TARGET_COFF
9708 #include "tcccoff.c"
9709 #endif
9711 #ifdef TCC_TARGET_PE
9712 #include "tccpe.c"
9713 #endif
9715 /* print the position in the source file of PC value 'pc' by reading
9716 the stabs debug information */
9717 static void rt_printline(unsigned long wanted_pc)
9719 Stab_Sym *sym, *sym_end;
9720 char func_name[128], last_func_name[128];
9721 unsigned long func_addr, last_pc, pc;
9722 const char *incl_files[INCLUDE_STACK_SIZE];
9723 int incl_index, len, last_line_num, i;
9724 const char *str, *p;
9726 fprintf(stderr, "0x%08lx:", wanted_pc);
9728 func_name[0] = '\0';
9729 func_addr = 0;
9730 incl_index = 0;
9731 last_func_name[0] = '\0';
9732 last_pc = 0xffffffff;
9733 last_line_num = 1;
9734 sym = (Stab_Sym *)stab_section->data + 1;
9735 sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset);
9736 while (sym < sym_end) {
9737 switch(sym->n_type) {
9738 /* function start or end */
9739 case N_FUN:
9740 if (sym->n_strx == 0) {
9741 /* we test if between last line and end of function */
9742 pc = sym->n_value + func_addr;
9743 if (wanted_pc >= last_pc && wanted_pc < pc)
9744 goto found;
9745 func_name[0] = '\0';
9746 func_addr = 0;
9747 } else {
9748 str = stabstr_section->data + sym->n_strx;
9749 p = strchr(str, ':');
9750 if (!p) {
9751 pstrcpy(func_name, sizeof(func_name), str);
9752 } else {
9753 len = p - str;
9754 if (len > sizeof(func_name) - 1)
9755 len = sizeof(func_name) - 1;
9756 memcpy(func_name, str, len);
9757 func_name[len] = '\0';
9759 func_addr = sym->n_value;
9761 break;
9762 /* line number info */
9763 case N_SLINE:
9764 pc = sym->n_value + func_addr;
9765 if (wanted_pc >= last_pc && wanted_pc < pc)
9766 goto found;
9767 last_pc = pc;
9768 last_line_num = sym->n_desc;
9769 /* XXX: slow! */
9770 strcpy(last_func_name, func_name);
9771 break;
9772 /* include files */
9773 case N_BINCL:
9774 str = stabstr_section->data + sym->n_strx;
9775 add_incl:
9776 if (incl_index < INCLUDE_STACK_SIZE) {
9777 incl_files[incl_index++] = str;
9779 break;
9780 case N_EINCL:
9781 if (incl_index > 1)
9782 incl_index--;
9783 break;
9784 case N_SO:
9785 if (sym->n_strx == 0) {
9786 incl_index = 0; /* end of translation unit */
9787 } else {
9788 str = stabstr_section->data + sym->n_strx;
9789 /* do not add path */
9790 len = strlen(str);
9791 if (len > 0 && str[len - 1] != '/')
9792 goto add_incl;
9794 break;
9796 sym++;
9799 /* second pass: we try symtab symbols (no line number info) */
9800 incl_index = 0;
9802 Elf32_Sym *sym, *sym_end;
9803 int type;
9805 sym_end = (Elf32_Sym *)(symtab_section->data + symtab_section->data_offset);
9806 for(sym = (Elf32_Sym *)symtab_section->data + 1;
9807 sym < sym_end;
9808 sym++) {
9809 type = ELF32_ST_TYPE(sym->st_info);
9810 if (type == STT_FUNC) {
9811 if (wanted_pc >= sym->st_value &&
9812 wanted_pc < sym->st_value + sym->st_size) {
9813 pstrcpy(last_func_name, sizeof(last_func_name),
9814 strtab_section->data + sym->st_name);
9815 goto found;
9820 /* did not find any info: */
9821 fprintf(stderr, " ???\n");
9822 return;
9823 found:
9824 if (last_func_name[0] != '\0') {
9825 fprintf(stderr, " %s()", last_func_name);
9827 if (incl_index > 0) {
9828 fprintf(stderr, " (%s:%d",
9829 incl_files[incl_index - 1], last_line_num);
9830 for(i = incl_index - 2; i >= 0; i--)
9831 fprintf(stderr, ", included from %s", incl_files[i]);
9832 fprintf(stderr, ")");
9834 fprintf(stderr, "\n");
9837 #if !defined(_WIN32) && !defined(CONFIG_TCCBOOT)
9839 #ifdef __i386__
9841 /* fix for glibc 2.1 */
9842 #ifndef REG_EIP
9843 #define REG_EIP EIP
9844 #define REG_EBP EBP
9845 #endif
9847 /* return the PC at frame level 'level'. Return non zero if not found */
9848 static int rt_get_caller_pc(unsigned long *paddr,
9849 ucontext_t *uc, int level)
9851 unsigned long fp;
9852 int i;
9854 if (level == 0) {
9855 #if defined(__FreeBSD__)
9856 *paddr = uc->uc_mcontext.mc_eip;
9857 #elif defined(__dietlibc__)
9858 *paddr = uc->uc_mcontext.eip;
9859 #else
9860 *paddr = uc->uc_mcontext.gregs[REG_EIP];
9861 #endif
9862 return 0;
9863 } else {
9864 #if defined(__FreeBSD__)
9865 fp = uc->uc_mcontext.mc_ebp;
9866 #elif defined(__dietlibc__)
9867 fp = uc->uc_mcontext.ebp;
9868 #else
9869 fp = uc->uc_mcontext.gregs[REG_EBP];
9870 #endif
9871 for(i=1;i<level;i++) {
9872 /* XXX: check address validity with program info */
9873 if (fp <= 0x1000 || fp >= 0xc0000000)
9874 return -1;
9875 fp = ((unsigned long *)fp)[0];
9877 *paddr = ((unsigned long *)fp)[1];
9878 return 0;
9881 #else
9883 #warning add arch specific rt_get_caller_pc()
9885 static int rt_get_caller_pc(unsigned long *paddr,
9886 ucontext_t *uc, int level)
9888 return -1;
9890 #endif
9892 /* emit a run time error at position 'pc' */
9893 void rt_error(ucontext_t *uc, const char *fmt, ...)
9895 va_list ap;
9896 unsigned long pc;
9897 int i;
9899 va_start(ap, fmt);
9900 fprintf(stderr, "Runtime error: ");
9901 vfprintf(stderr, fmt, ap);
9902 fprintf(stderr, "\n");
9903 for(i=0;i<num_callers;i++) {
9904 if (rt_get_caller_pc(&pc, uc, i) < 0)
9905 break;
9906 if (i == 0)
9907 fprintf(stderr, "at ");
9908 else
9909 fprintf(stderr, "by ");
9910 rt_printline(pc);
9912 exit(255);
9913 va_end(ap);
9916 /* signal handler for fatal errors */
9917 static void sig_error(int signum, siginfo_t *siginf, void *puc)
9919 ucontext_t *uc = puc;
9921 switch(signum) {
9922 case SIGFPE:
9923 switch(siginf->si_code) {
9924 case FPE_INTDIV:
9925 case FPE_FLTDIV:
9926 rt_error(uc, "division by zero");
9927 break;
9928 default:
9929 rt_error(uc, "floating point exception");
9930 break;
9932 break;
9933 case SIGBUS:
9934 case SIGSEGV:
9935 if (rt_bound_error_msg && *rt_bound_error_msg)
9936 rt_error(uc, *rt_bound_error_msg);
9937 else
9938 rt_error(uc, "dereferencing invalid pointer");
9939 break;
9940 case SIGILL:
9941 rt_error(uc, "illegal instruction");
9942 break;
9943 case SIGABRT:
9944 rt_error(uc, "abort() called");
9945 break;
9946 default:
9947 rt_error(uc, "caught signal %d", signum);
9948 break;
9950 exit(255);
9952 #endif
9954 /* do all relocations (needed before using tcc_get_symbol()) */
9955 int tcc_relocate(TCCState *s1)
9957 Section *s;
9958 int i;
9960 s1->nb_errors = 0;
9962 #ifdef TCC_TARGET_PE
9963 pe_add_runtime(s1);
9964 #else
9965 tcc_add_runtime(s1);
9966 #endif
9968 relocate_common_syms();
9970 tcc_add_linker_symbols(s1);
9971 #ifndef TCC_TARGET_PE
9972 build_got_entries(s1);
9973 #endif
9974 /* compute relocation address : section are relocated in place. We
9975 also alloc the bss space */
9976 for(i = 1; i < s1->nb_sections; i++) {
9977 s = s1->sections[i];
9978 if (s->sh_flags & SHF_ALLOC) {
9979 if (s->sh_type == SHT_NOBITS)
9980 s->data = tcc_mallocz(s->data_offset);
9981 s->sh_addr = (unsigned long)s->data;
9985 relocate_syms(s1, 1);
9987 if (s1->nb_errors != 0)
9988 return -1;
9990 /* relocate each section */
9991 for(i = 1; i < s1->nb_sections; i++) {
9992 s = s1->sections[i];
9993 if (s->reloc)
9994 relocate_section(s1, s);
9997 /* mark executable sections as executable in memory */
9998 for(i = 1; i < s1->nb_sections; i++) {
9999 s = s1->sections[i];
10000 if ((s->sh_flags & (SHF_ALLOC | SHF_EXECINSTR)) ==
10001 (SHF_ALLOC | SHF_EXECINSTR))
10002 set_pages_executable(s->data, s->data_offset);
10004 return 0;
10007 /* launch the compiled program with the given arguments */
10008 int tcc_run(TCCState *s1, int argc, char **argv)
10010 int (*prog_main)(int, char **);
10012 if (tcc_relocate(s1) < 0)
10013 return -1;
10015 prog_main = tcc_get_symbol_err(s1, "main");
10017 if (do_debug) {
10018 #if defined(_WIN32) || defined(CONFIG_TCCBOOT)
10019 error("debug mode currently not available for Windows");
10020 #else
10021 struct sigaction sigact;
10022 /* install TCC signal handlers to print debug info on fatal
10023 runtime errors */
10024 sigact.sa_flags = SA_SIGINFO | SA_RESETHAND;
10025 sigact.sa_sigaction = sig_error;
10026 sigemptyset(&sigact.sa_mask);
10027 sigaction(SIGFPE, &sigact, NULL);
10028 sigaction(SIGILL, &sigact, NULL);
10029 sigaction(SIGSEGV, &sigact, NULL);
10030 sigaction(SIGBUS, &sigact, NULL);
10031 sigaction(SIGABRT, &sigact, NULL);
10032 #endif
10035 #ifdef CONFIG_TCC_BCHECK
10036 if (do_bounds_check) {
10037 void (*bound_init)(void);
10039 /* set error function */
10040 rt_bound_error_msg = (void *)tcc_get_symbol_err(s1,
10041 "__bound_error_msg");
10043 /* XXX: use .init section so that it also work in binary ? */
10044 bound_init = (void *)tcc_get_symbol_err(s1, "__bound_init");
10045 bound_init();
10047 #endif
10048 return (*prog_main)(argc, argv);
10051 TCCState *tcc_new(void)
10053 const char *p, *r;
10054 TCCState *s;
10055 TokenSym *ts;
10056 int i, c;
10058 s = tcc_mallocz(sizeof(TCCState));
10059 if (!s)
10060 return NULL;
10061 tcc_state = s;
10062 s->output_type = TCC_OUTPUT_MEMORY;
10064 /* init isid table */
10065 for(i=0;i<256;i++)
10066 isidnum_table[i] = isid(i) || isnum(i);
10068 /* add all tokens */
10069 table_ident = NULL;
10070 memset(hash_ident, 0, TOK_HASH_SIZE * sizeof(TokenSym *));
10072 tok_ident = TOK_IDENT;
10073 p = tcc_keywords;
10074 while (*p) {
10075 r = p;
10076 for(;;) {
10077 c = *r++;
10078 if (c == '\0')
10079 break;
10081 ts = tok_alloc(p, r - p - 1);
10082 p = r;
10085 /* we add dummy defines for some special macros to speed up tests
10086 and to have working defined() */
10087 define_push(TOK___LINE__, MACRO_OBJ, NULL, NULL);
10088 define_push(TOK___FILE__, MACRO_OBJ, NULL, NULL);
10089 define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL);
10090 define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL);
10092 /* standard defines */
10093 tcc_define_symbol(s, "__STDC__", NULL);
10094 tcc_define_symbol(s, "__STDC_VERSION__", "199901L");
10095 #if defined(TCC_TARGET_I386)
10096 tcc_define_symbol(s, "__i386__", NULL);
10097 #endif
10098 #if defined(TCC_TARGET_ARM)
10099 tcc_define_symbol(s, "__ARM_ARCH_4__", NULL);
10100 tcc_define_symbol(s, "__arm_elf__", NULL);
10101 tcc_define_symbol(s, "__arm_elf", NULL);
10102 tcc_define_symbol(s, "arm_elf", NULL);
10103 tcc_define_symbol(s, "__arm__", NULL);
10104 tcc_define_symbol(s, "__arm", NULL);
10105 tcc_define_symbol(s, "arm", NULL);
10106 tcc_define_symbol(s, "__APCS_32__", NULL);
10107 #endif
10108 #ifdef TCC_TARGET_PE
10109 tcc_define_symbol(s, "_WIN32", NULL);
10110 #else
10111 tcc_define_symbol(s, "__unix__", NULL);
10112 tcc_define_symbol(s, "__unix", NULL);
10113 #if defined(__linux)
10114 tcc_define_symbol(s, "__linux__", NULL);
10115 tcc_define_symbol(s, "__linux", NULL);
10116 #endif
10117 #endif
10118 /* tiny C specific defines */
10119 tcc_define_symbol(s, "__TINYC__", NULL);
10121 /* tiny C & gcc defines */
10122 tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned int");
10123 tcc_define_symbol(s, "__PTRDIFF_TYPE__", "int");
10124 #ifdef TCC_TARGET_PE
10125 tcc_define_symbol(s, "__WCHAR_TYPE__", "unsigned short");
10126 #else
10127 tcc_define_symbol(s, "__WCHAR_TYPE__", "int");
10128 #endif
10130 #ifndef TCC_TARGET_PE
10131 /* default library paths */
10132 tcc_add_library_path(s, "/usr/local/lib");
10133 tcc_add_library_path(s, "/usr/lib");
10134 tcc_add_library_path(s, "/lib");
10135 #endif
10137 /* no section zero */
10138 dynarray_add((void ***)&s->sections, &s->nb_sections, NULL);
10140 /* create standard sections */
10141 text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
10142 data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
10143 bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
10145 /* symbols are always generated for linking stage */
10146 symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0,
10147 ".strtab",
10148 ".hashtab", SHF_PRIVATE);
10149 strtab_section = symtab_section->link;
10151 /* private symbol table for dynamic symbols */
10152 s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE,
10153 ".dynstrtab",
10154 ".dynhashtab", SHF_PRIVATE);
10155 s->alacarte_link = 1;
10157 #ifdef CHAR_IS_UNSIGNED
10158 s->char_is_unsigned = 1;
10159 #endif
10160 #if defined(TCC_TARGET_PE) && 0
10161 /* XXX: currently the PE linker is not ready to support that */
10162 s->leading_underscore = 1;
10163 #endif
10164 return s;
10167 void tcc_delete(TCCState *s1)
10169 int i, n;
10171 /* free -D defines */
10172 free_defines(NULL);
10174 /* free tokens */
10175 n = tok_ident - TOK_IDENT;
10176 for(i = 0; i < n; i++)
10177 tcc_free(table_ident[i]);
10178 tcc_free(table_ident);
10180 /* free all sections */
10182 free_section(symtab_section->hash);
10184 free_section(s1->dynsymtab_section->hash);
10185 free_section(s1->dynsymtab_section->link);
10186 free_section(s1->dynsymtab_section);
10188 for(i = 1; i < s1->nb_sections; i++)
10189 free_section(s1->sections[i]);
10190 tcc_free(s1->sections);
10192 /* free loaded dlls array */
10193 dynarray_reset(&s1->loaded_dlls, &s1->nb_loaded_dlls);
10195 /* free library paths */
10196 dynarray_reset(&s1->library_paths, &s1->nb_library_paths);
10198 /* free include paths */
10199 dynarray_reset(&s1->cached_includes, &s1->nb_cached_includes);
10200 dynarray_reset(&s1->include_paths, &s1->nb_include_paths);
10201 dynarray_reset(&s1->sysinclude_paths, &s1->nb_sysinclude_paths);
10203 tcc_free(s1);
10206 int tcc_add_include_path(TCCState *s1, const char *pathname)
10208 char *pathname1;
10210 pathname1 = tcc_strdup(pathname);
10211 dynarray_add((void ***)&s1->include_paths, &s1->nb_include_paths, pathname1);
10212 return 0;
10215 int tcc_add_sysinclude_path(TCCState *s1, const char *pathname)
10217 char *pathname1;
10219 pathname1 = tcc_strdup(pathname);
10220 dynarray_add((void ***)&s1->sysinclude_paths, &s1->nb_sysinclude_paths, pathname1);
10221 return 0;
10224 static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
10226 const char *ext;
10227 Elf32_Ehdr ehdr;
10228 int fd, ret;
10229 BufferedFile *saved_file;
10231 /* find source file type with extension */
10232 ext = tcc_fileextension(filename);
10233 if (ext[0])
10234 ext++;
10236 /* open the file */
10237 saved_file = file;
10238 file = tcc_open(s1, filename);
10239 if (!file) {
10240 if (flags & AFF_PRINT_ERROR) {
10241 error_noabort("file '%s' not found", filename);
10243 ret = -1;
10244 goto fail1;
10247 if (flags & AFF_PREPROCESS) {
10248 ret = tcc_preprocess(s1);
10249 } else if (!ext[0] || !strcmp(ext, "c")) {
10250 /* C file assumed */
10251 ret = tcc_compile(s1);
10252 } else
10253 #ifdef CONFIG_TCC_ASM
10254 if (!strcmp(ext, "S")) {
10255 /* preprocessed assembler */
10256 ret = tcc_assemble(s1, 1);
10257 } else if (!strcmp(ext, "s")) {
10258 /* non preprocessed assembler */
10259 ret = tcc_assemble(s1, 0);
10260 } else
10261 #endif
10262 #ifdef TCC_TARGET_PE
10263 if (!strcmp(ext, "def")) {
10264 ret = pe_load_def_file(s1, file->fd);
10265 } else
10266 #endif
10268 fd = file->fd;
10269 /* assume executable format: auto guess file type */
10270 ret = read(fd, &ehdr, sizeof(ehdr));
10271 lseek(fd, 0, SEEK_SET);
10272 if (ret <= 0) {
10273 error_noabort("could not read header");
10274 goto fail;
10275 } else if (ret != sizeof(ehdr)) {
10276 goto try_load_script;
10279 if (ehdr.e_ident[0] == ELFMAG0 &&
10280 ehdr.e_ident[1] == ELFMAG1 &&
10281 ehdr.e_ident[2] == ELFMAG2 &&
10282 ehdr.e_ident[3] == ELFMAG3) {
10283 file->line_num = 0; /* do not display line number if error */
10284 if (ehdr.e_type == ET_REL) {
10285 ret = tcc_load_object_file(s1, fd, 0);
10286 } else if (ehdr.e_type == ET_DYN) {
10287 if (s1->output_type == TCC_OUTPUT_MEMORY) {
10288 #ifdef TCC_TARGET_PE
10289 ret = -1;
10290 #else
10291 void *h;
10292 h = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY);
10293 if (h)
10294 ret = 0;
10295 else
10296 ret = -1;
10297 #endif
10298 } else {
10299 ret = tcc_load_dll(s1, fd, filename,
10300 (flags & AFF_REFERENCED_DLL) != 0);
10302 } else {
10303 error_noabort("unrecognized ELF file");
10304 goto fail;
10306 } else if (memcmp((char *)&ehdr, ARMAG, 8) == 0) {
10307 file->line_num = 0; /* do not display line number if error */
10308 ret = tcc_load_archive(s1, fd);
10309 } else
10310 #ifdef TCC_TARGET_COFF
10311 if (*(uint16_t *)(&ehdr) == COFF_C67_MAGIC) {
10312 ret = tcc_load_coff(s1, fd);
10313 } else
10314 #endif
10315 #ifdef TCC_TARGET_PE
10316 if (pe_test_res_file(&ehdr, ret)) {
10317 ret = pe_load_res_file(s1, fd);
10318 } else
10319 #endif
10321 /* as GNU ld, consider it is an ld script if not recognized */
10322 try_load_script:
10323 ret = tcc_load_ldscript(s1);
10324 if (ret < 0) {
10325 error_noabort("unrecognized file type");
10326 goto fail;
10330 the_end:
10331 tcc_close(file);
10332 fail1:
10333 file = saved_file;
10334 return ret;
10335 fail:
10336 ret = -1;
10337 goto the_end;
10340 int tcc_add_file(TCCState *s, const char *filename)
10342 return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR);
10345 int tcc_add_library_path(TCCState *s, const char *pathname)
10347 char *pathname1;
10349 pathname1 = tcc_strdup(pathname);
10350 dynarray_add((void ***)&s->library_paths, &s->nb_library_paths, pathname1);
10351 return 0;
10354 /* find and load a dll. Return non zero if not found */
10355 /* XXX: add '-rpath' option support ? */
10356 static int tcc_add_dll(TCCState *s, const char *filename, int flags)
10358 char buf[1024];
10359 int i;
10361 for(i = 0; i < s->nb_library_paths; i++) {
10362 snprintf(buf, sizeof(buf), "%s/%s",
10363 s->library_paths[i], filename);
10364 if (tcc_add_file_internal(s, buf, flags) == 0)
10365 return 0;
10367 return -1;
10370 /* the library name is the same as the argument of the '-l' option */
10371 int tcc_add_library(TCCState *s, const char *libraryname)
10373 char buf[1024];
10374 int i;
10376 /* first we look for the dynamic library if not static linking */
10377 if (!s->static_link) {
10378 #ifdef TCC_TARGET_PE
10379 snprintf(buf, sizeof(buf), "%s.def", libraryname);
10380 #else
10381 snprintf(buf, sizeof(buf), "lib%s.so", libraryname);
10382 #endif
10383 if (tcc_add_dll(s, buf, 0) == 0)
10384 return 0;
10387 /* then we look for the static library */
10388 for(i = 0; i < s->nb_library_paths; i++) {
10389 snprintf(buf, sizeof(buf), "%s/lib%s.a",
10390 s->library_paths[i], libraryname);
10391 if (tcc_add_file_internal(s, buf, 0) == 0)
10392 return 0;
10394 return -1;
10397 int tcc_add_symbol(TCCState *s, const char *name, unsigned long val)
10399 add_elf_sym(symtab_section, val, 0,
10400 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
10401 SHN_ABS, name);
10402 return 0;
10405 int tcc_set_output_type(TCCState *s, int output_type)
10407 char buf[1024];
10409 s->output_type = output_type;
10411 if (!s->nostdinc) {
10412 /* default include paths */
10413 /* XXX: reverse order needed if -isystem support */
10414 #ifndef TCC_TARGET_PE
10415 tcc_add_sysinclude_path(s, "/usr/local/include");
10416 tcc_add_sysinclude_path(s, "/usr/include");
10417 #endif
10418 snprintf(buf, sizeof(buf), "%s/include", tcc_lib_path);
10419 tcc_add_sysinclude_path(s, buf);
10420 #ifdef TCC_TARGET_PE
10421 snprintf(buf, sizeof(buf), "%s/include/winapi", tcc_lib_path);
10422 tcc_add_sysinclude_path(s, buf);
10423 #endif
10426 /* if bound checking, then add corresponding sections */
10427 #ifdef CONFIG_TCC_BCHECK
10428 if (do_bounds_check) {
10429 /* define symbol */
10430 tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL);
10431 /* create bounds sections */
10432 bounds_section = new_section(s, ".bounds",
10433 SHT_PROGBITS, SHF_ALLOC);
10434 lbounds_section = new_section(s, ".lbounds",
10435 SHT_PROGBITS, SHF_ALLOC);
10437 #endif
10439 if (s->char_is_unsigned) {
10440 tcc_define_symbol(s, "__CHAR_UNSIGNED__", NULL);
10443 /* add debug sections */
10444 if (do_debug) {
10445 /* stab symbols */
10446 stab_section = new_section(s, ".stab", SHT_PROGBITS, 0);
10447 stab_section->sh_entsize = sizeof(Stab_Sym);
10448 stabstr_section = new_section(s, ".stabstr", SHT_STRTAB, 0);
10449 put_elf_str(stabstr_section, "");
10450 stab_section->link = stabstr_section;
10451 /* put first entry */
10452 put_stabs("", 0, 0, 0, 0);
10455 /* add libc crt1/crti objects */
10456 #ifndef TCC_TARGET_PE
10457 if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) &&
10458 !s->nostdlib) {
10459 if (output_type != TCC_OUTPUT_DLL)
10460 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crt1.o");
10461 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crti.o");
10463 #endif
10465 #ifdef TCC_TARGET_PE
10466 snprintf(buf, sizeof(buf), "%s/lib", tcc_lib_path);
10467 tcc_add_library_path(s, buf);
10468 #endif
10470 return 0;
10473 #define WD_ALL 0x0001 /* warning is activated when using -Wall */
10474 #define FD_INVERT 0x0002 /* invert value before storing */
10476 typedef struct FlagDef {
10477 uint16_t offset;
10478 uint16_t flags;
10479 const char *name;
10480 } FlagDef;
10482 static const FlagDef warning_defs[] = {
10483 { offsetof(TCCState, warn_unsupported), 0, "unsupported" },
10484 { offsetof(TCCState, warn_write_strings), 0, "write-strings" },
10485 { offsetof(TCCState, warn_error), 0, "error" },
10486 { offsetof(TCCState, warn_implicit_function_declaration), WD_ALL,
10487 "implicit-function-declaration" },
10490 static int set_flag(TCCState *s, const FlagDef *flags, int nb_flags,
10491 const char *name, int value)
10493 int i;
10494 const FlagDef *p;
10495 const char *r;
10497 r = name;
10498 if (r[0] == 'n' && r[1] == 'o' && r[2] == '-') {
10499 r += 3;
10500 value = !value;
10502 for(i = 0, p = flags; i < nb_flags; i++, p++) {
10503 if (!strcmp(r, p->name))
10504 goto found;
10506 return -1;
10507 found:
10508 if (p->flags & FD_INVERT)
10509 value = !value;
10510 *(int *)((uint8_t *)s + p->offset) = value;
10511 return 0;
10515 /* set/reset a warning */
10516 int tcc_set_warning(TCCState *s, const char *warning_name, int value)
10518 int i;
10519 const FlagDef *p;
10521 if (!strcmp(warning_name, "all")) {
10522 for(i = 0, p = warning_defs; i < countof(warning_defs); i++, p++) {
10523 if (p->flags & WD_ALL)
10524 *(int *)((uint8_t *)s + p->offset) = 1;
10526 return 0;
10527 } else {
10528 return set_flag(s, warning_defs, countof(warning_defs),
10529 warning_name, value);
10533 static const FlagDef flag_defs[] = {
10534 { offsetof(TCCState, char_is_unsigned), 0, "unsigned-char" },
10535 { offsetof(TCCState, char_is_unsigned), FD_INVERT, "signed-char" },
10536 { offsetof(TCCState, nocommon), FD_INVERT, "common" },
10537 { offsetof(TCCState, leading_underscore), 0, "leading-underscore" },
10540 /* set/reset a flag */
10541 int tcc_set_flag(TCCState *s, const char *flag_name, int value)
10543 return set_flag(s, flag_defs, countof(flag_defs),
10544 flag_name, value);
10547 #if !defined(LIBTCC)
10549 static int64_t getclock_us(void)
10551 #ifdef _WIN32
10552 struct _timeb tb;
10553 _ftime(&tb);
10554 return (tb.time * 1000LL + tb.millitm) * 1000LL;
10555 #else
10556 struct timeval tv;
10557 gettimeofday(&tv, NULL);
10558 return tv.tv_sec * 1000000LL + tv.tv_usec;
10559 #endif
10562 void help(void)
10564 printf("tcc version " TCC_VERSION " - Tiny C Compiler - Copyright (C) 2001-2006 Fabrice Bellard\n"
10565 "usage: tcc [-v] [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
10566 " [-Wwarn] [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-soname name]\n"
10567 " [-static] [infile1 infile2...] [-run infile args...]\n"
10568 "\n"
10569 "General options:\n"
10570 " -v display current version\n"
10571 " -c compile only - generate an object file\n"
10572 " -o outfile set output filename\n"
10573 " -Bdir set tcc internal library path\n"
10574 " -bench output compilation statistics\n"
10575 " -run run compiled source\n"
10576 " -fflag set or reset (with 'no-' prefix) 'flag' (see man page)\n"
10577 " -Wwarning set or reset (with 'no-' prefix) 'warning' (see man page)\n"
10578 " -w disable all warnings\n"
10579 "Preprocessor options:\n"
10580 " -E preprocess only\n"
10581 " -Idir add include path 'dir'\n"
10582 " -Dsym[=val] define 'sym' with value 'val'\n"
10583 " -Usym undefine 'sym'\n"
10584 "Linker options:\n"
10585 " -Ldir add library path 'dir'\n"
10586 " -llib link with dynamic or static library 'lib'\n"
10587 " -shared generate a shared library\n"
10588 " -soname set name for shared library to be used at runtime\n"
10589 " -static static linking\n"
10590 " -rdynamic export all global symbols to dynamic linker\n"
10591 " -r generate (relocatable) object file\n"
10592 "Debugger options:\n"
10593 " -g generate runtime debug info\n"
10594 #ifdef CONFIG_TCC_BCHECK
10595 " -b compile with built-in memory and bounds checker (implies -g)\n"
10596 #endif
10597 " -bt N show N callers in stack traces\n"
10601 #define TCC_OPTION_HAS_ARG 0x0001
10602 #define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
10604 typedef struct TCCOption {
10605 const char *name;
10606 uint16_t index;
10607 uint16_t flags;
10608 } TCCOption;
10610 enum {
10611 TCC_OPTION_HELP,
10612 TCC_OPTION_I,
10613 TCC_OPTION_D,
10614 TCC_OPTION_U,
10615 TCC_OPTION_L,
10616 TCC_OPTION_B,
10617 TCC_OPTION_l,
10618 TCC_OPTION_bench,
10619 TCC_OPTION_bt,
10620 TCC_OPTION_b,
10621 TCC_OPTION_g,
10622 TCC_OPTION_c,
10623 TCC_OPTION_static,
10624 TCC_OPTION_shared,
10625 TCC_OPTION_soname,
10626 TCC_OPTION_o,
10627 TCC_OPTION_r,
10628 TCC_OPTION_Wl,
10629 TCC_OPTION_W,
10630 TCC_OPTION_O,
10631 TCC_OPTION_m,
10632 TCC_OPTION_f,
10633 TCC_OPTION_nostdinc,
10634 TCC_OPTION_nostdlib,
10635 TCC_OPTION_print_search_dirs,
10636 TCC_OPTION_rdynamic,
10637 TCC_OPTION_run,
10638 TCC_OPTION_v,
10639 TCC_OPTION_w,
10640 TCC_OPTION_pipe,
10641 TCC_OPTION_E,
10644 static const TCCOption tcc_options[] = {
10645 { "h", TCC_OPTION_HELP, 0 },
10646 { "?", TCC_OPTION_HELP, 0 },
10647 { "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG },
10648 { "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG },
10649 { "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG },
10650 { "L", TCC_OPTION_L, TCC_OPTION_HAS_ARG },
10651 { "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG },
10652 { "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10653 { "bench", TCC_OPTION_bench, 0 },
10654 { "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG },
10655 #ifdef CONFIG_TCC_BCHECK
10656 { "b", TCC_OPTION_b, 0 },
10657 #endif
10658 { "g", TCC_OPTION_g, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10659 { "c", TCC_OPTION_c, 0 },
10660 { "static", TCC_OPTION_static, 0 },
10661 { "shared", TCC_OPTION_shared, 0 },
10662 { "soname", TCC_OPTION_soname, TCC_OPTION_HAS_ARG },
10663 { "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG },
10664 { "run", TCC_OPTION_run, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10665 { "rdynamic", TCC_OPTION_rdynamic, 0 },
10666 { "r", TCC_OPTION_r, 0 },
10667 { "Wl,", TCC_OPTION_Wl, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10668 { "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10669 { "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10670 { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG },
10671 { "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10672 { "nostdinc", TCC_OPTION_nostdinc, 0 },
10673 { "nostdlib", TCC_OPTION_nostdlib, 0 },
10674 { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 },
10675 { "v", TCC_OPTION_v, 0 },
10676 { "w", TCC_OPTION_w, 0 },
10677 { "pipe", TCC_OPTION_pipe, 0},
10678 { "E", TCC_OPTION_E, 0},
10679 { NULL },
10682 /* convert 'str' into an array of space separated strings */
10683 static int expand_args(char ***pargv, const char *str)
10685 const char *s1;
10686 char **argv, *arg;
10687 int argc, len;
10689 argc = 0;
10690 argv = NULL;
10691 for(;;) {
10692 while (is_space(*str))
10693 str++;
10694 if (*str == '\0')
10695 break;
10696 s1 = str;
10697 while (*str != '\0' && !is_space(*str))
10698 str++;
10699 len = str - s1;
10700 arg = tcc_malloc(len + 1);
10701 memcpy(arg, s1, len);
10702 arg[len] = '\0';
10703 dynarray_add((void ***)&argv, &argc, arg);
10705 *pargv = argv;
10706 return argc;
10709 static char **files;
10710 static int nb_files, nb_libraries;
10711 static int multiple_files;
10712 static int print_search_dirs;
10713 static int output_type;
10714 static int reloc_output;
10715 static const char *outfile;
10717 int parse_args(TCCState *s, int argc, char **argv)
10719 int optind;
10720 const TCCOption *popt;
10721 const char *optarg, *p1, *r1;
10722 char *r;
10724 optind = 0;
10725 while (1) {
10726 if (optind >= argc) {
10727 if (nb_files == 0 && !print_search_dirs)
10728 goto show_help;
10729 else
10730 break;
10732 r = argv[optind++];
10733 if (r[0] != '-') {
10734 /* add a new file */
10735 dynarray_add((void ***)&files, &nb_files, r);
10736 if (!multiple_files) {
10737 optind--;
10738 /* argv[0] will be this file */
10739 break;
10741 } else {
10742 /* find option in table (match only the first chars */
10743 popt = tcc_options;
10744 for(;;) {
10745 p1 = popt->name;
10746 if (p1 == NULL)
10747 error("invalid option -- '%s'", r);
10748 r1 = r + 1;
10749 for(;;) {
10750 if (*p1 == '\0')
10751 goto option_found;
10752 if (*r1 != *p1)
10753 break;
10754 p1++;
10755 r1++;
10757 popt++;
10759 option_found:
10760 if (popt->flags & TCC_OPTION_HAS_ARG) {
10761 if (*r1 != '\0' || (popt->flags & TCC_OPTION_NOSEP)) {
10762 optarg = r1;
10763 } else {
10764 if (optind >= argc)
10765 error("argument to '%s' is missing", r);
10766 optarg = argv[optind++];
10768 } else {
10769 if (*r1 != '\0')
10770 goto show_help;
10771 optarg = NULL;
10774 switch(popt->index) {
10775 case TCC_OPTION_HELP:
10776 show_help:
10777 help();
10778 exit(1);
10779 case TCC_OPTION_I:
10780 if (tcc_add_include_path(s, optarg) < 0)
10781 error("too many include paths");
10782 break;
10783 case TCC_OPTION_D:
10785 char *sym, *value;
10786 sym = (char *)optarg;
10787 value = strchr(sym, '=');
10788 if (value) {
10789 *value = '\0';
10790 value++;
10792 tcc_define_symbol(s, sym, value);
10794 break;
10795 case TCC_OPTION_U:
10796 tcc_undefine_symbol(s, optarg);
10797 break;
10798 case TCC_OPTION_L:
10799 tcc_add_library_path(s, optarg);
10800 break;
10801 case TCC_OPTION_B:
10802 /* set tcc utilities path (mainly for tcc development) */
10803 tcc_lib_path = optarg;
10804 break;
10805 case TCC_OPTION_l:
10806 dynarray_add((void ***)&files, &nb_files, r);
10807 nb_libraries++;
10808 break;
10809 case TCC_OPTION_bench:
10810 do_bench = 1;
10811 break;
10812 case TCC_OPTION_bt:
10813 num_callers = atoi(optarg);
10814 break;
10815 #ifdef CONFIG_TCC_BCHECK
10816 case TCC_OPTION_b:
10817 do_bounds_check = 1;
10818 do_debug = 1;
10819 break;
10820 #endif
10821 case TCC_OPTION_g:
10822 do_debug = 1;
10823 break;
10824 case TCC_OPTION_c:
10825 multiple_files = 1;
10826 output_type = TCC_OUTPUT_OBJ;
10827 break;
10828 case TCC_OPTION_static:
10829 s->static_link = 1;
10830 break;
10831 case TCC_OPTION_shared:
10832 output_type = TCC_OUTPUT_DLL;
10833 break;
10834 case TCC_OPTION_soname:
10835 s->soname = optarg;
10836 break;
10837 case TCC_OPTION_o:
10838 multiple_files = 1;
10839 outfile = optarg;
10840 break;
10841 case TCC_OPTION_r:
10842 /* generate a .o merging several output files */
10843 reloc_output = 1;
10844 output_type = TCC_OUTPUT_OBJ;
10845 break;
10846 case TCC_OPTION_nostdinc:
10847 s->nostdinc = 1;
10848 break;
10849 case TCC_OPTION_nostdlib:
10850 s->nostdlib = 1;
10851 break;
10852 case TCC_OPTION_print_search_dirs:
10853 print_search_dirs = 1;
10854 break;
10855 case TCC_OPTION_run:
10857 int argc1;
10858 char **argv1;
10859 argc1 = expand_args(&argv1, optarg);
10860 if (argc1 > 0) {
10861 parse_args(s, argc1, argv1);
10863 multiple_files = 0;
10864 output_type = TCC_OUTPUT_MEMORY;
10866 break;
10867 case TCC_OPTION_v:
10868 printf("tcc version %s\n", TCC_VERSION);
10869 exit(0);
10870 case TCC_OPTION_f:
10871 if (tcc_set_flag(s, optarg, 1) < 0 && s->warn_unsupported)
10872 goto unsupported_option;
10873 break;
10874 case TCC_OPTION_W:
10875 if (tcc_set_warning(s, optarg, 1) < 0 &&
10876 s->warn_unsupported)
10877 goto unsupported_option;
10878 break;
10879 case TCC_OPTION_w:
10880 s->warn_none = 1;
10881 break;
10882 case TCC_OPTION_rdynamic:
10883 s->rdynamic = 1;
10884 break;
10885 case TCC_OPTION_Wl:
10887 const char *p;
10888 if (strstart(optarg, "-Ttext,", &p)) {
10889 s->text_addr = strtoul(p, NULL, 16);
10890 s->has_text_addr = 1;
10891 } else if (strstart(optarg, "--oformat,", &p)) {
10892 if (strstart(p, "elf32-", NULL)) {
10893 s->output_format = TCC_OUTPUT_FORMAT_ELF;
10894 } else if (!strcmp(p, "binary")) {
10895 s->output_format = TCC_OUTPUT_FORMAT_BINARY;
10896 } else
10897 #ifdef TCC_TARGET_COFF
10898 if (!strcmp(p, "coff")) {
10899 s->output_format = TCC_OUTPUT_FORMAT_COFF;
10900 } else
10901 #endif
10903 error("target %s not found", p);
10905 } else {
10906 error("unsupported linker option '%s'", optarg);
10909 break;
10910 case TCC_OPTION_E:
10911 output_type = TCC_OUTPUT_PREPROCESS;
10912 break;
10913 default:
10914 if (s->warn_unsupported) {
10915 unsupported_option:
10916 warning("unsupported option '%s'", r);
10918 break;
10922 return optind;
10925 int main(int argc, char **argv)
10927 int i;
10928 TCCState *s;
10929 int nb_objfiles, ret, optind;
10930 char objfilename[1024];
10931 int64_t start_time = 0;
10933 #ifdef _WIN32
10934 tcc_lib_path = w32_tcc_lib_path();
10935 #endif
10937 s = tcc_new();
10938 output_type = TCC_OUTPUT_EXE;
10939 outfile = NULL;
10940 multiple_files = 1;
10941 files = NULL;
10942 nb_files = 0;
10943 nb_libraries = 0;
10944 reloc_output = 0;
10945 print_search_dirs = 0;
10946 ret = 0;
10948 optind = parse_args(s, argc - 1, argv + 1) + 1;
10950 if (print_search_dirs) {
10951 /* enough for Linux kernel */
10952 printf("install: %s/\n", tcc_lib_path);
10953 return 0;
10956 nb_objfiles = nb_files - nb_libraries;
10958 /* if outfile provided without other options, we output an
10959 executable */
10960 if (outfile && output_type == TCC_OUTPUT_MEMORY)
10961 output_type = TCC_OUTPUT_EXE;
10963 /* check -c consistency : only single file handled. XXX: checks file type */
10964 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
10965 /* accepts only a single input file */
10966 if (nb_objfiles != 1)
10967 error("cannot specify multiple files with -c");
10968 if (nb_libraries != 0)
10969 error("cannot specify libraries with -c");
10973 if (output_type == TCC_OUTPUT_PREPROCESS) {
10974 if (!outfile) {
10975 s->outfile = stdout;
10976 } else {
10977 s->outfile = fopen(outfile, "w");
10978 if (!s->outfile)
10979 error("could not open '%s", outfile);
10981 } else if (output_type != TCC_OUTPUT_MEMORY) {
10982 if (!outfile) {
10983 /* compute default outfile name */
10984 char *ext;
10985 pstrcpy(objfilename, sizeof(objfilename), tcc_basename(files[0]));
10986 ext = tcc_fileextension(objfilename);
10987 #ifdef TCC_TARGET_PE
10988 if (output_type == TCC_OUTPUT_DLL)
10989 strcpy(ext, ".dll");
10990 else
10991 if (output_type == TCC_OUTPUT_EXE)
10992 strcpy(ext, ".exe");
10993 else
10994 #endif
10995 if (output_type == TCC_OUTPUT_OBJ && !reloc_output && *ext)
10996 strcpy(ext, ".o");
10997 else
10998 pstrcpy(objfilename, sizeof(objfilename), "a.out");
10999 outfile = objfilename;
11003 if (do_bench) {
11004 start_time = getclock_us();
11007 tcc_set_output_type(s, output_type);
11009 /* compile or add each files or library */
11010 for(i = 0; i < nb_files && ret == 0; i++) {
11011 const char *filename;
11013 filename = files[i];
11014 if (output_type == TCC_OUTPUT_PREPROCESS) {
11015 if (tcc_add_file_internal(s, filename,
11016 AFF_PRINT_ERROR | AFF_PREPROCESS) < 0)
11017 ret = 1;
11018 } else if (filename[0] == '-') {
11019 if (tcc_add_library(s, filename + 2) < 0)
11020 error("cannot find %s", filename);
11021 } else {
11022 if (tcc_add_file(s, filename) < 0)
11023 ret = 1;
11027 /* free all files */
11028 tcc_free(files);
11030 if (ret)
11031 goto the_end;
11033 if (do_bench) {
11034 double total_time;
11035 total_time = (double)(getclock_us() - start_time) / 1000000.0;
11036 if (total_time < 0.001)
11037 total_time = 0.001;
11038 if (total_bytes < 1)
11039 total_bytes = 1;
11040 printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
11041 tok_ident - TOK_IDENT, total_lines, total_bytes,
11042 total_time, (int)(total_lines / total_time),
11043 total_bytes / total_time / 1000000.0);
11046 if (s->output_type == TCC_OUTPUT_PREPROCESS) {
11047 if (outfile)
11048 fclose(s->outfile);
11049 } else if (s->output_type == TCC_OUTPUT_MEMORY) {
11050 ret = tcc_run(s, argc - optind, argv + optind);
11051 } else
11052 #ifdef TCC_TARGET_PE
11053 if (s->output_type != TCC_OUTPUT_OBJ) {
11054 ret = pe_output_file(s, outfile);
11055 } else
11056 #endif
11058 ret = tcc_output_file(s, outfile) ? 1 : 0;
11060 the_end:
11061 /* XXX: cannot do it with bound checking because of the malloc hooks */
11062 if (!do_bounds_check)
11063 tcc_delete(s);
11065 #ifdef MEM_DEBUG
11066 if (do_bench) {
11067 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size, mem_max_size);
11069 #endif
11070 return ret;
11073 #endif