Introduce ElfW macro and ELFW to encapsulate the difference between Elf32_* and Elf64...
[tinycc/kirr.git] / tcc.c
blobf223f68fbc10a19c1caa27d69309e94de6a192b4
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 CONFIG_SYSROOT "/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 void *handle;
226 char name[1];
227 } DLLReference;
229 /* GNUC attribute definition */
230 typedef struct AttributeDef {
231 int aligned;
232 int packed;
233 Section *section;
234 int func_attr; /* calling convention, exports, ... */
235 } AttributeDef;
237 /* -------------------------------------------------- */
238 /* gr: wrappers for casting sym->r for other purposes */
239 typedef struct {
240 unsigned
241 func_call : 8,
242 func_args : 8,
243 func_export : 1;
244 } func_attr_t;
246 #define FUNC_CALL(r) (((func_attr_t*)&(r))->func_call)
247 #define FUNC_EXPORT(r) (((func_attr_t*)&(r))->func_export)
248 #define FUNC_ARGS(r) (((func_attr_t*)&(r))->func_args)
249 #define INLINE_DEF(r) (*(int **)&(r))
250 /* -------------------------------------------------- */
252 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
253 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
254 #define SYM_FIRST_ANOM 0x10000000 /* first anonymous sym */
256 /* stored in 'Sym.c' field */
257 #define FUNC_NEW 1 /* ansi function prototype */
258 #define FUNC_OLD 2 /* old function prototype */
259 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
261 /* stored in 'Sym.r' field */
262 #define FUNC_CDECL 0 /* standard c call */
263 #define FUNC_STDCALL 1 /* pascal c call */
264 #define FUNC_FASTCALL1 2 /* first param in %eax */
265 #define FUNC_FASTCALL2 3 /* first parameters in %eax, %edx */
266 #define FUNC_FASTCALL3 4 /* first parameter in %eax, %edx, %ecx */
267 #define FUNC_FASTCALLW 5 /* first parameter in %ecx, %edx */
269 /* field 'Sym.t' for macros */
270 #define MACRO_OBJ 0 /* object like macro */
271 #define MACRO_FUNC 1 /* function like macro */
273 /* field 'Sym.r' for C labels */
274 #define LABEL_DEFINED 0 /* label is defined */
275 #define LABEL_FORWARD 1 /* label is forward defined */
276 #define LABEL_DECLARED 2 /* label is declared but never used */
278 /* type_decl() types */
279 #define TYPE_ABSTRACT 1 /* type without variable */
280 #define TYPE_DIRECT 2 /* type with variable */
282 #define IO_BUF_SIZE 8192
284 typedef struct BufferedFile {
285 uint8_t *buf_ptr;
286 uint8_t *buf_end;
287 int fd;
288 int line_num; /* current line number - here to simplify code */
289 int ifndef_macro; /* #ifndef macro / #endif search */
290 int ifndef_macro_saved; /* saved ifndef_macro */
291 int *ifdef_stack_ptr; /* ifdef_stack value at the start of the file */
292 char inc_type; /* type of include */
293 char inc_filename[512]; /* filename specified by the user */
294 char filename[1024]; /* current filename - here to simplify code */
295 unsigned char buffer[IO_BUF_SIZE + 1]; /* extra size for CH_EOB char */
296 } BufferedFile;
298 #define CH_EOB '\\' /* end of buffer or '\0' char in file */
299 #define CH_EOF (-1) /* end of file */
301 /* parsing state (used to save parser state to reparse part of the
302 source several times) */
303 typedef struct ParseState {
304 int *macro_ptr;
305 int line_num;
306 int tok;
307 CValue tokc;
308 } ParseState;
310 /* used to record tokens */
311 typedef struct TokenString {
312 int *str;
313 int len;
314 int allocated_len;
315 int last_line_num;
316 } TokenString;
318 /* include file cache, used to find files faster and also to eliminate
319 inclusion if the include file is protected by #ifndef ... #endif */
320 typedef struct CachedInclude {
321 int ifndef_macro;
322 int hash_next; /* -1 if none */
323 char type; /* '"' or '>' to give include type */
324 char filename[1]; /* path specified in #include */
325 } CachedInclude;
327 #define CACHED_INCLUDES_HASH_SIZE 512
329 /* parser */
330 static struct BufferedFile *file;
331 static int ch, tok;
332 static CValue tokc;
333 static CString tokcstr; /* current parsed string, if any */
334 /* additional informations about token */
335 static int tok_flags;
336 #define TOK_FLAG_BOL 0x0001 /* beginning of line before */
337 #define TOK_FLAG_BOF 0x0002 /* beginning of file before */
338 #define TOK_FLAG_ENDIF 0x0004 /* a endif was found matching starting #ifdef */
339 #define TOK_FLAG_EOF 0x0008 /* end of file */
341 static int *macro_ptr, *macro_ptr_allocated;
342 static int *unget_saved_macro_ptr;
343 static int unget_saved_buffer[TOK_MAX_SIZE + 1];
344 static int unget_buffer_enabled;
345 static int parse_flags;
346 #define PARSE_FLAG_PREPROCESS 0x0001 /* activate preprocessing */
347 #define PARSE_FLAG_TOK_NUM 0x0002 /* return numbers instead of TOK_PPNUM */
348 #define PARSE_FLAG_LINEFEED 0x0004 /* line feed is returned as a
349 token. line feed is also
350 returned at eof */
351 #define PARSE_FLAG_ASM_COMMENTS 0x0008 /* '#' can be used for line comment */
353 static Section *text_section, *data_section, *bss_section; /* predefined sections */
354 static Section *cur_text_section; /* current section where function code is
355 generated */
356 #ifdef CONFIG_TCC_ASM
357 static Section *last_text_section; /* to handle .previous asm directive */
358 #endif
359 /* bound check related sections */
360 static Section *bounds_section; /* contains global data bound description */
361 static Section *lbounds_section; /* contains local data bound description */
362 /* symbol sections */
363 static Section *symtab_section, *strtab_section;
365 /* debug sections */
366 static Section *stab_section, *stabstr_section;
368 /* loc : local variable index
369 ind : output code index
370 rsym: return symbol
371 anon_sym: anonymous symbol index
373 static int rsym, anon_sym, ind, loc;
374 /* expression generation modifiers */
375 static int const_wanted; /* true if constant wanted */
376 static int nocode_wanted; /* true if no code generation wanted for an expression */
377 static int global_expr; /* true if compound literals must be allocated
378 globally (used during initializers parsing */
379 static CType func_vt; /* current function return type (used by return
380 instruction) */
381 static int func_vc;
382 static int last_line_num, last_ind, func_ind; /* debug last line number and pc */
383 static int tok_ident;
384 static TokenSym **table_ident;
385 static TokenSym *hash_ident[TOK_HASH_SIZE];
386 static char token_buf[STRING_MAX_SIZE + 1];
387 static char *funcname;
388 static Sym *global_stack, *local_stack;
389 static Sym *define_stack;
390 static Sym *global_label_stack, *local_label_stack;
391 /* symbol allocator */
392 #define SYM_POOL_NB (8192 / sizeof(Sym))
393 static Sym *sym_free_first;
394 static void **sym_pools;
395 static int nb_sym_pools;
397 static SValue vstack[VSTACK_SIZE], *vtop;
398 /* some predefined types */
399 static CType char_pointer_type, func_old_type, int_type;
400 /* true if isid(c) || isnum(c) */
401 static unsigned char isidnum_table[256-CH_EOF];
403 /* display some information during compilation */
404 static int verbose = 0;
406 /* compile with debug symbol (and use them if error during execution) */
407 static int do_debug = 0;
409 /* compile with built-in memory and bounds checker */
410 static int do_bounds_check = 0;
412 /* display benchmark infos */
413 #if !defined(LIBTCC)
414 static int do_bench = 0;
415 #endif
416 static int total_lines;
417 static int total_bytes;
419 /* use GNU C extensions */
420 static int gnu_ext = 1;
422 /* use Tiny C extensions */
423 static int tcc_ext = 1;
425 /* max number of callers shown if error */
426 static int num_callers = 6;
427 static const char **rt_bound_error_msg;
429 /* XXX: get rid of this ASAP */
430 static struct TCCState *tcc_state;
432 /* give the path of the tcc libraries */
433 static const char *tcc_lib_path = CONFIG_TCCDIR;
435 struct TCCState {
436 int output_type;
438 BufferedFile **include_stack_ptr;
439 int *ifdef_stack_ptr;
441 /* include file handling */
442 char **include_paths;
443 int nb_include_paths;
444 char **sysinclude_paths;
445 int nb_sysinclude_paths;
446 CachedInclude **cached_includes;
447 int nb_cached_includes;
449 char **library_paths;
450 int nb_library_paths;
452 /* array of all loaded dlls (including those referenced by loaded
453 dlls) */
454 DLLReference **loaded_dlls;
455 int nb_loaded_dlls;
457 /* sections */
458 Section **sections;
459 int nb_sections; /* number of sections, including first dummy section */
461 /* got handling */
462 Section *got;
463 Section *plt;
464 unsigned long *got_offsets;
465 int nb_got_offsets;
466 /* give the correspondance from symtab indexes to dynsym indexes */
467 int *symtab_to_dynsym;
469 /* temporary dynamic symbol sections (for dll loading) */
470 Section *dynsymtab_section;
471 /* exported dynamic symbol section */
472 Section *dynsym;
474 int nostdinc; /* if true, no standard headers are added */
475 int nostdlib; /* if true, no standard libraries are added */
477 int nocommon; /* if true, do not use common symbols for .bss data */
479 /* if true, static linking is performed */
480 int static_link;
482 /* soname as specified on the command line (-soname) */
483 const char *soname;
485 /* if true, all symbols are exported */
486 int rdynamic;
488 /* if true, only link in referenced objects from archive */
489 int alacarte_link;
491 /* address of text section */
492 unsigned long text_addr;
493 int has_text_addr;
495 /* output format, see TCC_OUTPUT_FORMAT_xxx */
496 int output_format;
498 /* C language options */
499 int char_is_unsigned;
500 int leading_underscore;
502 /* warning switches */
503 int warn_write_strings;
504 int warn_unsupported;
505 int warn_error;
506 int warn_none;
507 int warn_implicit_function_declaration;
509 /* error handling */
510 void *error_opaque;
511 void (*error_func)(void *opaque, const char *msg);
512 int error_set_jmp_enabled;
513 jmp_buf error_jmp_buf;
514 int nb_errors;
516 /* tiny assembler state */
517 Sym *asm_labels;
519 /* see include_stack_ptr */
520 BufferedFile *include_stack[INCLUDE_STACK_SIZE];
522 /* see ifdef_stack_ptr */
523 int ifdef_stack[IFDEF_STACK_SIZE];
525 /* see cached_includes */
526 int cached_includes_hash[CACHED_INCLUDES_HASH_SIZE];
528 /* pack stack */
529 int pack_stack[PACK_STACK_SIZE];
530 int *pack_stack_ptr;
532 /* output file for preprocessing */
533 FILE *outfile;
536 /* The current value can be: */
537 #define VT_VALMASK 0x00ff
538 #define VT_CONST 0x00f0 /* constant in vc
539 (must be first non register value) */
540 #define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */
541 #define VT_LOCAL 0x00f2 /* offset on stack */
542 #define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */
543 #define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */
544 #define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */
545 #define VT_LVAL 0x0100 /* var is an lvalue */
546 #define VT_SYM 0x0200 /* a symbol value is added */
547 #define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for
548 char/short stored in integer registers) */
549 #define VT_MUSTBOUND 0x0800 /* bound checking must be done before
550 dereferencing value */
551 #define VT_BOUNDED 0x8000 /* value is bounded. The address of the
552 bounding function call point is in vc */
553 #define VT_LVAL_BYTE 0x1000 /* lvalue is a byte */
554 #define VT_LVAL_SHORT 0x2000 /* lvalue is a short */
555 #define VT_LVAL_UNSIGNED 0x4000 /* lvalue is unsigned */
556 #define VT_LVAL_TYPE (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)
558 /* types */
559 #define VT_INT 0 /* integer type */
560 #define VT_BYTE 1 /* signed byte type */
561 #define VT_SHORT 2 /* short type */
562 #define VT_VOID 3 /* void type */
563 #define VT_PTR 4 /* pointer */
564 #define VT_ENUM 5 /* enum definition */
565 #define VT_FUNC 6 /* function type */
566 #define VT_STRUCT 7 /* struct/union definition */
567 #define VT_FLOAT 8 /* IEEE float */
568 #define VT_DOUBLE 9 /* IEEE double */
569 #define VT_LDOUBLE 10 /* IEEE long double */
570 #define VT_BOOL 11 /* ISOC99 boolean type */
571 #define VT_LLONG 12 /* 64 bit integer */
572 #define VT_LONG 13 /* long integer (NEVER USED as type, only
573 during parsing) */
574 #define VT_BTYPE 0x000f /* mask for basic type */
575 #define VT_UNSIGNED 0x0010 /* unsigned type */
576 #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
577 #define VT_BITFIELD 0x0040 /* bitfield modifier */
578 #define VT_CONSTANT 0x0800 /* const modifier */
579 #define VT_VOLATILE 0x1000 /* volatile modifier */
580 #define VT_SIGNED 0x2000 /* signed type */
582 /* storage */
583 #define VT_EXTERN 0x00000080 /* extern definition */
584 #define VT_STATIC 0x00000100 /* static variable */
585 #define VT_TYPEDEF 0x00000200 /* typedef definition */
586 #define VT_INLINE 0x00000400 /* inline definition */
588 #define VT_STRUCT_SHIFT 16 /* shift for bitfield shift values */
590 /* type mask (except storage) */
591 #define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE)
592 #define VT_TYPE (~(VT_STORAGE))
594 /* token values */
596 /* warning: the following compare tokens depend on i386 asm code */
597 #define TOK_ULT 0x92
598 #define TOK_UGE 0x93
599 #define TOK_EQ 0x94
600 #define TOK_NE 0x95
601 #define TOK_ULE 0x96
602 #define TOK_UGT 0x97
603 #define TOK_Nset 0x98
604 #define TOK_Nclear 0x99
605 #define TOK_LT 0x9c
606 #define TOK_GE 0x9d
607 #define TOK_LE 0x9e
608 #define TOK_GT 0x9f
610 #define TOK_LAND 0xa0
611 #define TOK_LOR 0xa1
613 #define TOK_DEC 0xa2
614 #define TOK_MID 0xa3 /* inc/dec, to void constant */
615 #define TOK_INC 0xa4
616 #define TOK_UDIV 0xb0 /* unsigned division */
617 #define TOK_UMOD 0xb1 /* unsigned modulo */
618 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
619 #define TOK_CINT 0xb3 /* number in tokc */
620 #define TOK_CCHAR 0xb4 /* char constant in tokc */
621 #define TOK_STR 0xb5 /* pointer to string in tokc */
622 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
623 #define TOK_LCHAR 0xb7
624 #define TOK_LSTR 0xb8
625 #define TOK_CFLOAT 0xb9 /* float constant */
626 #define TOK_LINENUM 0xba /* line number info */
627 #define TOK_CDOUBLE 0xc0 /* double constant */
628 #define TOK_CLDOUBLE 0xc1 /* long double constant */
629 #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
630 #define TOK_ADDC1 0xc3 /* add with carry generation */
631 #define TOK_ADDC2 0xc4 /* add with carry use */
632 #define TOK_SUBC1 0xc5 /* add with carry generation */
633 #define TOK_SUBC2 0xc6 /* add with carry use */
634 #define TOK_CUINT 0xc8 /* unsigned int constant */
635 #define TOK_CLLONG 0xc9 /* long long constant */
636 #define TOK_CULLONG 0xca /* unsigned long long constant */
637 #define TOK_ARROW 0xcb
638 #define TOK_DOTS 0xcc /* three dots */
639 #define TOK_SHR 0xcd /* unsigned shift right */
640 #define TOK_PPNUM 0xce /* preprocessor number */
642 #define TOK_SHL 0x01 /* shift left */
643 #define TOK_SAR 0x02 /* signed shift right */
645 /* assignement operators : normal operator or 0x80 */
646 #define TOK_A_MOD 0xa5
647 #define TOK_A_AND 0xa6
648 #define TOK_A_MUL 0xaa
649 #define TOK_A_ADD 0xab
650 #define TOK_A_SUB 0xad
651 #define TOK_A_DIV 0xaf
652 #define TOK_A_XOR 0xde
653 #define TOK_A_OR 0xfc
654 #define TOK_A_SHL 0x81
655 #define TOK_A_SAR 0x82
657 #ifndef offsetof
658 #define offsetof(type, field) ((size_t) &((type *)0)->field)
659 #endif
661 #ifndef countof
662 #define countof(tab) (sizeof(tab) / sizeof((tab)[0]))
663 #endif
665 /* WARNING: the content of this string encodes token numbers */
666 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";
668 #define TOK_EOF (-1) /* end of file */
669 #define TOK_LINEFEED 10 /* line feed */
671 /* all identificators and strings have token above that */
672 #define TOK_IDENT 256
674 /* only used for i386 asm opcodes definitions */
675 #define DEF_ASM(x) DEF(TOK_ASM_ ## x, #x)
677 #define DEF_BWL(x) \
678 DEF(TOK_ASM_ ## x ## b, #x "b") \
679 DEF(TOK_ASM_ ## x ## w, #x "w") \
680 DEF(TOK_ASM_ ## x ## l, #x "l") \
681 DEF(TOK_ASM_ ## x, #x)
683 #define DEF_WL(x) \
684 DEF(TOK_ASM_ ## x ## w, #x "w") \
685 DEF(TOK_ASM_ ## x ## l, #x "l") \
686 DEF(TOK_ASM_ ## x, #x)
688 #define DEF_FP1(x) \
689 DEF(TOK_ASM_ ## f ## x ## s, "f" #x "s") \
690 DEF(TOK_ASM_ ## fi ## x ## l, "fi" #x "l") \
691 DEF(TOK_ASM_ ## f ## x ## l, "f" #x "l") \
692 DEF(TOK_ASM_ ## fi ## x ## s, "fi" #x "s")
694 #define DEF_FP(x) \
695 DEF(TOK_ASM_ ## f ## x, "f" #x ) \
696 DEF(TOK_ASM_ ## f ## x ## p, "f" #x "p") \
697 DEF_FP1(x)
699 #define DEF_ASMTEST(x) \
700 DEF_ASM(x ## o) \
701 DEF_ASM(x ## no) \
702 DEF_ASM(x ## b) \
703 DEF_ASM(x ## c) \
704 DEF_ASM(x ## nae) \
705 DEF_ASM(x ## nb) \
706 DEF_ASM(x ## nc) \
707 DEF_ASM(x ## ae) \
708 DEF_ASM(x ## e) \
709 DEF_ASM(x ## z) \
710 DEF_ASM(x ## ne) \
711 DEF_ASM(x ## nz) \
712 DEF_ASM(x ## be) \
713 DEF_ASM(x ## na) \
714 DEF_ASM(x ## nbe) \
715 DEF_ASM(x ## a) \
716 DEF_ASM(x ## s) \
717 DEF_ASM(x ## ns) \
718 DEF_ASM(x ## p) \
719 DEF_ASM(x ## pe) \
720 DEF_ASM(x ## np) \
721 DEF_ASM(x ## po) \
722 DEF_ASM(x ## l) \
723 DEF_ASM(x ## nge) \
724 DEF_ASM(x ## nl) \
725 DEF_ASM(x ## ge) \
726 DEF_ASM(x ## le) \
727 DEF_ASM(x ## ng) \
728 DEF_ASM(x ## nle) \
729 DEF_ASM(x ## g)
731 #define TOK_ASM_int TOK_INT
733 enum tcc_token {
734 TOK_LAST = TOK_IDENT - 1,
735 #define DEF(id, str) id,
736 #include "tcctok.h"
737 #undef DEF
740 static const char tcc_keywords[] =
741 #define DEF(id, str) str "\0"
742 #include "tcctok.h"
743 #undef DEF
746 #define TOK_UIDENT TOK_DEFINE
748 #ifdef _WIN32
749 #define snprintf _snprintf
750 #define vsnprintf _vsnprintf
751 #ifndef __GNUC__
752 #define strtold (long double)strtod
753 #define strtof (float)strtod
754 #define strtoll (long long)strtol
755 #endif
756 #elif defined(TCC_UCLIBC) || defined(__FreeBSD__) || defined(__DragonFly__) \
757 || defined(__OpenBSD__)
758 /* currently incorrect */
759 long double strtold(const char *nptr, char **endptr)
761 return (long double)strtod(nptr, endptr);
763 float strtof(const char *nptr, char **endptr)
765 return (float)strtod(nptr, endptr);
767 #else
768 /* XXX: need to define this to use them in non ISOC99 context */
769 extern float strtof (const char *__nptr, char **__endptr);
770 extern long double strtold (const char *__nptr, char **__endptr);
771 #endif
773 static char *pstrcpy(char *buf, int buf_size, const char *s);
774 static char *pstrcat(char *buf, int buf_size, const char *s);
775 static char *tcc_basename(const char *name);
776 static char *tcc_fileextension (const char *p);
778 static void next(void);
779 static void next_nomacro(void);
780 static void parse_expr_type(CType *type);
781 static void expr_type(CType *type);
782 static void unary_type(CType *type);
783 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
784 int case_reg, int is_expr);
785 static int expr_const(void);
786 static void expr_eq(void);
787 static void gexpr(void);
788 static void gen_inline_functions(void);
789 static void decl(int l);
790 static void decl_initializer(CType *type, Section *sec, unsigned long c,
791 int first, int size_only);
792 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
793 int has_init, int v, int scope);
794 int gv(int rc);
795 void gv2(int rc1, int rc2);
796 void move_reg(int r, int s);
797 void save_regs(int n);
798 void save_reg(int r);
799 void vpop(void);
800 void vswap(void);
801 void vdup(void);
802 int get_reg(int rc);
803 int get_reg_ex(int rc,int rc2);
805 struct macro_level {
806 struct macro_level *prev;
807 int *p;
810 static void macro_subst(TokenString *tok_str, Sym **nested_list,
811 const int *macro_str, struct macro_level **can_read_stream);
812 void gen_op(int op);
813 void force_charshort_cast(int t);
814 static void gen_cast(CType *type);
815 void vstore(void);
816 static Sym *sym_find(int v);
817 static Sym *sym_push(int v, CType *type, int r, int c);
819 /* type handling */
820 static int type_size(CType *type, int *a);
821 static inline CType *pointed_type(CType *type);
822 static int pointed_size(CType *type);
823 static int lvalue_type(int t);
824 static int parse_btype(CType *type, AttributeDef *ad);
825 static void type_decl(CType *type, AttributeDef *ad, int *v, int td);
826 static int compare_types(CType *type1, CType *type2, int unqualified);
827 static int is_compatible_types(CType *type1, CType *type2);
828 static int is_compatible_parameter_types(CType *type1, CType *type2);
830 int ieee_finite(double d);
831 void error(const char *fmt, ...);
832 void vpushi(int v);
833 void vrott(int n);
834 void vnrott(int n);
835 void lexpand_nr(void);
836 static void vpush_global_sym(CType *type, int v);
837 void vset(CType *type, int r, int v);
838 void type_to_str(char *buf, int buf_size,
839 CType *type, const char *varstr);
840 char *get_tok_str(int v, CValue *cv);
841 static Sym *get_sym_ref(CType *type, Section *sec,
842 unsigned long offset, unsigned long size);
843 static Sym *external_global_sym(int v, CType *type, int r);
845 /* section generation */
846 static void section_realloc(Section *sec, unsigned long new_size);
847 static void *section_ptr_add(Section *sec, unsigned long size);
848 static void put_extern_sym(Sym *sym, Section *section,
849 unsigned long value, unsigned long size);
850 static void greloc(Section *s, Sym *sym, unsigned long addr, int type);
851 static int put_elf_str(Section *s, const char *sym);
852 static int put_elf_sym(Section *s,
853 unsigned long value, unsigned long size,
854 int info, int other, int shndx, const char *name);
855 static int add_elf_sym(Section *s, unsigned long value, unsigned long size,
856 int info, int other, int sh_num, const char *name);
857 static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
858 int type, int symbol);
859 static void put_stabs(const char *str, int type, int other, int desc,
860 unsigned long value);
861 static void put_stabs_r(const char *str, int type, int other, int desc,
862 unsigned long value, Section *sec, int sym_index);
863 static void put_stabn(int type, int other, int desc, int value);
864 static void put_stabd(int type, int other, int desc);
865 static int tcc_add_dll(TCCState *s, const char *filename, int flags);
867 #define AFF_PRINT_ERROR 0x0001 /* print error if file not found */
868 #define AFF_REFERENCED_DLL 0x0002 /* load a referenced dll from another dll */
869 #define AFF_PREPROCESS 0x0004 /* preprocess file */
870 static int tcc_add_file_internal(TCCState *s, const char *filename, int flags);
872 /* tcccoff.c */
873 int tcc_output_coff(TCCState *s1, FILE *f);
875 /* tccpe.c */
876 void *resolve_sym(TCCState *s1, const char *sym, int type);
877 int pe_load_def_file(struct TCCState *s1, int fd);
878 int pe_test_res_file(void *v, int size);
879 int pe_load_res_file(struct TCCState *s1, int fd);
880 void pe_add_runtime(struct TCCState *s1);
881 void pe_guess_outfile(char *objfilename, int output_type);
882 int pe_output_file(struct TCCState *s1, const char *filename);
884 /* tccasm.c */
886 #ifdef CONFIG_TCC_ASM
888 typedef struct ExprValue {
889 uint32_t v;
890 Sym *sym;
891 } ExprValue;
893 #define MAX_ASM_OPERANDS 30
895 typedef struct ASMOperand {
896 int id; /* GCC 3 optionnal identifier (0 if number only supported */
897 char *constraint;
898 char asm_str[16]; /* computed asm string for operand */
899 SValue *vt; /* C value of the expression */
900 int ref_index; /* if >= 0, gives reference to a output constraint */
901 int input_index; /* if >= 0, gives reference to an input constraint */
902 int priority; /* priority, used to assign registers */
903 int reg; /* if >= 0, register number used for this operand */
904 int is_llong; /* true if double register value */
905 int is_memory; /* true if memory operand */
906 int is_rw; /* for '+' modifier */
907 } ASMOperand;
909 static void asm_expr(TCCState *s1, ExprValue *pe);
910 static int asm_int_expr(TCCState *s1);
911 static int find_constraint(ASMOperand *operands, int nb_operands,
912 const char *name, const char **pp);
914 static int tcc_assemble(TCCState *s1, int do_preprocess);
916 #endif
918 static void asm_instr(void);
919 static void asm_global_instr(void);
921 /* true if float/double/long double type */
922 static inline int is_float(int t)
924 int bt;
925 bt = t & VT_BTYPE;
926 return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT;
929 #ifdef TCC_TARGET_I386
930 #include "i386-gen.c"
931 #endif
933 #ifdef TCC_TARGET_ARM
934 #include "arm-gen.c"
935 #endif
937 #ifdef TCC_TARGET_C67
938 #include "c67-gen.c"
939 #endif
941 #ifdef CONFIG_TCC_STATIC
943 #define RTLD_LAZY 0x001
944 #define RTLD_NOW 0x002
945 #define RTLD_GLOBAL 0x100
946 #define RTLD_DEFAULT NULL
948 /* dummy function for profiling */
949 void *dlopen(const char *filename, int flag)
951 return NULL;
954 const char *dlerror(void)
956 return "error";
959 typedef struct TCCSyms {
960 char *str;
961 void *ptr;
962 } TCCSyms;
964 #define TCCSYM(a) { #a, &a, },
966 /* add the symbol you want here if no dynamic linking is done */
967 static TCCSyms tcc_syms[] = {
968 #if !defined(CONFIG_TCCBOOT)
969 TCCSYM(printf)
970 TCCSYM(fprintf)
971 TCCSYM(fopen)
972 TCCSYM(fclose)
973 #endif
974 { NULL, NULL },
977 void *resolve_sym(TCCState *s1, const char *symbol, int type)
979 TCCSyms *p;
980 p = tcc_syms;
981 while (p->str != NULL) {
982 if (!strcmp(p->str, symbol))
983 return p->ptr;
984 p++;
986 return NULL;
989 #elif !defined(_WIN32)
991 #include <dlfcn.h>
993 void *resolve_sym(TCCState *s1, const char *sym, int type)
995 return dlsym(RTLD_DEFAULT, sym);
998 #endif
1000 /********************************************************/
1002 /* we use our own 'finite' function to avoid potential problems with
1003 non standard math libs */
1004 /* XXX: endianness dependent */
1005 int ieee_finite(double d)
1007 int *p = (int *)&d;
1008 return ((unsigned)((p[1] | 0x800fffff) + 1)) >> 31;
1011 /* copy a string and truncate it. */
1012 static char *pstrcpy(char *buf, int buf_size, const char *s)
1014 char *q, *q_end;
1015 int c;
1017 if (buf_size > 0) {
1018 q = buf;
1019 q_end = buf + buf_size - 1;
1020 while (q < q_end) {
1021 c = *s++;
1022 if (c == '\0')
1023 break;
1024 *q++ = c;
1026 *q = '\0';
1028 return buf;
1031 /* strcat and truncate. */
1032 static char *pstrcat(char *buf, int buf_size, const char *s)
1034 int len;
1035 len = strlen(buf);
1036 if (len < buf_size)
1037 pstrcpy(buf + len, buf_size - len, s);
1038 return buf;
1041 #ifndef LIBTCC
1042 static int strstart(const char *str, const char *val, const char **ptr)
1044 const char *p, *q;
1045 p = str;
1046 q = val;
1047 while (*q != '\0') {
1048 if (*p != *q)
1049 return 0;
1050 p++;
1051 q++;
1053 if (ptr)
1054 *ptr = p;
1055 return 1;
1057 #endif
1059 /* extract the basename of a file */
1060 static char *tcc_basename(const char *name)
1062 char *p = strchr(name, 0);
1063 while (p > name
1064 && p[-1] != '/'
1065 #ifdef _WIN32
1066 && p[-1] != '\\'
1067 #endif
1069 --p;
1070 return p;
1073 static char *tcc_fileextension (const char *name)
1075 char *b = tcc_basename(name);
1076 char *e = strrchr(b, '.');
1077 return e ? e : strchr(b, 0);
1080 #ifdef _WIN32
1081 char *normalize_slashes(char *path)
1083 char *p;
1084 for (p = path; *p; ++p)
1085 if (*p == '\\')
1086 *p = '/';
1087 return path;
1090 char *w32_tcc_lib_path(void)
1092 /* on win32, we suppose the lib and includes are at the location
1093 of 'tcc.exe' */
1094 char path[1024], *p;
1095 GetModuleFileNameA(NULL, path, sizeof path);
1096 p = tcc_basename(normalize_slashes(strlwr(path)));
1097 if (p - 5 > path && 0 == strncmp(p - 5, "/bin/", 5))
1098 p -= 5;
1099 else if (p > path)
1100 p--;
1101 *p = 0;
1102 return strdup(path);
1104 #endif
1106 void set_pages_executable(void *ptr, unsigned long length)
1108 #ifdef _WIN32
1109 unsigned long old_protect;
1110 VirtualProtect(ptr, length, PAGE_EXECUTE_READWRITE, &old_protect);
1111 #else
1112 unsigned long start, end;
1113 start = (unsigned long)ptr & ~(PAGESIZE - 1);
1114 end = (unsigned long)ptr + length;
1115 end = (end + PAGESIZE - 1) & ~(PAGESIZE - 1);
1116 mprotect((void *)start, end - start, PROT_READ | PROT_WRITE | PROT_EXEC);
1117 #endif
1120 /* memory management */
1121 #ifdef MEM_DEBUG
1122 int mem_cur_size;
1123 int mem_max_size;
1124 unsigned malloc_usable_size(void*);
1125 #endif
1127 static inline void tcc_free(void *ptr)
1129 #ifdef MEM_DEBUG
1130 mem_cur_size -= malloc_usable_size(ptr);
1131 #endif
1132 free(ptr);
1135 static void *tcc_malloc(unsigned long size)
1137 void *ptr;
1138 ptr = malloc(size);
1139 if (!ptr && size)
1140 error("memory full");
1141 #ifdef MEM_DEBUG
1142 mem_cur_size += malloc_usable_size(ptr);
1143 if (mem_cur_size > mem_max_size)
1144 mem_max_size = mem_cur_size;
1145 #endif
1146 return ptr;
1149 static void *tcc_mallocz(unsigned long size)
1151 void *ptr;
1152 ptr = tcc_malloc(size);
1153 memset(ptr, 0, size);
1154 return ptr;
1157 static inline void *tcc_realloc(void *ptr, unsigned long size)
1159 void *ptr1;
1160 #ifdef MEM_DEBUG
1161 mem_cur_size -= malloc_usable_size(ptr);
1162 #endif
1163 ptr1 = realloc(ptr, size);
1164 #ifdef MEM_DEBUG
1165 /* NOTE: count not correct if alloc error, but not critical */
1166 mem_cur_size += malloc_usable_size(ptr1);
1167 if (mem_cur_size > mem_max_size)
1168 mem_max_size = mem_cur_size;
1169 #endif
1170 return ptr1;
1173 static char *tcc_strdup(const char *str)
1175 char *ptr;
1176 ptr = tcc_malloc(strlen(str) + 1);
1177 strcpy(ptr, str);
1178 return ptr;
1181 #define free(p) use_tcc_free(p)
1182 #define malloc(s) use_tcc_malloc(s)
1183 #define realloc(p, s) use_tcc_realloc(p, s)
1185 static void dynarray_add(void ***ptab, int *nb_ptr, void *data)
1187 int nb, nb_alloc;
1188 void **pp;
1190 nb = *nb_ptr;
1191 pp = *ptab;
1192 /* every power of two we double array size */
1193 if ((nb & (nb - 1)) == 0) {
1194 if (!nb)
1195 nb_alloc = 1;
1196 else
1197 nb_alloc = nb * 2;
1198 pp = tcc_realloc(pp, nb_alloc * sizeof(void *));
1199 if (!pp)
1200 error("memory full");
1201 *ptab = pp;
1203 pp[nb++] = data;
1204 *nb_ptr = nb;
1207 static void dynarray_reset(void *pp, int *n)
1209 void **p;
1210 for (p = *(void***)pp; *n; ++p, --*n)
1211 if (*p)
1212 tcc_free(*p);
1213 tcc_free(*(void**)pp);
1214 *(void**)pp = NULL;
1217 /* symbol allocator */
1218 static Sym *__sym_malloc(void)
1220 Sym *sym_pool, *sym, *last_sym;
1221 int i;
1223 sym_pool = tcc_malloc(SYM_POOL_NB * sizeof(Sym));
1224 dynarray_add(&sym_pools, &nb_sym_pools, sym_pool);
1226 last_sym = sym_free_first;
1227 sym = sym_pool;
1228 for(i = 0; i < SYM_POOL_NB; i++) {
1229 sym->next = last_sym;
1230 last_sym = sym;
1231 sym++;
1233 sym_free_first = last_sym;
1234 return last_sym;
1237 static inline Sym *sym_malloc(void)
1239 Sym *sym;
1240 sym = sym_free_first;
1241 if (!sym)
1242 sym = __sym_malloc();
1243 sym_free_first = sym->next;
1244 return sym;
1247 static inline void sym_free(Sym *sym)
1249 sym->next = sym_free_first;
1250 sym_free_first = sym;
1253 Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags)
1255 Section *sec;
1257 sec = tcc_mallocz(sizeof(Section) + strlen(name));
1258 strcpy(sec->name, name);
1259 sec->sh_type = sh_type;
1260 sec->sh_flags = sh_flags;
1261 switch(sh_type) {
1262 case SHT_HASH:
1263 case SHT_REL:
1264 case SHT_RELA:
1265 case SHT_DYNSYM:
1266 case SHT_SYMTAB:
1267 case SHT_DYNAMIC:
1268 sec->sh_addralign = 4;
1269 break;
1270 case SHT_STRTAB:
1271 sec->sh_addralign = 1;
1272 break;
1273 default:
1274 sec->sh_addralign = 32; /* default conservative alignment */
1275 break;
1278 /* only add section if not private */
1279 if (!(sh_flags & SHF_PRIVATE)) {
1280 sec->sh_num = s1->nb_sections;
1281 dynarray_add((void ***)&s1->sections, &s1->nb_sections, sec);
1283 return sec;
1286 static void free_section(Section *s)
1288 if (s->link && (s->link->sh_flags & SHF_PRIVATE))
1289 free_section(s->link);
1290 if (s->hash && (s->hash->sh_flags & SHF_PRIVATE))
1291 s->hash->link = NULL, free_section(s->hash);
1292 tcc_free(s->data);
1293 tcc_free(s);
1296 /* realloc section and set its content to zero */
1297 static void section_realloc(Section *sec, unsigned long new_size)
1299 unsigned long size;
1300 unsigned char *data;
1302 size = sec->data_allocated;
1303 if (size == 0)
1304 size = 1;
1305 while (size < new_size)
1306 size = size * 2;
1307 data = tcc_realloc(sec->data, size);
1308 if (!data)
1309 error("memory full");
1310 memset(data + sec->data_allocated, 0, size - sec->data_allocated);
1311 sec->data = data;
1312 sec->data_allocated = size;
1315 /* reserve at least 'size' bytes in section 'sec' from
1316 sec->data_offset. */
1317 static void *section_ptr_add(Section *sec, unsigned long size)
1319 unsigned long offset, offset1;
1321 offset = sec->data_offset;
1322 offset1 = offset + size;
1323 if (offset1 > sec->data_allocated)
1324 section_realloc(sec, offset1);
1325 sec->data_offset = offset1;
1326 return sec->data + offset;
1329 /* return a reference to a section, and create it if it does not
1330 exists */
1331 Section *find_section(TCCState *s1, const char *name)
1333 Section *sec;
1334 int i;
1335 for(i = 1; i < s1->nb_sections; i++) {
1336 sec = s1->sections[i];
1337 if (!strcmp(name, sec->name))
1338 return sec;
1340 /* sections are created as PROGBITS */
1341 return new_section(s1, name, SHT_PROGBITS, SHF_ALLOC);
1344 #define SECTION_ABS ((void *)1)
1346 /* update sym->c so that it points to an external symbol in section
1347 'section' with value 'value' */
1348 static void put_extern_sym2(Sym *sym, Section *section,
1349 unsigned long value, unsigned long size,
1350 int can_add_underscore)
1352 int sym_type, sym_bind, sh_num, info, other, attr;
1353 ElfW(Sym) *esym;
1354 const char *name;
1355 char buf1[256];
1357 if (section == NULL)
1358 sh_num = SHN_UNDEF;
1359 else if (section == SECTION_ABS)
1360 sh_num = SHN_ABS;
1361 else
1362 sh_num = section->sh_num;
1364 other = attr = 0;
1366 if ((sym->type.t & VT_BTYPE) == VT_FUNC) {
1367 sym_type = STT_FUNC;
1368 #ifdef TCC_TARGET_PE
1369 if (sym->type.ref)
1370 attr = sym->type.ref->r;
1371 if (FUNC_EXPORT(attr))
1372 other |= 1;
1373 if (FUNC_CALL(attr) == FUNC_STDCALL)
1374 other |= 2;
1375 #endif
1376 } else {
1377 sym_type = STT_OBJECT;
1380 if (sym->type.t & VT_STATIC)
1381 sym_bind = STB_LOCAL;
1382 else
1383 sym_bind = STB_GLOBAL;
1385 if (!sym->c) {
1386 name = get_tok_str(sym->v, NULL);
1387 #ifdef CONFIG_TCC_BCHECK
1388 if (do_bounds_check) {
1389 char buf[32];
1391 /* XXX: avoid doing that for statics ? */
1392 /* if bound checking is activated, we change some function
1393 names by adding the "__bound" prefix */
1394 switch(sym->v) {
1395 #if 0
1396 /* XXX: we rely only on malloc hooks */
1397 case TOK_malloc:
1398 case TOK_free:
1399 case TOK_realloc:
1400 case TOK_memalign:
1401 case TOK_calloc:
1402 #endif
1403 case TOK_memcpy:
1404 case TOK_memmove:
1405 case TOK_memset:
1406 case TOK_strlen:
1407 case TOK_strcpy:
1408 case TOK__alloca:
1409 strcpy(buf, "__bound_");
1410 strcat(buf, name);
1411 name = buf;
1412 break;
1415 #endif
1417 #ifdef TCC_TARGET_PE
1418 if ((other & 2) && can_add_underscore) {
1419 sprintf(buf1, "_%s@%d", name, FUNC_ARGS(attr));
1420 name = buf1;
1421 } else
1422 #endif
1423 if (tcc_state->leading_underscore && can_add_underscore) {
1424 buf1[0] = '_';
1425 pstrcpy(buf1 + 1, sizeof(buf1) - 1, name);
1426 name = buf1;
1428 info = ELFW(ST_INFO)(sym_bind, sym_type);
1429 sym->c = add_elf_sym(symtab_section, value, size, info, other, sh_num, name);
1430 } else {
1431 esym = &((ElfW(Sym) *)symtab_section->data)[sym->c];
1432 esym->st_value = value;
1433 esym->st_size = size;
1434 esym->st_shndx = sh_num;
1435 esym->st_other |= other;
1439 static void put_extern_sym(Sym *sym, Section *section,
1440 unsigned long value, unsigned long size)
1442 put_extern_sym2(sym, section, value, size, 1);
1445 /* add a new relocation entry to symbol 'sym' in section 's' */
1446 static void greloc(Section *s, Sym *sym, unsigned long offset, int type)
1448 if (!sym->c)
1449 put_extern_sym(sym, NULL, 0, 0);
1450 /* now we can add ELF relocation info */
1451 put_elf_reloc(symtab_section, s, offset, type, sym->c);
1454 static inline int isid(int c)
1456 return (c >= 'a' && c <= 'z') ||
1457 (c >= 'A' && c <= 'Z') ||
1458 c == '_';
1461 static inline int isnum(int c)
1463 return c >= '0' && c <= '9';
1466 static inline int isoct(int c)
1468 return c >= '0' && c <= '7';
1471 static inline int toup(int c)
1473 if (c >= 'a' && c <= 'z')
1474 return c - 'a' + 'A';
1475 else
1476 return c;
1479 static void strcat_vprintf(char *buf, int buf_size, const char *fmt, va_list ap)
1481 int len;
1482 len = strlen(buf);
1483 vsnprintf(buf + len, buf_size - len, fmt, ap);
1486 static void strcat_printf(char *buf, int buf_size, const char *fmt, ...)
1488 va_list ap;
1489 va_start(ap, fmt);
1490 strcat_vprintf(buf, buf_size, fmt, ap);
1491 va_end(ap);
1494 void error1(TCCState *s1, int is_warning, const char *fmt, va_list ap)
1496 char buf[2048];
1497 BufferedFile **f;
1499 buf[0] = '\0';
1500 if (file) {
1501 for(f = s1->include_stack; f < s1->include_stack_ptr; f++)
1502 strcat_printf(buf, sizeof(buf), "In file included from %s:%d:\n",
1503 (*f)->filename, (*f)->line_num);
1504 if (file->line_num > 0) {
1505 strcat_printf(buf, sizeof(buf),
1506 "%s:%d: ", file->filename, file->line_num);
1507 } else {
1508 strcat_printf(buf, sizeof(buf),
1509 "%s: ", file->filename);
1511 } else {
1512 strcat_printf(buf, sizeof(buf),
1513 "tcc: ");
1515 if (is_warning)
1516 strcat_printf(buf, sizeof(buf), "warning: ");
1517 strcat_vprintf(buf, sizeof(buf), fmt, ap);
1519 if (!s1->error_func) {
1520 /* default case: stderr */
1521 fprintf(stderr, "%s\n", buf);
1522 } else {
1523 s1->error_func(s1->error_opaque, buf);
1525 if (!is_warning || s1->warn_error)
1526 s1->nb_errors++;
1529 #ifdef LIBTCC
1530 void tcc_set_error_func(TCCState *s, void *error_opaque,
1531 void (*error_func)(void *opaque, const char *msg))
1533 s->error_opaque = error_opaque;
1534 s->error_func = error_func;
1536 #endif
1538 /* error without aborting current compilation */
1539 void error_noabort(const char *fmt, ...)
1541 TCCState *s1 = tcc_state;
1542 va_list ap;
1544 va_start(ap, fmt);
1545 error1(s1, 0, fmt, ap);
1546 va_end(ap);
1549 void error(const char *fmt, ...)
1551 TCCState *s1 = tcc_state;
1552 va_list ap;
1554 va_start(ap, fmt);
1555 error1(s1, 0, fmt, ap);
1556 va_end(ap);
1557 /* better than nothing: in some cases, we accept to handle errors */
1558 if (s1->error_set_jmp_enabled) {
1559 longjmp(s1->error_jmp_buf, 1);
1560 } else {
1561 /* XXX: eliminate this someday */
1562 exit(1);
1566 void expect(const char *msg)
1568 error("%s expected", msg);
1571 void warning(const char *fmt, ...)
1573 TCCState *s1 = tcc_state;
1574 va_list ap;
1576 if (s1->warn_none)
1577 return;
1579 va_start(ap, fmt);
1580 error1(s1, 1, fmt, ap);
1581 va_end(ap);
1584 void skip(int c)
1586 if (tok != c)
1587 error("'%c' expected", c);
1588 next();
1591 static void test_lvalue(void)
1593 if (!(vtop->r & VT_LVAL))
1594 expect("lvalue");
1597 /* allocate a new token */
1598 static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len)
1600 TokenSym *ts, **ptable;
1601 int i;
1603 if (tok_ident >= SYM_FIRST_ANOM)
1604 error("memory full");
1606 /* expand token table if needed */
1607 i = tok_ident - TOK_IDENT;
1608 if ((i % TOK_ALLOC_INCR) == 0) {
1609 ptable = tcc_realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *));
1610 if (!ptable)
1611 error("memory full");
1612 table_ident = ptable;
1615 ts = tcc_malloc(sizeof(TokenSym) + len);
1616 table_ident[i] = ts;
1617 ts->tok = tok_ident++;
1618 ts->sym_define = NULL;
1619 ts->sym_label = NULL;
1620 ts->sym_struct = NULL;
1621 ts->sym_identifier = NULL;
1622 ts->len = len;
1623 ts->hash_next = NULL;
1624 memcpy(ts->str, str, len);
1625 ts->str[len] = '\0';
1626 *pts = ts;
1627 return ts;
1630 #define TOK_HASH_INIT 1
1631 #define TOK_HASH_FUNC(h, c) ((h) * 263 + (c))
1633 /* find a token and add it if not found */
1634 static TokenSym *tok_alloc(const char *str, int len)
1636 TokenSym *ts, **pts;
1637 int i;
1638 unsigned int h;
1640 h = TOK_HASH_INIT;
1641 for(i=0;i<len;i++)
1642 h = TOK_HASH_FUNC(h, ((unsigned char *)str)[i]);
1643 h &= (TOK_HASH_SIZE - 1);
1645 pts = &hash_ident[h];
1646 for(;;) {
1647 ts = *pts;
1648 if (!ts)
1649 break;
1650 if (ts->len == len && !memcmp(ts->str, str, len))
1651 return ts;
1652 pts = &(ts->hash_next);
1654 return tok_alloc_new(pts, str, len);
1657 /* CString handling */
1659 static void cstr_realloc(CString *cstr, int new_size)
1661 int size;
1662 void *data;
1664 size = cstr->size_allocated;
1665 if (size == 0)
1666 size = 8; /* no need to allocate a too small first string */
1667 while (size < new_size)
1668 size = size * 2;
1669 data = tcc_realloc(cstr->data_allocated, size);
1670 if (!data)
1671 error("memory full");
1672 cstr->data_allocated = data;
1673 cstr->size_allocated = size;
1674 cstr->data = data;
1677 /* add a byte */
1678 static inline void cstr_ccat(CString *cstr, int ch)
1680 int size;
1681 size = cstr->size + 1;
1682 if (size > cstr->size_allocated)
1683 cstr_realloc(cstr, size);
1684 ((unsigned char *)cstr->data)[size - 1] = ch;
1685 cstr->size = size;
1688 static void cstr_cat(CString *cstr, const char *str)
1690 int c;
1691 for(;;) {
1692 c = *str;
1693 if (c == '\0')
1694 break;
1695 cstr_ccat(cstr, c);
1696 str++;
1700 /* add a wide char */
1701 static void cstr_wccat(CString *cstr, int ch)
1703 int size;
1704 size = cstr->size + sizeof(nwchar_t);
1705 if (size > cstr->size_allocated)
1706 cstr_realloc(cstr, size);
1707 *(nwchar_t *)(((unsigned char *)cstr->data) + size - sizeof(nwchar_t)) = ch;
1708 cstr->size = size;
1711 static void cstr_new(CString *cstr)
1713 memset(cstr, 0, sizeof(CString));
1716 /* free string and reset it to NULL */
1717 static void cstr_free(CString *cstr)
1719 tcc_free(cstr->data_allocated);
1720 cstr_new(cstr);
1723 #define cstr_reset(cstr) cstr_free(cstr)
1725 /* XXX: unicode ? */
1726 static void add_char(CString *cstr, int c)
1728 if (c == '\'' || c == '\"' || c == '\\') {
1729 /* XXX: could be more precise if char or string */
1730 cstr_ccat(cstr, '\\');
1732 if (c >= 32 && c <= 126) {
1733 cstr_ccat(cstr, c);
1734 } else {
1735 cstr_ccat(cstr, '\\');
1736 if (c == '\n') {
1737 cstr_ccat(cstr, 'n');
1738 } else {
1739 cstr_ccat(cstr, '0' + ((c >> 6) & 7));
1740 cstr_ccat(cstr, '0' + ((c >> 3) & 7));
1741 cstr_ccat(cstr, '0' + (c & 7));
1746 /* XXX: buffer overflow */
1747 /* XXX: float tokens */
1748 char *get_tok_str(int v, CValue *cv)
1750 static char buf[STRING_MAX_SIZE + 1];
1751 static CString cstr_buf;
1752 CString *cstr;
1753 unsigned char *q;
1754 char *p;
1755 int i, len;
1757 /* NOTE: to go faster, we give a fixed buffer for small strings */
1758 cstr_reset(&cstr_buf);
1759 cstr_buf.data = buf;
1760 cstr_buf.size_allocated = sizeof(buf);
1761 p = buf;
1763 switch(v) {
1764 case TOK_CINT:
1765 case TOK_CUINT:
1766 /* XXX: not quite exact, but only useful for testing */
1767 sprintf(p, "%u", cv->ui);
1768 break;
1769 case TOK_CLLONG:
1770 case TOK_CULLONG:
1771 /* XXX: not quite exact, but only useful for testing */
1772 sprintf(p, "%Lu", cv->ull);
1773 break;
1774 case TOK_LCHAR:
1775 cstr_ccat(&cstr_buf, 'L');
1776 case TOK_CCHAR:
1777 cstr_ccat(&cstr_buf, '\'');
1778 add_char(&cstr_buf, cv->i);
1779 cstr_ccat(&cstr_buf, '\'');
1780 cstr_ccat(&cstr_buf, '\0');
1781 break;
1782 case TOK_PPNUM:
1783 cstr = cv->cstr;
1784 len = cstr->size - 1;
1785 for(i=0;i<len;i++)
1786 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1787 cstr_ccat(&cstr_buf, '\0');
1788 break;
1789 case TOK_LSTR:
1790 cstr_ccat(&cstr_buf, 'L');
1791 case TOK_STR:
1792 cstr = cv->cstr;
1793 cstr_ccat(&cstr_buf, '\"');
1794 if (v == TOK_STR) {
1795 len = cstr->size - 1;
1796 for(i=0;i<len;i++)
1797 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1798 } else {
1799 len = (cstr->size / sizeof(nwchar_t)) - 1;
1800 for(i=0;i<len;i++)
1801 add_char(&cstr_buf, ((nwchar_t *)cstr->data)[i]);
1803 cstr_ccat(&cstr_buf, '\"');
1804 cstr_ccat(&cstr_buf, '\0');
1805 break;
1806 case TOK_LT:
1807 v = '<';
1808 goto addv;
1809 case TOK_GT:
1810 v = '>';
1811 goto addv;
1812 case TOK_DOTS:
1813 return strcpy(p, "...");
1814 case TOK_A_SHL:
1815 return strcpy(p, "<<=");
1816 case TOK_A_SAR:
1817 return strcpy(p, ">>=");
1818 default:
1819 if (v < TOK_IDENT) {
1820 /* search in two bytes table */
1821 q = tok_two_chars;
1822 while (*q) {
1823 if (q[2] == v) {
1824 *p++ = q[0];
1825 *p++ = q[1];
1826 *p = '\0';
1827 return buf;
1829 q += 3;
1831 addv:
1832 *p++ = v;
1833 *p = '\0';
1834 } else if (v < tok_ident) {
1835 return table_ident[v - TOK_IDENT]->str;
1836 } else if (v >= SYM_FIRST_ANOM) {
1837 /* special name for anonymous symbol */
1838 sprintf(p, "L.%u", v - SYM_FIRST_ANOM);
1839 } else {
1840 /* should never happen */
1841 return NULL;
1843 break;
1845 return cstr_buf.data;
1848 /* push, without hashing */
1849 static Sym *sym_push2(Sym **ps, int v, int t, int c)
1851 Sym *s;
1852 s = sym_malloc();
1853 s->v = v;
1854 s->type.t = t;
1855 s->c = c;
1856 s->next = NULL;
1857 /* add in stack */
1858 s->prev = *ps;
1859 *ps = s;
1860 return s;
1863 /* find a symbol and return its associated structure. 's' is the top
1864 of the symbol stack */
1865 static Sym *sym_find2(Sym *s, int v)
1867 while (s) {
1868 if (s->v == v)
1869 return s;
1870 s = s->prev;
1872 return NULL;
1875 /* structure lookup */
1876 static inline Sym *struct_find(int v)
1878 v -= TOK_IDENT;
1879 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1880 return NULL;
1881 return table_ident[v]->sym_struct;
1884 /* find an identifier */
1885 static inline Sym *sym_find(int v)
1887 v -= TOK_IDENT;
1888 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1889 return NULL;
1890 return table_ident[v]->sym_identifier;
1893 /* push a given symbol on the symbol stack */
1894 static Sym *sym_push(int v, CType *type, int r, int c)
1896 Sym *s, **ps;
1897 TokenSym *ts;
1899 if (local_stack)
1900 ps = &local_stack;
1901 else
1902 ps = &global_stack;
1903 s = sym_push2(ps, v, type->t, c);
1904 s->type.ref = type->ref;
1905 s->r = r;
1906 /* don't record fields or anonymous symbols */
1907 /* XXX: simplify */
1908 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1909 /* record symbol in token array */
1910 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1911 if (v & SYM_STRUCT)
1912 ps = &ts->sym_struct;
1913 else
1914 ps = &ts->sym_identifier;
1915 s->prev_tok = *ps;
1916 *ps = s;
1918 return s;
1921 /* push a global identifier */
1922 static Sym *global_identifier_push(int v, int t, int c)
1924 Sym *s, **ps;
1925 s = sym_push2(&global_stack, v, t, c);
1926 /* don't record anonymous symbol */
1927 if (v < SYM_FIRST_ANOM) {
1928 ps = &table_ident[v - TOK_IDENT]->sym_identifier;
1929 /* modify the top most local identifier, so that
1930 sym_identifier will point to 's' when popped */
1931 while (*ps != NULL)
1932 ps = &(*ps)->prev_tok;
1933 s->prev_tok = NULL;
1934 *ps = s;
1936 return s;
1939 /* pop symbols until top reaches 'b' */
1940 static void sym_pop(Sym **ptop, Sym *b)
1942 Sym *s, *ss, **ps;
1943 TokenSym *ts;
1944 int v;
1946 s = *ptop;
1947 while(s != b) {
1948 ss = s->prev;
1949 v = s->v;
1950 /* remove symbol in token array */
1951 /* XXX: simplify */
1952 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1953 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1954 if (v & SYM_STRUCT)
1955 ps = &ts->sym_struct;
1956 else
1957 ps = &ts->sym_identifier;
1958 *ps = s->prev_tok;
1960 sym_free(s);
1961 s = ss;
1963 *ptop = b;
1966 /* I/O layer */
1968 BufferedFile *tcc_open(TCCState *s1, const char *filename)
1970 int fd;
1971 BufferedFile *bf;
1973 if (strcmp(filename, "-") == 0)
1974 fd = 0, filename = "stdin";
1975 else
1976 fd = open(filename, O_RDONLY | O_BINARY);
1977 if ((verbose == 2 && fd >= 0) || verbose == 3)
1978 printf("%s %*s%s\n", fd < 0 ? "nf":"->",
1979 (s1->include_stack_ptr - s1->include_stack), "", filename);
1980 if (fd < 0)
1981 return NULL;
1982 bf = tcc_malloc(sizeof(BufferedFile));
1983 bf->fd = fd;
1984 bf->buf_ptr = bf->buffer;
1985 bf->buf_end = bf->buffer;
1986 bf->buffer[0] = CH_EOB; /* put eob symbol */
1987 pstrcpy(bf->filename, sizeof(bf->filename), filename);
1988 #ifdef _WIN32
1989 normalize_slashes(bf->filename);
1990 #endif
1991 bf->line_num = 1;
1992 bf->ifndef_macro = 0;
1993 bf->ifdef_stack_ptr = s1->ifdef_stack_ptr;
1994 // printf("opening '%s'\n", filename);
1995 return bf;
1998 void tcc_close(BufferedFile *bf)
2000 total_lines += bf->line_num;
2001 close(bf->fd);
2002 tcc_free(bf);
2005 /* fill input buffer and peek next char */
2006 static int tcc_peekc_slow(BufferedFile *bf)
2008 int len;
2009 /* only tries to read if really end of buffer */
2010 if (bf->buf_ptr >= bf->buf_end) {
2011 if (bf->fd != -1) {
2012 #if defined(PARSE_DEBUG)
2013 len = 8;
2014 #else
2015 len = IO_BUF_SIZE;
2016 #endif
2017 len = read(bf->fd, bf->buffer, len);
2018 if (len < 0)
2019 len = 0;
2020 } else {
2021 len = 0;
2023 total_bytes += len;
2024 bf->buf_ptr = bf->buffer;
2025 bf->buf_end = bf->buffer + len;
2026 *bf->buf_end = CH_EOB;
2028 if (bf->buf_ptr < bf->buf_end) {
2029 return bf->buf_ptr[0];
2030 } else {
2031 bf->buf_ptr = bf->buf_end;
2032 return CH_EOF;
2036 /* return the current character, handling end of block if necessary
2037 (but not stray) */
2038 static int handle_eob(void)
2040 return tcc_peekc_slow(file);
2043 /* read next char from current input file and handle end of input buffer */
2044 static inline void inp(void)
2046 ch = *(++(file->buf_ptr));
2047 /* end of buffer/file handling */
2048 if (ch == CH_EOB)
2049 ch = handle_eob();
2052 /* handle '\[\r]\n' */
2053 static int handle_stray_noerror(void)
2055 while (ch == '\\') {
2056 inp();
2057 if (ch == '\n') {
2058 file->line_num++;
2059 inp();
2060 } else if (ch == '\r') {
2061 inp();
2062 if (ch != '\n')
2063 goto fail;
2064 file->line_num++;
2065 inp();
2066 } else {
2067 fail:
2068 return 1;
2071 return 0;
2074 static void handle_stray(void)
2076 if (handle_stray_noerror())
2077 error("stray '\\' in program");
2080 /* skip the stray and handle the \\n case. Output an error if
2081 incorrect char after the stray */
2082 static int handle_stray1(uint8_t *p)
2084 int c;
2086 if (p >= file->buf_end) {
2087 file->buf_ptr = p;
2088 c = handle_eob();
2089 p = file->buf_ptr;
2090 if (c == '\\')
2091 goto parse_stray;
2092 } else {
2093 parse_stray:
2094 file->buf_ptr = p;
2095 ch = *p;
2096 handle_stray();
2097 p = file->buf_ptr;
2098 c = *p;
2100 return c;
2103 /* handle just the EOB case, but not stray */
2104 #define PEEKC_EOB(c, p)\
2106 p++;\
2107 c = *p;\
2108 if (c == '\\') {\
2109 file->buf_ptr = p;\
2110 c = handle_eob();\
2111 p = file->buf_ptr;\
2115 /* handle the complicated stray case */
2116 #define PEEKC(c, p)\
2118 p++;\
2119 c = *p;\
2120 if (c == '\\') {\
2121 c = handle_stray1(p);\
2122 p = file->buf_ptr;\
2126 /* input with '\[\r]\n' handling. Note that this function cannot
2127 handle other characters after '\', so you cannot call it inside
2128 strings or comments */
2129 static void minp(void)
2131 inp();
2132 if (ch == '\\')
2133 handle_stray();
2137 /* single line C++ comments */
2138 static uint8_t *parse_line_comment(uint8_t *p)
2140 int c;
2142 p++;
2143 for(;;) {
2144 c = *p;
2145 redo:
2146 if (c == '\n' || c == CH_EOF) {
2147 break;
2148 } else if (c == '\\') {
2149 file->buf_ptr = p;
2150 c = handle_eob();
2151 p = file->buf_ptr;
2152 if (c == '\\') {
2153 PEEKC_EOB(c, p);
2154 if (c == '\n') {
2155 file->line_num++;
2156 PEEKC_EOB(c, p);
2157 } else if (c == '\r') {
2158 PEEKC_EOB(c, p);
2159 if (c == '\n') {
2160 file->line_num++;
2161 PEEKC_EOB(c, p);
2164 } else {
2165 goto redo;
2167 } else {
2168 p++;
2171 return p;
2174 /* C comments */
2175 static uint8_t *parse_comment(uint8_t *p)
2177 int c;
2179 p++;
2180 for(;;) {
2181 /* fast skip loop */
2182 for(;;) {
2183 c = *p;
2184 if (c == '\n' || c == '*' || c == '\\')
2185 break;
2186 p++;
2187 c = *p;
2188 if (c == '\n' || c == '*' || c == '\\')
2189 break;
2190 p++;
2192 /* now we can handle all the cases */
2193 if (c == '\n') {
2194 file->line_num++;
2195 p++;
2196 } else if (c == '*') {
2197 p++;
2198 for(;;) {
2199 c = *p;
2200 if (c == '*') {
2201 p++;
2202 } else if (c == '/') {
2203 goto end_of_comment;
2204 } else if (c == '\\') {
2205 file->buf_ptr = p;
2206 c = handle_eob();
2207 p = file->buf_ptr;
2208 if (c == '\\') {
2209 /* skip '\[\r]\n', otherwise just skip the stray */
2210 while (c == '\\') {
2211 PEEKC_EOB(c, p);
2212 if (c == '\n') {
2213 file->line_num++;
2214 PEEKC_EOB(c, p);
2215 } else if (c == '\r') {
2216 PEEKC_EOB(c, p);
2217 if (c == '\n') {
2218 file->line_num++;
2219 PEEKC_EOB(c, p);
2221 } else {
2222 goto after_star;
2226 } else {
2227 break;
2230 after_star: ;
2231 } else {
2232 /* stray, eob or eof */
2233 file->buf_ptr = p;
2234 c = handle_eob();
2235 p = file->buf_ptr;
2236 if (c == CH_EOF) {
2237 error("unexpected end of file in comment");
2238 } else if (c == '\\') {
2239 p++;
2243 end_of_comment:
2244 p++;
2245 return p;
2248 #define cinp minp
2250 /* space exlcuding newline */
2251 static inline int is_space(int ch)
2253 return ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f' || ch == '\r';
2256 static inline void skip_spaces(void)
2258 while (is_space(ch))
2259 cinp();
2262 /* parse a string without interpreting escapes */
2263 static uint8_t *parse_pp_string(uint8_t *p,
2264 int sep, CString *str)
2266 int c;
2267 p++;
2268 for(;;) {
2269 c = *p;
2270 if (c == sep) {
2271 break;
2272 } else if (c == '\\') {
2273 file->buf_ptr = p;
2274 c = handle_eob();
2275 p = file->buf_ptr;
2276 if (c == CH_EOF) {
2277 unterminated_string:
2278 /* XXX: indicate line number of start of string */
2279 error("missing terminating %c character", sep);
2280 } else if (c == '\\') {
2281 /* escape : just skip \[\r]\n */
2282 PEEKC_EOB(c, p);
2283 if (c == '\n') {
2284 file->line_num++;
2285 p++;
2286 } else if (c == '\r') {
2287 PEEKC_EOB(c, p);
2288 if (c != '\n')
2289 expect("'\n' after '\r'");
2290 file->line_num++;
2291 p++;
2292 } else if (c == CH_EOF) {
2293 goto unterminated_string;
2294 } else {
2295 if (str) {
2296 cstr_ccat(str, '\\');
2297 cstr_ccat(str, c);
2299 p++;
2302 } else if (c == '\n') {
2303 file->line_num++;
2304 goto add_char;
2305 } else if (c == '\r') {
2306 PEEKC_EOB(c, p);
2307 if (c != '\n') {
2308 if (str)
2309 cstr_ccat(str, '\r');
2310 } else {
2311 file->line_num++;
2312 goto add_char;
2314 } else {
2315 add_char:
2316 if (str)
2317 cstr_ccat(str, c);
2318 p++;
2321 p++;
2322 return p;
2325 /* skip block of text until #else, #elif or #endif. skip also pairs of
2326 #if/#endif */
2327 void preprocess_skip(void)
2329 int a, start_of_line, c, in_warn_or_error;
2330 uint8_t *p;
2332 p = file->buf_ptr;
2333 a = 0;
2334 redo_start:
2335 start_of_line = 1;
2336 in_warn_or_error = 0;
2337 for(;;) {
2338 redo_no_start:
2339 c = *p;
2340 switch(c) {
2341 case ' ':
2342 case '\t':
2343 case '\f':
2344 case '\v':
2345 case '\r':
2346 p++;
2347 goto redo_no_start;
2348 case '\n':
2349 file->line_num++;
2350 p++;
2351 goto redo_start;
2352 case '\\':
2353 file->buf_ptr = p;
2354 c = handle_eob();
2355 if (c == CH_EOF) {
2356 expect("#endif");
2357 } else if (c == '\\') {
2358 ch = file->buf_ptr[0];
2359 handle_stray_noerror();
2361 p = file->buf_ptr;
2362 goto redo_no_start;
2363 /* skip strings */
2364 case '\"':
2365 case '\'':
2366 if (in_warn_or_error)
2367 goto _default;
2368 p = parse_pp_string(p, c, NULL);
2369 break;
2370 /* skip comments */
2371 case '/':
2372 if (in_warn_or_error)
2373 goto _default;
2374 file->buf_ptr = p;
2375 ch = *p;
2376 minp();
2377 p = file->buf_ptr;
2378 if (ch == '*') {
2379 p = parse_comment(p);
2380 } else if (ch == '/') {
2381 p = parse_line_comment(p);
2383 break;
2384 case '#':
2385 p++;
2386 if (start_of_line) {
2387 file->buf_ptr = p;
2388 next_nomacro();
2389 p = file->buf_ptr;
2390 if (a == 0 &&
2391 (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
2392 goto the_end;
2393 if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
2394 a++;
2395 else if (tok == TOK_ENDIF)
2396 a--;
2397 else if( tok == TOK_ERROR || tok == TOK_WARNING)
2398 in_warn_or_error = 1;
2400 break;
2401 _default:
2402 default:
2403 p++;
2404 break;
2406 start_of_line = 0;
2408 the_end: ;
2409 file->buf_ptr = p;
2412 /* ParseState handling */
2414 /* XXX: currently, no include file info is stored. Thus, we cannot display
2415 accurate messages if the function or data definition spans multiple
2416 files */
2418 /* save current parse state in 's' */
2419 void save_parse_state(ParseState *s)
2421 s->line_num = file->line_num;
2422 s->macro_ptr = macro_ptr;
2423 s->tok = tok;
2424 s->tokc = tokc;
2427 /* restore parse state from 's' */
2428 void restore_parse_state(ParseState *s)
2430 file->line_num = s->line_num;
2431 macro_ptr = s->macro_ptr;
2432 tok = s->tok;
2433 tokc = s->tokc;
2436 /* return the number of additional 'ints' necessary to store the
2437 token */
2438 static inline int tok_ext_size(int t)
2440 switch(t) {
2441 /* 4 bytes */
2442 case TOK_CINT:
2443 case TOK_CUINT:
2444 case TOK_CCHAR:
2445 case TOK_LCHAR:
2446 case TOK_CFLOAT:
2447 case TOK_LINENUM:
2448 return 1;
2449 case TOK_STR:
2450 case TOK_LSTR:
2451 case TOK_PPNUM:
2452 error("unsupported token");
2453 return 1;
2454 case TOK_CDOUBLE:
2455 case TOK_CLLONG:
2456 case TOK_CULLONG:
2457 return 2;
2458 case TOK_CLDOUBLE:
2459 return LDOUBLE_SIZE / 4;
2460 default:
2461 return 0;
2465 /* token string handling */
2467 static inline void tok_str_new(TokenString *s)
2469 s->str = NULL;
2470 s->len = 0;
2471 s->allocated_len = 0;
2472 s->last_line_num = -1;
2475 static void tok_str_free(int *str)
2477 tcc_free(str);
2480 static int *tok_str_realloc(TokenString *s)
2482 int *str, len;
2484 if (s->allocated_len == 0) {
2485 len = 8;
2486 } else {
2487 len = s->allocated_len * 2;
2489 str = tcc_realloc(s->str, len * sizeof(int));
2490 if (!str)
2491 error("memory full");
2492 s->allocated_len = len;
2493 s->str = str;
2494 return str;
2497 static void tok_str_add(TokenString *s, int t)
2499 int len, *str;
2501 len = s->len;
2502 str = s->str;
2503 if (len >= s->allocated_len)
2504 str = tok_str_realloc(s);
2505 str[len++] = t;
2506 s->len = len;
2509 static void tok_str_add2(TokenString *s, int t, CValue *cv)
2511 int len, *str;
2513 len = s->len;
2514 str = s->str;
2516 /* allocate space for worst case */
2517 if (len + TOK_MAX_SIZE > s->allocated_len)
2518 str = tok_str_realloc(s);
2519 str[len++] = t;
2520 switch(t) {
2521 case TOK_CINT:
2522 case TOK_CUINT:
2523 case TOK_CCHAR:
2524 case TOK_LCHAR:
2525 case TOK_CFLOAT:
2526 case TOK_LINENUM:
2527 str[len++] = cv->tab[0];
2528 break;
2529 case TOK_PPNUM:
2530 case TOK_STR:
2531 case TOK_LSTR:
2533 int nb_words;
2534 CString *cstr;
2536 nb_words = (sizeof(CString) + cv->cstr->size + 3) >> 2;
2537 while ((len + nb_words) > s->allocated_len)
2538 str = tok_str_realloc(s);
2539 cstr = (CString *)(str + len);
2540 cstr->data = NULL;
2541 cstr->size = cv->cstr->size;
2542 cstr->data_allocated = NULL;
2543 cstr->size_allocated = cstr->size;
2544 memcpy((char *)cstr + sizeof(CString),
2545 cv->cstr->data, cstr->size);
2546 len += nb_words;
2548 break;
2549 case TOK_CDOUBLE:
2550 case TOK_CLLONG:
2551 case TOK_CULLONG:
2552 #if LDOUBLE_SIZE == 8
2553 case TOK_CLDOUBLE:
2554 #endif
2555 str[len++] = cv->tab[0];
2556 str[len++] = cv->tab[1];
2557 break;
2558 #if LDOUBLE_SIZE == 12
2559 case TOK_CLDOUBLE:
2560 str[len++] = cv->tab[0];
2561 str[len++] = cv->tab[1];
2562 str[len++] = cv->tab[2];
2563 #elif LDOUBLE_SIZE != 8
2564 #error add long double size support
2565 #endif
2566 break;
2567 default:
2568 break;
2570 s->len = len;
2573 /* add the current parse token in token string 's' */
2574 static void tok_str_add_tok(TokenString *s)
2576 CValue cval;
2578 /* save line number info */
2579 if (file->line_num != s->last_line_num) {
2580 s->last_line_num = file->line_num;
2581 cval.i = s->last_line_num;
2582 tok_str_add2(s, TOK_LINENUM, &cval);
2584 tok_str_add2(s, tok, &tokc);
2587 #if LDOUBLE_SIZE == 12
2588 #define LDOUBLE_GET(p, cv) \
2589 cv.tab[0] = p[0]; \
2590 cv.tab[1] = p[1]; \
2591 cv.tab[2] = p[2];
2592 #elif LDOUBLE_SIZE == 8
2593 #define LDOUBLE_GET(p, cv) \
2594 cv.tab[0] = p[0]; \
2595 cv.tab[1] = p[1];
2596 #else
2597 #error add long double size support
2598 #endif
2601 /* get a token from an integer array and increment pointer
2602 accordingly. we code it as a macro to avoid pointer aliasing. */
2603 #define TOK_GET(t, p, cv) \
2605 t = *p++; \
2606 switch(t) { \
2607 case TOK_CINT: \
2608 case TOK_CUINT: \
2609 case TOK_CCHAR: \
2610 case TOK_LCHAR: \
2611 case TOK_CFLOAT: \
2612 case TOK_LINENUM: \
2613 cv.tab[0] = *p++; \
2614 break; \
2615 case TOK_STR: \
2616 case TOK_LSTR: \
2617 case TOK_PPNUM: \
2618 cv.cstr = (CString *)p; \
2619 cv.cstr->data = (char *)p + sizeof(CString);\
2620 p += (sizeof(CString) + cv.cstr->size + 3) >> 2;\
2621 break; \
2622 case TOK_CDOUBLE: \
2623 case TOK_CLLONG: \
2624 case TOK_CULLONG: \
2625 cv.tab[0] = p[0]; \
2626 cv.tab[1] = p[1]; \
2627 p += 2; \
2628 break; \
2629 case TOK_CLDOUBLE: \
2630 LDOUBLE_GET(p, cv); \
2631 p += LDOUBLE_SIZE / 4; \
2632 break; \
2633 default: \
2634 break; \
2638 /* defines handling */
2639 static inline void define_push(int v, int macro_type, int *str, Sym *first_arg)
2641 Sym *s;
2643 s = sym_push2(&define_stack, v, macro_type, (int)str);
2644 s->next = first_arg;
2645 table_ident[v - TOK_IDENT]->sym_define = s;
2648 /* undefined a define symbol. Its name is just set to zero */
2649 static void define_undef(Sym *s)
2651 int v;
2652 v = s->v;
2653 if (v >= TOK_IDENT && v < tok_ident)
2654 table_ident[v - TOK_IDENT]->sym_define = NULL;
2655 s->v = 0;
2658 static inline Sym *define_find(int v)
2660 v -= TOK_IDENT;
2661 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2662 return NULL;
2663 return table_ident[v]->sym_define;
2666 /* free define stack until top reaches 'b' */
2667 static void free_defines(Sym *b)
2669 Sym *top, *top1;
2670 int v;
2672 top = define_stack;
2673 while (top != b) {
2674 top1 = top->prev;
2675 /* do not free args or predefined defines */
2676 if (top->c)
2677 tok_str_free((int *)top->c);
2678 v = top->v;
2679 if (v >= TOK_IDENT && v < tok_ident)
2680 table_ident[v - TOK_IDENT]->sym_define = NULL;
2681 sym_free(top);
2682 top = top1;
2684 define_stack = b;
2687 /* label lookup */
2688 static Sym *label_find(int v)
2690 v -= TOK_IDENT;
2691 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2692 return NULL;
2693 return table_ident[v]->sym_label;
2696 static Sym *label_push(Sym **ptop, int v, int flags)
2698 Sym *s, **ps;
2699 s = sym_push2(ptop, v, 0, 0);
2700 s->r = flags;
2701 ps = &table_ident[v - TOK_IDENT]->sym_label;
2702 if (ptop == &global_label_stack) {
2703 /* modify the top most local identifier, so that
2704 sym_identifier will point to 's' when popped */
2705 while (*ps != NULL)
2706 ps = &(*ps)->prev_tok;
2708 s->prev_tok = *ps;
2709 *ps = s;
2710 return s;
2713 /* pop labels until element last is reached. Look if any labels are
2714 undefined. Define symbols if '&&label' was used. */
2715 static void label_pop(Sym **ptop, Sym *slast)
2717 Sym *s, *s1;
2718 for(s = *ptop; s != slast; s = s1) {
2719 s1 = s->prev;
2720 if (s->r == LABEL_DECLARED) {
2721 warning("label '%s' declared but not used", get_tok_str(s->v, NULL));
2722 } else if (s->r == LABEL_FORWARD) {
2723 error("label '%s' used but not defined",
2724 get_tok_str(s->v, NULL));
2725 } else {
2726 if (s->c) {
2727 /* define corresponding symbol. A size of
2728 1 is put. */
2729 put_extern_sym(s, cur_text_section, (long)s->next, 1);
2732 /* remove label */
2733 table_ident[s->v - TOK_IDENT]->sym_label = s->prev_tok;
2734 sym_free(s);
2736 *ptop = slast;
2739 /* eval an expression for #if/#elif */
2740 static int expr_preprocess(void)
2742 int c, t;
2743 TokenString str;
2745 tok_str_new(&str);
2746 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2747 next(); /* do macro subst */
2748 if (tok == TOK_DEFINED) {
2749 next_nomacro();
2750 t = tok;
2751 if (t == '(')
2752 next_nomacro();
2753 c = define_find(tok) != 0;
2754 if (t == '(')
2755 next_nomacro();
2756 tok = TOK_CINT;
2757 tokc.i = c;
2758 } else if (tok >= TOK_IDENT) {
2759 /* if undefined macro */
2760 tok = TOK_CINT;
2761 tokc.i = 0;
2763 tok_str_add_tok(&str);
2765 tok_str_add(&str, -1); /* simulate end of file */
2766 tok_str_add(&str, 0);
2767 /* now evaluate C constant expression */
2768 macro_ptr = str.str;
2769 next();
2770 c = expr_const();
2771 macro_ptr = NULL;
2772 tok_str_free(str.str);
2773 return c != 0;
2776 #if defined(PARSE_DEBUG) || defined(PP_DEBUG)
2777 static void tok_print(int *str)
2779 int t;
2780 CValue cval;
2782 while (1) {
2783 TOK_GET(t, str, cval);
2784 if (!t)
2785 break;
2786 printf(" %s", get_tok_str(t, &cval));
2788 printf("\n");
2790 #endif
2792 /* parse after #define */
2793 static void parse_define(void)
2795 Sym *s, *first, **ps;
2796 int v, t, varg, is_vaargs, c;
2797 TokenString str;
2799 v = tok;
2800 if (v < TOK_IDENT)
2801 error("invalid macro name '%s'", get_tok_str(tok, &tokc));
2802 /* XXX: should check if same macro (ANSI) */
2803 first = NULL;
2804 t = MACRO_OBJ;
2805 /* '(' must be just after macro definition for MACRO_FUNC */
2806 c = file->buf_ptr[0];
2807 if (c == '\\')
2808 c = handle_stray1(file->buf_ptr);
2809 if (c == '(') {
2810 next_nomacro();
2811 next_nomacro();
2812 ps = &first;
2813 while (tok != ')') {
2814 varg = tok;
2815 next_nomacro();
2816 is_vaargs = 0;
2817 if (varg == TOK_DOTS) {
2818 varg = TOK___VA_ARGS__;
2819 is_vaargs = 1;
2820 } else if (tok == TOK_DOTS && gnu_ext) {
2821 is_vaargs = 1;
2822 next_nomacro();
2824 if (varg < TOK_IDENT)
2825 error("badly punctuated parameter list");
2826 s = sym_push2(&define_stack, varg | SYM_FIELD, is_vaargs, 0);
2827 *ps = s;
2828 ps = &s->next;
2829 if (tok != ',')
2830 break;
2831 next_nomacro();
2833 t = MACRO_FUNC;
2835 tok_str_new(&str);
2836 next_nomacro();
2837 /* EOF testing necessary for '-D' handling */
2838 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2839 tok_str_add2(&str, tok, &tokc);
2840 next_nomacro();
2842 tok_str_add(&str, 0);
2843 #ifdef PP_DEBUG
2844 printf("define %s %d: ", get_tok_str(v, NULL), t);
2845 tok_print(str.str);
2846 #endif
2847 define_push(v, t, str.str, first);
2850 static inline int hash_cached_include(int type, const char *filename)
2852 const unsigned char *s;
2853 unsigned int h;
2855 h = TOK_HASH_INIT;
2856 h = TOK_HASH_FUNC(h, type);
2857 s = filename;
2858 while (*s) {
2859 h = TOK_HASH_FUNC(h, *s);
2860 s++;
2862 h &= (CACHED_INCLUDES_HASH_SIZE - 1);
2863 return h;
2866 /* XXX: use a token or a hash table to accelerate matching ? */
2867 static CachedInclude *search_cached_include(TCCState *s1,
2868 int type, const char *filename)
2870 CachedInclude *e;
2871 int i, h;
2872 h = hash_cached_include(type, filename);
2873 i = s1->cached_includes_hash[h];
2874 for(;;) {
2875 if (i == 0)
2876 break;
2877 e = s1->cached_includes[i - 1];
2878 if (e->type == type && !strcmp(e->filename, filename))
2879 return e;
2880 i = e->hash_next;
2882 return NULL;
2885 static inline void add_cached_include(TCCState *s1, int type,
2886 const char *filename, int ifndef_macro)
2888 CachedInclude *e;
2889 int h;
2891 if (search_cached_include(s1, type, filename))
2892 return;
2893 #ifdef INC_DEBUG
2894 printf("adding cached '%s' %s\n", filename, get_tok_str(ifndef_macro, NULL));
2895 #endif
2896 e = tcc_malloc(sizeof(CachedInclude) + strlen(filename));
2897 if (!e)
2898 return;
2899 e->type = type;
2900 strcpy(e->filename, filename);
2901 e->ifndef_macro = ifndef_macro;
2902 dynarray_add((void ***)&s1->cached_includes, &s1->nb_cached_includes, e);
2903 /* add in hash table */
2904 h = hash_cached_include(type, filename);
2905 e->hash_next = s1->cached_includes_hash[h];
2906 s1->cached_includes_hash[h] = s1->nb_cached_includes;
2909 static void pragma_parse(TCCState *s1)
2911 int val;
2913 next();
2914 if (tok == TOK_pack) {
2916 This may be:
2917 #pragma pack(1) // set
2918 #pragma pack() // reset to default
2919 #pragma pack(push,1) // push & set
2920 #pragma pack(pop) // restore previous
2922 next();
2923 skip('(');
2924 if (tok == TOK_ASM_pop) {
2925 next();
2926 if (s1->pack_stack_ptr <= s1->pack_stack) {
2927 stk_error:
2928 error("out of pack stack");
2930 s1->pack_stack_ptr--;
2931 } else {
2932 val = 0;
2933 if (tok != ')') {
2934 if (tok == TOK_ASM_push) {
2935 next();
2936 if (s1->pack_stack_ptr >= s1->pack_stack + PACK_STACK_SIZE - 1)
2937 goto stk_error;
2938 s1->pack_stack_ptr++;
2939 skip(',');
2941 if (tok != TOK_CINT) {
2942 pack_error:
2943 error("invalid pack pragma");
2945 val = tokc.i;
2946 if (val < 1 || val > 16 || (val & (val - 1)) != 0)
2947 goto pack_error;
2948 next();
2950 *s1->pack_stack_ptr = val;
2951 skip(')');
2956 /* is_bof is true if first non space token at beginning of file */
2957 static void preprocess(int is_bof)
2959 TCCState *s1 = tcc_state;
2960 int size, i, c, n, saved_parse_flags;
2961 char buf[1024], *q;
2962 char buf1[1024];
2963 BufferedFile *f;
2964 Sym *s;
2965 CachedInclude *e;
2967 saved_parse_flags = parse_flags;
2968 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM |
2969 PARSE_FLAG_LINEFEED;
2970 next_nomacro();
2971 redo:
2972 switch(tok) {
2973 case TOK_DEFINE:
2974 next_nomacro();
2975 parse_define();
2976 break;
2977 case TOK_UNDEF:
2978 next_nomacro();
2979 s = define_find(tok);
2980 /* undefine symbol by putting an invalid name */
2981 if (s)
2982 define_undef(s);
2983 break;
2984 case TOK_INCLUDE:
2985 case TOK_INCLUDE_NEXT:
2986 ch = file->buf_ptr[0];
2987 /* XXX: incorrect if comments : use next_nomacro with a special mode */
2988 skip_spaces();
2989 if (ch == '<') {
2990 c = '>';
2991 goto read_name;
2992 } else if (ch == '\"') {
2993 c = ch;
2994 read_name:
2995 inp();
2996 q = buf;
2997 while (ch != c && ch != '\n' && ch != CH_EOF) {
2998 if ((q - buf) < sizeof(buf) - 1)
2999 *q++ = ch;
3000 if (ch == '\\') {
3001 if (handle_stray_noerror() == 0)
3002 --q;
3003 } else
3004 inp();
3006 *q = '\0';
3007 minp();
3008 #if 0
3009 /* eat all spaces and comments after include */
3010 /* XXX: slightly incorrect */
3011 while (ch1 != '\n' && ch1 != CH_EOF)
3012 inp();
3013 #endif
3014 } else {
3015 /* computed #include : either we have only strings or
3016 we have anything enclosed in '<>' */
3017 next();
3018 buf[0] = '\0';
3019 if (tok == TOK_STR) {
3020 while (tok != TOK_LINEFEED) {
3021 if (tok != TOK_STR) {
3022 include_syntax:
3023 error("'#include' expects \"FILENAME\" or <FILENAME>");
3025 pstrcat(buf, sizeof(buf), (char *)tokc.cstr->data);
3026 next();
3028 c = '\"';
3029 } else {
3030 int len;
3031 while (tok != TOK_LINEFEED) {
3032 pstrcat(buf, sizeof(buf), get_tok_str(tok, &tokc));
3033 next();
3035 len = strlen(buf);
3036 /* check syntax and remove '<>' */
3037 if (len < 2 || buf[0] != '<' || buf[len - 1] != '>')
3038 goto include_syntax;
3039 memmove(buf, buf + 1, len - 2);
3040 buf[len - 2] = '\0';
3041 c = '>';
3045 e = search_cached_include(s1, c, buf);
3046 if (e && define_find(e->ifndef_macro)) {
3047 /* no need to parse the include because the 'ifndef macro'
3048 is defined */
3049 #ifdef INC_DEBUG
3050 printf("%s: skipping %s\n", file->filename, buf);
3051 #endif
3052 } else {
3053 if (s1->include_stack_ptr >= s1->include_stack + INCLUDE_STACK_SIZE)
3054 error("#include recursion too deep");
3055 /* push current file in stack */
3056 /* XXX: fix current line init */
3057 *s1->include_stack_ptr++ = file;
3058 if (c == '\"') {
3059 /* first search in current dir if "header.h" */
3060 size = tcc_basename(file->filename) - file->filename;
3061 if (size > sizeof(buf1) - 1)
3062 size = sizeof(buf1) - 1;
3063 memcpy(buf1, file->filename, size);
3064 buf1[size] = '\0';
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 /* now search in all the include paths */
3075 n = s1->nb_include_paths + s1->nb_sysinclude_paths;
3076 for(i = 0; i < n; i++) {
3077 const char *path;
3078 if (i < s1->nb_include_paths)
3079 path = s1->include_paths[i];
3080 else
3081 path = s1->sysinclude_paths[i - s1->nb_include_paths];
3082 pstrcpy(buf1, sizeof(buf1), path);
3083 pstrcat(buf1, sizeof(buf1), "/");
3084 pstrcat(buf1, sizeof(buf1), buf);
3085 f = tcc_open(s1, buf1);
3086 if (f) {
3087 if (tok == TOK_INCLUDE_NEXT)
3088 tok = TOK_INCLUDE;
3089 else
3090 goto found;
3093 --s1->include_stack_ptr;
3094 error("include file '%s' not found", buf);
3095 break;
3096 found:
3097 #ifdef INC_DEBUG
3098 printf("%s: including %s\n", file->filename, buf1);
3099 #endif
3100 f->inc_type = c;
3101 pstrcpy(f->inc_filename, sizeof(f->inc_filename), buf);
3102 file = f;
3103 /* add include file debug info */
3104 if (do_debug) {
3105 put_stabs(file->filename, N_BINCL, 0, 0, 0);
3107 tok_flags |= TOK_FLAG_BOF | TOK_FLAG_BOL;
3108 ch = file->buf_ptr[0];
3109 goto the_end;
3111 break;
3112 case TOK_IFNDEF:
3113 c = 1;
3114 goto do_ifdef;
3115 case TOK_IF:
3116 c = expr_preprocess();
3117 goto do_if;
3118 case TOK_IFDEF:
3119 c = 0;
3120 do_ifdef:
3121 next_nomacro();
3122 if (tok < TOK_IDENT)
3123 error("invalid argument for '#if%sdef'", c ? "n" : "");
3124 if (is_bof) {
3125 if (c) {
3126 #ifdef INC_DEBUG
3127 printf("#ifndef %s\n", get_tok_str(tok, NULL));
3128 #endif
3129 file->ifndef_macro = tok;
3132 c = (define_find(tok) != 0) ^ c;
3133 do_if:
3134 if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE)
3135 error("memory full");
3136 *s1->ifdef_stack_ptr++ = c;
3137 goto test_skip;
3138 case TOK_ELSE:
3139 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
3140 error("#else without matching #if");
3141 if (s1->ifdef_stack_ptr[-1] & 2)
3142 error("#else after #else");
3143 c = (s1->ifdef_stack_ptr[-1] ^= 3);
3144 goto test_skip;
3145 case TOK_ELIF:
3146 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
3147 error("#elif without matching #if");
3148 c = s1->ifdef_stack_ptr[-1];
3149 if (c > 1)
3150 error("#elif after #else");
3151 /* last #if/#elif expression was true: we skip */
3152 if (c == 1)
3153 goto skip;
3154 c = expr_preprocess();
3155 s1->ifdef_stack_ptr[-1] = c;
3156 test_skip:
3157 if (!(c & 1)) {
3158 skip:
3159 preprocess_skip();
3160 is_bof = 0;
3161 goto redo;
3163 break;
3164 case TOK_ENDIF:
3165 if (s1->ifdef_stack_ptr <= file->ifdef_stack_ptr)
3166 error("#endif without matching #if");
3167 s1->ifdef_stack_ptr--;
3168 /* '#ifndef macro' was at the start of file. Now we check if
3169 an '#endif' is exactly at the end of file */
3170 if (file->ifndef_macro &&
3171 s1->ifdef_stack_ptr == file->ifdef_stack_ptr) {
3172 file->ifndef_macro_saved = file->ifndef_macro;
3173 /* need to set to zero to avoid false matches if another
3174 #ifndef at middle of file */
3175 file->ifndef_macro = 0;
3176 while (tok != TOK_LINEFEED)
3177 next_nomacro();
3178 tok_flags |= TOK_FLAG_ENDIF;
3179 goto the_end;
3181 break;
3182 case TOK_LINE:
3183 next();
3184 if (tok != TOK_CINT)
3185 error("#line");
3186 file->line_num = tokc.i - 1; /* the line number will be incremented after */
3187 next();
3188 if (tok != TOK_LINEFEED) {
3189 if (tok != TOK_STR)
3190 error("#line");
3191 pstrcpy(file->filename, sizeof(file->filename),
3192 (char *)tokc.cstr->data);
3194 break;
3195 case TOK_ERROR:
3196 case TOK_WARNING:
3197 c = tok;
3198 ch = file->buf_ptr[0];
3199 skip_spaces();
3200 q = buf;
3201 while (ch != '\n' && ch != CH_EOF) {
3202 if ((q - buf) < sizeof(buf) - 1)
3203 *q++ = ch;
3204 if (ch == '\\') {
3205 if (handle_stray_noerror() == 0)
3206 --q;
3207 } else
3208 inp();
3210 *q = '\0';
3211 if (c == TOK_ERROR)
3212 error("#error %s", buf);
3213 else
3214 warning("#warning %s", buf);
3215 break;
3216 case TOK_PRAGMA:
3217 pragma_parse(s1);
3218 break;
3219 default:
3220 if (tok == TOK_LINEFEED || tok == '!' || tok == TOK_CINT) {
3221 /* '!' is ignored to allow C scripts. numbers are ignored
3222 to emulate cpp behaviour */
3223 } else {
3224 if (!(saved_parse_flags & PARSE_FLAG_ASM_COMMENTS))
3225 warning("Ignoring unknown preprocessing directive #%s", get_tok_str(tok, &tokc));
3227 break;
3229 /* ignore other preprocess commands or #! for C scripts */
3230 while (tok != TOK_LINEFEED)
3231 next_nomacro();
3232 the_end:
3233 parse_flags = saved_parse_flags;
3236 /* evaluate escape codes in a string. */
3237 static void parse_escape_string(CString *outstr, const uint8_t *buf, int is_long)
3239 int c, n;
3240 const uint8_t *p;
3242 p = buf;
3243 for(;;) {
3244 c = *p;
3245 if (c == '\0')
3246 break;
3247 if (c == '\\') {
3248 p++;
3249 /* escape */
3250 c = *p;
3251 switch(c) {
3252 case '0': case '1': case '2': case '3':
3253 case '4': case '5': case '6': case '7':
3254 /* at most three octal digits */
3255 n = c - '0';
3256 p++;
3257 c = *p;
3258 if (isoct(c)) {
3259 n = n * 8 + c - '0';
3260 p++;
3261 c = *p;
3262 if (isoct(c)) {
3263 n = n * 8 + c - '0';
3264 p++;
3267 c = n;
3268 goto add_char_nonext;
3269 case 'x':
3270 case 'u':
3271 case 'U':
3272 p++;
3273 n = 0;
3274 for(;;) {
3275 c = *p;
3276 if (c >= 'a' && c <= 'f')
3277 c = c - 'a' + 10;
3278 else if (c >= 'A' && c <= 'F')
3279 c = c - 'A' + 10;
3280 else if (isnum(c))
3281 c = c - '0';
3282 else
3283 break;
3284 n = n * 16 + c;
3285 p++;
3287 c = n;
3288 goto add_char_nonext;
3289 case 'a':
3290 c = '\a';
3291 break;
3292 case 'b':
3293 c = '\b';
3294 break;
3295 case 'f':
3296 c = '\f';
3297 break;
3298 case 'n':
3299 c = '\n';
3300 break;
3301 case 'r':
3302 c = '\r';
3303 break;
3304 case 't':
3305 c = '\t';
3306 break;
3307 case 'v':
3308 c = '\v';
3309 break;
3310 case 'e':
3311 if (!gnu_ext)
3312 goto invalid_escape;
3313 c = 27;
3314 break;
3315 case '\'':
3316 case '\"':
3317 case '\\':
3318 case '?':
3319 break;
3320 default:
3321 invalid_escape:
3322 if (c >= '!' && c <= '~')
3323 warning("unknown escape sequence: \'\\%c\'", c);
3324 else
3325 warning("unknown escape sequence: \'\\x%x\'", c);
3326 break;
3329 p++;
3330 add_char_nonext:
3331 if (!is_long)
3332 cstr_ccat(outstr, c);
3333 else
3334 cstr_wccat(outstr, c);
3336 /* add a trailing '\0' */
3337 if (!is_long)
3338 cstr_ccat(outstr, '\0');
3339 else
3340 cstr_wccat(outstr, '\0');
3343 /* we use 64 bit numbers */
3344 #define BN_SIZE 2
3346 /* bn = (bn << shift) | or_val */
3347 void bn_lshift(unsigned int *bn, int shift, int or_val)
3349 int i;
3350 unsigned int v;
3351 for(i=0;i<BN_SIZE;i++) {
3352 v = bn[i];
3353 bn[i] = (v << shift) | or_val;
3354 or_val = v >> (32 - shift);
3358 void bn_zero(unsigned int *bn)
3360 int i;
3361 for(i=0;i<BN_SIZE;i++) {
3362 bn[i] = 0;
3366 /* parse number in null terminated string 'p' and return it in the
3367 current token */
3368 void parse_number(const char *p)
3370 int b, t, shift, frac_bits, s, exp_val, ch;
3371 char *q;
3372 unsigned int bn[BN_SIZE];
3373 double d;
3375 /* number */
3376 q = token_buf;
3377 ch = *p++;
3378 t = ch;
3379 ch = *p++;
3380 *q++ = t;
3381 b = 10;
3382 if (t == '.') {
3383 goto float_frac_parse;
3384 } else if (t == '0') {
3385 if (ch == 'x' || ch == 'X') {
3386 q--;
3387 ch = *p++;
3388 b = 16;
3389 } else if (tcc_ext && (ch == 'b' || ch == 'B')) {
3390 q--;
3391 ch = *p++;
3392 b = 2;
3395 /* parse all digits. cannot check octal numbers at this stage
3396 because of floating point constants */
3397 while (1) {
3398 if (ch >= 'a' && ch <= 'f')
3399 t = ch - 'a' + 10;
3400 else if (ch >= 'A' && ch <= 'F')
3401 t = ch - 'A' + 10;
3402 else if (isnum(ch))
3403 t = ch - '0';
3404 else
3405 break;
3406 if (t >= b)
3407 break;
3408 if (q >= token_buf + STRING_MAX_SIZE) {
3409 num_too_long:
3410 error("number too long");
3412 *q++ = ch;
3413 ch = *p++;
3415 if (ch == '.' ||
3416 ((ch == 'e' || ch == 'E') && b == 10) ||
3417 ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
3418 if (b != 10) {
3419 /* NOTE: strtox should support that for hexa numbers, but
3420 non ISOC99 libcs do not support it, so we prefer to do
3421 it by hand */
3422 /* hexadecimal or binary floats */
3423 /* XXX: handle overflows */
3424 *q = '\0';
3425 if (b == 16)
3426 shift = 4;
3427 else
3428 shift = 2;
3429 bn_zero(bn);
3430 q = token_buf;
3431 while (1) {
3432 t = *q++;
3433 if (t == '\0') {
3434 break;
3435 } else if (t >= 'a') {
3436 t = t - 'a' + 10;
3437 } else if (t >= 'A') {
3438 t = t - 'A' + 10;
3439 } else {
3440 t = t - '0';
3442 bn_lshift(bn, shift, t);
3444 frac_bits = 0;
3445 if (ch == '.') {
3446 ch = *p++;
3447 while (1) {
3448 t = ch;
3449 if (t >= 'a' && t <= 'f') {
3450 t = t - 'a' + 10;
3451 } else if (t >= 'A' && t <= 'F') {
3452 t = t - 'A' + 10;
3453 } else if (t >= '0' && t <= '9') {
3454 t = t - '0';
3455 } else {
3456 break;
3458 if (t >= b)
3459 error("invalid digit");
3460 bn_lshift(bn, shift, t);
3461 frac_bits += shift;
3462 ch = *p++;
3465 if (ch != 'p' && ch != 'P')
3466 expect("exponent");
3467 ch = *p++;
3468 s = 1;
3469 exp_val = 0;
3470 if (ch == '+') {
3471 ch = *p++;
3472 } else if (ch == '-') {
3473 s = -1;
3474 ch = *p++;
3476 if (ch < '0' || ch > '9')
3477 expect("exponent digits");
3478 while (ch >= '0' && ch <= '9') {
3479 exp_val = exp_val * 10 + ch - '0';
3480 ch = *p++;
3482 exp_val = exp_val * s;
3484 /* now we can generate the number */
3485 /* XXX: should patch directly float number */
3486 d = (double)bn[1] * 4294967296.0 + (double)bn[0];
3487 d = ldexp(d, exp_val - frac_bits);
3488 t = toup(ch);
3489 if (t == 'F') {
3490 ch = *p++;
3491 tok = TOK_CFLOAT;
3492 /* float : should handle overflow */
3493 tokc.f = (float)d;
3494 } else if (t == 'L') {
3495 ch = *p++;
3496 tok = TOK_CLDOUBLE;
3497 /* XXX: not large enough */
3498 tokc.ld = (long double)d;
3499 } else {
3500 tok = TOK_CDOUBLE;
3501 tokc.d = d;
3503 } else {
3504 /* decimal floats */
3505 if (ch == '.') {
3506 if (q >= token_buf + STRING_MAX_SIZE)
3507 goto num_too_long;
3508 *q++ = ch;
3509 ch = *p++;
3510 float_frac_parse:
3511 while (ch >= '0' && ch <= '9') {
3512 if (q >= token_buf + STRING_MAX_SIZE)
3513 goto num_too_long;
3514 *q++ = ch;
3515 ch = *p++;
3518 if (ch == 'e' || ch == 'E') {
3519 if (q >= token_buf + STRING_MAX_SIZE)
3520 goto num_too_long;
3521 *q++ = ch;
3522 ch = *p++;
3523 if (ch == '-' || ch == '+') {
3524 if (q >= token_buf + STRING_MAX_SIZE)
3525 goto num_too_long;
3526 *q++ = ch;
3527 ch = *p++;
3529 if (ch < '0' || ch > '9')
3530 expect("exponent digits");
3531 while (ch >= '0' && ch <= '9') {
3532 if (q >= token_buf + STRING_MAX_SIZE)
3533 goto num_too_long;
3534 *q++ = ch;
3535 ch = *p++;
3538 *q = '\0';
3539 t = toup(ch);
3540 errno = 0;
3541 if (t == 'F') {
3542 ch = *p++;
3543 tok = TOK_CFLOAT;
3544 tokc.f = strtof(token_buf, NULL);
3545 } else if (t == 'L') {
3546 ch = *p++;
3547 tok = TOK_CLDOUBLE;
3548 tokc.ld = strtold(token_buf, NULL);
3549 } else {
3550 tok = TOK_CDOUBLE;
3551 tokc.d = strtod(token_buf, NULL);
3554 } else {
3555 unsigned long long n, n1;
3556 int lcount, ucount;
3558 /* integer number */
3559 *q = '\0';
3560 q = token_buf;
3561 if (b == 10 && *q == '0') {
3562 b = 8;
3563 q++;
3565 n = 0;
3566 while(1) {
3567 t = *q++;
3568 /* no need for checks except for base 10 / 8 errors */
3569 if (t == '\0') {
3570 break;
3571 } else if (t >= 'a') {
3572 t = t - 'a' + 10;
3573 } else if (t >= 'A') {
3574 t = t - 'A' + 10;
3575 } else {
3576 t = t - '0';
3577 if (t >= b)
3578 error("invalid digit");
3580 n1 = n;
3581 n = n * b + t;
3582 /* detect overflow */
3583 /* XXX: this test is not reliable */
3584 if (n < n1)
3585 error("integer constant overflow");
3588 /* XXX: not exactly ANSI compliant */
3589 if ((n & 0xffffffff00000000LL) != 0) {
3590 if ((n >> 63) != 0)
3591 tok = TOK_CULLONG;
3592 else
3593 tok = TOK_CLLONG;
3594 } else if (n > 0x7fffffff) {
3595 tok = TOK_CUINT;
3596 } else {
3597 tok = TOK_CINT;
3599 lcount = 0;
3600 ucount = 0;
3601 for(;;) {
3602 t = toup(ch);
3603 if (t == 'L') {
3604 if (lcount >= 2)
3605 error("three 'l's in integer constant");
3606 lcount++;
3607 if (lcount == 2) {
3608 if (tok == TOK_CINT)
3609 tok = TOK_CLLONG;
3610 else if (tok == TOK_CUINT)
3611 tok = TOK_CULLONG;
3613 ch = *p++;
3614 } else if (t == 'U') {
3615 if (ucount >= 1)
3616 error("two 'u's in integer constant");
3617 ucount++;
3618 if (tok == TOK_CINT)
3619 tok = TOK_CUINT;
3620 else if (tok == TOK_CLLONG)
3621 tok = TOK_CULLONG;
3622 ch = *p++;
3623 } else {
3624 break;
3627 if (tok == TOK_CINT || tok == TOK_CUINT)
3628 tokc.ui = n;
3629 else
3630 tokc.ull = n;
3635 #define PARSE2(c1, tok1, c2, tok2) \
3636 case c1: \
3637 PEEKC(c, p); \
3638 if (c == c2) { \
3639 p++; \
3640 tok = tok2; \
3641 } else { \
3642 tok = tok1; \
3644 break;
3646 /* return next token without macro substitution */
3647 static inline void next_nomacro1(void)
3649 int t, c, is_long;
3650 TokenSym *ts;
3651 uint8_t *p, *p1;
3652 unsigned int h;
3654 p = file->buf_ptr;
3655 redo_no_start:
3656 c = *p;
3657 switch(c) {
3658 case ' ':
3659 case '\t':
3660 case '\f':
3661 case '\v':
3662 case '\r':
3663 p++;
3664 goto redo_no_start;
3666 case '\\':
3667 /* first look if it is in fact an end of buffer */
3668 if (p >= file->buf_end) {
3669 file->buf_ptr = p;
3670 handle_eob();
3671 p = file->buf_ptr;
3672 if (p >= file->buf_end)
3673 goto parse_eof;
3674 else
3675 goto redo_no_start;
3676 } else {
3677 file->buf_ptr = p;
3678 ch = *p;
3679 handle_stray();
3680 p = file->buf_ptr;
3681 goto redo_no_start;
3683 parse_eof:
3685 TCCState *s1 = tcc_state;
3686 if ((parse_flags & PARSE_FLAG_LINEFEED)
3687 && !(tok_flags & TOK_FLAG_EOF)) {
3688 tok_flags |= TOK_FLAG_EOF;
3689 tok = TOK_LINEFEED;
3690 goto keep_tok_flags;
3691 } else if (s1->include_stack_ptr == s1->include_stack ||
3692 !(parse_flags & PARSE_FLAG_PREPROCESS)) {
3693 /* no include left : end of file. */
3694 tok = TOK_EOF;
3695 } else {
3696 tok_flags &= ~TOK_FLAG_EOF;
3697 /* pop include file */
3699 /* test if previous '#endif' was after a #ifdef at
3700 start of file */
3701 if (tok_flags & TOK_FLAG_ENDIF) {
3702 #ifdef INC_DEBUG
3703 printf("#endif %s\n", get_tok_str(file->ifndef_macro_saved, NULL));
3704 #endif
3705 add_cached_include(s1, file->inc_type, file->inc_filename,
3706 file->ifndef_macro_saved);
3709 /* add end of include file debug info */
3710 if (do_debug) {
3711 put_stabd(N_EINCL, 0, 0);
3713 /* pop include stack */
3714 tcc_close(file);
3715 s1->include_stack_ptr--;
3716 file = *s1->include_stack_ptr;
3717 p = file->buf_ptr;
3718 goto redo_no_start;
3721 break;
3723 case '\n':
3724 file->line_num++;
3725 tok_flags |= TOK_FLAG_BOL;
3726 p++;
3727 if (0 == (parse_flags & PARSE_FLAG_LINEFEED))
3728 goto redo_no_start;
3729 tok = TOK_LINEFEED;
3730 goto keep_tok_flags;
3732 case '#':
3733 /* XXX: simplify */
3734 PEEKC(c, p);
3735 if ((tok_flags & TOK_FLAG_BOL) &&
3736 (parse_flags & PARSE_FLAG_PREPROCESS)) {
3737 file->buf_ptr = p;
3738 preprocess(tok_flags & TOK_FLAG_BOF);
3739 p = file->buf_ptr;
3740 goto redo_no_start;
3741 } else {
3742 if (c == '#') {
3743 p++;
3744 tok = TOK_TWOSHARPS;
3745 } else {
3746 if (parse_flags & PARSE_FLAG_ASM_COMMENTS) {
3747 p = parse_line_comment(p - 1);
3748 goto redo_no_start;
3749 } else {
3750 tok = '#';
3754 break;
3756 case 'a': case 'b': case 'c': case 'd':
3757 case 'e': case 'f': case 'g': case 'h':
3758 case 'i': case 'j': case 'k': case 'l':
3759 case 'm': case 'n': case 'o': case 'p':
3760 case 'q': case 'r': case 's': case 't':
3761 case 'u': case 'v': case 'w': case 'x':
3762 case 'y': case 'z':
3763 case 'A': case 'B': case 'C': case 'D':
3764 case 'E': case 'F': case 'G': case 'H':
3765 case 'I': case 'J': case 'K':
3766 case 'M': case 'N': case 'O': case 'P':
3767 case 'Q': case 'R': case 'S': case 'T':
3768 case 'U': case 'V': case 'W': case 'X':
3769 case 'Y': case 'Z':
3770 case '_':
3771 parse_ident_fast:
3772 p1 = p;
3773 h = TOK_HASH_INIT;
3774 h = TOK_HASH_FUNC(h, c);
3775 p++;
3776 for(;;) {
3777 c = *p;
3778 if (!isidnum_table[c-CH_EOF])
3779 break;
3780 h = TOK_HASH_FUNC(h, c);
3781 p++;
3783 if (c != '\\') {
3784 TokenSym **pts;
3785 int len;
3787 /* fast case : no stray found, so we have the full token
3788 and we have already hashed it */
3789 len = p - p1;
3790 h &= (TOK_HASH_SIZE - 1);
3791 pts = &hash_ident[h];
3792 for(;;) {
3793 ts = *pts;
3794 if (!ts)
3795 break;
3796 if (ts->len == len && !memcmp(ts->str, p1, len))
3797 goto token_found;
3798 pts = &(ts->hash_next);
3800 ts = tok_alloc_new(pts, p1, len);
3801 token_found: ;
3802 } else {
3803 /* slower case */
3804 cstr_reset(&tokcstr);
3806 while (p1 < p) {
3807 cstr_ccat(&tokcstr, *p1);
3808 p1++;
3810 p--;
3811 PEEKC(c, p);
3812 parse_ident_slow:
3813 while (isidnum_table[c-CH_EOF]) {
3814 cstr_ccat(&tokcstr, c);
3815 PEEKC(c, p);
3817 ts = tok_alloc(tokcstr.data, tokcstr.size);
3819 tok = ts->tok;
3820 break;
3821 case 'L':
3822 t = p[1];
3823 if (t != '\\' && t != '\'' && t != '\"') {
3824 /* fast case */
3825 goto parse_ident_fast;
3826 } else {
3827 PEEKC(c, p);
3828 if (c == '\'' || c == '\"') {
3829 is_long = 1;
3830 goto str_const;
3831 } else {
3832 cstr_reset(&tokcstr);
3833 cstr_ccat(&tokcstr, 'L');
3834 goto parse_ident_slow;
3837 break;
3838 case '0': case '1': case '2': case '3':
3839 case '4': case '5': case '6': case '7':
3840 case '8': case '9':
3842 cstr_reset(&tokcstr);
3843 /* after the first digit, accept digits, alpha, '.' or sign if
3844 prefixed by 'eEpP' */
3845 parse_num:
3846 for(;;) {
3847 t = c;
3848 cstr_ccat(&tokcstr, c);
3849 PEEKC(c, p);
3850 if (!(isnum(c) || isid(c) || c == '.' ||
3851 ((c == '+' || c == '-') &&
3852 (t == 'e' || t == 'E' || t == 'p' || t == 'P'))))
3853 break;
3855 /* We add a trailing '\0' to ease parsing */
3856 cstr_ccat(&tokcstr, '\0');
3857 tokc.cstr = &tokcstr;
3858 tok = TOK_PPNUM;
3859 break;
3860 case '.':
3861 /* special dot handling because it can also start a number */
3862 PEEKC(c, p);
3863 if (isnum(c)) {
3864 cstr_reset(&tokcstr);
3865 cstr_ccat(&tokcstr, '.');
3866 goto parse_num;
3867 } else if (c == '.') {
3868 PEEKC(c, p);
3869 if (c != '.')
3870 expect("'.'");
3871 PEEKC(c, p);
3872 tok = TOK_DOTS;
3873 } else {
3874 tok = '.';
3876 break;
3877 case '\'':
3878 case '\"':
3879 is_long = 0;
3880 str_const:
3882 CString str;
3883 int sep;
3885 sep = c;
3887 /* parse the string */
3888 cstr_new(&str);
3889 p = parse_pp_string(p, sep, &str);
3890 cstr_ccat(&str, '\0');
3892 /* eval the escape (should be done as TOK_PPNUM) */
3893 cstr_reset(&tokcstr);
3894 parse_escape_string(&tokcstr, str.data, is_long);
3895 cstr_free(&str);
3897 if (sep == '\'') {
3898 int char_size;
3899 /* XXX: make it portable */
3900 if (!is_long)
3901 char_size = 1;
3902 else
3903 char_size = sizeof(nwchar_t);
3904 if (tokcstr.size <= char_size)
3905 error("empty character constant");
3906 if (tokcstr.size > 2 * char_size)
3907 warning("multi-character character constant");
3908 if (!is_long) {
3909 tokc.i = *(int8_t *)tokcstr.data;
3910 tok = TOK_CCHAR;
3911 } else {
3912 tokc.i = *(nwchar_t *)tokcstr.data;
3913 tok = TOK_LCHAR;
3915 } else {
3916 tokc.cstr = &tokcstr;
3917 if (!is_long)
3918 tok = TOK_STR;
3919 else
3920 tok = TOK_LSTR;
3923 break;
3925 case '<':
3926 PEEKC(c, p);
3927 if (c == '=') {
3928 p++;
3929 tok = TOK_LE;
3930 } else if (c == '<') {
3931 PEEKC(c, p);
3932 if (c == '=') {
3933 p++;
3934 tok = TOK_A_SHL;
3935 } else {
3936 tok = TOK_SHL;
3938 } else {
3939 tok = TOK_LT;
3941 break;
3943 case '>':
3944 PEEKC(c, p);
3945 if (c == '=') {
3946 p++;
3947 tok = TOK_GE;
3948 } else if (c == '>') {
3949 PEEKC(c, p);
3950 if (c == '=') {
3951 p++;
3952 tok = TOK_A_SAR;
3953 } else {
3954 tok = TOK_SAR;
3956 } else {
3957 tok = TOK_GT;
3959 break;
3961 case '&':
3962 PEEKC(c, p);
3963 if (c == '&') {
3964 p++;
3965 tok = TOK_LAND;
3966 } else if (c == '=') {
3967 p++;
3968 tok = TOK_A_AND;
3969 } else {
3970 tok = '&';
3972 break;
3974 case '|':
3975 PEEKC(c, p);
3976 if (c == '|') {
3977 p++;
3978 tok = TOK_LOR;
3979 } else if (c == '=') {
3980 p++;
3981 tok = TOK_A_OR;
3982 } else {
3983 tok = '|';
3985 break;
3987 case '+':
3988 PEEKC(c, p);
3989 if (c == '+') {
3990 p++;
3991 tok = TOK_INC;
3992 } else if (c == '=') {
3993 p++;
3994 tok = TOK_A_ADD;
3995 } else {
3996 tok = '+';
3998 break;
4000 case '-':
4001 PEEKC(c, p);
4002 if (c == '-') {
4003 p++;
4004 tok = TOK_DEC;
4005 } else if (c == '=') {
4006 p++;
4007 tok = TOK_A_SUB;
4008 } else if (c == '>') {
4009 p++;
4010 tok = TOK_ARROW;
4011 } else {
4012 tok = '-';
4014 break;
4016 PARSE2('!', '!', '=', TOK_NE)
4017 PARSE2('=', '=', '=', TOK_EQ)
4018 PARSE2('*', '*', '=', TOK_A_MUL)
4019 PARSE2('%', '%', '=', TOK_A_MOD)
4020 PARSE2('^', '^', '=', TOK_A_XOR)
4022 /* comments or operator */
4023 case '/':
4024 PEEKC(c, p);
4025 if (c == '*') {
4026 p = parse_comment(p);
4027 goto redo_no_start;
4028 } else if (c == '/') {
4029 p = parse_line_comment(p);
4030 goto redo_no_start;
4031 } else if (c == '=') {
4032 p++;
4033 tok = TOK_A_DIV;
4034 } else {
4035 tok = '/';
4037 break;
4039 /* simple tokens */
4040 case '(':
4041 case ')':
4042 case '[':
4043 case ']':
4044 case '{':
4045 case '}':
4046 case ',':
4047 case ';':
4048 case ':':
4049 case '?':
4050 case '~':
4051 case '$': /* only used in assembler */
4052 case '@': /* dito */
4053 tok = c;
4054 p++;
4055 break;
4056 default:
4057 error("unrecognized character \\x%02x", c);
4058 break;
4060 tok_flags = 0;
4061 keep_tok_flags:
4062 file->buf_ptr = p;
4063 #if defined(PARSE_DEBUG)
4064 printf("token = %s\n", get_tok_str(tok, &tokc));
4065 #endif
4068 /* return next token without macro substitution. Can read input from
4069 macro_ptr buffer */
4070 static void next_nomacro(void)
4072 if (macro_ptr) {
4073 redo:
4074 tok = *macro_ptr;
4075 if (tok) {
4076 TOK_GET(tok, macro_ptr, tokc);
4077 if (tok == TOK_LINENUM) {
4078 file->line_num = tokc.i;
4079 goto redo;
4082 } else {
4083 next_nomacro1();
4087 /* substitute args in macro_str and return allocated string */
4088 static int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
4090 int *st, last_tok, t, notfirst;
4091 Sym *s;
4092 CValue cval;
4093 TokenString str;
4094 CString cstr;
4096 tok_str_new(&str);
4097 last_tok = 0;
4098 while(1) {
4099 TOK_GET(t, macro_str, cval);
4100 if (!t)
4101 break;
4102 if (t == '#') {
4103 /* stringize */
4104 TOK_GET(t, macro_str, cval);
4105 if (!t)
4106 break;
4107 s = sym_find2(args, t);
4108 if (s) {
4109 cstr_new(&cstr);
4110 st = (int *)s->c;
4111 notfirst = 0;
4112 while (*st) {
4113 if (notfirst)
4114 cstr_ccat(&cstr, ' ');
4115 TOK_GET(t, st, cval);
4116 cstr_cat(&cstr, get_tok_str(t, &cval));
4117 #ifndef PP_NOSPACES
4118 notfirst = 1;
4119 #endif
4121 cstr_ccat(&cstr, '\0');
4122 #ifdef PP_DEBUG
4123 printf("stringize: %s\n", (char *)cstr.data);
4124 #endif
4125 /* add string */
4126 cval.cstr = &cstr;
4127 tok_str_add2(&str, TOK_STR, &cval);
4128 cstr_free(&cstr);
4129 } else {
4130 tok_str_add2(&str, t, &cval);
4132 } else if (t >= TOK_IDENT) {
4133 s = sym_find2(args, t);
4134 if (s) {
4135 st = (int *)s->c;
4136 /* if '##' is present before or after, no arg substitution */
4137 if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) {
4138 /* special case for var arg macros : ## eats the
4139 ',' if empty VA_ARGS variable. */
4140 /* XXX: test of the ',' is not 100%
4141 reliable. should fix it to avoid security
4142 problems */
4143 if (gnu_ext && s->type.t &&
4144 last_tok == TOK_TWOSHARPS &&
4145 str.len >= 2 && str.str[str.len - 2] == ',') {
4146 if (*st == 0) {
4147 /* suppress ',' '##' */
4148 str.len -= 2;
4149 } else {
4150 /* suppress '##' and add variable */
4151 str.len--;
4152 goto add_var;
4154 } else {
4155 int t1;
4156 add_var:
4157 for(;;) {
4158 TOK_GET(t1, st, cval);
4159 if (!t1)
4160 break;
4161 tok_str_add2(&str, t1, &cval);
4164 } else {
4165 /* NOTE: the stream cannot be read when macro
4166 substituing an argument */
4167 macro_subst(&str, nested_list, st, NULL);
4169 } else {
4170 tok_str_add(&str, t);
4172 } else {
4173 tok_str_add2(&str, t, &cval);
4175 last_tok = t;
4177 tok_str_add(&str, 0);
4178 return str.str;
4181 static char const ab_month_name[12][4] =
4183 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
4184 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
4187 /* do macro substitution of current token with macro 's' and add
4188 result to (tok_str,tok_len). 'nested_list' is the list of all
4189 macros we got inside to avoid recursing. Return non zero if no
4190 substitution needs to be done */
4191 static int macro_subst_tok(TokenString *tok_str,
4192 Sym **nested_list, Sym *s, struct macro_level **can_read_stream)
4194 Sym *args, *sa, *sa1;
4195 int mstr_allocated, parlevel, *mstr, t, t1;
4196 TokenString str;
4197 char *cstrval;
4198 CValue cval;
4199 CString cstr;
4200 char buf[32];
4202 /* if symbol is a macro, prepare substitution */
4203 /* special macros */
4204 if (tok == TOK___LINE__) {
4205 snprintf(buf, sizeof(buf), "%d", file->line_num);
4206 cstrval = buf;
4207 t1 = TOK_PPNUM;
4208 goto add_cstr1;
4209 } else if (tok == TOK___FILE__) {
4210 cstrval = file->filename;
4211 goto add_cstr;
4212 } else if (tok == TOK___DATE__ || tok == TOK___TIME__) {
4213 time_t ti;
4214 struct tm *tm;
4216 time(&ti);
4217 tm = localtime(&ti);
4218 if (tok == TOK___DATE__) {
4219 snprintf(buf, sizeof(buf), "%s %2d %d",
4220 ab_month_name[tm->tm_mon], tm->tm_mday, tm->tm_year + 1900);
4221 } else {
4222 snprintf(buf, sizeof(buf), "%02d:%02d:%02d",
4223 tm->tm_hour, tm->tm_min, tm->tm_sec);
4225 cstrval = buf;
4226 add_cstr:
4227 t1 = TOK_STR;
4228 add_cstr1:
4229 cstr_new(&cstr);
4230 cstr_cat(&cstr, cstrval);
4231 cstr_ccat(&cstr, '\0');
4232 cval.cstr = &cstr;
4233 tok_str_add2(tok_str, t1, &cval);
4234 cstr_free(&cstr);
4235 } else {
4236 mstr = (int *)s->c;
4237 mstr_allocated = 0;
4238 if (s->type.t == MACRO_FUNC) {
4239 /* NOTE: we do not use next_nomacro to avoid eating the
4240 next token. XXX: find better solution */
4241 redo:
4242 if (macro_ptr) {
4243 t = *macro_ptr;
4244 if (t == 0 && can_read_stream) {
4245 /* end of macro stream: we must look at the token
4246 after in the file */
4247 struct macro_level *ml = *can_read_stream;
4248 macro_ptr = NULL;
4249 if (ml)
4251 macro_ptr = ml->p;
4252 ml->p = NULL;
4253 *can_read_stream = ml -> prev;
4255 goto redo;
4257 } else {
4258 /* XXX: incorrect with comments */
4259 ch = file->buf_ptr[0];
4260 while (is_space(ch) || ch == '\n')
4261 cinp();
4262 t = ch;
4264 if (t != '(') /* no macro subst */
4265 return -1;
4267 /* argument macro */
4268 next_nomacro();
4269 next_nomacro();
4270 args = NULL;
4271 sa = s->next;
4272 /* NOTE: empty args are allowed, except if no args */
4273 for(;;) {
4274 /* handle '()' case */
4275 if (!args && !sa && tok == ')')
4276 break;
4277 if (!sa)
4278 error("macro '%s' used with too many args",
4279 get_tok_str(s->v, 0));
4280 tok_str_new(&str);
4281 parlevel = 0;
4282 /* NOTE: non zero sa->t indicates VA_ARGS */
4283 while ((parlevel > 0 ||
4284 (tok != ')' &&
4285 (tok != ',' || sa->type.t))) &&
4286 tok != -1) {
4287 if (tok == '(')
4288 parlevel++;
4289 else if (tok == ')')
4290 parlevel--;
4291 if (tok != TOK_LINEFEED)
4292 tok_str_add2(&str, tok, &tokc);
4293 next_nomacro();
4295 tok_str_add(&str, 0);
4296 sym_push2(&args, sa->v & ~SYM_FIELD, sa->type.t, (int)str.str);
4297 sa = sa->next;
4298 if (tok == ')') {
4299 /* special case for gcc var args: add an empty
4300 var arg argument if it is omitted */
4301 if (sa && sa->type.t && gnu_ext)
4302 continue;
4303 else
4304 break;
4306 if (tok != ',')
4307 expect(",");
4308 next_nomacro();
4310 if (sa) {
4311 error("macro '%s' used with too few args",
4312 get_tok_str(s->v, 0));
4315 /* now subst each arg */
4316 mstr = macro_arg_subst(nested_list, mstr, args);
4317 /* free memory */
4318 sa = args;
4319 while (sa) {
4320 sa1 = sa->prev;
4321 tok_str_free((int *)sa->c);
4322 sym_free(sa);
4323 sa = sa1;
4325 mstr_allocated = 1;
4327 sym_push2(nested_list, s->v, 0, 0);
4328 macro_subst(tok_str, nested_list, mstr, can_read_stream);
4329 /* pop nested defined symbol */
4330 sa1 = *nested_list;
4331 *nested_list = sa1->prev;
4332 sym_free(sa1);
4333 if (mstr_allocated)
4334 tok_str_free(mstr);
4336 return 0;
4339 /* handle the '##' operator. Return NULL if no '##' seen. Otherwise
4340 return the resulting string (which must be freed). */
4341 static inline int *macro_twosharps(const int *macro_str)
4343 TokenSym *ts;
4344 const int *macro_ptr1, *start_macro_ptr, *ptr, *saved_macro_ptr;
4345 int t;
4346 const char *p1, *p2;
4347 CValue cval;
4348 TokenString macro_str1;
4349 CString cstr;
4351 start_macro_ptr = macro_str;
4352 /* we search the first '##' */
4353 for(;;) {
4354 macro_ptr1 = macro_str;
4355 TOK_GET(t, macro_str, cval);
4356 /* nothing more to do if end of string */
4357 if (t == 0)
4358 return NULL;
4359 if (*macro_str == TOK_TWOSHARPS)
4360 break;
4363 /* we saw '##', so we need more processing to handle it */
4364 cstr_new(&cstr);
4365 tok_str_new(&macro_str1);
4366 tok = t;
4367 tokc = cval;
4369 /* add all tokens seen so far */
4370 for(ptr = start_macro_ptr; ptr < macro_ptr1;) {
4371 TOK_GET(t, ptr, cval);
4372 tok_str_add2(&macro_str1, t, &cval);
4374 saved_macro_ptr = macro_ptr;
4375 /* XXX: get rid of the use of macro_ptr here */
4376 macro_ptr = (int *)macro_str;
4377 for(;;) {
4378 while (*macro_ptr == TOK_TWOSHARPS) {
4379 macro_ptr++;
4380 macro_ptr1 = macro_ptr;
4381 t = *macro_ptr;
4382 if (t) {
4383 TOK_GET(t, macro_ptr, cval);
4384 /* We concatenate the two tokens if we have an
4385 identifier or a preprocessing number */
4386 cstr_reset(&cstr);
4387 p1 = get_tok_str(tok, &tokc);
4388 cstr_cat(&cstr, p1);
4389 p2 = get_tok_str(t, &cval);
4390 cstr_cat(&cstr, p2);
4391 cstr_ccat(&cstr, '\0');
4393 if ((tok >= TOK_IDENT || tok == TOK_PPNUM) &&
4394 (t >= TOK_IDENT || t == TOK_PPNUM)) {
4395 if (tok == TOK_PPNUM) {
4396 /* if number, then create a number token */
4397 /* NOTE: no need to allocate because
4398 tok_str_add2() does it */
4399 cstr_reset(&tokcstr);
4400 tokcstr = cstr;
4401 cstr_new(&cstr);
4402 tokc.cstr = &tokcstr;
4403 } else {
4404 /* if identifier, we must do a test to
4405 validate we have a correct identifier */
4406 if (t == TOK_PPNUM) {
4407 const char *p;
4408 int c;
4410 p = p2;
4411 for(;;) {
4412 c = *p;
4413 if (c == '\0')
4414 break;
4415 p++;
4416 if (!isnum(c) && !isid(c))
4417 goto error_pasting;
4420 ts = tok_alloc(cstr.data, strlen(cstr.data));
4421 tok = ts->tok; /* modify current token */
4423 } else {
4424 const char *str = cstr.data;
4425 const unsigned char *q;
4427 /* we look for a valid token */
4428 /* XXX: do more extensive checks */
4429 if (!strcmp(str, ">>=")) {
4430 tok = TOK_A_SAR;
4431 } else if (!strcmp(str, "<<=")) {
4432 tok = TOK_A_SHL;
4433 } else if (strlen(str) == 2) {
4434 /* search in two bytes table */
4435 q = tok_two_chars;
4436 for(;;) {
4437 if (!*q)
4438 goto error_pasting;
4439 if (q[0] == str[0] && q[1] == str[1])
4440 break;
4441 q += 3;
4443 tok = q[2];
4444 } else {
4445 error_pasting:
4446 /* NOTE: because get_tok_str use a static buffer,
4447 we must save it */
4448 cstr_reset(&cstr);
4449 p1 = get_tok_str(tok, &tokc);
4450 cstr_cat(&cstr, p1);
4451 cstr_ccat(&cstr, '\0');
4452 p2 = get_tok_str(t, &cval);
4453 warning("pasting \"%s\" and \"%s\" does not give a valid preprocessing token", cstr.data, p2);
4454 /* cannot merge tokens: just add them separately */
4455 tok_str_add2(&macro_str1, tok, &tokc);
4456 /* XXX: free associated memory ? */
4457 tok = t;
4458 tokc = cval;
4463 tok_str_add2(&macro_str1, tok, &tokc);
4464 next_nomacro();
4465 if (tok == 0)
4466 break;
4468 macro_ptr = (int *)saved_macro_ptr;
4469 cstr_free(&cstr);
4470 tok_str_add(&macro_str1, 0);
4471 return macro_str1.str;
4475 /* do macro substitution of macro_str and add result to
4476 (tok_str,tok_len). 'nested_list' is the list of all macros we got
4477 inside to avoid recursing. */
4478 static void macro_subst(TokenString *tok_str, Sym **nested_list,
4479 const int *macro_str, struct macro_level ** can_read_stream)
4481 Sym *s;
4482 int *macro_str1;
4483 const int *ptr;
4484 int t, ret;
4485 CValue cval;
4486 struct macro_level ml;
4488 /* first scan for '##' operator handling */
4489 ptr = macro_str;
4490 macro_str1 = macro_twosharps(ptr);
4491 if (macro_str1)
4492 ptr = macro_str1;
4493 while (1) {
4494 /* NOTE: ptr == NULL can only happen if tokens are read from
4495 file stream due to a macro function call */
4496 if (ptr == NULL)
4497 break;
4498 TOK_GET(t, ptr, cval);
4499 if (t == 0)
4500 break;
4501 s = define_find(t);
4502 if (s != NULL) {
4503 /* if nested substitution, do nothing */
4504 if (sym_find2(*nested_list, t))
4505 goto no_subst;
4506 ml.p = macro_ptr;
4507 if (can_read_stream)
4508 ml.prev = *can_read_stream, *can_read_stream = &ml;
4509 macro_ptr = (int *)ptr;
4510 tok = t;
4511 ret = macro_subst_tok(tok_str, nested_list, s, can_read_stream);
4512 ptr = (int *)macro_ptr;
4513 macro_ptr = ml.p;
4514 if (can_read_stream && *can_read_stream == &ml)
4515 *can_read_stream = ml.prev;
4516 if (ret != 0)
4517 goto no_subst;
4518 } else {
4519 no_subst:
4520 tok_str_add2(tok_str, t, &cval);
4523 if (macro_str1)
4524 tok_str_free(macro_str1);
4527 /* return next token with macro substitution */
4528 static void next(void)
4530 Sym *nested_list, *s;
4531 TokenString str;
4532 struct macro_level *ml;
4534 redo:
4535 next_nomacro();
4536 if (!macro_ptr) {
4537 /* if not reading from macro substituted string, then try
4538 to substitute macros */
4539 if (tok >= TOK_IDENT &&
4540 (parse_flags & PARSE_FLAG_PREPROCESS)) {
4541 s = define_find(tok);
4542 if (s) {
4543 /* we have a macro: we try to substitute */
4544 tok_str_new(&str);
4545 nested_list = NULL;
4546 ml = NULL;
4547 if (macro_subst_tok(&str, &nested_list, s, &ml) == 0) {
4548 /* substitution done, NOTE: maybe empty */
4549 tok_str_add(&str, 0);
4550 macro_ptr = str.str;
4551 macro_ptr_allocated = str.str;
4552 goto redo;
4556 } else {
4557 if (tok == 0) {
4558 /* end of macro or end of unget buffer */
4559 if (unget_buffer_enabled) {
4560 macro_ptr = unget_saved_macro_ptr;
4561 unget_buffer_enabled = 0;
4562 } else {
4563 /* end of macro string: free it */
4564 tok_str_free(macro_ptr_allocated);
4565 macro_ptr = NULL;
4567 goto redo;
4571 /* convert preprocessor tokens into C tokens */
4572 if (tok == TOK_PPNUM &&
4573 (parse_flags & PARSE_FLAG_TOK_NUM)) {
4574 parse_number((char *)tokc.cstr->data);
4578 /* push back current token and set current token to 'last_tok'. Only
4579 identifier case handled for labels. */
4580 static inline void unget_tok(int last_tok)
4582 int i, n;
4583 int *q;
4584 unget_saved_macro_ptr = macro_ptr;
4585 unget_buffer_enabled = 1;
4586 q = unget_saved_buffer;
4587 macro_ptr = q;
4588 *q++ = tok;
4589 n = tok_ext_size(tok) - 1;
4590 for(i=0;i<n;i++)
4591 *q++ = tokc.tab[i];
4592 *q = 0; /* end of token string */
4593 tok = last_tok;
4597 void swap(int *p, int *q)
4599 int t;
4600 t = *p;
4601 *p = *q;
4602 *q = t;
4605 void vsetc(CType *type, int r, CValue *vc)
4607 int v;
4609 if (vtop >= vstack + (VSTACK_SIZE - 1))
4610 error("memory full");
4611 /* cannot let cpu flags if other instruction are generated. Also
4612 avoid leaving VT_JMP anywhere except on the top of the stack
4613 because it would complicate the code generator. */
4614 if (vtop >= vstack) {
4615 v = vtop->r & VT_VALMASK;
4616 if (v == VT_CMP || (v & ~1) == VT_JMP)
4617 gv(RC_INT);
4619 vtop++;
4620 vtop->type = *type;
4621 vtop->r = r;
4622 vtop->r2 = VT_CONST;
4623 vtop->c = *vc;
4626 /* push integer constant */
4627 void vpushi(int v)
4629 CValue cval;
4630 cval.i = v;
4631 vsetc(&int_type, VT_CONST, &cval);
4634 /* Return a static symbol pointing to a section */
4635 static Sym *get_sym_ref(CType *type, Section *sec,
4636 unsigned long offset, unsigned long size)
4638 int v;
4639 Sym *sym;
4641 v = anon_sym++;
4642 sym = global_identifier_push(v, type->t | VT_STATIC, 0);
4643 sym->type.ref = type->ref;
4644 sym->r = VT_CONST | VT_SYM;
4645 put_extern_sym(sym, sec, offset, size);
4646 return sym;
4649 /* push a reference to a section offset by adding a dummy symbol */
4650 static void vpush_ref(CType *type, Section *sec, unsigned long offset, unsigned long size)
4652 CValue cval;
4654 cval.ul = 0;
4655 vsetc(type, VT_CONST | VT_SYM, &cval);
4656 vtop->sym = get_sym_ref(type, sec, offset, size);
4659 /* define a new external reference to a symbol 'v' of type 'u' */
4660 static Sym *external_global_sym(int v, CType *type, int r)
4662 Sym *s;
4664 s = sym_find(v);
4665 if (!s) {
4666 /* push forward reference */
4667 s = global_identifier_push(v, type->t | VT_EXTERN, 0);
4668 s->type.ref = type->ref;
4669 s->r = r | VT_CONST | VT_SYM;
4671 return s;
4674 /* define a new external reference to a symbol 'v' of type 'u' */
4675 static Sym *external_sym(int v, CType *type, int r)
4677 Sym *s;
4679 s = sym_find(v);
4680 if (!s) {
4681 /* push forward reference */
4682 s = sym_push(v, type, r | VT_CONST | VT_SYM, 0);
4683 s->type.t |= VT_EXTERN;
4684 } else {
4685 if (!is_compatible_types(&s->type, type))
4686 error("incompatible types for redefinition of '%s'",
4687 get_tok_str(v, NULL));
4689 return s;
4692 /* push a reference to global symbol v */
4693 static void vpush_global_sym(CType *type, int v)
4695 Sym *sym;
4696 CValue cval;
4698 sym = external_global_sym(v, type, 0);
4699 cval.ul = 0;
4700 vsetc(type, VT_CONST | VT_SYM, &cval);
4701 vtop->sym = sym;
4704 void vset(CType *type, int r, int v)
4706 CValue cval;
4708 cval.i = v;
4709 vsetc(type, r, &cval);
4712 void vseti(int r, int v)
4714 CType type;
4715 type.t = VT_INT;
4716 vset(&type, r, v);
4719 void vswap(void)
4721 SValue tmp;
4723 tmp = vtop[0];
4724 vtop[0] = vtop[-1];
4725 vtop[-1] = tmp;
4728 void vpushv(SValue *v)
4730 if (vtop >= vstack + (VSTACK_SIZE - 1))
4731 error("memory full");
4732 vtop++;
4733 *vtop = *v;
4736 void vdup(void)
4738 vpushv(vtop);
4741 /* save r to the memory stack, and mark it as being free */
4742 void save_reg(int r)
4744 int l, saved, size, align;
4745 SValue *p, sv;
4746 CType *type;
4748 /* modify all stack values */
4749 saved = 0;
4750 l = 0;
4751 for(p=vstack;p<=vtop;p++) {
4752 if ((p->r & VT_VALMASK) == r ||
4753 ((p->type.t & VT_BTYPE) == VT_LLONG && (p->r2 & VT_VALMASK) == r)) {
4754 /* must save value on stack if not already done */
4755 if (!saved) {
4756 /* NOTE: must reload 'r' because r might be equal to r2 */
4757 r = p->r & VT_VALMASK;
4758 /* store register in the stack */
4759 type = &p->type;
4760 if ((p->r & VT_LVAL) ||
4761 (!is_float(type->t) && (type->t & VT_BTYPE) != VT_LLONG))
4762 type = &int_type;
4763 size = type_size(type, &align);
4764 loc = (loc - size) & -align;
4765 sv.type.t = type->t;
4766 sv.r = VT_LOCAL | VT_LVAL;
4767 sv.c.ul = loc;
4768 store(r, &sv);
4769 #ifdef TCC_TARGET_I386
4770 /* x86 specific: need to pop fp register ST0 if saved */
4771 if (r == TREG_ST0) {
4772 o(0xd9dd); /* fstp %st(1) */
4774 #endif
4775 /* special long long case */
4776 if ((type->t & VT_BTYPE) == VT_LLONG) {
4777 sv.c.ul += 4;
4778 store(p->r2, &sv);
4780 l = loc;
4781 saved = 1;
4783 /* mark that stack entry as being saved on the stack */
4784 if (p->r & VT_LVAL) {
4785 /* also clear the bounded flag because the
4786 relocation address of the function was stored in
4787 p->c.ul */
4788 p->r = (p->r & ~(VT_VALMASK | VT_BOUNDED)) | VT_LLOCAL;
4789 } else {
4790 p->r = lvalue_type(p->type.t) | VT_LOCAL;
4792 p->r2 = VT_CONST;
4793 p->c.ul = l;
4798 /* find a register of class 'rc2' with at most one reference on stack.
4799 * If none, call get_reg(rc) */
4800 int get_reg_ex(int rc, int rc2)
4802 int r;
4803 SValue *p;
4805 for(r=0;r<NB_REGS;r++) {
4806 if (reg_classes[r] & rc2) {
4807 int n;
4808 n=0;
4809 for(p = vstack; p <= vtop; p++) {
4810 if ((p->r & VT_VALMASK) == r ||
4811 (p->r2 & VT_VALMASK) == r)
4812 n++;
4814 if (n <= 1)
4815 return r;
4818 return get_reg(rc);
4821 /* find a free register of class 'rc'. If none, save one register */
4822 int get_reg(int rc)
4824 int r;
4825 SValue *p;
4827 /* find a free register */
4828 for(r=0;r<NB_REGS;r++) {
4829 if (reg_classes[r] & rc) {
4830 for(p=vstack;p<=vtop;p++) {
4831 if ((p->r & VT_VALMASK) == r ||
4832 (p->r2 & VT_VALMASK) == r)
4833 goto notfound;
4835 return r;
4837 notfound: ;
4840 /* no register left : free the first one on the stack (VERY
4841 IMPORTANT to start from the bottom to ensure that we don't
4842 spill registers used in gen_opi()) */
4843 for(p=vstack;p<=vtop;p++) {
4844 r = p->r & VT_VALMASK;
4845 if (r < VT_CONST && (reg_classes[r] & rc))
4846 goto save_found;
4847 /* also look at second register (if long long) */
4848 r = p->r2 & VT_VALMASK;
4849 if (r < VT_CONST && (reg_classes[r] & rc)) {
4850 save_found:
4851 save_reg(r);
4852 return r;
4855 /* Should never comes here */
4856 return -1;
4859 /* save registers up to (vtop - n) stack entry */
4860 void save_regs(int n)
4862 int r;
4863 SValue *p, *p1;
4864 p1 = vtop - n;
4865 for(p = vstack;p <= p1; p++) {
4866 r = p->r & VT_VALMASK;
4867 if (r < VT_CONST) {
4868 save_reg(r);
4873 /* move register 's' to 'r', and flush previous value of r to memory
4874 if needed */
4875 void move_reg(int r, int s)
4877 SValue sv;
4879 if (r != s) {
4880 save_reg(r);
4881 sv.type.t = VT_INT;
4882 sv.r = s;
4883 sv.c.ul = 0;
4884 load(r, &sv);
4888 /* get address of vtop (vtop MUST BE an lvalue) */
4889 void gaddrof(void)
4891 vtop->r &= ~VT_LVAL;
4892 /* tricky: if saved lvalue, then we can go back to lvalue */
4893 if ((vtop->r & VT_VALMASK) == VT_LLOCAL)
4894 vtop->r = (vtop->r & ~(VT_VALMASK | VT_LVAL_TYPE)) | VT_LOCAL | VT_LVAL;
4897 #ifdef CONFIG_TCC_BCHECK
4898 /* generate lvalue bound code */
4899 void gbound(void)
4901 int lval_type;
4902 CType type1;
4904 vtop->r &= ~VT_MUSTBOUND;
4905 /* if lvalue, then use checking code before dereferencing */
4906 if (vtop->r & VT_LVAL) {
4907 /* if not VT_BOUNDED value, then make one */
4908 if (!(vtop->r & VT_BOUNDED)) {
4909 lval_type = vtop->r & (VT_LVAL_TYPE | VT_LVAL);
4910 /* must save type because we must set it to int to get pointer */
4911 type1 = vtop->type;
4912 vtop->type.t = VT_INT;
4913 gaddrof();
4914 vpushi(0);
4915 gen_bounded_ptr_add();
4916 vtop->r |= lval_type;
4917 vtop->type = type1;
4919 /* then check for dereferencing */
4920 gen_bounded_ptr_deref();
4923 #endif
4925 /* store vtop a register belonging to class 'rc'. lvalues are
4926 converted to values. Cannot be used if cannot be converted to
4927 register value (such as structures). */
4928 int gv(int rc)
4930 int r, r2, rc2, bit_pos, bit_size, size, align, i;
4931 unsigned long long ll;
4933 /* NOTE: get_reg can modify vstack[] */
4934 if (vtop->type.t & VT_BITFIELD) {
4935 CType type;
4936 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
4937 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
4938 /* remove bit field info to avoid loops */
4939 vtop->type.t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
4940 /* cast to int to propagate signedness in following ops */
4941 type.t = VT_INT;
4942 if((vtop->type.t & VT_UNSIGNED) ||
4943 (vtop->type.t & VT_BTYPE) == VT_BOOL)
4944 type.t |= VT_UNSIGNED;
4945 gen_cast(&type);
4946 /* generate shifts */
4947 vpushi(32 - (bit_pos + bit_size));
4948 gen_op(TOK_SHL);
4949 vpushi(32 - bit_size);
4950 /* NOTE: transformed to SHR if unsigned */
4951 gen_op(TOK_SAR);
4952 r = gv(rc);
4953 } else {
4954 if (is_float(vtop->type.t) &&
4955 (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4956 Sym *sym;
4957 int *ptr;
4958 unsigned long offset;
4959 #if defined(TCC_TARGET_ARM) && !defined(TCC_ARM_VFP)
4960 CValue check;
4961 #endif
4963 /* XXX: unify with initializers handling ? */
4964 /* CPUs usually cannot use float constants, so we store them
4965 generically in data segment */
4966 size = type_size(&vtop->type, &align);
4967 offset = (data_section->data_offset + align - 1) & -align;
4968 data_section->data_offset = offset;
4969 /* XXX: not portable yet */
4970 #ifdef __i386__
4971 /* Zero pad x87 tenbyte long doubles */
4972 if (size == 12)
4973 vtop->c.tab[2] &= 0xffff;
4974 #endif
4975 ptr = section_ptr_add(data_section, size);
4976 size = size >> 2;
4977 #if defined(TCC_TARGET_ARM) && !defined(TCC_ARM_VFP)
4978 check.d = 1;
4979 if(check.tab[0])
4980 for(i=0;i<size;i++)
4981 ptr[i] = vtop->c.tab[size-1-i];
4982 else
4983 #endif
4984 for(i=0;i<size;i++)
4985 ptr[i] = vtop->c.tab[i];
4986 sym = get_sym_ref(&vtop->type, data_section, offset, size << 2);
4987 vtop->r |= VT_LVAL | VT_SYM;
4988 vtop->sym = sym;
4989 vtop->c.ul = 0;
4991 #ifdef CONFIG_TCC_BCHECK
4992 if (vtop->r & VT_MUSTBOUND)
4993 gbound();
4994 #endif
4996 r = vtop->r & VT_VALMASK;
4997 rc2 = RC_INT;
4998 if (rc == RC_IRET)
4999 rc2 = RC_LRET;
5000 /* need to reload if:
5001 - constant
5002 - lvalue (need to dereference pointer)
5003 - already a register, but not in the right class */
5004 if (r >= VT_CONST ||
5005 (vtop->r & VT_LVAL) ||
5006 !(reg_classes[r] & rc) ||
5007 ((vtop->type.t & VT_BTYPE) == VT_LLONG &&
5008 !(reg_classes[vtop->r2] & rc2))) {
5009 r = get_reg(rc);
5010 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
5011 /* two register type load : expand to two words
5012 temporarily */
5013 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
5014 /* load constant */
5015 ll = vtop->c.ull;
5016 vtop->c.ui = ll; /* first word */
5017 load(r, vtop);
5018 vtop->r = r; /* save register value */
5019 vpushi(ll >> 32); /* second word */
5020 } else if (r >= VT_CONST || /* XXX: test to VT_CONST incorrect ? */
5021 (vtop->r & VT_LVAL)) {
5022 /* We do not want to modifier the long long
5023 pointer here, so the safest (and less
5024 efficient) is to save all the other registers
5025 in the stack. XXX: totally inefficient. */
5026 save_regs(1);
5027 /* load from memory */
5028 load(r, vtop);
5029 vdup();
5030 vtop[-1].r = r; /* save register value */
5031 /* increment pointer to get second word */
5032 vtop->type.t = VT_INT;
5033 gaddrof();
5034 vpushi(4);
5035 gen_op('+');
5036 vtop->r |= VT_LVAL;
5037 } else {
5038 /* move registers */
5039 load(r, vtop);
5040 vdup();
5041 vtop[-1].r = r; /* save register value */
5042 vtop->r = vtop[-1].r2;
5044 /* allocate second register */
5045 r2 = get_reg(rc2);
5046 load(r2, vtop);
5047 vpop();
5048 /* write second register */
5049 vtop->r2 = r2;
5050 } else if ((vtop->r & VT_LVAL) && !is_float(vtop->type.t)) {
5051 int t1, t;
5052 /* lvalue of scalar type : need to use lvalue type
5053 because of possible cast */
5054 t = vtop->type.t;
5055 t1 = t;
5056 /* compute memory access type */
5057 if (vtop->r & VT_LVAL_BYTE)
5058 t = VT_BYTE;
5059 else if (vtop->r & VT_LVAL_SHORT)
5060 t = VT_SHORT;
5061 if (vtop->r & VT_LVAL_UNSIGNED)
5062 t |= VT_UNSIGNED;
5063 vtop->type.t = t;
5064 load(r, vtop);
5065 /* restore wanted type */
5066 vtop->type.t = t1;
5067 } else {
5068 /* one register type load */
5069 load(r, vtop);
5072 vtop->r = r;
5073 #ifdef TCC_TARGET_C67
5074 /* uses register pairs for doubles */
5075 if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE)
5076 vtop->r2 = r+1;
5077 #endif
5079 return r;
5082 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
5083 void gv2(int rc1, int rc2)
5085 int v;
5087 /* generate more generic register first. But VT_JMP or VT_CMP
5088 values must be generated first in all cases to avoid possible
5089 reload errors */
5090 v = vtop[0].r & VT_VALMASK;
5091 if (v != VT_CMP && (v & ~1) != VT_JMP && rc1 <= rc2) {
5092 vswap();
5093 gv(rc1);
5094 vswap();
5095 gv(rc2);
5096 /* test if reload is needed for first register */
5097 if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
5098 vswap();
5099 gv(rc1);
5100 vswap();
5102 } else {
5103 gv(rc2);
5104 vswap();
5105 gv(rc1);
5106 vswap();
5107 /* test if reload is needed for first register */
5108 if ((vtop[0].r & VT_VALMASK) >= VT_CONST) {
5109 gv(rc2);
5114 /* expand long long on stack in two int registers */
5115 void lexpand(void)
5117 int u;
5119 u = vtop->type.t & VT_UNSIGNED;
5120 gv(RC_INT);
5121 vdup();
5122 vtop[0].r = vtop[-1].r2;
5123 vtop[0].r2 = VT_CONST;
5124 vtop[-1].r2 = VT_CONST;
5125 vtop[0].type.t = VT_INT | u;
5126 vtop[-1].type.t = VT_INT | u;
5129 #ifdef TCC_TARGET_ARM
5130 /* expand long long on stack */
5131 void lexpand_nr(void)
5133 int u,v;
5135 u = vtop->type.t & VT_UNSIGNED;
5136 vdup();
5137 vtop->r2 = VT_CONST;
5138 vtop->type.t = VT_INT | u;
5139 v=vtop[-1].r & (VT_VALMASK | VT_LVAL);
5140 if (v == VT_CONST) {
5141 vtop[-1].c.ui = vtop->c.ull;
5142 vtop->c.ui = vtop->c.ull >> 32;
5143 vtop->r = VT_CONST;
5144 } else if (v == (VT_LVAL|VT_CONST) || v == (VT_LVAL|VT_LOCAL)) {
5145 vtop->c.ui += 4;
5146 vtop->r = vtop[-1].r;
5147 } else if (v > VT_CONST) {
5148 vtop--;
5149 lexpand();
5150 } else
5151 vtop->r = vtop[-1].r2;
5152 vtop[-1].r2 = VT_CONST;
5153 vtop[-1].type.t = VT_INT | u;
5155 #endif
5157 /* build a long long from two ints */
5158 void lbuild(int t)
5160 gv2(RC_INT, RC_INT);
5161 vtop[-1].r2 = vtop[0].r;
5162 vtop[-1].type.t = t;
5163 vpop();
5166 /* rotate n first stack elements to the bottom
5167 I1 ... In -> I2 ... In I1 [top is right]
5169 void vrotb(int n)
5171 int i;
5172 SValue tmp;
5174 tmp = vtop[-n + 1];
5175 for(i=-n+1;i!=0;i++)
5176 vtop[i] = vtop[i+1];
5177 vtop[0] = tmp;
5180 /* rotate n first stack elements to the top
5181 I1 ... In -> In I1 ... I(n-1) [top is right]
5183 void vrott(int n)
5185 int i;
5186 SValue tmp;
5188 tmp = vtop[0];
5189 for(i = 0;i < n - 1; i++)
5190 vtop[-i] = vtop[-i - 1];
5191 vtop[-n + 1] = tmp;
5194 #ifdef TCC_TARGET_ARM
5195 /* like vrott but in other direction
5196 In ... I1 -> I(n-1) ... I1 In [top is right]
5198 void vnrott(int n)
5200 int i;
5201 SValue tmp;
5203 tmp = vtop[-n + 1];
5204 for(i = n - 1; i > 0; i--)
5205 vtop[-i] = vtop[-i + 1];
5206 vtop[0] = tmp;
5208 #endif
5210 /* pop stack value */
5211 void vpop(void)
5213 int v;
5214 v = vtop->r & VT_VALMASK;
5215 #ifdef TCC_TARGET_I386
5216 /* for x86, we need to pop the FP stack */
5217 if (v == TREG_ST0 && !nocode_wanted) {
5218 o(0xd9dd); /* fstp %st(1) */
5219 } else
5220 #endif
5221 if (v == VT_JMP || v == VT_JMPI) {
5222 /* need to put correct jump if && or || without test */
5223 gsym(vtop->c.ul);
5225 vtop--;
5228 /* convert stack entry to register and duplicate its value in another
5229 register */
5230 void gv_dup(void)
5232 int rc, t, r, r1;
5233 SValue sv;
5235 t = vtop->type.t;
5236 if ((t & VT_BTYPE) == VT_LLONG) {
5237 lexpand();
5238 gv_dup();
5239 vswap();
5240 vrotb(3);
5241 gv_dup();
5242 vrotb(4);
5243 /* stack: H L L1 H1 */
5244 lbuild(t);
5245 vrotb(3);
5246 vrotb(3);
5247 vswap();
5248 lbuild(t);
5249 vswap();
5250 } else {
5251 /* duplicate value */
5252 rc = RC_INT;
5253 sv.type.t = VT_INT;
5254 if (is_float(t)) {
5255 rc = RC_FLOAT;
5256 sv.type.t = t;
5258 r = gv(rc);
5259 r1 = get_reg(rc);
5260 sv.r = r;
5261 sv.c.ul = 0;
5262 load(r1, &sv); /* move r to r1 */
5263 vdup();
5264 /* duplicates value */
5265 vtop->r = r1;
5269 /* generate CPU independent (unsigned) long long operations */
5270 void gen_opl(int op)
5272 int t, a, b, op1, c, i;
5273 int func;
5274 unsigned short reg_iret = REG_IRET;
5275 unsigned short reg_lret = REG_LRET;
5276 SValue tmp;
5278 switch(op) {
5279 case '/':
5280 case TOK_PDIV:
5281 func = TOK___divdi3;
5282 goto gen_func;
5283 case TOK_UDIV:
5284 func = TOK___udivdi3;
5285 goto gen_func;
5286 case '%':
5287 func = TOK___moddi3;
5288 goto gen_mod_func;
5289 case TOK_UMOD:
5290 func = TOK___umoddi3;
5291 gen_mod_func:
5292 #ifdef TCC_ARM_EABI
5293 reg_iret = TREG_R2;
5294 reg_lret = TREG_R3;
5295 #endif
5296 gen_func:
5297 /* call generic long long function */
5298 vpush_global_sym(&func_old_type, func);
5299 vrott(3);
5300 gfunc_call(2);
5301 vpushi(0);
5302 vtop->r = reg_iret;
5303 vtop->r2 = reg_lret;
5304 break;
5305 case '^':
5306 case '&':
5307 case '|':
5308 case '*':
5309 case '+':
5310 case '-':
5311 t = vtop->type.t;
5312 vswap();
5313 lexpand();
5314 vrotb(3);
5315 lexpand();
5316 /* stack: L1 H1 L2 H2 */
5317 tmp = vtop[0];
5318 vtop[0] = vtop[-3];
5319 vtop[-3] = tmp;
5320 tmp = vtop[-2];
5321 vtop[-2] = vtop[-3];
5322 vtop[-3] = tmp;
5323 vswap();
5324 /* stack: H1 H2 L1 L2 */
5325 if (op == '*') {
5326 vpushv(vtop - 1);
5327 vpushv(vtop - 1);
5328 gen_op(TOK_UMULL);
5329 lexpand();
5330 /* stack: H1 H2 L1 L2 ML MH */
5331 for(i=0;i<4;i++)
5332 vrotb(6);
5333 /* stack: ML MH H1 H2 L1 L2 */
5334 tmp = vtop[0];
5335 vtop[0] = vtop[-2];
5336 vtop[-2] = tmp;
5337 /* stack: ML MH H1 L2 H2 L1 */
5338 gen_op('*');
5339 vrotb(3);
5340 vrotb(3);
5341 gen_op('*');
5342 /* stack: ML MH M1 M2 */
5343 gen_op('+');
5344 gen_op('+');
5345 } else if (op == '+' || op == '-') {
5346 /* XXX: add non carry method too (for MIPS or alpha) */
5347 if (op == '+')
5348 op1 = TOK_ADDC1;
5349 else
5350 op1 = TOK_SUBC1;
5351 gen_op(op1);
5352 /* stack: H1 H2 (L1 op L2) */
5353 vrotb(3);
5354 vrotb(3);
5355 gen_op(op1 + 1); /* TOK_xxxC2 */
5356 } else {
5357 gen_op(op);
5358 /* stack: H1 H2 (L1 op L2) */
5359 vrotb(3);
5360 vrotb(3);
5361 /* stack: (L1 op L2) H1 H2 */
5362 gen_op(op);
5363 /* stack: (L1 op L2) (H1 op H2) */
5365 /* stack: L H */
5366 lbuild(t);
5367 break;
5368 case TOK_SAR:
5369 case TOK_SHR:
5370 case TOK_SHL:
5371 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
5372 t = vtop[-1].type.t;
5373 vswap();
5374 lexpand();
5375 vrotb(3);
5376 /* stack: L H shift */
5377 c = (int)vtop->c.i;
5378 /* constant: simpler */
5379 /* NOTE: all comments are for SHL. the other cases are
5380 done by swaping words */
5381 vpop();
5382 if (op != TOK_SHL)
5383 vswap();
5384 if (c >= 32) {
5385 /* stack: L H */
5386 vpop();
5387 if (c > 32) {
5388 vpushi(c - 32);
5389 gen_op(op);
5391 if (op != TOK_SAR) {
5392 vpushi(0);
5393 } else {
5394 gv_dup();
5395 vpushi(31);
5396 gen_op(TOK_SAR);
5398 vswap();
5399 } else {
5400 vswap();
5401 gv_dup();
5402 /* stack: H L L */
5403 vpushi(c);
5404 gen_op(op);
5405 vswap();
5406 vpushi(32 - c);
5407 if (op == TOK_SHL)
5408 gen_op(TOK_SHR);
5409 else
5410 gen_op(TOK_SHL);
5411 vrotb(3);
5412 /* stack: L L H */
5413 vpushi(c);
5414 if (op == TOK_SHL)
5415 gen_op(TOK_SHL);
5416 else
5417 gen_op(TOK_SHR);
5418 gen_op('|');
5420 if (op != TOK_SHL)
5421 vswap();
5422 lbuild(t);
5423 } else {
5424 /* XXX: should provide a faster fallback on x86 ? */
5425 switch(op) {
5426 case TOK_SAR:
5427 func = TOK___ashrdi3;
5428 goto gen_func;
5429 case TOK_SHR:
5430 func = TOK___lshrdi3;
5431 goto gen_func;
5432 case TOK_SHL:
5433 func = TOK___ashldi3;
5434 goto gen_func;
5437 break;
5438 default:
5439 /* compare operations */
5440 t = vtop->type.t;
5441 vswap();
5442 lexpand();
5443 vrotb(3);
5444 lexpand();
5445 /* stack: L1 H1 L2 H2 */
5446 tmp = vtop[-1];
5447 vtop[-1] = vtop[-2];
5448 vtop[-2] = tmp;
5449 /* stack: L1 L2 H1 H2 */
5450 /* compare high */
5451 op1 = op;
5452 /* when values are equal, we need to compare low words. since
5453 the jump is inverted, we invert the test too. */
5454 if (op1 == TOK_LT)
5455 op1 = TOK_LE;
5456 else if (op1 == TOK_GT)
5457 op1 = TOK_GE;
5458 else if (op1 == TOK_ULT)
5459 op1 = TOK_ULE;
5460 else if (op1 == TOK_UGT)
5461 op1 = TOK_UGE;
5462 a = 0;
5463 b = 0;
5464 gen_op(op1);
5465 if (op1 != TOK_NE) {
5466 a = gtst(1, 0);
5468 if (op != TOK_EQ) {
5469 /* generate non equal test */
5470 /* XXX: NOT PORTABLE yet */
5471 if (a == 0) {
5472 b = gtst(0, 0);
5473 } else {
5474 #if defined(TCC_TARGET_I386)
5475 b = psym(0x850f, 0);
5476 #elif defined(TCC_TARGET_ARM)
5477 b = ind;
5478 o(0x1A000000 | encbranch(ind, 0, 1));
5479 #elif defined(TCC_TARGET_C67)
5480 error("not implemented");
5481 #else
5482 #error not supported
5483 #endif
5486 /* compare low. Always unsigned */
5487 op1 = op;
5488 if (op1 == TOK_LT)
5489 op1 = TOK_ULT;
5490 else if (op1 == TOK_LE)
5491 op1 = TOK_ULE;
5492 else if (op1 == TOK_GT)
5493 op1 = TOK_UGT;
5494 else if (op1 == TOK_GE)
5495 op1 = TOK_UGE;
5496 gen_op(op1);
5497 a = gtst(1, a);
5498 gsym(b);
5499 vseti(VT_JMPI, a);
5500 break;
5504 /* handle integer constant optimizations and various machine
5505 independent opt */
5506 void gen_opic(int op)
5508 int c1, c2, t1, t2, n;
5509 SValue *v1, *v2;
5510 long long l1, l2;
5511 typedef unsigned long long U;
5513 v1 = vtop - 1;
5514 v2 = vtop;
5515 t1 = v1->type.t & VT_BTYPE;
5516 t2 = v2->type.t & VT_BTYPE;
5517 l1 = (t1 == VT_LLONG) ? v1->c.ll : v1->c.i;
5518 l2 = (t2 == VT_LLONG) ? v2->c.ll : v2->c.i;
5520 /* currently, we cannot do computations with forward symbols */
5521 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5522 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5523 if (c1 && c2) {
5524 switch(op) {
5525 case '+': l1 += l2; break;
5526 case '-': l1 -= l2; break;
5527 case '&': l1 &= l2; break;
5528 case '^': l1 ^= l2; break;
5529 case '|': l1 |= l2; break;
5530 case '*': l1 *= l2; break;
5532 case TOK_PDIV:
5533 case '/':
5534 case '%':
5535 case TOK_UDIV:
5536 case TOK_UMOD:
5537 /* if division by zero, generate explicit division */
5538 if (l2 == 0) {
5539 if (const_wanted)
5540 error("division by zero in constant");
5541 goto general_case;
5543 switch(op) {
5544 default: l1 /= l2; break;
5545 case '%': l1 %= l2; break;
5546 case TOK_UDIV: l1 = (U)l1 / l2; break;
5547 case TOK_UMOD: l1 = (U)l1 % l2; break;
5549 break;
5550 case TOK_SHL: l1 <<= l2; break;
5551 case TOK_SHR: l1 = (U)l1 >> l2; break;
5552 case TOK_SAR: l1 >>= l2; break;
5553 /* tests */
5554 case TOK_ULT: l1 = (U)l1 < (U)l2; break;
5555 case TOK_UGE: l1 = (U)l1 >= (U)l2; break;
5556 case TOK_EQ: l1 = l1 == l2; break;
5557 case TOK_NE: l1 = l1 != l2; break;
5558 case TOK_ULE: l1 = (U)l1 <= (U)l2; break;
5559 case TOK_UGT: l1 = (U)l1 > (U)l2; break;
5560 case TOK_LT: l1 = l1 < l2; break;
5561 case TOK_GE: l1 = l1 >= l2; break;
5562 case TOK_LE: l1 = l1 <= l2; break;
5563 case TOK_GT: l1 = l1 > l2; break;
5564 /* logical */
5565 case TOK_LAND: l1 = l1 && l2; break;
5566 case TOK_LOR: l1 = l1 || l2; break;
5567 default:
5568 goto general_case;
5570 v1->c.ll = l1;
5571 vtop--;
5572 } else {
5573 /* if commutative ops, put c2 as constant */
5574 if (c1 && (op == '+' || op == '&' || op == '^' ||
5575 op == '|' || op == '*')) {
5576 vswap();
5577 c2 = c1; //c = c1, c1 = c2, c2 = c;
5578 l2 = l1; //l = l1, l1 = l2, l2 = l;
5580 /* Filter out NOP operations like x*1, x-0, x&-1... */
5581 if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
5582 op == TOK_PDIV) &&
5583 l2 == 1) ||
5584 ((op == '+' || op == '-' || op == '|' || op == '^' ||
5585 op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
5586 l2 == 0) ||
5587 (op == '&' &&
5588 l2 == -1))) {
5589 /* nothing to do */
5590 vtop--;
5591 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
5592 /* try to use shifts instead of muls or divs */
5593 if (l2 > 0 && (l2 & (l2 - 1)) == 0) {
5594 n = -1;
5595 while (l2) {
5596 l2 >>= 1;
5597 n++;
5599 vtop->c.ll = n;
5600 if (op == '*')
5601 op = TOK_SHL;
5602 else if (op == TOK_PDIV)
5603 op = TOK_SAR;
5604 else
5605 op = TOK_SHR;
5607 goto general_case;
5608 } else if (c2 && (op == '+' || op == '-') &&
5609 ((vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) ==
5610 (VT_CONST | VT_SYM) ||
5611 (vtop[-1].r & (VT_VALMASK | VT_LVAL)) == VT_LOCAL)) {
5612 /* symbol + constant case */
5613 if (op == '-')
5614 l2 = -l2;
5615 vtop--;
5616 vtop->c.ll += l2;
5617 } else {
5618 general_case:
5619 if (!nocode_wanted) {
5620 /* call low level op generator */
5621 if (t1 == VT_LLONG || t2 == VT_LLONG)
5622 gen_opl(op);
5623 else
5624 gen_opi(op);
5625 } else {
5626 vtop--;
5632 /* generate a floating point operation with constant propagation */
5633 void gen_opif(int op)
5635 int c1, c2;
5636 SValue *v1, *v2;
5637 long double f1, f2;
5639 v1 = vtop - 1;
5640 v2 = vtop;
5641 /* currently, we cannot do computations with forward symbols */
5642 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5643 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5644 if (c1 && c2) {
5645 if (v1->type.t == VT_FLOAT) {
5646 f1 = v1->c.f;
5647 f2 = v2->c.f;
5648 } else if (v1->type.t == VT_DOUBLE) {
5649 f1 = v1->c.d;
5650 f2 = v2->c.d;
5651 } else {
5652 f1 = v1->c.ld;
5653 f2 = v2->c.ld;
5656 /* NOTE: we only do constant propagation if finite number (not
5657 NaN or infinity) (ANSI spec) */
5658 if (!ieee_finite(f1) || !ieee_finite(f2))
5659 goto general_case;
5661 switch(op) {
5662 case '+': f1 += f2; break;
5663 case '-': f1 -= f2; break;
5664 case '*': f1 *= f2; break;
5665 case '/':
5666 if (f2 == 0.0) {
5667 if (const_wanted)
5668 error("division by zero in constant");
5669 goto general_case;
5671 f1 /= f2;
5672 break;
5673 /* XXX: also handles tests ? */
5674 default:
5675 goto general_case;
5677 /* XXX: overflow test ? */
5678 if (v1->type.t == VT_FLOAT) {
5679 v1->c.f = f1;
5680 } else if (v1->type.t == VT_DOUBLE) {
5681 v1->c.d = f1;
5682 } else {
5683 v1->c.ld = f1;
5685 vtop--;
5686 } else {
5687 general_case:
5688 if (!nocode_wanted) {
5689 gen_opf(op);
5690 } else {
5691 vtop--;
5696 static int pointed_size(CType *type)
5698 int align;
5699 return type_size(pointed_type(type), &align);
5702 static inline int is_null_pointer(SValue *p)
5704 if ((p->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
5705 return 0;
5706 return ((p->type.t & VT_BTYPE) == VT_INT && p->c.i == 0) ||
5707 ((p->type.t & VT_BTYPE) == VT_LLONG && p->c.ll == 0);
5710 static inline int is_integer_btype(int bt)
5712 return (bt == VT_BYTE || bt == VT_SHORT ||
5713 bt == VT_INT || bt == VT_LLONG);
5716 /* check types for comparison or substraction of pointers */
5717 static void check_comparison_pointer_types(SValue *p1, SValue *p2, int op)
5719 CType *type1, *type2, tmp_type1, tmp_type2;
5720 int bt1, bt2;
5722 /* null pointers are accepted for all comparisons as gcc */
5723 if (is_null_pointer(p1) || is_null_pointer(p2))
5724 return;
5725 type1 = &p1->type;
5726 type2 = &p2->type;
5727 bt1 = type1->t & VT_BTYPE;
5728 bt2 = type2->t & VT_BTYPE;
5729 /* accept comparison between pointer and integer with a warning */
5730 if ((is_integer_btype(bt1) || is_integer_btype(bt2)) && op != '-') {
5731 if (op != TOK_LOR && op != TOK_LAND )
5732 warning("comparison between pointer and integer");
5733 return;
5736 /* both must be pointers or implicit function pointers */
5737 if (bt1 == VT_PTR) {
5738 type1 = pointed_type(type1);
5739 } else if (bt1 != VT_FUNC)
5740 goto invalid_operands;
5742 if (bt2 == VT_PTR) {
5743 type2 = pointed_type(type2);
5744 } else if (bt2 != VT_FUNC) {
5745 invalid_operands:
5746 error("invalid operands to binary %s", get_tok_str(op, NULL));
5748 if ((type1->t & VT_BTYPE) == VT_VOID ||
5749 (type2->t & VT_BTYPE) == VT_VOID)
5750 return;
5751 tmp_type1 = *type1;
5752 tmp_type2 = *type2;
5753 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5754 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5755 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
5756 /* gcc-like error if '-' is used */
5757 if (op == '-')
5758 goto invalid_operands;
5759 else
5760 warning("comparison of distinct pointer types lacks a cast");
5764 /* generic gen_op: handles types problems */
5765 void gen_op(int op)
5767 int u, t1, t2, bt1, bt2, t;
5768 CType type1;
5770 t1 = vtop[-1].type.t;
5771 t2 = vtop[0].type.t;
5772 bt1 = t1 & VT_BTYPE;
5773 bt2 = t2 & VT_BTYPE;
5775 if (bt1 == VT_PTR || bt2 == VT_PTR) {
5776 /* at least one operand is a pointer */
5777 /* relationnal op: must be both pointers */
5778 if (op >= TOK_ULT && op <= TOK_LOR) {
5779 check_comparison_pointer_types(vtop - 1, vtop, op);
5780 /* pointers are handled are unsigned */
5781 t = VT_INT | VT_UNSIGNED;
5782 goto std_op;
5784 /* if both pointers, then it must be the '-' op */
5785 if (bt1 == VT_PTR && bt2 == VT_PTR) {
5786 if (op != '-')
5787 error("cannot use pointers here");
5788 check_comparison_pointer_types(vtop - 1, vtop, op);
5789 /* XXX: check that types are compatible */
5790 u = pointed_size(&vtop[-1].type);
5791 gen_opic(op);
5792 /* set to integer type */
5793 vtop->type.t = VT_INT;
5794 vpushi(u);
5795 gen_op(TOK_PDIV);
5796 } else {
5797 /* exactly one pointer : must be '+' or '-'. */
5798 if (op != '-' && op != '+')
5799 error("cannot use pointers here");
5800 /* Put pointer as first operand */
5801 if (bt2 == VT_PTR) {
5802 vswap();
5803 swap(&t1, &t2);
5805 type1 = vtop[-1].type;
5806 /* XXX: cast to int ? (long long case) */
5807 vpushi(pointed_size(&vtop[-1].type));
5808 gen_op('*');
5809 #ifdef CONFIG_TCC_BCHECK
5810 /* if evaluating constant expression, no code should be
5811 generated, so no bound check */
5812 if (do_bounds_check && !const_wanted) {
5813 /* if bounded pointers, we generate a special code to
5814 test bounds */
5815 if (op == '-') {
5816 vpushi(0);
5817 vswap();
5818 gen_op('-');
5820 gen_bounded_ptr_add();
5821 } else
5822 #endif
5824 gen_opic(op);
5826 /* put again type if gen_opic() swaped operands */
5827 vtop->type = type1;
5829 } else if (is_float(bt1) || is_float(bt2)) {
5830 /* compute bigger type and do implicit casts */
5831 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
5832 t = VT_LDOUBLE;
5833 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
5834 t = VT_DOUBLE;
5835 } else {
5836 t = VT_FLOAT;
5838 /* floats can only be used for a few operations */
5839 if (op != '+' && op != '-' && op != '*' && op != '/' &&
5840 (op < TOK_ULT || op > TOK_GT))
5841 error("invalid operands for binary operation");
5842 goto std_op;
5843 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
5844 /* cast to biggest op */
5845 t = VT_LLONG;
5846 /* convert to unsigned if it does not fit in a long long */
5847 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
5848 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
5849 t |= VT_UNSIGNED;
5850 goto std_op;
5851 } else {
5852 /* integer operations */
5853 t = VT_INT;
5854 /* convert to unsigned if it does not fit in an integer */
5855 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
5856 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
5857 t |= VT_UNSIGNED;
5858 std_op:
5859 /* XXX: currently, some unsigned operations are explicit, so
5860 we modify them here */
5861 if (t & VT_UNSIGNED) {
5862 if (op == TOK_SAR)
5863 op = TOK_SHR;
5864 else if (op == '/')
5865 op = TOK_UDIV;
5866 else if (op == '%')
5867 op = TOK_UMOD;
5868 else if (op == TOK_LT)
5869 op = TOK_ULT;
5870 else if (op == TOK_GT)
5871 op = TOK_UGT;
5872 else if (op == TOK_LE)
5873 op = TOK_ULE;
5874 else if (op == TOK_GE)
5875 op = TOK_UGE;
5877 vswap();
5878 type1.t = t;
5879 gen_cast(&type1);
5880 vswap();
5881 /* special case for shifts and long long: we keep the shift as
5882 an integer */
5883 if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL)
5884 type1.t = VT_INT;
5885 gen_cast(&type1);
5886 if (is_float(t))
5887 gen_opif(op);
5888 else
5889 gen_opic(op);
5890 if (op >= TOK_ULT && op <= TOK_GT) {
5891 /* relationnal op: the result is an int */
5892 vtop->type.t = VT_INT;
5893 } else {
5894 vtop->type.t = t;
5899 #ifndef TCC_TARGET_ARM
5900 /* generic itof for unsigned long long case */
5901 void gen_cvt_itof1(int t)
5903 if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
5904 (VT_LLONG | VT_UNSIGNED)) {
5906 if (t == VT_FLOAT)
5907 vpush_global_sym(&func_old_type, TOK___floatundisf);
5908 #if LDOUBLE_SIZE != 8
5909 else if (t == VT_LDOUBLE)
5910 vpush_global_sym(&func_old_type, TOK___floatundixf);
5911 #endif
5912 else
5913 vpush_global_sym(&func_old_type, TOK___floatundidf);
5914 vrott(2);
5915 gfunc_call(1);
5916 vpushi(0);
5917 vtop->r = REG_FRET;
5918 } else {
5919 gen_cvt_itof(t);
5922 #endif
5924 /* generic ftoi for unsigned long long case */
5925 void gen_cvt_ftoi1(int t)
5927 int st;
5929 if (t == (VT_LLONG | VT_UNSIGNED)) {
5930 /* not handled natively */
5931 st = vtop->type.t & VT_BTYPE;
5932 if (st == VT_FLOAT)
5933 vpush_global_sym(&func_old_type, TOK___fixunssfdi);
5934 #if LDOUBLE_SIZE != 8
5935 else if (st == VT_LDOUBLE)
5936 vpush_global_sym(&func_old_type, TOK___fixunsxfdi);
5937 #endif
5938 else
5939 vpush_global_sym(&func_old_type, TOK___fixunsdfdi);
5940 vrott(2);
5941 gfunc_call(1);
5942 vpushi(0);
5943 vtop->r = REG_IRET;
5944 vtop->r2 = REG_LRET;
5945 } else {
5946 gen_cvt_ftoi(t);
5950 /* force char or short cast */
5951 void force_charshort_cast(int t)
5953 int bits, dbt;
5954 dbt = t & VT_BTYPE;
5955 /* XXX: add optimization if lvalue : just change type and offset */
5956 if (dbt == VT_BYTE)
5957 bits = 8;
5958 else
5959 bits = 16;
5960 if (t & VT_UNSIGNED) {
5961 vpushi((1 << bits) - 1);
5962 gen_op('&');
5963 } else {
5964 bits = 32 - bits;
5965 vpushi(bits);
5966 gen_op(TOK_SHL);
5967 /* result must be signed or the SAR is converted to an SHL
5968 This was not the case when "t" was a signed short
5969 and the last value on the stack was an unsigned int */
5970 vtop->type.t &= ~VT_UNSIGNED;
5971 vpushi(bits);
5972 gen_op(TOK_SAR);
5976 /* cast 'vtop' to 'type'. Casting to bitfields is forbidden. */
5977 static void gen_cast(CType *type)
5979 int sbt, dbt, sf, df, c, p;
5981 /* special delayed cast for char/short */
5982 /* XXX: in some cases (multiple cascaded casts), it may still
5983 be incorrect */
5984 if (vtop->r & VT_MUSTCAST) {
5985 vtop->r &= ~VT_MUSTCAST;
5986 force_charshort_cast(vtop->type.t);
5989 /* bitfields first get cast to ints */
5990 if (vtop->type.t & VT_BITFIELD) {
5991 gv(RC_INT);
5994 dbt = type->t & (VT_BTYPE | VT_UNSIGNED);
5995 sbt = vtop->type.t & (VT_BTYPE | VT_UNSIGNED);
5997 if (sbt != dbt) {
5998 sf = is_float(sbt);
5999 df = is_float(dbt);
6000 c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
6001 p = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == (VT_CONST | VT_SYM);
6002 if (c) {
6003 /* constant case: we can do it now */
6004 /* XXX: in ISOC, cannot do it if error in convert */
6005 if (sbt == VT_FLOAT)
6006 vtop->c.ld = vtop->c.f;
6007 else if (sbt == VT_DOUBLE)
6008 vtop->c.ld = vtop->c.d;
6010 if (df) {
6011 if ((sbt & VT_BTYPE) == VT_LLONG) {
6012 if (sbt & VT_UNSIGNED)
6013 vtop->c.ld = vtop->c.ull;
6014 else
6015 vtop->c.ld = vtop->c.ll;
6016 } else if(!sf) {
6017 if (sbt & VT_UNSIGNED)
6018 vtop->c.ld = vtop->c.ui;
6019 else
6020 vtop->c.ld = vtop->c.i;
6023 if (dbt == VT_FLOAT)
6024 vtop->c.f = (float)vtop->c.ld;
6025 else if (dbt == VT_DOUBLE)
6026 vtop->c.d = (double)vtop->c.ld;
6027 } else if (sf && dbt == (VT_LLONG|VT_UNSIGNED)) {
6028 vtop->c.ull = (unsigned long long)vtop->c.ld;
6029 } else if (sf && dbt == VT_BOOL) {
6030 vtop->c.i = (vtop->c.ld != 0);
6031 } else {
6032 if(sf)
6033 vtop->c.ll = (long long)vtop->c.ld;
6034 else if (sbt == (VT_LLONG|VT_UNSIGNED))
6035 vtop->c.ll = vtop->c.ull;
6036 else if (sbt & VT_UNSIGNED)
6037 vtop->c.ll = vtop->c.ui;
6038 else if (sbt != VT_LLONG)
6039 vtop->c.ll = vtop->c.i;
6041 if (dbt == (VT_LLONG|VT_UNSIGNED))
6042 vtop->c.ull = vtop->c.ll;
6043 else if (dbt == VT_BOOL)
6044 vtop->c.i = (vtop->c.ll != 0);
6045 else if (dbt != VT_LLONG) {
6046 int s = 0;
6047 if ((dbt & VT_BTYPE) == VT_BYTE)
6048 s = 24;
6049 else if ((dbt & VT_BTYPE) == VT_SHORT)
6050 s = 16;
6052 if(dbt & VT_UNSIGNED)
6053 vtop->c.ui = ((unsigned int)vtop->c.ll << s) >> s;
6054 else
6055 vtop->c.i = ((int)vtop->c.ll << s) >> s;
6058 } else if (p && dbt == VT_BOOL) {
6059 vtop->r = VT_CONST;
6060 vtop->c.i = 1;
6061 } else if (!nocode_wanted) {
6062 /* non constant case: generate code */
6063 if (sf && df) {
6064 /* convert from fp to fp */
6065 gen_cvt_ftof(dbt);
6066 } else if (df) {
6067 /* convert int to fp */
6068 gen_cvt_itof1(dbt);
6069 } else if (sf) {
6070 /* convert fp to int */
6071 if (dbt == VT_BOOL) {
6072 vpushi(0);
6073 gen_op(TOK_NE);
6074 } else {
6075 /* we handle char/short/etc... with generic code */
6076 if (dbt != (VT_INT | VT_UNSIGNED) &&
6077 dbt != (VT_LLONG | VT_UNSIGNED) &&
6078 dbt != VT_LLONG)
6079 dbt = VT_INT;
6080 gen_cvt_ftoi1(dbt);
6081 if (dbt == VT_INT && (type->t & (VT_BTYPE | VT_UNSIGNED)) != dbt) {
6082 /* additional cast for char/short... */
6083 vtop->type.t = dbt;
6084 gen_cast(type);
6087 } else if ((dbt & VT_BTYPE) == VT_LLONG) {
6088 if ((sbt & VT_BTYPE) != VT_LLONG) {
6089 /* scalar to long long */
6090 /* machine independent conversion */
6091 gv(RC_INT);
6092 /* generate high word */
6093 if (sbt == (VT_INT | VT_UNSIGNED)) {
6094 vpushi(0);
6095 gv(RC_INT);
6096 } else {
6097 gv_dup();
6098 vpushi(31);
6099 gen_op(TOK_SAR);
6101 /* patch second register */
6102 vtop[-1].r2 = vtop->r;
6103 vpop();
6105 } else if (dbt == VT_BOOL) {
6106 /* scalar to bool */
6107 vpushi(0);
6108 gen_op(TOK_NE);
6109 } else if ((dbt & VT_BTYPE) == VT_BYTE ||
6110 (dbt & VT_BTYPE) == VT_SHORT) {
6111 if (sbt == VT_PTR) {
6112 vtop->type.t = VT_INT;
6113 warning("nonportable conversion from pointer to char/short");
6115 force_charshort_cast(dbt);
6116 } else if ((dbt & VT_BTYPE) == VT_INT) {
6117 /* scalar to int */
6118 if (sbt == VT_LLONG) {
6119 /* from long long: just take low order word */
6120 lexpand();
6121 vpop();
6123 /* if lvalue and single word type, nothing to do because
6124 the lvalue already contains the real type size (see
6125 VT_LVAL_xxx constants) */
6128 } else if ((dbt & VT_BTYPE) == VT_PTR && !(vtop->r & VT_LVAL)) {
6129 /* if we are casting between pointer types,
6130 we must update the VT_LVAL_xxx size */
6131 vtop->r = (vtop->r & ~VT_LVAL_TYPE)
6132 | (lvalue_type(type->ref->type.t) & VT_LVAL_TYPE);
6134 vtop->type = *type;
6137 /* return type size. Put alignment at 'a' */
6138 static int type_size(CType *type, int *a)
6140 Sym *s;
6141 int bt;
6143 bt = type->t & VT_BTYPE;
6144 if (bt == VT_STRUCT) {
6145 /* struct/union */
6146 s = type->ref;
6147 *a = s->r;
6148 return s->c;
6149 } else if (bt == VT_PTR) {
6150 if (type->t & VT_ARRAY) {
6151 s = type->ref;
6152 return type_size(&s->type, a) * s->c;
6153 } else {
6154 *a = PTR_SIZE;
6155 return PTR_SIZE;
6157 } else if (bt == VT_LDOUBLE) {
6158 *a = LDOUBLE_ALIGN;
6159 return LDOUBLE_SIZE;
6160 } else if (bt == VT_DOUBLE || bt == VT_LLONG) {
6161 #ifdef TCC_TARGET_I386
6162 *a = 4;
6163 #elif defined(TCC_TARGET_ARM)
6164 #ifdef TCC_ARM_EABI
6165 *a = 8;
6166 #else
6167 *a = 4;
6168 #endif
6169 #else
6170 *a = 8;
6171 #endif
6172 return 8;
6173 } else if (bt == VT_INT || bt == VT_ENUM || bt == VT_FLOAT) {
6174 *a = 4;
6175 return 4;
6176 } else if (bt == VT_SHORT) {
6177 *a = 2;
6178 return 2;
6179 } else {
6180 /* char, void, function, _Bool */
6181 *a = 1;
6182 return 1;
6186 /* return the pointed type of t */
6187 static inline CType *pointed_type(CType *type)
6189 return &type->ref->type;
6192 /* modify type so that its it is a pointer to type. */
6193 static void mk_pointer(CType *type)
6195 Sym *s;
6196 s = sym_push(SYM_FIELD, type, 0, -1);
6197 type->t = VT_PTR | (type->t & ~VT_TYPE);
6198 type->ref = s;
6201 /* compare function types. OLD functions match any new functions */
6202 static int is_compatible_func(CType *type1, CType *type2)
6204 Sym *s1, *s2;
6206 s1 = type1->ref;
6207 s2 = type2->ref;
6208 if (!is_compatible_types(&s1->type, &s2->type))
6209 return 0;
6210 /* check func_call */
6211 if (FUNC_CALL(s1->r) != FUNC_CALL(s2->r))
6212 return 0;
6213 /* XXX: not complete */
6214 if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
6215 return 1;
6216 if (s1->c != s2->c)
6217 return 0;
6218 while (s1 != NULL) {
6219 if (s2 == NULL)
6220 return 0;
6221 if (!is_compatible_parameter_types(&s1->type, &s2->type))
6222 return 0;
6223 s1 = s1->next;
6224 s2 = s2->next;
6226 if (s2)
6227 return 0;
6228 return 1;
6231 /* return true if type1 and type2 are the same. If unqualified is
6232 true, qualifiers on the types are ignored.
6234 - enums are not checked as gcc __builtin_types_compatible_p ()
6236 static int compare_types(CType *type1, CType *type2, int unqualified)
6238 int bt1, t1, t2;
6240 t1 = type1->t & VT_TYPE;
6241 t2 = type2->t & VT_TYPE;
6242 if (unqualified) {
6243 /* strip qualifiers before comparing */
6244 t1 &= ~(VT_CONSTANT | VT_VOLATILE);
6245 t2 &= ~(VT_CONSTANT | VT_VOLATILE);
6247 /* XXX: bitfields ? */
6248 if (t1 != t2)
6249 return 0;
6250 /* test more complicated cases */
6251 bt1 = t1 & VT_BTYPE;
6252 if (bt1 == VT_PTR) {
6253 type1 = pointed_type(type1);
6254 type2 = pointed_type(type2);
6255 return is_compatible_types(type1, type2);
6256 } else if (bt1 == VT_STRUCT) {
6257 return (type1->ref == type2->ref);
6258 } else if (bt1 == VT_FUNC) {
6259 return is_compatible_func(type1, type2);
6260 } else {
6261 return 1;
6265 /* return true if type1 and type2 are exactly the same (including
6266 qualifiers).
6268 static int is_compatible_types(CType *type1, CType *type2)
6270 return compare_types(type1,type2,0);
6273 /* return true if type1 and type2 are the same (ignoring qualifiers).
6275 static int is_compatible_parameter_types(CType *type1, CType *type2)
6277 return compare_types(type1,type2,1);
6280 /* print a type. If 'varstr' is not NULL, then the variable is also
6281 printed in the type */
6282 /* XXX: union */
6283 /* XXX: add array and function pointers */
6284 void type_to_str(char *buf, int buf_size,
6285 CType *type, const char *varstr)
6287 int bt, v, t;
6288 Sym *s, *sa;
6289 char buf1[256];
6290 const char *tstr;
6292 t = type->t & VT_TYPE;
6293 bt = t & VT_BTYPE;
6294 buf[0] = '\0';
6295 if (t & VT_CONSTANT)
6296 pstrcat(buf, buf_size, "const ");
6297 if (t & VT_VOLATILE)
6298 pstrcat(buf, buf_size, "volatile ");
6299 if (t & VT_UNSIGNED)
6300 pstrcat(buf, buf_size, "unsigned ");
6301 switch(bt) {
6302 case VT_VOID:
6303 tstr = "void";
6304 goto add_tstr;
6305 case VT_BOOL:
6306 tstr = "_Bool";
6307 goto add_tstr;
6308 case VT_BYTE:
6309 tstr = "char";
6310 goto add_tstr;
6311 case VT_SHORT:
6312 tstr = "short";
6313 goto add_tstr;
6314 case VT_INT:
6315 tstr = "int";
6316 goto add_tstr;
6317 case VT_LONG:
6318 tstr = "long";
6319 goto add_tstr;
6320 case VT_LLONG:
6321 tstr = "long long";
6322 goto add_tstr;
6323 case VT_FLOAT:
6324 tstr = "float";
6325 goto add_tstr;
6326 case VT_DOUBLE:
6327 tstr = "double";
6328 goto add_tstr;
6329 case VT_LDOUBLE:
6330 tstr = "long double";
6331 add_tstr:
6332 pstrcat(buf, buf_size, tstr);
6333 break;
6334 case VT_ENUM:
6335 case VT_STRUCT:
6336 if (bt == VT_STRUCT)
6337 tstr = "struct ";
6338 else
6339 tstr = "enum ";
6340 pstrcat(buf, buf_size, tstr);
6341 v = type->ref->v & ~SYM_STRUCT;
6342 if (v >= SYM_FIRST_ANOM)
6343 pstrcat(buf, buf_size, "<anonymous>");
6344 else
6345 pstrcat(buf, buf_size, get_tok_str(v, NULL));
6346 break;
6347 case VT_FUNC:
6348 s = type->ref;
6349 type_to_str(buf, buf_size, &s->type, varstr);
6350 pstrcat(buf, buf_size, "(");
6351 sa = s->next;
6352 while (sa != NULL) {
6353 type_to_str(buf1, sizeof(buf1), &sa->type, NULL);
6354 pstrcat(buf, buf_size, buf1);
6355 sa = sa->next;
6356 if (sa)
6357 pstrcat(buf, buf_size, ", ");
6359 pstrcat(buf, buf_size, ")");
6360 goto no_var;
6361 case VT_PTR:
6362 s = type->ref;
6363 pstrcpy(buf1, sizeof(buf1), "*");
6364 if (varstr)
6365 pstrcat(buf1, sizeof(buf1), varstr);
6366 type_to_str(buf, buf_size, &s->type, buf1);
6367 goto no_var;
6369 if (varstr) {
6370 pstrcat(buf, buf_size, " ");
6371 pstrcat(buf, buf_size, varstr);
6373 no_var: ;
6376 /* verify type compatibility to store vtop in 'dt' type, and generate
6377 casts if needed. */
6378 static void gen_assign_cast(CType *dt)
6380 CType *st, *type1, *type2, tmp_type1, tmp_type2;
6381 char buf1[256], buf2[256];
6382 int dbt, sbt;
6384 st = &vtop->type; /* source type */
6385 dbt = dt->t & VT_BTYPE;
6386 sbt = st->t & VT_BTYPE;
6387 if (dt->t & VT_CONSTANT)
6388 warning("assignment of read-only location");
6389 switch(dbt) {
6390 case VT_PTR:
6391 /* special cases for pointers */
6392 /* '0' can also be a pointer */
6393 if (is_null_pointer(vtop))
6394 goto type_ok;
6395 /* accept implicit pointer to integer cast with warning */
6396 if (is_integer_btype(sbt)) {
6397 warning("assignment makes pointer from integer without a cast");
6398 goto type_ok;
6400 type1 = pointed_type(dt);
6401 /* a function is implicitely a function pointer */
6402 if (sbt == VT_FUNC) {
6403 if ((type1->t & VT_BTYPE) != VT_VOID &&
6404 !is_compatible_types(pointed_type(dt), st))
6405 goto error;
6406 else
6407 goto type_ok;
6409 if (sbt != VT_PTR)
6410 goto error;
6411 type2 = pointed_type(st);
6412 if ((type1->t & VT_BTYPE) == VT_VOID ||
6413 (type2->t & VT_BTYPE) == VT_VOID) {
6414 /* void * can match anything */
6415 } else {
6416 /* exact type match, except for unsigned */
6417 tmp_type1 = *type1;
6418 tmp_type2 = *type2;
6419 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
6420 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
6421 if (!is_compatible_types(&tmp_type1, &tmp_type2))
6422 warning("assignment from incompatible pointer type");
6424 /* check const and volatile */
6425 if ((!(type1->t & VT_CONSTANT) && (type2->t & VT_CONSTANT)) ||
6426 (!(type1->t & VT_VOLATILE) && (type2->t & VT_VOLATILE)))
6427 warning("assignment discards qualifiers from pointer target type");
6428 break;
6429 case VT_BYTE:
6430 case VT_SHORT:
6431 case VT_INT:
6432 case VT_LLONG:
6433 if (sbt == VT_PTR || sbt == VT_FUNC) {
6434 warning("assignment makes integer from pointer without a cast");
6436 /* XXX: more tests */
6437 break;
6438 case VT_STRUCT:
6439 tmp_type1 = *dt;
6440 tmp_type2 = *st;
6441 tmp_type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
6442 tmp_type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
6443 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
6444 error:
6445 type_to_str(buf1, sizeof(buf1), st, NULL);
6446 type_to_str(buf2, sizeof(buf2), dt, NULL);
6447 error("cannot cast '%s' to '%s'", buf1, buf2);
6449 break;
6451 type_ok:
6452 gen_cast(dt);
6455 /* store vtop in lvalue pushed on stack */
6456 void vstore(void)
6458 int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
6460 ft = vtop[-1].type.t;
6461 sbt = vtop->type.t & VT_BTYPE;
6462 dbt = ft & VT_BTYPE;
6463 if (((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
6464 (sbt == VT_INT && dbt == VT_SHORT)) {
6465 /* optimize char/short casts */
6466 delayed_cast = VT_MUSTCAST;
6467 vtop->type.t = ft & (VT_TYPE & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT)));
6468 /* XXX: factorize */
6469 if (ft & VT_CONSTANT)
6470 warning("assignment of read-only location");
6471 } else {
6472 delayed_cast = 0;
6473 if (!(ft & VT_BITFIELD))
6474 gen_assign_cast(&vtop[-1].type);
6477 if (sbt == VT_STRUCT) {
6478 /* if structure, only generate pointer */
6479 /* structure assignment : generate memcpy */
6480 /* XXX: optimize if small size */
6481 if (!nocode_wanted) {
6482 size = type_size(&vtop->type, &align);
6484 #ifdef TCC_ARM_EABI
6485 if(!(align & 7))
6486 vpush_global_sym(&func_old_type, TOK_memcpy8);
6487 else if(!(align & 3))
6488 vpush_global_sym(&func_old_type, TOK_memcpy4);
6489 else
6490 #endif
6491 vpush_global_sym(&func_old_type, TOK_memcpy);
6493 /* destination */
6494 vpushv(vtop - 2);
6495 vtop->type.t = VT_INT;
6496 gaddrof();
6497 /* source */
6498 vpushv(vtop - 2);
6499 vtop->type.t = VT_INT;
6500 gaddrof();
6501 /* type size */
6502 vpushi(size);
6503 gfunc_call(3);
6505 vswap();
6506 vpop();
6507 } else {
6508 vswap();
6509 vpop();
6511 /* leave source on stack */
6512 } else if (ft & VT_BITFIELD) {
6513 /* bitfield store handling */
6514 bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
6515 bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
6516 /* remove bit field info to avoid loops */
6517 vtop[-1].type.t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
6519 /* duplicate source into other register */
6520 gv_dup();
6521 vswap();
6522 vrott(3);
6524 if((ft & VT_BTYPE) == VT_BOOL) {
6525 gen_cast(&vtop[-1].type);
6526 vtop[-1].type.t = (vtop[-1].type.t & ~VT_BTYPE) | (VT_BYTE | VT_UNSIGNED);
6529 /* duplicate destination */
6530 vdup();
6531 vtop[-1] = vtop[-2];
6533 /* mask and shift source */
6534 if((ft & VT_BTYPE) != VT_BOOL) {
6535 vpushi((1 << bit_size) - 1);
6536 gen_op('&');
6538 vpushi(bit_pos);
6539 gen_op(TOK_SHL);
6540 /* load destination, mask and or with source */
6541 vswap();
6542 vpushi(~(((1 << bit_size) - 1) << bit_pos));
6543 gen_op('&');
6544 gen_op('|');
6545 /* store result */
6546 vstore();
6548 /* pop off shifted source from "duplicate source..." above */
6549 vpop();
6551 } else {
6552 #ifdef CONFIG_TCC_BCHECK
6553 /* bound check case */
6554 if (vtop[-1].r & VT_MUSTBOUND) {
6555 vswap();
6556 gbound();
6557 vswap();
6559 #endif
6560 if (!nocode_wanted) {
6561 rc = RC_INT;
6562 if (is_float(ft))
6563 rc = RC_FLOAT;
6564 r = gv(rc); /* generate value */
6565 /* if lvalue was saved on stack, must read it */
6566 if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
6567 SValue sv;
6568 t = get_reg(RC_INT);
6569 sv.type.t = VT_INT;
6570 sv.r = VT_LOCAL | VT_LVAL;
6571 sv.c.ul = vtop[-1].c.ul;
6572 load(t, &sv);
6573 vtop[-1].r = t | VT_LVAL;
6575 store(r, vtop - 1);
6576 /* two word case handling : store second register at word + 4 */
6577 if ((ft & VT_BTYPE) == VT_LLONG) {
6578 vswap();
6579 /* convert to int to increment easily */
6580 vtop->type.t = VT_INT;
6581 gaddrof();
6582 vpushi(4);
6583 gen_op('+');
6584 vtop->r |= VT_LVAL;
6585 vswap();
6586 /* XXX: it works because r2 is spilled last ! */
6587 store(vtop->r2, vtop - 1);
6590 vswap();
6591 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
6592 vtop->r |= delayed_cast;
6596 /* post defines POST/PRE add. c is the token ++ or -- */
6597 void inc(int post, int c)
6599 test_lvalue();
6600 vdup(); /* save lvalue */
6601 if (post) {
6602 gv_dup(); /* duplicate value */
6603 vrotb(3);
6604 vrotb(3);
6606 /* add constant */
6607 vpushi(c - TOK_MID);
6608 gen_op('+');
6609 vstore(); /* store value */
6610 if (post)
6611 vpop(); /* if post op, return saved value */
6614 /* Parse GNUC __attribute__ extension. Currently, the following
6615 extensions are recognized:
6616 - aligned(n) : set data/function alignment.
6617 - packed : force data alignment to 1
6618 - section(x) : generate data/code in this section.
6619 - unused : currently ignored, but may be used someday.
6620 - regparm(n) : pass function parameters in registers (i386 only)
6622 static void parse_attribute(AttributeDef *ad)
6624 int t, n;
6626 while (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) {
6627 next();
6628 skip('(');
6629 skip('(');
6630 while (tok != ')') {
6631 if (tok < TOK_IDENT)
6632 expect("attribute name");
6633 t = tok;
6634 next();
6635 switch(t) {
6636 case TOK_SECTION1:
6637 case TOK_SECTION2:
6638 skip('(');
6639 if (tok != TOK_STR)
6640 expect("section name");
6641 ad->section = find_section(tcc_state, (char *)tokc.cstr->data);
6642 next();
6643 skip(')');
6644 break;
6645 case TOK_ALIGNED1:
6646 case TOK_ALIGNED2:
6647 if (tok == '(') {
6648 next();
6649 n = expr_const();
6650 if (n <= 0 || (n & (n - 1)) != 0)
6651 error("alignment must be a positive power of two");
6652 skip(')');
6653 } else {
6654 n = MAX_ALIGN;
6656 ad->aligned = n;
6657 break;
6658 case TOK_PACKED1:
6659 case TOK_PACKED2:
6660 ad->packed = 1;
6661 break;
6662 case TOK_UNUSED1:
6663 case TOK_UNUSED2:
6664 /* currently, no need to handle it because tcc does not
6665 track unused objects */
6666 break;
6667 case TOK_NORETURN1:
6668 case TOK_NORETURN2:
6669 /* currently, no need to handle it because tcc does not
6670 track unused objects */
6671 break;
6672 case TOK_CDECL1:
6673 case TOK_CDECL2:
6674 case TOK_CDECL3:
6675 FUNC_CALL(ad->func_attr) = FUNC_CDECL;
6676 break;
6677 case TOK_STDCALL1:
6678 case TOK_STDCALL2:
6679 case TOK_STDCALL3:
6680 FUNC_CALL(ad->func_attr) = FUNC_STDCALL;
6681 break;
6682 #ifdef TCC_TARGET_I386
6683 case TOK_REGPARM1:
6684 case TOK_REGPARM2:
6685 skip('(');
6686 n = expr_const();
6687 if (n > 3)
6688 n = 3;
6689 else if (n < 0)
6690 n = 0;
6691 if (n > 0)
6692 FUNC_CALL(ad->func_attr) = FUNC_FASTCALL1 + n - 1;
6693 skip(')');
6694 break;
6695 case TOK_FASTCALL1:
6696 case TOK_FASTCALL2:
6697 case TOK_FASTCALL3:
6698 FUNC_CALL(ad->func_attr) = FUNC_FASTCALLW;
6699 break;
6700 #endif
6701 case TOK_DLLEXPORT:
6702 FUNC_EXPORT(ad->func_attr) = 1;
6703 break;
6704 default:
6705 if (tcc_state->warn_unsupported)
6706 warning("'%s' attribute ignored", get_tok_str(t, NULL));
6707 /* skip parameters */
6708 if (tok == '(') {
6709 int parenthesis = 0;
6710 do {
6711 if (tok == '(')
6712 parenthesis++;
6713 else if (tok == ')')
6714 parenthesis--;
6715 next();
6716 } while (parenthesis && tok != -1);
6718 break;
6720 if (tok != ',')
6721 break;
6722 next();
6724 skip(')');
6725 skip(')');
6729 /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
6730 static void struct_decl(CType *type, int u)
6732 int a, v, size, align, maxalign, c, offset;
6733 int bit_size, bit_pos, bsize, bt, lbit_pos, prevbt;
6734 Sym *s, *ss, *ass, **ps;
6735 AttributeDef ad;
6736 CType type1, btype;
6738 a = tok; /* save decl type */
6739 next();
6740 if (tok != '{') {
6741 v = tok;
6742 next();
6743 /* struct already defined ? return it */
6744 if (v < TOK_IDENT)
6745 expect("struct/union/enum name");
6746 s = struct_find(v);
6747 if (s) {
6748 if (s->type.t != a)
6749 error("invalid type");
6750 goto do_decl;
6752 } else {
6753 v = anon_sym++;
6755 type1.t = a;
6756 /* we put an undefined size for struct/union */
6757 s = sym_push(v | SYM_STRUCT, &type1, 0, -1);
6758 s->r = 0; /* default alignment is zero as gcc */
6759 /* put struct/union/enum name in type */
6760 do_decl:
6761 type->t = u;
6762 type->ref = s;
6764 if (tok == '{') {
6765 next();
6766 if (s->c != -1)
6767 error("struct/union/enum already defined");
6768 /* cannot be empty */
6769 c = 0;
6770 /* non empty enums are not allowed */
6771 if (a == TOK_ENUM) {
6772 for(;;) {
6773 v = tok;
6774 if (v < TOK_UIDENT)
6775 expect("identifier");
6776 next();
6777 if (tok == '=') {
6778 next();
6779 c = expr_const();
6781 /* enum symbols have static storage */
6782 ss = sym_push(v, &int_type, VT_CONST, c);
6783 ss->type.t |= VT_STATIC;
6784 if (tok != ',')
6785 break;
6786 next();
6787 c++;
6788 /* NOTE: we accept a trailing comma */
6789 if (tok == '}')
6790 break;
6792 skip('}');
6793 } else {
6794 maxalign = 1;
6795 ps = &s->next;
6796 prevbt = VT_INT;
6797 bit_pos = 0;
6798 offset = 0;
6799 while (tok != '}') {
6800 parse_btype(&btype, &ad);
6801 while (1) {
6802 bit_size = -1;
6803 v = 0;
6804 type1 = btype;
6805 if (tok != ':') {
6806 type_decl(&type1, &ad, &v, TYPE_DIRECT | TYPE_ABSTRACT);
6807 if (v == 0 && (type1.t & VT_BTYPE) != VT_STRUCT)
6808 expect("identifier");
6809 if ((type1.t & VT_BTYPE) == VT_FUNC ||
6810 (type1.t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN | VT_INLINE)))
6811 error("invalid type for '%s'",
6812 get_tok_str(v, NULL));
6814 if (tok == ':') {
6815 next();
6816 bit_size = expr_const();
6817 /* XXX: handle v = 0 case for messages */
6818 if (bit_size < 0)
6819 error("negative width in bit-field '%s'",
6820 get_tok_str(v, NULL));
6821 if (v && bit_size == 0)
6822 error("zero width for bit-field '%s'",
6823 get_tok_str(v, NULL));
6825 size = type_size(&type1, &align);
6826 if (ad.aligned) {
6827 if (align < ad.aligned)
6828 align = ad.aligned;
6829 } else if (ad.packed) {
6830 align = 1;
6831 } else if (*tcc_state->pack_stack_ptr) {
6832 if (align > *tcc_state->pack_stack_ptr)
6833 align = *tcc_state->pack_stack_ptr;
6835 lbit_pos = 0;
6836 if (bit_size >= 0) {
6837 bt = type1.t & VT_BTYPE;
6838 if (bt != VT_INT &&
6839 bt != VT_BYTE &&
6840 bt != VT_SHORT &&
6841 bt != VT_BOOL &&
6842 bt != VT_ENUM)
6843 error("bitfields must have scalar type");
6844 bsize = size * 8;
6845 if (bit_size > bsize) {
6846 error("width of '%s' exceeds its type",
6847 get_tok_str(v, NULL));
6848 } else if (bit_size == bsize) {
6849 /* no need for bit fields */
6850 bit_pos = 0;
6851 } else if (bit_size == 0) {
6852 /* XXX: what to do if only padding in a
6853 structure ? */
6854 /* zero size: means to pad */
6855 bit_pos = 0;
6856 } else {
6857 /* we do not have enough room ?
6858 did the type change?
6859 is it a union? */
6860 if ((bit_pos + bit_size) > bsize ||
6861 bt != prevbt || a == TOK_UNION)
6862 bit_pos = 0;
6863 lbit_pos = bit_pos;
6864 /* XXX: handle LSB first */
6865 type1.t |= VT_BITFIELD |
6866 (bit_pos << VT_STRUCT_SHIFT) |
6867 (bit_size << (VT_STRUCT_SHIFT + 6));
6868 bit_pos += bit_size;
6870 prevbt = bt;
6871 } else {
6872 bit_pos = 0;
6874 if (v != 0 || (type1.t & VT_BTYPE) == VT_STRUCT) {
6875 /* add new memory data only if starting
6876 bit field */
6877 if (lbit_pos == 0) {
6878 if (a == TOK_STRUCT) {
6879 c = (c + align - 1) & -align;
6880 offset = c;
6881 if (size > 0)
6882 c += size;
6883 } else {
6884 offset = 0;
6885 if (size > c)
6886 c = size;
6888 if (align > maxalign)
6889 maxalign = align;
6891 #if 0
6892 printf("add field %s offset=%d",
6893 get_tok_str(v, NULL), offset);
6894 if (type1.t & VT_BITFIELD) {
6895 printf(" pos=%d size=%d",
6896 (type1.t >> VT_STRUCT_SHIFT) & 0x3f,
6897 (type1.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
6899 printf("\n");
6900 #endif
6902 if (v == 0 && (type1.t & VT_BTYPE) == VT_STRUCT) {
6903 ass = type1.ref;
6904 while ((ass = ass->next) != NULL) {
6905 ss = sym_push(ass->v, &ass->type, 0, offset + ass->c);
6906 *ps = ss;
6907 ps = &ss->next;
6909 } else if (v) {
6910 ss = sym_push(v | SYM_FIELD, &type1, 0, offset);
6911 *ps = ss;
6912 ps = &ss->next;
6914 if (tok == ';' || tok == TOK_EOF)
6915 break;
6916 skip(',');
6918 skip(';');
6920 skip('}');
6921 /* store size and alignment */
6922 s->c = (c + maxalign - 1) & -maxalign;
6923 s->r = maxalign;
6928 /* return 0 if no type declaration. otherwise, return the basic type
6929 and skip it.
6931 static int parse_btype(CType *type, AttributeDef *ad)
6933 int t, u, type_found, typespec_found, typedef_found;
6934 Sym *s;
6935 CType type1;
6937 memset(ad, 0, sizeof(AttributeDef));
6938 type_found = 0;
6939 typespec_found = 0;
6940 typedef_found = 0;
6941 t = 0;
6942 while(1) {
6943 switch(tok) {
6944 case TOK_EXTENSION:
6945 /* currently, we really ignore extension */
6946 next();
6947 continue;
6949 /* basic types */
6950 case TOK_CHAR:
6951 u = VT_BYTE;
6952 basic_type:
6953 next();
6954 basic_type1:
6955 if ((t & VT_BTYPE) != 0)
6956 error("too many basic types");
6957 t |= u;
6958 typespec_found = 1;
6959 break;
6960 case TOK_VOID:
6961 u = VT_VOID;
6962 goto basic_type;
6963 case TOK_SHORT:
6964 u = VT_SHORT;
6965 goto basic_type;
6966 case TOK_INT:
6967 next();
6968 typespec_found = 1;
6969 break;
6970 case TOK_LONG:
6971 next();
6972 if ((t & VT_BTYPE) == VT_DOUBLE) {
6973 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6974 } else if ((t & VT_BTYPE) == VT_LONG) {
6975 t = (t & ~VT_BTYPE) | VT_LLONG;
6976 } else {
6977 u = VT_LONG;
6978 goto basic_type1;
6980 break;
6981 case TOK_BOOL:
6982 u = VT_BOOL;
6983 goto basic_type;
6984 case TOK_FLOAT:
6985 u = VT_FLOAT;
6986 goto basic_type;
6987 case TOK_DOUBLE:
6988 next();
6989 if ((t & VT_BTYPE) == VT_LONG) {
6990 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6991 } else {
6992 u = VT_DOUBLE;
6993 goto basic_type1;
6995 break;
6996 case TOK_ENUM:
6997 struct_decl(&type1, VT_ENUM);
6998 basic_type2:
6999 u = type1.t;
7000 type->ref = type1.ref;
7001 goto basic_type1;
7002 case TOK_STRUCT:
7003 case TOK_UNION:
7004 struct_decl(&type1, VT_STRUCT);
7005 goto basic_type2;
7007 /* type modifiers */
7008 case TOK_CONST1:
7009 case TOK_CONST2:
7010 case TOK_CONST3:
7011 t |= VT_CONSTANT;
7012 next();
7013 break;
7014 case TOK_VOLATILE1:
7015 case TOK_VOLATILE2:
7016 case TOK_VOLATILE3:
7017 t |= VT_VOLATILE;
7018 next();
7019 break;
7020 case TOK_SIGNED1:
7021 case TOK_SIGNED2:
7022 case TOK_SIGNED3:
7023 typespec_found = 1;
7024 t |= VT_SIGNED;
7025 next();
7026 break;
7027 case TOK_REGISTER:
7028 case TOK_AUTO:
7029 case TOK_RESTRICT1:
7030 case TOK_RESTRICT2:
7031 case TOK_RESTRICT3:
7032 next();
7033 break;
7034 case TOK_UNSIGNED:
7035 t |= VT_UNSIGNED;
7036 next();
7037 typespec_found = 1;
7038 break;
7040 /* storage */
7041 case TOK_EXTERN:
7042 t |= VT_EXTERN;
7043 next();
7044 break;
7045 case TOK_STATIC:
7046 t |= VT_STATIC;
7047 next();
7048 break;
7049 case TOK_TYPEDEF:
7050 t |= VT_TYPEDEF;
7051 next();
7052 break;
7053 case TOK_INLINE1:
7054 case TOK_INLINE2:
7055 case TOK_INLINE3:
7056 t |= VT_INLINE;
7057 next();
7058 break;
7060 /* GNUC attribute */
7061 case TOK_ATTRIBUTE1:
7062 case TOK_ATTRIBUTE2:
7063 parse_attribute(ad);
7064 break;
7065 /* GNUC typeof */
7066 case TOK_TYPEOF1:
7067 case TOK_TYPEOF2:
7068 case TOK_TYPEOF3:
7069 next();
7070 parse_expr_type(&type1);
7071 goto basic_type2;
7072 default:
7073 if (typespec_found || typedef_found)
7074 goto the_end;
7075 s = sym_find(tok);
7076 if (!s || !(s->type.t & VT_TYPEDEF))
7077 goto the_end;
7078 typedef_found = 1;
7079 t |= (s->type.t & ~VT_TYPEDEF);
7080 type->ref = s->type.ref;
7081 next();
7082 typespec_found = 1;
7083 break;
7085 type_found = 1;
7087 the_end:
7088 if ((t & (VT_SIGNED|VT_UNSIGNED)) == (VT_SIGNED|VT_UNSIGNED))
7089 error("signed and unsigned modifier");
7090 if (tcc_state->char_is_unsigned) {
7091 if ((t & (VT_SIGNED|VT_UNSIGNED|VT_BTYPE)) == VT_BYTE)
7092 t |= VT_UNSIGNED;
7094 t &= ~VT_SIGNED;
7096 /* long is never used as type */
7097 if ((t & VT_BTYPE) == VT_LONG)
7098 t = (t & ~VT_BTYPE) | VT_INT;
7099 type->t = t;
7100 return type_found;
7103 /* convert a function parameter type (array to pointer and function to
7104 function pointer) */
7105 static inline void convert_parameter_type(CType *pt)
7107 /* remove const and volatile qualifiers (XXX: const could be used
7108 to indicate a const function parameter */
7109 pt->t &= ~(VT_CONSTANT | VT_VOLATILE);
7110 /* array must be transformed to pointer according to ANSI C */
7111 pt->t &= ~VT_ARRAY;
7112 if ((pt->t & VT_BTYPE) == VT_FUNC) {
7113 mk_pointer(pt);
7117 static void post_type(CType *type, AttributeDef *ad)
7119 int n, l, t1, arg_size, align;
7120 Sym **plast, *s, *first;
7121 AttributeDef ad1;
7122 CType pt;
7124 if (tok == '(') {
7125 /* function declaration */
7126 next();
7127 l = 0;
7128 first = NULL;
7129 plast = &first;
7130 arg_size = 0;
7131 if (tok != ')') {
7132 for(;;) {
7133 /* read param name and compute offset */
7134 if (l != FUNC_OLD) {
7135 if (!parse_btype(&pt, &ad1)) {
7136 if (l) {
7137 error("invalid type");
7138 } else {
7139 l = FUNC_OLD;
7140 goto old_proto;
7143 l = FUNC_NEW;
7144 if ((pt.t & VT_BTYPE) == VT_VOID && tok == ')')
7145 break;
7146 type_decl(&pt, &ad1, &n, TYPE_DIRECT | TYPE_ABSTRACT);
7147 if ((pt.t & VT_BTYPE) == VT_VOID)
7148 error("parameter declared as void");
7149 arg_size += (type_size(&pt, &align) + 3) & ~3;
7150 } else {
7151 old_proto:
7152 n = tok;
7153 if (n < TOK_UIDENT)
7154 expect("identifier");
7155 pt.t = VT_INT;
7156 next();
7158 convert_parameter_type(&pt);
7159 s = sym_push(n | SYM_FIELD, &pt, 0, 0);
7160 *plast = s;
7161 plast = &s->next;
7162 if (tok == ')')
7163 break;
7164 skip(',');
7165 if (l == FUNC_NEW && tok == TOK_DOTS) {
7166 l = FUNC_ELLIPSIS;
7167 next();
7168 break;
7172 /* if no parameters, then old type prototype */
7173 if (l == 0)
7174 l = FUNC_OLD;
7175 skip(')');
7176 t1 = type->t & VT_STORAGE;
7177 /* NOTE: const is ignored in returned type as it has a special
7178 meaning in gcc / C++ */
7179 type->t &= ~(VT_STORAGE | VT_CONSTANT);
7180 post_type(type, ad);
7181 /* we push a anonymous symbol which will contain the function prototype */
7182 FUNC_ARGS(ad->func_attr) = arg_size;
7183 s = sym_push(SYM_FIELD, type, ad->func_attr, l);
7184 s->next = first;
7185 type->t = t1 | VT_FUNC;
7186 type->ref = s;
7187 } else if (tok == '[') {
7188 /* array definition */
7189 next();
7190 n = -1;
7191 if (tok != ']') {
7192 n = expr_const();
7193 if (n < 0)
7194 error("invalid array size");
7196 skip(']');
7197 /* parse next post type */
7198 t1 = type->t & VT_STORAGE;
7199 type->t &= ~VT_STORAGE;
7200 post_type(type, ad);
7202 /* we push a anonymous symbol which will contain the array
7203 element type */
7204 s = sym_push(SYM_FIELD, type, 0, n);
7205 type->t = t1 | VT_ARRAY | VT_PTR;
7206 type->ref = s;
7210 /* Parse a type declaration (except basic type), and return the type
7211 in 'type'. 'td' is a bitmask indicating which kind of type decl is
7212 expected. 'type' should contain the basic type. 'ad' is the
7213 attribute definition of the basic type. It can be modified by
7214 type_decl().
7216 static void type_decl(CType *type, AttributeDef *ad, int *v, int td)
7218 Sym *s;
7219 CType type1, *type2;
7220 int qualifiers;
7222 while (tok == '*') {
7223 qualifiers = 0;
7224 redo:
7225 next();
7226 switch(tok) {
7227 case TOK_CONST1:
7228 case TOK_CONST2:
7229 case TOK_CONST3:
7230 qualifiers |= VT_CONSTANT;
7231 goto redo;
7232 case TOK_VOLATILE1:
7233 case TOK_VOLATILE2:
7234 case TOK_VOLATILE3:
7235 qualifiers |= VT_VOLATILE;
7236 goto redo;
7237 case TOK_RESTRICT1:
7238 case TOK_RESTRICT2:
7239 case TOK_RESTRICT3:
7240 goto redo;
7242 mk_pointer(type);
7243 type->t |= qualifiers;
7246 /* XXX: clarify attribute handling */
7247 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
7248 parse_attribute(ad);
7250 /* recursive type */
7251 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
7252 type1.t = 0; /* XXX: same as int */
7253 if (tok == '(') {
7254 next();
7255 /* XXX: this is not correct to modify 'ad' at this point, but
7256 the syntax is not clear */
7257 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
7258 parse_attribute(ad);
7259 type_decl(&type1, ad, v, td);
7260 skip(')');
7261 } else {
7262 /* type identifier */
7263 if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
7264 *v = tok;
7265 next();
7266 } else {
7267 if (!(td & TYPE_ABSTRACT))
7268 expect("identifier");
7269 *v = 0;
7272 post_type(type, ad);
7273 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
7274 parse_attribute(ad);
7275 if (!type1.t)
7276 return;
7277 /* append type at the end of type1 */
7278 type2 = &type1;
7279 for(;;) {
7280 s = type2->ref;
7281 type2 = &s->type;
7282 if (!type2->t) {
7283 *type2 = *type;
7284 break;
7287 *type = type1;
7290 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
7291 static int lvalue_type(int t)
7293 int bt, r;
7294 r = VT_LVAL;
7295 bt = t & VT_BTYPE;
7296 if (bt == VT_BYTE || bt == VT_BOOL)
7297 r |= VT_LVAL_BYTE;
7298 else if (bt == VT_SHORT)
7299 r |= VT_LVAL_SHORT;
7300 else
7301 return r;
7302 if (t & VT_UNSIGNED)
7303 r |= VT_LVAL_UNSIGNED;
7304 return r;
7307 /* indirection with full error checking and bound check */
7308 static void indir(void)
7310 if ((vtop->type.t & VT_BTYPE) != VT_PTR) {
7311 if ((vtop->type.t & VT_BTYPE) == VT_FUNC)
7312 return;
7313 expect("pointer");
7315 if ((vtop->r & VT_LVAL) && !nocode_wanted)
7316 gv(RC_INT);
7317 vtop->type = *pointed_type(&vtop->type);
7318 /* Arrays and functions are never lvalues */
7319 if (!(vtop->type.t & VT_ARRAY)
7320 && (vtop->type.t & VT_BTYPE) != VT_FUNC) {
7321 vtop->r |= lvalue_type(vtop->type.t);
7322 /* if bound checking, the referenced pointer must be checked */
7323 if (do_bounds_check)
7324 vtop->r |= VT_MUSTBOUND;
7328 /* pass a parameter to a function and do type checking and casting */
7329 static void gfunc_param_typed(Sym *func, Sym *arg)
7331 int func_type;
7332 CType type;
7334 func_type = func->c;
7335 if (func_type == FUNC_OLD ||
7336 (func_type == FUNC_ELLIPSIS && arg == NULL)) {
7337 /* default casting : only need to convert float to double */
7338 if ((vtop->type.t & VT_BTYPE) == VT_FLOAT) {
7339 type.t = VT_DOUBLE;
7340 gen_cast(&type);
7342 } else if (arg == NULL) {
7343 error("too many arguments to function");
7344 } else {
7345 type = arg->type;
7346 type.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
7347 gen_assign_cast(&type);
7351 /* parse an expression of the form '(type)' or '(expr)' and return its
7352 type */
7353 static void parse_expr_type(CType *type)
7355 int n;
7356 AttributeDef ad;
7358 skip('(');
7359 if (parse_btype(type, &ad)) {
7360 type_decl(type, &ad, &n, TYPE_ABSTRACT);
7361 } else {
7362 expr_type(type);
7364 skip(')');
7367 static void parse_type(CType *type)
7369 AttributeDef ad;
7370 int n;
7372 if (!parse_btype(type, &ad)) {
7373 expect("type");
7375 type_decl(type, &ad, &n, TYPE_ABSTRACT);
7378 static void vpush_tokc(int t)
7380 CType type;
7381 type.t = t;
7382 vsetc(&type, VT_CONST, &tokc);
7385 static void unary(void)
7387 int n, t, align, size, r;
7388 CType type;
7389 Sym *s;
7390 AttributeDef ad;
7392 /* XXX: GCC 2.95.3 does not generate a table although it should be
7393 better here */
7394 tok_next:
7395 switch(tok) {
7396 case TOK_EXTENSION:
7397 next();
7398 goto tok_next;
7399 case TOK_CINT:
7400 case TOK_CCHAR:
7401 case TOK_LCHAR:
7402 vpushi(tokc.i);
7403 next();
7404 break;
7405 case TOK_CUINT:
7406 vpush_tokc(VT_INT | VT_UNSIGNED);
7407 next();
7408 break;
7409 case TOK_CLLONG:
7410 vpush_tokc(VT_LLONG);
7411 next();
7412 break;
7413 case TOK_CULLONG:
7414 vpush_tokc(VT_LLONG | VT_UNSIGNED);
7415 next();
7416 break;
7417 case TOK_CFLOAT:
7418 vpush_tokc(VT_FLOAT);
7419 next();
7420 break;
7421 case TOK_CDOUBLE:
7422 vpush_tokc(VT_DOUBLE);
7423 next();
7424 break;
7425 case TOK_CLDOUBLE:
7426 vpush_tokc(VT_LDOUBLE);
7427 next();
7428 break;
7429 case TOK___FUNCTION__:
7430 if (!gnu_ext)
7431 goto tok_identifier;
7432 /* fall thru */
7433 case TOK___FUNC__:
7435 void *ptr;
7436 int len;
7437 /* special function name identifier */
7438 len = strlen(funcname) + 1;
7439 /* generate char[len] type */
7440 type.t = VT_BYTE;
7441 mk_pointer(&type);
7442 type.t |= VT_ARRAY;
7443 type.ref->c = len;
7444 vpush_ref(&type, data_section, data_section->data_offset, len);
7445 ptr = section_ptr_add(data_section, len);
7446 memcpy(ptr, funcname, len);
7447 next();
7449 break;
7450 case TOK_LSTR:
7451 #ifdef TCC_TARGET_PE
7452 t = VT_SHORT | VT_UNSIGNED;
7453 #else
7454 t = VT_INT;
7455 #endif
7456 goto str_init;
7457 case TOK_STR:
7458 /* string parsing */
7459 t = VT_BYTE;
7460 str_init:
7461 if (tcc_state->warn_write_strings)
7462 t |= VT_CONSTANT;
7463 type.t = t;
7464 mk_pointer(&type);
7465 type.t |= VT_ARRAY;
7466 memset(&ad, 0, sizeof(AttributeDef));
7467 decl_initializer_alloc(&type, &ad, VT_CONST, 2, 0, 0);
7468 break;
7469 case '(':
7470 next();
7471 /* cast ? */
7472 if (parse_btype(&type, &ad)) {
7473 type_decl(&type, &ad, &n, TYPE_ABSTRACT);
7474 skip(')');
7475 /* check ISOC99 compound literal */
7476 if (tok == '{') {
7477 /* data is allocated locally by default */
7478 if (global_expr)
7479 r = VT_CONST;
7480 else
7481 r = VT_LOCAL;
7482 /* all except arrays are lvalues */
7483 if (!(type.t & VT_ARRAY))
7484 r |= lvalue_type(type.t);
7485 memset(&ad, 0, sizeof(AttributeDef));
7486 decl_initializer_alloc(&type, &ad, r, 1, 0, 0);
7487 } else {
7488 unary();
7489 gen_cast(&type);
7491 } else if (tok == '{') {
7492 /* save all registers */
7493 save_regs(0);
7494 /* statement expression : we do not accept break/continue
7495 inside as GCC does */
7496 block(NULL, NULL, NULL, NULL, 0, 1);
7497 skip(')');
7498 } else {
7499 gexpr();
7500 skip(')');
7502 break;
7503 case '*':
7504 next();
7505 unary();
7506 indir();
7507 break;
7508 case '&':
7509 next();
7510 unary();
7511 /* functions names must be treated as function pointers,
7512 except for unary '&' and sizeof. Since we consider that
7513 functions are not lvalues, we only have to handle it
7514 there and in function calls. */
7515 /* arrays can also be used although they are not lvalues */
7516 if ((vtop->type.t & VT_BTYPE) != VT_FUNC &&
7517 !(vtop->type.t & VT_ARRAY) && !(vtop->type.t & VT_LLOCAL))
7518 test_lvalue();
7519 mk_pointer(&vtop->type);
7520 gaddrof();
7521 break;
7522 case '!':
7523 next();
7524 unary();
7525 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
7526 CType boolean;
7527 boolean.t = VT_BOOL;
7528 gen_cast(&boolean);
7529 vtop->c.i = !vtop->c.i;
7530 } else if ((vtop->r & VT_VALMASK) == VT_CMP)
7531 vtop->c.i = vtop->c.i ^ 1;
7532 else {
7533 save_regs(1);
7534 vseti(VT_JMP, gtst(1, 0));
7536 break;
7537 case '~':
7538 next();
7539 unary();
7540 vpushi(-1);
7541 gen_op('^');
7542 break;
7543 case '+':
7544 next();
7545 /* in order to force cast, we add zero */
7546 unary();
7547 if ((vtop->type.t & VT_BTYPE) == VT_PTR)
7548 error("pointer not accepted for unary plus");
7549 vpushi(0);
7550 gen_op('+');
7551 break;
7552 case TOK_SIZEOF:
7553 case TOK_ALIGNOF1:
7554 case TOK_ALIGNOF2:
7555 t = tok;
7556 next();
7557 if (tok == '(') {
7558 parse_expr_type(&type);
7559 } else {
7560 unary_type(&type);
7562 size = type_size(&type, &align);
7563 if (t == TOK_SIZEOF) {
7564 if (size < 0)
7565 error("sizeof applied to an incomplete type");
7566 vpushi(size);
7567 } else {
7568 vpushi(align);
7570 vtop->type.t |= VT_UNSIGNED;
7571 break;
7573 case TOK_builtin_types_compatible_p:
7575 CType type1, type2;
7576 next();
7577 skip('(');
7578 parse_type(&type1);
7579 skip(',');
7580 parse_type(&type2);
7581 skip(')');
7582 type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
7583 type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
7584 vpushi(is_compatible_types(&type1, &type2));
7586 break;
7587 case TOK_builtin_constant_p:
7589 int saved_nocode_wanted, res;
7590 next();
7591 skip('(');
7592 saved_nocode_wanted = nocode_wanted;
7593 nocode_wanted = 1;
7594 gexpr();
7595 res = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
7596 vpop();
7597 nocode_wanted = saved_nocode_wanted;
7598 skip(')');
7599 vpushi(res);
7601 break;
7602 case TOK_INC:
7603 case TOK_DEC:
7604 t = tok;
7605 next();
7606 unary();
7607 inc(0, t);
7608 break;
7609 case '-':
7610 next();
7611 vpushi(0);
7612 unary();
7613 gen_op('-');
7614 break;
7615 case TOK_LAND:
7616 if (!gnu_ext)
7617 goto tok_identifier;
7618 next();
7619 /* allow to take the address of a label */
7620 if (tok < TOK_UIDENT)
7621 expect("label identifier");
7622 s = label_find(tok);
7623 if (!s) {
7624 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
7625 } else {
7626 if (s->r == LABEL_DECLARED)
7627 s->r = LABEL_FORWARD;
7629 if (!s->type.t) {
7630 s->type.t = VT_VOID;
7631 mk_pointer(&s->type);
7632 s->type.t |= VT_STATIC;
7634 vset(&s->type, VT_CONST | VT_SYM, 0);
7635 vtop->sym = s;
7636 next();
7637 break;
7638 default:
7639 tok_identifier:
7640 t = tok;
7641 next();
7642 if (t < TOK_UIDENT)
7643 expect("identifier");
7644 s = sym_find(t);
7645 if (!s) {
7646 if (tok != '(')
7647 error("'%s' undeclared", get_tok_str(t, NULL));
7648 /* for simple function calls, we tolerate undeclared
7649 external reference to int() function */
7650 if (tcc_state->warn_implicit_function_declaration)
7651 warning("implicit declaration of function '%s'",
7652 get_tok_str(t, NULL));
7653 s = external_global_sym(t, &func_old_type, 0);
7655 if ((s->type.t & (VT_STATIC | VT_INLINE | VT_BTYPE)) ==
7656 (VT_STATIC | VT_INLINE | VT_FUNC)) {
7657 /* if referencing an inline function, then we generate a
7658 symbol to it if not already done. It will have the
7659 effect to generate code for it at the end of the
7660 compilation unit. Inline function as always
7661 generated in the text section. */
7662 if (!s->c)
7663 put_extern_sym(s, text_section, 0, 0);
7664 r = VT_SYM | VT_CONST;
7665 } else {
7666 r = s->r;
7668 vset(&s->type, r, s->c);
7669 /* if forward reference, we must point to s */
7670 if (vtop->r & VT_SYM) {
7671 vtop->sym = s;
7672 vtop->c.ul = 0;
7674 break;
7677 /* post operations */
7678 while (1) {
7679 if (tok == TOK_INC || tok == TOK_DEC) {
7680 inc(1, tok);
7681 next();
7682 } else if (tok == '.' || tok == TOK_ARROW) {
7683 /* field */
7684 if (tok == TOK_ARROW)
7685 indir();
7686 test_lvalue();
7687 gaddrof();
7688 next();
7689 /* expect pointer on structure */
7690 if ((vtop->type.t & VT_BTYPE) != VT_STRUCT)
7691 expect("struct or union");
7692 s = vtop->type.ref;
7693 /* find field */
7694 tok |= SYM_FIELD;
7695 while ((s = s->next) != NULL) {
7696 if (s->v == tok)
7697 break;
7699 if (!s)
7700 error("field not found: %s", get_tok_str(tok & ~SYM_FIELD, NULL));
7701 /* add field offset to pointer */
7702 vtop->type = char_pointer_type; /* change type to 'char *' */
7703 vpushi(s->c);
7704 gen_op('+');
7705 /* change type to field type, and set to lvalue */
7706 vtop->type = s->type;
7707 /* an array is never an lvalue */
7708 if (!(vtop->type.t & VT_ARRAY)) {
7709 vtop->r |= lvalue_type(vtop->type.t);
7710 /* if bound checking, the referenced pointer must be checked */
7711 if (do_bounds_check)
7712 vtop->r |= VT_MUSTBOUND;
7714 next();
7715 } else if (tok == '[') {
7716 next();
7717 gexpr();
7718 gen_op('+');
7719 indir();
7720 skip(']');
7721 } else if (tok == '(') {
7722 SValue ret;
7723 Sym *sa;
7724 int nb_args;
7726 /* function call */
7727 if ((vtop->type.t & VT_BTYPE) != VT_FUNC) {
7728 /* pointer test (no array accepted) */
7729 if ((vtop->type.t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
7730 vtop->type = *pointed_type(&vtop->type);
7731 if ((vtop->type.t & VT_BTYPE) != VT_FUNC)
7732 goto error_func;
7733 } else {
7734 error_func:
7735 expect("function pointer");
7737 } else {
7738 vtop->r &= ~VT_LVAL; /* no lvalue */
7740 /* get return type */
7741 s = vtop->type.ref;
7742 next();
7743 sa = s->next; /* first parameter */
7744 nb_args = 0;
7745 ret.r2 = VT_CONST;
7746 /* compute first implicit argument if a structure is returned */
7747 if ((s->type.t & VT_BTYPE) == VT_STRUCT) {
7748 /* get some space for the returned structure */
7749 size = type_size(&s->type, &align);
7750 loc = (loc - size) & -align;
7751 ret.type = s->type;
7752 ret.r = VT_LOCAL | VT_LVAL;
7753 /* pass it as 'int' to avoid structure arg passing
7754 problems */
7755 vseti(VT_LOCAL, loc);
7756 ret.c = vtop->c;
7757 nb_args++;
7758 } else {
7759 ret.type = s->type;
7760 /* return in register */
7761 if (is_float(ret.type.t)) {
7762 ret.r = REG_FRET;
7763 } else {
7764 if ((ret.type.t & VT_BTYPE) == VT_LLONG)
7765 ret.r2 = REG_LRET;
7766 ret.r = REG_IRET;
7768 ret.c.i = 0;
7770 if (tok != ')') {
7771 for(;;) {
7772 expr_eq();
7773 gfunc_param_typed(s, sa);
7774 nb_args++;
7775 if (sa)
7776 sa = sa->next;
7777 if (tok == ')')
7778 break;
7779 skip(',');
7782 if (sa)
7783 error("too few arguments to function");
7784 skip(')');
7785 if (!nocode_wanted) {
7786 gfunc_call(nb_args);
7787 } else {
7788 vtop -= (nb_args + 1);
7790 /* return value */
7791 vsetc(&ret.type, ret.r, &ret.c);
7792 vtop->r2 = ret.r2;
7793 } else {
7794 break;
7799 static void uneq(void)
7801 int t;
7803 unary();
7804 if (tok == '=' ||
7805 (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
7806 tok == TOK_A_XOR || tok == TOK_A_OR ||
7807 tok == TOK_A_SHL || tok == TOK_A_SAR) {
7808 test_lvalue();
7809 t = tok;
7810 next();
7811 if (t == '=') {
7812 expr_eq();
7813 } else {
7814 vdup();
7815 expr_eq();
7816 gen_op(t & 0x7f);
7818 vstore();
7822 static void expr_prod(void)
7824 int t;
7826 uneq();
7827 while (tok == '*' || tok == '/' || tok == '%') {
7828 t = tok;
7829 next();
7830 uneq();
7831 gen_op(t);
7835 static void expr_sum(void)
7837 int t;
7839 expr_prod();
7840 while (tok == '+' || tok == '-') {
7841 t = tok;
7842 next();
7843 expr_prod();
7844 gen_op(t);
7848 static void expr_shift(void)
7850 int t;
7852 expr_sum();
7853 while (tok == TOK_SHL || tok == TOK_SAR) {
7854 t = tok;
7855 next();
7856 expr_sum();
7857 gen_op(t);
7861 static void expr_cmp(void)
7863 int t;
7865 expr_shift();
7866 while ((tok >= TOK_ULE && tok <= TOK_GT) ||
7867 tok == TOK_ULT || tok == TOK_UGE) {
7868 t = tok;
7869 next();
7870 expr_shift();
7871 gen_op(t);
7875 static void expr_cmpeq(void)
7877 int t;
7879 expr_cmp();
7880 while (tok == TOK_EQ || tok == TOK_NE) {
7881 t = tok;
7882 next();
7883 expr_cmp();
7884 gen_op(t);
7888 static void expr_and(void)
7890 expr_cmpeq();
7891 while (tok == '&') {
7892 next();
7893 expr_cmpeq();
7894 gen_op('&');
7898 static void expr_xor(void)
7900 expr_and();
7901 while (tok == '^') {
7902 next();
7903 expr_and();
7904 gen_op('^');
7908 static void expr_or(void)
7910 expr_xor();
7911 while (tok == '|') {
7912 next();
7913 expr_xor();
7914 gen_op('|');
7918 /* XXX: fix this mess */
7919 static void expr_land_const(void)
7921 expr_or();
7922 while (tok == TOK_LAND) {
7923 next();
7924 expr_or();
7925 gen_op(TOK_LAND);
7929 /* XXX: fix this mess */
7930 static void expr_lor_const(void)
7932 expr_land_const();
7933 while (tok == TOK_LOR) {
7934 next();
7935 expr_land_const();
7936 gen_op(TOK_LOR);
7940 /* only used if non constant */
7941 static void expr_land(void)
7943 int t;
7945 expr_or();
7946 if (tok == TOK_LAND) {
7947 t = 0;
7948 save_regs(1);
7949 for(;;) {
7950 t = gtst(1, t);
7951 if (tok != TOK_LAND) {
7952 vseti(VT_JMPI, t);
7953 break;
7955 next();
7956 expr_or();
7961 static void expr_lor(void)
7963 int t;
7965 expr_land();
7966 if (tok == TOK_LOR) {
7967 t = 0;
7968 save_regs(1);
7969 for(;;) {
7970 t = gtst(0, t);
7971 if (tok != TOK_LOR) {
7972 vseti(VT_JMP, t);
7973 break;
7975 next();
7976 expr_land();
7981 /* XXX: better constant handling */
7982 static void expr_eq(void)
7984 int tt, u, r1, r2, rc, t1, t2, bt1, bt2;
7985 SValue sv;
7986 CType type, type1, type2;
7988 if (const_wanted) {
7989 expr_lor_const();
7990 if (tok == '?') {
7991 CType boolean;
7992 int c;
7993 boolean.t = VT_BOOL;
7994 vdup();
7995 gen_cast(&boolean);
7996 c = vtop->c.i;
7997 vpop();
7998 next();
7999 if (tok != ':' || !gnu_ext) {
8000 vpop();
8001 gexpr();
8003 if (!c)
8004 vpop();
8005 skip(':');
8006 expr_eq();
8007 if (c)
8008 vpop();
8010 } else {
8011 expr_lor();
8012 if (tok == '?') {
8013 next();
8014 if (vtop != vstack) {
8015 /* needed to avoid having different registers saved in
8016 each branch */
8017 if (is_float(vtop->type.t))
8018 rc = RC_FLOAT;
8019 else
8020 rc = RC_INT;
8021 gv(rc);
8022 save_regs(1);
8024 if (tok == ':' && gnu_ext) {
8025 gv_dup();
8026 tt = gtst(1, 0);
8027 } else {
8028 tt = gtst(1, 0);
8029 gexpr();
8031 type1 = vtop->type;
8032 sv = *vtop; /* save value to handle it later */
8033 vtop--; /* no vpop so that FP stack is not flushed */
8034 skip(':');
8035 u = gjmp(0);
8036 gsym(tt);
8037 expr_eq();
8038 type2 = vtop->type;
8040 t1 = type1.t;
8041 bt1 = t1 & VT_BTYPE;
8042 t2 = type2.t;
8043 bt2 = t2 & VT_BTYPE;
8044 /* cast operands to correct type according to ISOC rules */
8045 if (is_float(bt1) || is_float(bt2)) {
8046 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
8047 type.t = VT_LDOUBLE;
8048 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
8049 type.t = VT_DOUBLE;
8050 } else {
8051 type.t = VT_FLOAT;
8053 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
8054 /* cast to biggest op */
8055 type.t = VT_LLONG;
8056 /* convert to unsigned if it does not fit in a long long */
8057 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
8058 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
8059 type.t |= VT_UNSIGNED;
8060 } else if (bt1 == VT_PTR || bt2 == VT_PTR) {
8061 /* XXX: test pointer compatibility */
8062 type = type1;
8063 } else if (bt1 == VT_FUNC || bt2 == VT_FUNC) {
8064 /* XXX: test function pointer compatibility */
8065 type = type1;
8066 } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
8067 /* XXX: test structure compatibility */
8068 type = type1;
8069 } else if (bt1 == VT_VOID || bt2 == VT_VOID) {
8070 /* NOTE: as an extension, we accept void on only one side */
8071 type.t = VT_VOID;
8072 } else {
8073 /* integer operations */
8074 type.t = VT_INT;
8075 /* convert to unsigned if it does not fit in an integer */
8076 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
8077 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
8078 type.t |= VT_UNSIGNED;
8081 /* now we convert second operand */
8082 gen_cast(&type);
8083 if (VT_STRUCT == (vtop->type.t & VT_BTYPE))
8084 gaddrof();
8085 rc = RC_INT;
8086 if (is_float(type.t)) {
8087 rc = RC_FLOAT;
8088 } else if ((type.t & VT_BTYPE) == VT_LLONG) {
8089 /* for long longs, we use fixed registers to avoid having
8090 to handle a complicated move */
8091 rc = RC_IRET;
8094 r2 = gv(rc);
8095 /* this is horrible, but we must also convert first
8096 operand */
8097 tt = gjmp(0);
8098 gsym(u);
8099 /* put again first value and cast it */
8100 *vtop = sv;
8101 gen_cast(&type);
8102 if (VT_STRUCT == (vtop->type.t & VT_BTYPE))
8103 gaddrof();
8104 r1 = gv(rc);
8105 move_reg(r2, r1);
8106 vtop->r = r2;
8107 gsym(tt);
8112 static void gexpr(void)
8114 while (1) {
8115 expr_eq();
8116 if (tok != ',')
8117 break;
8118 vpop();
8119 next();
8123 /* parse an expression and return its type without any side effect. */
8124 static void expr_type(CType *type)
8126 int saved_nocode_wanted;
8128 saved_nocode_wanted = nocode_wanted;
8129 nocode_wanted = 1;
8130 gexpr();
8131 *type = vtop->type;
8132 vpop();
8133 nocode_wanted = saved_nocode_wanted;
8136 /* parse a unary expression and return its type without any side
8137 effect. */
8138 static void unary_type(CType *type)
8140 int a;
8142 a = nocode_wanted;
8143 nocode_wanted = 1;
8144 unary();
8145 *type = vtop->type;
8146 vpop();
8147 nocode_wanted = a;
8150 /* parse a constant expression and return value in vtop. */
8151 static void expr_const1(void)
8153 int a;
8154 a = const_wanted;
8155 const_wanted = 1;
8156 expr_eq();
8157 const_wanted = a;
8160 /* parse an integer constant and return its value. */
8161 static int expr_const(void)
8163 int c;
8164 expr_const1();
8165 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
8166 expect("constant expression");
8167 c = vtop->c.i;
8168 vpop();
8169 return c;
8172 /* return the label token if current token is a label, otherwise
8173 return zero */
8174 static int is_label(void)
8176 int last_tok;
8178 /* fast test first */
8179 if (tok < TOK_UIDENT)
8180 return 0;
8181 /* no need to save tokc because tok is an identifier */
8182 last_tok = tok;
8183 next();
8184 if (tok == ':') {
8185 next();
8186 return last_tok;
8187 } else {
8188 unget_tok(last_tok);
8189 return 0;
8193 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
8194 int case_reg, int is_expr)
8196 int a, b, c, d;
8197 Sym *s;
8199 /* generate line number info */
8200 if (do_debug &&
8201 (last_line_num != file->line_num || last_ind != ind)) {
8202 put_stabn(N_SLINE, 0, file->line_num, ind - func_ind);
8203 last_ind = ind;
8204 last_line_num = file->line_num;
8207 if (is_expr) {
8208 /* default return value is (void) */
8209 vpushi(0);
8210 vtop->type.t = VT_VOID;
8213 if (tok == TOK_IF) {
8214 /* if test */
8215 next();
8216 skip('(');
8217 gexpr();
8218 skip(')');
8219 a = gtst(1, 0);
8220 block(bsym, csym, case_sym, def_sym, case_reg, 0);
8221 c = tok;
8222 if (c == TOK_ELSE) {
8223 next();
8224 d = gjmp(0);
8225 gsym(a);
8226 block(bsym, csym, case_sym, def_sym, case_reg, 0);
8227 gsym(d); /* patch else jmp */
8228 } else
8229 gsym(a);
8230 } else if (tok == TOK_WHILE) {
8231 next();
8232 d = ind;
8233 skip('(');
8234 gexpr();
8235 skip(')');
8236 a = gtst(1, 0);
8237 b = 0;
8238 block(&a, &b, case_sym, def_sym, case_reg, 0);
8239 gjmp_addr(d);
8240 gsym(a);
8241 gsym_addr(b, d);
8242 } else if (tok == '{') {
8243 Sym *llabel;
8245 next();
8246 /* record local declaration stack position */
8247 s = local_stack;
8248 llabel = local_label_stack;
8249 /* handle local labels declarations */
8250 if (tok == TOK_LABEL) {
8251 next();
8252 for(;;) {
8253 if (tok < TOK_UIDENT)
8254 expect("label identifier");
8255 label_push(&local_label_stack, tok, LABEL_DECLARED);
8256 next();
8257 if (tok == ',') {
8258 next();
8259 } else {
8260 skip(';');
8261 break;
8265 while (tok != '}') {
8266 decl(VT_LOCAL);
8267 if (tok != '}') {
8268 if (is_expr)
8269 vpop();
8270 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
8273 /* pop locally defined labels */
8274 label_pop(&local_label_stack, llabel);
8275 /* pop locally defined symbols */
8276 if(is_expr) {
8277 /* XXX: this solution makes only valgrind happy...
8278 triggered by gcc.c-torture/execute/20000917-1.c */
8279 Sym *p;
8280 switch(vtop->type.t & VT_BTYPE) {
8281 case VT_PTR:
8282 case VT_STRUCT:
8283 case VT_ENUM:
8284 case VT_FUNC:
8285 for(p=vtop->type.ref;p;p=p->prev)
8286 if(p->prev==s)
8287 error("unsupported expression type");
8290 sym_pop(&local_stack, s);
8291 next();
8292 } else if (tok == TOK_RETURN) {
8293 next();
8294 if (tok != ';') {
8295 gexpr();
8296 gen_assign_cast(&func_vt);
8297 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
8298 CType type;
8299 /* if returning structure, must copy it to implicit
8300 first pointer arg location */
8301 #ifdef TCC_ARM_EABI
8302 int align, size;
8303 size = type_size(&func_vt,&align);
8304 if(size <= 4)
8306 if((vtop->r != (VT_LOCAL | VT_LVAL) || (vtop->c.i & 3))
8307 && (align & 3))
8309 int addr;
8310 loc = (loc - size) & -4;
8311 addr = loc;
8312 type = func_vt;
8313 vset(&type, VT_LOCAL | VT_LVAL, addr);
8314 vswap();
8315 vstore();
8316 vset(&int_type, VT_LOCAL | VT_LVAL, addr);
8318 vtop->type = int_type;
8319 gv(RC_IRET);
8320 } else {
8321 #endif
8322 type = func_vt;
8323 mk_pointer(&type);
8324 vset(&type, VT_LOCAL | VT_LVAL, func_vc);
8325 indir();
8326 vswap();
8327 /* copy structure value to pointer */
8328 vstore();
8329 #ifdef TCC_ARM_EABI
8331 #endif
8332 } else if (is_float(func_vt.t)) {
8333 gv(RC_FRET);
8334 } else {
8335 gv(RC_IRET);
8337 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
8339 skip(';');
8340 rsym = gjmp(rsym); /* jmp */
8341 } else if (tok == TOK_BREAK) {
8342 /* compute jump */
8343 if (!bsym)
8344 error("cannot break");
8345 *bsym = gjmp(*bsym);
8346 next();
8347 skip(';');
8348 } else if (tok == TOK_CONTINUE) {
8349 /* compute jump */
8350 if (!csym)
8351 error("cannot continue");
8352 *csym = gjmp(*csym);
8353 next();
8354 skip(';');
8355 } else if (tok == TOK_FOR) {
8356 int e;
8357 next();
8358 skip('(');
8359 if (tok != ';') {
8360 gexpr();
8361 vpop();
8363 skip(';');
8364 d = ind;
8365 c = ind;
8366 a = 0;
8367 b = 0;
8368 if (tok != ';') {
8369 gexpr();
8370 a = gtst(1, 0);
8372 skip(';');
8373 if (tok != ')') {
8374 e = gjmp(0);
8375 c = ind;
8376 gexpr();
8377 vpop();
8378 gjmp_addr(d);
8379 gsym(e);
8381 skip(')');
8382 block(&a, &b, case_sym, def_sym, case_reg, 0);
8383 gjmp_addr(c);
8384 gsym(a);
8385 gsym_addr(b, c);
8386 } else
8387 if (tok == TOK_DO) {
8388 next();
8389 a = 0;
8390 b = 0;
8391 d = ind;
8392 block(&a, &b, case_sym, def_sym, case_reg, 0);
8393 skip(TOK_WHILE);
8394 skip('(');
8395 gsym(b);
8396 gexpr();
8397 c = gtst(0, 0);
8398 gsym_addr(c, d);
8399 skip(')');
8400 gsym(a);
8401 skip(';');
8402 } else
8403 if (tok == TOK_SWITCH) {
8404 next();
8405 skip('(');
8406 gexpr();
8407 /* XXX: other types than integer */
8408 case_reg = gv(RC_INT);
8409 vpop();
8410 skip(')');
8411 a = 0;
8412 b = gjmp(0); /* jump to first case */
8413 c = 0;
8414 block(&a, csym, &b, &c, case_reg, 0);
8415 /* if no default, jmp after switch */
8416 if (c == 0)
8417 c = ind;
8418 /* default label */
8419 gsym_addr(b, c);
8420 /* break label */
8421 gsym(a);
8422 } else
8423 if (tok == TOK_CASE) {
8424 int v1, v2;
8425 if (!case_sym)
8426 expect("switch");
8427 next();
8428 v1 = expr_const();
8429 v2 = v1;
8430 if (gnu_ext && tok == TOK_DOTS) {
8431 next();
8432 v2 = expr_const();
8433 if (v2 < v1)
8434 warning("empty case range");
8436 /* since a case is like a label, we must skip it with a jmp */
8437 b = gjmp(0);
8438 gsym(*case_sym);
8439 vseti(case_reg, 0);
8440 vpushi(v1);
8441 if (v1 == v2) {
8442 gen_op(TOK_EQ);
8443 *case_sym = gtst(1, 0);
8444 } else {
8445 gen_op(TOK_GE);
8446 *case_sym = gtst(1, 0);
8447 vseti(case_reg, 0);
8448 vpushi(v2);
8449 gen_op(TOK_LE);
8450 *case_sym = gtst(1, *case_sym);
8452 gsym(b);
8453 skip(':');
8454 is_expr = 0;
8455 goto block_after_label;
8456 } else
8457 if (tok == TOK_DEFAULT) {
8458 next();
8459 skip(':');
8460 if (!def_sym)
8461 expect("switch");
8462 if (*def_sym)
8463 error("too many 'default'");
8464 *def_sym = ind;
8465 is_expr = 0;
8466 goto block_after_label;
8467 } else
8468 if (tok == TOK_GOTO) {
8469 next();
8470 if (tok == '*' && gnu_ext) {
8471 /* computed goto */
8472 next();
8473 gexpr();
8474 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
8475 expect("pointer");
8476 ggoto();
8477 } else if (tok >= TOK_UIDENT) {
8478 s = label_find(tok);
8479 /* put forward definition if needed */
8480 if (!s) {
8481 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
8482 } else {
8483 if (s->r == LABEL_DECLARED)
8484 s->r = LABEL_FORWARD;
8486 /* label already defined */
8487 if (s->r & LABEL_FORWARD)
8488 s->next = (void *)gjmp((long)s->next);
8489 else
8490 gjmp_addr((long)s->next);
8491 next();
8492 } else {
8493 expect("label identifier");
8495 skip(';');
8496 } else if (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3) {
8497 asm_instr();
8498 } else {
8499 b = is_label();
8500 if (b) {
8501 /* label case */
8502 s = label_find(b);
8503 if (s) {
8504 if (s->r == LABEL_DEFINED)
8505 error("duplicate label '%s'", get_tok_str(s->v, NULL));
8506 gsym((long)s->next);
8507 s->r = LABEL_DEFINED;
8508 } else {
8509 s = label_push(&global_label_stack, b, LABEL_DEFINED);
8511 s->next = (void *)ind;
8512 /* we accept this, but it is a mistake */
8513 block_after_label:
8514 if (tok == '}') {
8515 warning("deprecated use of label at end of compound statement");
8516 } else {
8517 if (is_expr)
8518 vpop();
8519 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
8521 } else {
8522 /* expression case */
8523 if (tok != ';') {
8524 if (is_expr) {
8525 vpop();
8526 gexpr();
8527 } else {
8528 gexpr();
8529 vpop();
8532 skip(';');
8537 /* t is the array or struct type. c is the array or struct
8538 address. cur_index/cur_field is the pointer to the current
8539 value. 'size_only' is true if only size info is needed (only used
8540 in arrays) */
8541 static void decl_designator(CType *type, Section *sec, unsigned long c,
8542 int *cur_index, Sym **cur_field,
8543 int size_only)
8545 Sym *s, *f;
8546 int notfirst, index, index_last, align, l, nb_elems, elem_size;
8547 CType type1;
8549 notfirst = 0;
8550 elem_size = 0;
8551 nb_elems = 1;
8552 if (gnu_ext && (l = is_label()) != 0)
8553 goto struct_field;
8554 while (tok == '[' || tok == '.') {
8555 if (tok == '[') {
8556 if (!(type->t & VT_ARRAY))
8557 expect("array type");
8558 s = type->ref;
8559 next();
8560 index = expr_const();
8561 if (index < 0 || (s->c >= 0 && index >= s->c))
8562 expect("invalid index");
8563 if (tok == TOK_DOTS && gnu_ext) {
8564 next();
8565 index_last = expr_const();
8566 if (index_last < 0 ||
8567 (s->c >= 0 && index_last >= s->c) ||
8568 index_last < index)
8569 expect("invalid index");
8570 } else {
8571 index_last = index;
8573 skip(']');
8574 if (!notfirst)
8575 *cur_index = index_last;
8576 type = pointed_type(type);
8577 elem_size = type_size(type, &align);
8578 c += index * elem_size;
8579 /* NOTE: we only support ranges for last designator */
8580 nb_elems = index_last - index + 1;
8581 if (nb_elems != 1) {
8582 notfirst = 1;
8583 break;
8585 } else {
8586 next();
8587 l = tok;
8588 next();
8589 struct_field:
8590 if ((type->t & VT_BTYPE) != VT_STRUCT)
8591 expect("struct/union type");
8592 s = type->ref;
8593 l |= SYM_FIELD;
8594 f = s->next;
8595 while (f) {
8596 if (f->v == l)
8597 break;
8598 f = f->next;
8600 if (!f)
8601 expect("field");
8602 if (!notfirst)
8603 *cur_field = f;
8604 /* XXX: fix this mess by using explicit storage field */
8605 type1 = f->type;
8606 type1.t |= (type->t & ~VT_TYPE);
8607 type = &type1;
8608 c += f->c;
8610 notfirst = 1;
8612 if (notfirst) {
8613 if (tok == '=') {
8614 next();
8615 } else {
8616 if (!gnu_ext)
8617 expect("=");
8619 } else {
8620 if (type->t & VT_ARRAY) {
8621 index = *cur_index;
8622 type = pointed_type(type);
8623 c += index * type_size(type, &align);
8624 } else {
8625 f = *cur_field;
8626 if (!f)
8627 error("too many field init");
8628 /* XXX: fix this mess by using explicit storage field */
8629 type1 = f->type;
8630 type1.t |= (type->t & ~VT_TYPE);
8631 type = &type1;
8632 c += f->c;
8635 decl_initializer(type, sec, c, 0, size_only);
8637 /* XXX: make it more general */
8638 if (!size_only && nb_elems > 1) {
8639 unsigned long c_end;
8640 uint8_t *src, *dst;
8641 int i;
8643 if (!sec)
8644 error("range init not supported yet for dynamic storage");
8645 c_end = c + nb_elems * elem_size;
8646 if (c_end > sec->data_allocated)
8647 section_realloc(sec, c_end);
8648 src = sec->data + c;
8649 dst = src;
8650 for(i = 1; i < nb_elems; i++) {
8651 dst += elem_size;
8652 memcpy(dst, src, elem_size);
8657 #define EXPR_VAL 0
8658 #define EXPR_CONST 1
8659 #define EXPR_ANY 2
8661 /* store a value or an expression directly in global data or in local array */
8662 static void init_putv(CType *type, Section *sec, unsigned long c,
8663 int v, int expr_type)
8665 int saved_global_expr, bt, bit_pos, bit_size;
8666 void *ptr;
8667 unsigned long long bit_mask;
8668 CType dtype;
8670 switch(expr_type) {
8671 case EXPR_VAL:
8672 vpushi(v);
8673 break;
8674 case EXPR_CONST:
8675 /* compound literals must be allocated globally in this case */
8676 saved_global_expr = global_expr;
8677 global_expr = 1;
8678 expr_const1();
8679 global_expr = saved_global_expr;
8680 /* NOTE: symbols are accepted */
8681 if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST)
8682 error("initializer element is not constant");
8683 break;
8684 case EXPR_ANY:
8685 expr_eq();
8686 break;
8689 dtype = *type;
8690 dtype.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
8692 if (sec) {
8693 /* XXX: not portable */
8694 /* XXX: generate error if incorrect relocation */
8695 gen_assign_cast(&dtype);
8696 bt = type->t & VT_BTYPE;
8697 ptr = sec->data + c;
8698 /* XXX: make code faster ? */
8699 if (!(type->t & VT_BITFIELD)) {
8700 bit_pos = 0;
8701 bit_size = 32;
8702 bit_mask = -1LL;
8703 } else {
8704 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
8705 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
8706 bit_mask = (1LL << bit_size) - 1;
8708 if ((vtop->r & VT_SYM) &&
8709 (bt == VT_BYTE ||
8710 bt == VT_SHORT ||
8711 bt == VT_DOUBLE ||
8712 bt == VT_LDOUBLE ||
8713 bt == VT_LLONG ||
8714 (bt == VT_INT && bit_size != 32)))
8715 error("initializer element is not computable at load time");
8716 switch(bt) {
8717 case VT_BOOL:
8718 vtop->c.i = (vtop->c.i != 0);
8719 case VT_BYTE:
8720 *(char *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8721 break;
8722 case VT_SHORT:
8723 *(short *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8724 break;
8725 case VT_DOUBLE:
8726 *(double *)ptr = vtop->c.d;
8727 break;
8728 case VT_LDOUBLE:
8729 *(long double *)ptr = vtop->c.ld;
8730 break;
8731 case VT_LLONG:
8732 *(long long *)ptr |= (vtop->c.ll & bit_mask) << bit_pos;
8733 break;
8734 default:
8735 if (vtop->r & VT_SYM) {
8736 greloc(sec, vtop->sym, c, R_DATA_32);
8738 *(int *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8739 break;
8741 vtop--;
8742 } else {
8743 vset(&dtype, VT_LOCAL|VT_LVAL, c);
8744 vswap();
8745 vstore();
8746 vpop();
8750 /* put zeros for variable based init */
8751 static void init_putz(CType *t, Section *sec, unsigned long c, int size)
8753 if (sec) {
8754 /* nothing to do because globals are already set to zero */
8755 } else {
8756 vpush_global_sym(&func_old_type, TOK_memset);
8757 vseti(VT_LOCAL, c);
8758 vpushi(0);
8759 vpushi(size);
8760 gfunc_call(3);
8764 /* 't' contains the type and storage info. 'c' is the offset of the
8765 object in section 'sec'. If 'sec' is NULL, it means stack based
8766 allocation. 'first' is true if array '{' must be read (multi
8767 dimension implicit array init handling). 'size_only' is true if
8768 size only evaluation is wanted (only for arrays). */
8769 static void decl_initializer(CType *type, Section *sec, unsigned long c,
8770 int first, int size_only)
8772 int index, array_length, n, no_oblock, nb, parlevel, i;
8773 int size1, align1, expr_type;
8774 Sym *s, *f;
8775 CType *t1;
8777 if (type->t & VT_ARRAY) {
8778 s = type->ref;
8779 n = s->c;
8780 array_length = 0;
8781 t1 = pointed_type(type);
8782 size1 = type_size(t1, &align1);
8784 no_oblock = 1;
8785 if ((first && tok != TOK_LSTR && tok != TOK_STR) ||
8786 tok == '{') {
8787 skip('{');
8788 no_oblock = 0;
8791 /* only parse strings here if correct type (otherwise: handle
8792 them as ((w)char *) expressions */
8793 if ((tok == TOK_LSTR &&
8794 #ifdef TCC_TARGET_PE
8795 (t1->t & VT_BTYPE) == VT_SHORT && (t1->t & VT_UNSIGNED)
8796 #else
8797 (t1->t & VT_BTYPE) == VT_INT
8798 #endif
8799 ) || (tok == TOK_STR && (t1->t & VT_BTYPE) == VT_BYTE)) {
8800 while (tok == TOK_STR || tok == TOK_LSTR) {
8801 int cstr_len, ch;
8802 CString *cstr;
8804 cstr = tokc.cstr;
8805 /* compute maximum number of chars wanted */
8806 if (tok == TOK_STR)
8807 cstr_len = cstr->size;
8808 else
8809 cstr_len = cstr->size / sizeof(nwchar_t);
8810 cstr_len--;
8811 nb = cstr_len;
8812 if (n >= 0 && nb > (n - array_length))
8813 nb = n - array_length;
8814 if (!size_only) {
8815 if (cstr_len > nb)
8816 warning("initializer-string for array is too long");
8817 /* in order to go faster for common case (char
8818 string in global variable, we handle it
8819 specifically */
8820 if (sec && tok == TOK_STR && size1 == 1) {
8821 memcpy(sec->data + c + array_length, cstr->data, nb);
8822 } else {
8823 for(i=0;i<nb;i++) {
8824 if (tok == TOK_STR)
8825 ch = ((unsigned char *)cstr->data)[i];
8826 else
8827 ch = ((nwchar_t *)cstr->data)[i];
8828 init_putv(t1, sec, c + (array_length + i) * size1,
8829 ch, EXPR_VAL);
8833 array_length += nb;
8834 next();
8836 /* only add trailing zero if enough storage (no
8837 warning in this case since it is standard) */
8838 if (n < 0 || array_length < n) {
8839 if (!size_only) {
8840 init_putv(t1, sec, c + (array_length * size1), 0, EXPR_VAL);
8842 array_length++;
8844 } else {
8845 index = 0;
8846 while (tok != '}') {
8847 decl_designator(type, sec, c, &index, NULL, size_only);
8848 if (n >= 0 && index >= n)
8849 error("index too large");
8850 /* must put zero in holes (note that doing it that way
8851 ensures that it even works with designators) */
8852 if (!size_only && array_length < index) {
8853 init_putz(t1, sec, c + array_length * size1,
8854 (index - array_length) * size1);
8856 index++;
8857 if (index > array_length)
8858 array_length = index;
8859 /* special test for multi dimensional arrays (may not
8860 be strictly correct if designators are used at the
8861 same time) */
8862 if (index >= n && no_oblock)
8863 break;
8864 if (tok == '}')
8865 break;
8866 skip(',');
8869 if (!no_oblock)
8870 skip('}');
8871 /* put zeros at the end */
8872 if (!size_only && n >= 0 && array_length < n) {
8873 init_putz(t1, sec, c + array_length * size1,
8874 (n - array_length) * size1);
8876 /* patch type size if needed */
8877 if (n < 0)
8878 s->c = array_length;
8879 } else if ((type->t & VT_BTYPE) == VT_STRUCT &&
8880 (sec || !first || tok == '{')) {
8881 int par_count;
8883 /* NOTE: the previous test is a specific case for automatic
8884 struct/union init */
8885 /* XXX: union needs only one init */
8887 /* XXX: this test is incorrect for local initializers
8888 beginning with ( without {. It would be much more difficult
8889 to do it correctly (ideally, the expression parser should
8890 be used in all cases) */
8891 par_count = 0;
8892 if (tok == '(') {
8893 AttributeDef ad1;
8894 CType type1;
8895 next();
8896 while (tok == '(') {
8897 par_count++;
8898 next();
8900 if (!parse_btype(&type1, &ad1))
8901 expect("cast");
8902 type_decl(&type1, &ad1, &n, TYPE_ABSTRACT);
8903 #if 0
8904 if (!is_assignable_types(type, &type1))
8905 error("invalid type for cast");
8906 #endif
8907 skip(')');
8909 no_oblock = 1;
8910 if (first || tok == '{') {
8911 skip('{');
8912 no_oblock = 0;
8914 s = type->ref;
8915 f = s->next;
8916 array_length = 0;
8917 index = 0;
8918 n = s->c;
8919 while (tok != '}') {
8920 decl_designator(type, sec, c, NULL, &f, size_only);
8921 index = f->c;
8922 if (!size_only && array_length < index) {
8923 init_putz(type, sec, c + array_length,
8924 index - array_length);
8926 index = index + type_size(&f->type, &align1);
8927 if (index > array_length)
8928 array_length = index;
8929 f = f->next;
8930 if (no_oblock && f == NULL)
8931 break;
8932 if (tok == '}')
8933 break;
8934 skip(',');
8936 /* put zeros at the end */
8937 if (!size_only && array_length < n) {
8938 init_putz(type, sec, c + array_length,
8939 n - array_length);
8941 if (!no_oblock)
8942 skip('}');
8943 while (par_count) {
8944 skip(')');
8945 par_count--;
8947 } else if (tok == '{') {
8948 next();
8949 decl_initializer(type, sec, c, first, size_only);
8950 skip('}');
8951 } else if (size_only) {
8952 /* just skip expression */
8953 parlevel = 0;
8954 while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
8955 tok != -1) {
8956 if (tok == '(')
8957 parlevel++;
8958 else if (tok == ')')
8959 parlevel--;
8960 next();
8962 } else {
8963 /* currently, we always use constant expression for globals
8964 (may change for scripting case) */
8965 expr_type = EXPR_CONST;
8966 if (!sec)
8967 expr_type = EXPR_ANY;
8968 init_putv(type, sec, c, 0, expr_type);
8972 /* parse an initializer for type 't' if 'has_init' is non zero, and
8973 allocate space in local or global data space ('r' is either
8974 VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
8975 variable 'v' of scope 'scope' is declared before initializers are
8976 parsed. If 'v' is zero, then a reference to the new object is put
8977 in the value stack. If 'has_init' is 2, a special parsing is done
8978 to handle string constants. */
8979 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
8980 int has_init, int v, int scope)
8982 int size, align, addr, data_offset;
8983 int level;
8984 ParseState saved_parse_state;
8985 TokenString init_str;
8986 Section *sec;
8988 size = type_size(type, &align);
8989 /* If unknown size, we must evaluate it before
8990 evaluating initializers because
8991 initializers can generate global data too
8992 (e.g. string pointers or ISOC99 compound
8993 literals). It also simplifies local
8994 initializers handling */
8995 tok_str_new(&init_str);
8996 if (size < 0) {
8997 if (!has_init)
8998 error("unknown type size");
8999 /* get all init string */
9000 if (has_init == 2) {
9001 /* only get strings */
9002 while (tok == TOK_STR || tok == TOK_LSTR) {
9003 tok_str_add_tok(&init_str);
9004 next();
9006 } else {
9007 level = 0;
9008 while (level > 0 || (tok != ',' && tok != ';')) {
9009 if (tok < 0)
9010 error("unexpected end of file in initializer");
9011 tok_str_add_tok(&init_str);
9012 if (tok == '{')
9013 level++;
9014 else if (tok == '}') {
9015 if (level == 0)
9016 break;
9017 level--;
9019 next();
9022 tok_str_add(&init_str, -1);
9023 tok_str_add(&init_str, 0);
9025 /* compute size */
9026 save_parse_state(&saved_parse_state);
9028 macro_ptr = init_str.str;
9029 next();
9030 decl_initializer(type, NULL, 0, 1, 1);
9031 /* prepare second initializer parsing */
9032 macro_ptr = init_str.str;
9033 next();
9035 /* if still unknown size, error */
9036 size = type_size(type, &align);
9037 if (size < 0)
9038 error("unknown type size");
9040 /* take into account specified alignment if bigger */
9041 if (ad->aligned) {
9042 if (ad->aligned > align)
9043 align = ad->aligned;
9044 } else if (ad->packed) {
9045 align = 1;
9047 if ((r & VT_VALMASK) == VT_LOCAL) {
9048 sec = NULL;
9049 if (do_bounds_check && (type->t & VT_ARRAY))
9050 loc--;
9051 loc = (loc - size) & -align;
9052 addr = loc;
9053 /* handles bounds */
9054 /* XXX: currently, since we do only one pass, we cannot track
9055 '&' operators, so we add only arrays */
9056 if (do_bounds_check && (type->t & VT_ARRAY)) {
9057 unsigned long *bounds_ptr;
9058 /* add padding between regions */
9059 loc--;
9060 /* then add local bound info */
9061 bounds_ptr = section_ptr_add(lbounds_section, 2 * sizeof(unsigned long));
9062 bounds_ptr[0] = addr;
9063 bounds_ptr[1] = size;
9065 if (v) {
9066 /* local variable */
9067 sym_push(v, type, r, addr);
9068 } else {
9069 /* push local reference */
9070 vset(type, r, addr);
9072 } else {
9073 Sym *sym;
9075 sym = NULL;
9076 if (v && scope == VT_CONST) {
9077 /* see if the symbol was already defined */
9078 sym = sym_find(v);
9079 if (sym) {
9080 if (!is_compatible_types(&sym->type, type))
9081 error("incompatible types for redefinition of '%s'",
9082 get_tok_str(v, NULL));
9083 if (sym->type.t & VT_EXTERN) {
9084 /* if the variable is extern, it was not allocated */
9085 sym->type.t &= ~VT_EXTERN;
9086 /* set array size if it was ommited in extern
9087 declaration */
9088 if ((sym->type.t & VT_ARRAY) &&
9089 sym->type.ref->c < 0 &&
9090 type->ref->c >= 0)
9091 sym->type.ref->c = type->ref->c;
9092 } else {
9093 /* we accept several definitions of the same
9094 global variable. this is tricky, because we
9095 must play with the SHN_COMMON type of the symbol */
9096 /* XXX: should check if the variable was already
9097 initialized. It is incorrect to initialized it
9098 twice */
9099 /* no init data, we won't add more to the symbol */
9100 if (!has_init)
9101 goto no_alloc;
9106 /* allocate symbol in corresponding section */
9107 sec = ad->section;
9108 if (!sec) {
9109 if (has_init)
9110 sec = data_section;
9111 else if (tcc_state->nocommon)
9112 sec = bss_section;
9114 if (sec) {
9115 data_offset = sec->data_offset;
9116 data_offset = (data_offset + align - 1) & -align;
9117 addr = data_offset;
9118 /* very important to increment global pointer at this time
9119 because initializers themselves can create new initializers */
9120 data_offset += size;
9121 /* add padding if bound check */
9122 if (do_bounds_check)
9123 data_offset++;
9124 sec->data_offset = data_offset;
9125 /* allocate section space to put the data */
9126 if (sec->sh_type != SHT_NOBITS &&
9127 data_offset > sec->data_allocated)
9128 section_realloc(sec, data_offset);
9129 /* align section if needed */
9130 if (align > sec->sh_addralign)
9131 sec->sh_addralign = align;
9132 } else {
9133 addr = 0; /* avoid warning */
9136 if (v) {
9137 if (scope != VT_CONST || !sym) {
9138 sym = sym_push(v, type, r | VT_SYM, 0);
9140 /* update symbol definition */
9141 if (sec) {
9142 put_extern_sym(sym, sec, addr, size);
9143 } else {
9144 ElfW(Sym) *esym;
9145 /* put a common area */
9146 put_extern_sym(sym, NULL, align, size);
9147 /* XXX: find a nicer way */
9148 esym = &((ElfW(Sym) *)symtab_section->data)[sym->c];
9149 esym->st_shndx = SHN_COMMON;
9151 } else {
9152 CValue cval;
9154 /* push global reference */
9155 sym = get_sym_ref(type, sec, addr, size);
9156 cval.ul = 0;
9157 vsetc(type, VT_CONST | VT_SYM, &cval);
9158 vtop->sym = sym;
9161 /* handles bounds now because the symbol must be defined
9162 before for the relocation */
9163 if (do_bounds_check) {
9164 unsigned long *bounds_ptr;
9166 greloc(bounds_section, sym, bounds_section->data_offset, R_DATA_32);
9167 /* then add global bound info */
9168 bounds_ptr = section_ptr_add(bounds_section, 2 * sizeof(long));
9169 bounds_ptr[0] = 0; /* relocated */
9170 bounds_ptr[1] = size;
9173 if (has_init) {
9174 decl_initializer(type, sec, addr, 1, 0);
9175 /* restore parse state if needed */
9176 if (init_str.str) {
9177 tok_str_free(init_str.str);
9178 restore_parse_state(&saved_parse_state);
9181 no_alloc: ;
9184 void put_func_debug(Sym *sym)
9186 char buf[512];
9188 /* stabs info */
9189 /* XXX: we put here a dummy type */
9190 snprintf(buf, sizeof(buf), "%s:%c1",
9191 funcname, sym->type.t & VT_STATIC ? 'f' : 'F');
9192 put_stabs_r(buf, N_FUN, 0, file->line_num, 0,
9193 cur_text_section, sym->c);
9194 /* //gr gdb wants a line at the function */
9195 put_stabn(N_SLINE, 0, file->line_num, 0);
9196 last_ind = 0;
9197 last_line_num = 0;
9200 /* parse an old style function declaration list */
9201 /* XXX: check multiple parameter */
9202 static void func_decl_list(Sym *func_sym)
9204 AttributeDef ad;
9205 int v;
9206 Sym *s;
9207 CType btype, type;
9209 /* parse each declaration */
9210 while (tok != '{' && tok != ';' && tok != ',' && tok != TOK_EOF) {
9211 if (!parse_btype(&btype, &ad))
9212 expect("declaration list");
9213 if (((btype.t & VT_BTYPE) == VT_ENUM ||
9214 (btype.t & VT_BTYPE) == VT_STRUCT) &&
9215 tok == ';') {
9216 /* we accept no variable after */
9217 } else {
9218 for(;;) {
9219 type = btype;
9220 type_decl(&type, &ad, &v, TYPE_DIRECT);
9221 /* find parameter in function parameter list */
9222 s = func_sym->next;
9223 while (s != NULL) {
9224 if ((s->v & ~SYM_FIELD) == v)
9225 goto found;
9226 s = s->next;
9228 error("declaration for parameter '%s' but no such parameter",
9229 get_tok_str(v, NULL));
9230 found:
9231 /* check that no storage specifier except 'register' was given */
9232 if (type.t & VT_STORAGE)
9233 error("storage class specified for '%s'", get_tok_str(v, NULL));
9234 convert_parameter_type(&type);
9235 /* we can add the type (NOTE: it could be local to the function) */
9236 s->type = type;
9237 /* accept other parameters */
9238 if (tok == ',')
9239 next();
9240 else
9241 break;
9244 skip(';');
9248 /* parse a function defined by symbol 'sym' and generate its code in
9249 'cur_text_section' */
9250 static void gen_function(Sym *sym)
9252 int saved_nocode_wanted = nocode_wanted;
9253 nocode_wanted = 0;
9254 ind = cur_text_section->data_offset;
9255 /* NOTE: we patch the symbol size later */
9256 put_extern_sym(sym, cur_text_section, ind, 0);
9257 funcname = get_tok_str(sym->v, NULL);
9258 func_ind = ind;
9259 /* put debug symbol */
9260 if (do_debug)
9261 put_func_debug(sym);
9262 /* push a dummy symbol to enable local sym storage */
9263 sym_push2(&local_stack, SYM_FIELD, 0, 0);
9264 gfunc_prolog(&sym->type);
9265 rsym = 0;
9266 block(NULL, NULL, NULL, NULL, 0, 0);
9267 gsym(rsym);
9268 gfunc_epilog();
9269 cur_text_section->data_offset = ind;
9270 label_pop(&global_label_stack, NULL);
9271 sym_pop(&local_stack, NULL); /* reset local stack */
9272 /* end of function */
9273 /* patch symbol size */
9274 ((ElfW(Sym) *)symtab_section->data)[sym->c].st_size =
9275 ind - func_ind;
9276 if (do_debug) {
9277 put_stabn(N_FUN, 0, 0, ind - func_ind);
9279 /* It's better to crash than to generate wrong code */
9280 cur_text_section = NULL;
9281 funcname = ""; /* for safety */
9282 func_vt.t = VT_VOID; /* for safety */
9283 ind = 0; /* for safety */
9284 nocode_wanted = saved_nocode_wanted;
9287 static void gen_inline_functions(void)
9289 Sym *sym;
9290 CType *type;
9291 int *str, inline_generated;
9293 /* iterate while inline function are referenced */
9294 for(;;) {
9295 inline_generated = 0;
9296 for(sym = global_stack; sym != NULL; sym = sym->prev) {
9297 type = &sym->type;
9298 if (((type->t & VT_BTYPE) == VT_FUNC) &&
9299 (type->t & (VT_STATIC | VT_INLINE)) ==
9300 (VT_STATIC | VT_INLINE) &&
9301 sym->c != 0) {
9302 /* the function was used: generate its code and
9303 convert it to a normal function */
9304 str = INLINE_DEF(sym->r);
9305 sym->r = VT_SYM | VT_CONST;
9306 sym->type.t &= ~VT_INLINE;
9308 macro_ptr = str;
9309 next();
9310 cur_text_section = text_section;
9311 gen_function(sym);
9312 macro_ptr = NULL; /* fail safe */
9314 tok_str_free(str);
9315 inline_generated = 1;
9318 if (!inline_generated)
9319 break;
9322 /* free all remaining inline function tokens */
9323 for(sym = global_stack; sym != NULL; sym = sym->prev) {
9324 type = &sym->type;
9325 if (((type->t & VT_BTYPE) == VT_FUNC) &&
9326 (type->t & (VT_STATIC | VT_INLINE)) ==
9327 (VT_STATIC | VT_INLINE)) {
9328 //gr printf("sym %d %s\n", sym->r, get_tok_str(sym->v, NULL));
9329 if (sym->r == (VT_SYM | VT_CONST)) //gr beware!
9330 continue;
9331 str = INLINE_DEF(sym->r);
9332 tok_str_free(str);
9333 sym->r = 0; /* fail safe */
9338 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
9339 static void decl(int l)
9341 int v, has_init, r;
9342 CType type, btype;
9343 Sym *sym;
9344 AttributeDef ad;
9346 while (1) {
9347 if (!parse_btype(&btype, &ad)) {
9348 /* skip redundant ';' */
9349 /* XXX: find more elegant solution */
9350 if (tok == ';') {
9351 next();
9352 continue;
9354 if (l == VT_CONST &&
9355 (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3)) {
9356 /* global asm block */
9357 asm_global_instr();
9358 continue;
9360 /* special test for old K&R protos without explicit int
9361 type. Only accepted when defining global data */
9362 if (l == VT_LOCAL || tok < TOK_DEFINE)
9363 break;
9364 btype.t = VT_INT;
9366 if (((btype.t & VT_BTYPE) == VT_ENUM ||
9367 (btype.t & VT_BTYPE) == VT_STRUCT) &&
9368 tok == ';') {
9369 /* we accept no variable after */
9370 next();
9371 continue;
9373 while (1) { /* iterate thru each declaration */
9374 type = btype;
9375 type_decl(&type, &ad, &v, TYPE_DIRECT);
9376 #if 0
9378 char buf[500];
9379 type_to_str(buf, sizeof(buf), t, get_tok_str(v, NULL));
9380 printf("type = '%s'\n", buf);
9382 #endif
9383 if ((type.t & VT_BTYPE) == VT_FUNC) {
9384 /* if old style function prototype, we accept a
9385 declaration list */
9386 sym = type.ref;
9387 if (sym->c == FUNC_OLD)
9388 func_decl_list(sym);
9391 if (tok == '{') {
9392 if (l == VT_LOCAL)
9393 error("cannot use local functions");
9394 if ((type.t & VT_BTYPE) != VT_FUNC)
9395 expect("function definition");
9397 /* reject abstract declarators in function definition */
9398 sym = type.ref;
9399 while ((sym = sym->next) != NULL)
9400 if (!(sym->v & ~SYM_FIELD))
9401 expect("identifier");
9403 /* XXX: cannot do better now: convert extern line to static inline */
9404 if ((type.t & (VT_EXTERN | VT_INLINE)) == (VT_EXTERN | VT_INLINE))
9405 type.t = (type.t & ~VT_EXTERN) | VT_STATIC;
9407 sym = sym_find(v);
9408 if (sym) {
9409 if ((sym->type.t & VT_BTYPE) != VT_FUNC)
9410 goto func_error1;
9411 /* specific case: if not func_call defined, we put
9412 the one of the prototype */
9413 /* XXX: should have default value */
9414 r = sym->type.ref->r;
9415 if (FUNC_CALL(r) != FUNC_CDECL
9416 && FUNC_CALL(type.ref->r) == FUNC_CDECL)
9417 FUNC_CALL(type.ref->r) = FUNC_CALL(r);
9418 if (FUNC_EXPORT(r))
9419 FUNC_EXPORT(type.ref->r) = 1;
9421 if (!is_compatible_types(&sym->type, &type)) {
9422 func_error1:
9423 error("incompatible types for redefinition of '%s'",
9424 get_tok_str(v, NULL));
9426 /* if symbol is already defined, then put complete type */
9427 sym->type = type;
9428 } else {
9429 /* put function symbol */
9430 sym = global_identifier_push(v, type.t, 0);
9431 sym->type.ref = type.ref;
9434 /* static inline functions are just recorded as a kind
9435 of macro. Their code will be emitted at the end of
9436 the compilation unit only if they are used */
9437 if ((type.t & (VT_INLINE | VT_STATIC)) ==
9438 (VT_INLINE | VT_STATIC)) {
9439 TokenString func_str;
9440 int block_level;
9442 tok_str_new(&func_str);
9444 block_level = 0;
9445 for(;;) {
9446 int t;
9447 if (tok == TOK_EOF)
9448 error("unexpected end of file");
9449 tok_str_add_tok(&func_str);
9450 t = tok;
9451 next();
9452 if (t == '{') {
9453 block_level++;
9454 } else if (t == '}') {
9455 block_level--;
9456 if (block_level == 0)
9457 break;
9460 tok_str_add(&func_str, -1);
9461 tok_str_add(&func_str, 0);
9462 INLINE_DEF(sym->r) = func_str.str;
9463 } else {
9464 /* compute text section */
9465 cur_text_section = ad.section;
9466 if (!cur_text_section)
9467 cur_text_section = text_section;
9468 sym->r = VT_SYM | VT_CONST;
9469 gen_function(sym);
9471 break;
9472 } else {
9473 if (btype.t & VT_TYPEDEF) {
9474 /* save typedefed type */
9475 /* XXX: test storage specifiers ? */
9476 sym = sym_push(v, &type, 0, 0);
9477 sym->type.t |= VT_TYPEDEF;
9478 } else if ((type.t & VT_BTYPE) == VT_FUNC) {
9479 /* external function definition */
9480 /* specific case for func_call attribute */
9481 if (ad.func_attr)
9482 type.ref->r = ad.func_attr;
9483 external_sym(v, &type, 0);
9484 } else {
9485 /* not lvalue if array */
9486 r = 0;
9487 if (!(type.t & VT_ARRAY))
9488 r |= lvalue_type(type.t);
9489 has_init = (tok == '=');
9490 if ((btype.t & VT_EXTERN) ||
9491 ((type.t & VT_ARRAY) && (type.t & VT_STATIC) &&
9492 !has_init && l == VT_CONST && type.ref->c < 0)) {
9493 /* external variable */
9494 /* NOTE: as GCC, uninitialized global static
9495 arrays of null size are considered as
9496 extern */
9497 external_sym(v, &type, r);
9498 } else {
9499 type.t |= (btype.t & VT_STATIC); /* Retain "static". */
9500 if (type.t & VT_STATIC)
9501 r |= VT_CONST;
9502 else
9503 r |= l;
9504 if (has_init)
9505 next();
9506 decl_initializer_alloc(&type, &ad, r,
9507 has_init, v, l);
9510 if (tok != ',') {
9511 skip(';');
9512 break;
9514 next();
9520 /* better than nothing, but needs extension to handle '-E' option
9521 correctly too */
9522 static void preprocess_init(TCCState *s1)
9524 s1->include_stack_ptr = s1->include_stack;
9525 /* XXX: move that before to avoid having to initialize
9526 file->ifdef_stack_ptr ? */
9527 s1->ifdef_stack_ptr = s1->ifdef_stack;
9528 file->ifdef_stack_ptr = s1->ifdef_stack_ptr;
9530 /* XXX: not ANSI compliant: bound checking says error */
9531 vtop = vstack - 1;
9532 s1->pack_stack[0] = 0;
9533 s1->pack_stack_ptr = s1->pack_stack;
9536 /* compile the C file opened in 'file'. Return non zero if errors. */
9537 static int tcc_compile(TCCState *s1)
9539 Sym *define_start;
9540 char buf[512];
9541 volatile int section_sym;
9543 #ifdef INC_DEBUG
9544 printf("%s: **** new file\n", file->filename);
9545 #endif
9546 preprocess_init(s1);
9548 cur_text_section = NULL;
9549 funcname = "";
9550 anon_sym = SYM_FIRST_ANOM;
9552 /* file info: full path + filename */
9553 section_sym = 0; /* avoid warning */
9554 if (do_debug) {
9555 section_sym = put_elf_sym(symtab_section, 0, 0,
9556 ELFW(ST_INFO)(STB_LOCAL, STT_SECTION), 0,
9557 text_section->sh_num, NULL);
9558 getcwd(buf, sizeof(buf));
9559 #ifdef _WIN32
9560 normalize_slashes(buf);
9561 #endif
9562 pstrcat(buf, sizeof(buf), "/");
9563 put_stabs_r(buf, N_SO, 0, 0,
9564 text_section->data_offset, text_section, section_sym);
9565 put_stabs_r(file->filename, N_SO, 0, 0,
9566 text_section->data_offset, text_section, section_sym);
9568 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
9569 symbols can be safely used */
9570 put_elf_sym(symtab_section, 0, 0,
9571 ELFW(ST_INFO)(STB_LOCAL, STT_FILE), 0,
9572 SHN_ABS, file->filename);
9574 /* define some often used types */
9575 int_type.t = VT_INT;
9577 char_pointer_type.t = VT_BYTE;
9578 mk_pointer(&char_pointer_type);
9580 func_old_type.t = VT_FUNC;
9581 func_old_type.ref = sym_push(SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD);
9583 #if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)
9584 float_type.t = VT_FLOAT;
9585 double_type.t = VT_DOUBLE;
9587 func_float_type.t = VT_FUNC;
9588 func_float_type.ref = sym_push(SYM_FIELD, &float_type, FUNC_CDECL, FUNC_OLD);
9589 func_double_type.t = VT_FUNC;
9590 func_double_type.ref = sym_push(SYM_FIELD, &double_type, FUNC_CDECL, FUNC_OLD);
9591 #endif
9593 #if 0
9594 /* define 'void *alloca(unsigned int)' builtin function */
9596 Sym *s1;
9598 p = anon_sym++;
9599 sym = sym_push(p, mk_pointer(VT_VOID), FUNC_CDECL, FUNC_NEW);
9600 s1 = sym_push(SYM_FIELD, VT_UNSIGNED | VT_INT, 0, 0);
9601 s1->next = NULL;
9602 sym->next = s1;
9603 sym_push(TOK_alloca, VT_FUNC | (p << VT_STRUCT_SHIFT), VT_CONST, 0);
9605 #endif
9607 define_start = define_stack;
9608 nocode_wanted = 1;
9610 if (setjmp(s1->error_jmp_buf) == 0) {
9611 s1->nb_errors = 0;
9612 s1->error_set_jmp_enabled = 1;
9614 ch = file->buf_ptr[0];
9615 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
9616 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM;
9617 next();
9618 decl(VT_CONST);
9619 if (tok != TOK_EOF)
9620 expect("declaration");
9622 /* end of translation unit info */
9623 if (do_debug) {
9624 put_stabs_r(NULL, N_SO, 0, 0,
9625 text_section->data_offset, text_section, section_sym);
9628 s1->error_set_jmp_enabled = 0;
9630 /* reset define stack, but leave -Dsymbols (may be incorrect if
9631 they are undefined) */
9632 free_defines(define_start);
9634 gen_inline_functions();
9636 sym_pop(&global_stack, NULL);
9637 sym_pop(&local_stack, NULL);
9639 return s1->nb_errors != 0 ? -1 : 0;
9642 /* Preprocess the current file */
9643 /* XXX: add line and file infos, add options to preserve spaces */
9644 static int tcc_preprocess(TCCState *s1)
9646 Sym *define_start;
9647 BufferedFile *file_ref;
9648 int token_seen, line_ref;
9650 preprocess_init(s1);
9651 define_start = define_stack;
9652 ch = file->buf_ptr[0];
9654 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
9655 parse_flags = PARSE_FLAG_ASM_COMMENTS | PARSE_FLAG_PREPROCESS |
9656 PARSE_FLAG_LINEFEED;
9658 token_seen = 0;
9659 line_ref = 0;
9660 file_ref = NULL;
9662 for (;;) {
9663 next();
9664 if (tok == TOK_EOF) {
9665 break;
9666 } else if (tok == TOK_LINEFEED) {
9667 if (!token_seen)
9668 continue;
9669 ++line_ref;
9670 token_seen = 0;
9671 } else if (token_seen) {
9672 fputc(' ', s1->outfile);
9673 } else {
9674 int d = file->line_num - line_ref;
9675 if (file != file_ref || d < 0 || d >= 8)
9676 fprintf(s1->outfile, "# %d \"%s\"\n", file->line_num, file->filename);
9677 else
9678 while (d)
9679 fputs("\n", s1->outfile), --d;
9680 line_ref = (file_ref = file)->line_num;
9681 token_seen = 1;
9683 fputs(get_tok_str(tok, &tokc), s1->outfile);
9685 free_defines(define_start);
9686 return 0;
9689 #ifdef LIBTCC
9690 int tcc_compile_string(TCCState *s, const char *str)
9692 BufferedFile bf1, *bf = &bf1;
9693 int ret, len;
9694 char *buf;
9696 /* init file structure */
9697 bf->fd = -1;
9698 /* XXX: avoid copying */
9699 len = strlen(str);
9700 buf = tcc_malloc(len + 1);
9701 if (!buf)
9702 return -1;
9703 memcpy(buf, str, len);
9704 buf[len] = CH_EOB;
9705 bf->buf_ptr = buf;
9706 bf->buf_end = buf + len;
9707 pstrcpy(bf->filename, sizeof(bf->filename), "<string>");
9708 bf->line_num = 1;
9709 file = bf;
9710 ret = tcc_compile(s);
9711 file = NULL;
9712 tcc_free(buf);
9714 /* currently, no need to close */
9715 return ret;
9717 #endif
9719 /* define a preprocessor symbol. A value can also be provided with the '=' operator */
9720 void tcc_define_symbol(TCCState *s1, const char *sym, const char *value)
9722 BufferedFile bf1, *bf = &bf1;
9724 pstrcpy(bf->buffer, IO_BUF_SIZE, sym);
9725 pstrcat(bf->buffer, IO_BUF_SIZE, " ");
9726 /* default value */
9727 if (!value)
9728 value = "1";
9729 pstrcat(bf->buffer, IO_BUF_SIZE, value);
9731 /* init file structure */
9732 bf->fd = -1;
9733 bf->buf_ptr = bf->buffer;
9734 bf->buf_end = bf->buffer + strlen(bf->buffer);
9735 *bf->buf_end = CH_EOB;
9736 bf->filename[0] = '\0';
9737 bf->line_num = 1;
9738 file = bf;
9740 s1->include_stack_ptr = s1->include_stack;
9742 /* parse with define parser */
9743 ch = file->buf_ptr[0];
9744 next_nomacro();
9745 parse_define();
9746 file = NULL;
9749 /* undefine a preprocessor symbol */
9750 void tcc_undefine_symbol(TCCState *s1, const char *sym)
9752 TokenSym *ts;
9753 Sym *s;
9754 ts = tok_alloc(sym, strlen(sym));
9755 s = define_find(ts->tok);
9756 /* undefine symbol by putting an invalid name */
9757 if (s)
9758 define_undef(s);
9761 #ifdef CONFIG_TCC_ASM
9763 #ifdef TCC_TARGET_I386
9764 #include "i386-asm.c"
9765 #endif
9766 #include "tccasm.c"
9768 #else
9769 static void asm_instr(void)
9771 error("inline asm() not supported");
9773 static void asm_global_instr(void)
9775 error("inline asm() not supported");
9777 #endif
9779 #include "tccelf.c"
9781 #ifdef TCC_TARGET_COFF
9782 #include "tcccoff.c"
9783 #endif
9785 #ifdef TCC_TARGET_PE
9786 #include "tccpe.c"
9787 #endif
9789 /* print the position in the source file of PC value 'pc' by reading
9790 the stabs debug information */
9791 static void rt_printline(unsigned long wanted_pc)
9793 Stab_Sym *sym, *sym_end;
9794 char func_name[128], last_func_name[128];
9795 unsigned long func_addr, last_pc, pc;
9796 const char *incl_files[INCLUDE_STACK_SIZE];
9797 int incl_index, len, last_line_num, i;
9798 const char *str, *p;
9800 fprintf(stderr, "0x%08lx:", wanted_pc);
9802 func_name[0] = '\0';
9803 func_addr = 0;
9804 incl_index = 0;
9805 last_func_name[0] = '\0';
9806 last_pc = 0xffffffff;
9807 last_line_num = 1;
9808 sym = (Stab_Sym *)stab_section->data + 1;
9809 sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset);
9810 while (sym < sym_end) {
9811 switch(sym->n_type) {
9812 /* function start or end */
9813 case N_FUN:
9814 if (sym->n_strx == 0) {
9815 /* we test if between last line and end of function */
9816 pc = sym->n_value + func_addr;
9817 if (wanted_pc >= last_pc && wanted_pc < pc)
9818 goto found;
9819 func_name[0] = '\0';
9820 func_addr = 0;
9821 } else {
9822 str = stabstr_section->data + sym->n_strx;
9823 p = strchr(str, ':');
9824 if (!p) {
9825 pstrcpy(func_name, sizeof(func_name), str);
9826 } else {
9827 len = p - str;
9828 if (len > sizeof(func_name) - 1)
9829 len = sizeof(func_name) - 1;
9830 memcpy(func_name, str, len);
9831 func_name[len] = '\0';
9833 func_addr = sym->n_value;
9835 break;
9836 /* line number info */
9837 case N_SLINE:
9838 pc = sym->n_value + func_addr;
9839 if (wanted_pc >= last_pc && wanted_pc < pc)
9840 goto found;
9841 last_pc = pc;
9842 last_line_num = sym->n_desc;
9843 /* XXX: slow! */
9844 strcpy(last_func_name, func_name);
9845 break;
9846 /* include files */
9847 case N_BINCL:
9848 str = stabstr_section->data + sym->n_strx;
9849 add_incl:
9850 if (incl_index < INCLUDE_STACK_SIZE) {
9851 incl_files[incl_index++] = str;
9853 break;
9854 case N_EINCL:
9855 if (incl_index > 1)
9856 incl_index--;
9857 break;
9858 case N_SO:
9859 if (sym->n_strx == 0) {
9860 incl_index = 0; /* end of translation unit */
9861 } else {
9862 str = stabstr_section->data + sym->n_strx;
9863 /* do not add path */
9864 len = strlen(str);
9865 if (len > 0 && str[len - 1] != '/')
9866 goto add_incl;
9868 break;
9870 sym++;
9873 /* second pass: we try symtab symbols (no line number info) */
9874 incl_index = 0;
9876 ElfW(Sym) *sym, *sym_end;
9877 int type;
9879 sym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset);
9880 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
9881 sym < sym_end;
9882 sym++) {
9883 type = ELFW(ST_TYPE)(sym->st_info);
9884 if (type == STT_FUNC) {
9885 if (wanted_pc >= sym->st_value &&
9886 wanted_pc < sym->st_value + sym->st_size) {
9887 pstrcpy(last_func_name, sizeof(last_func_name),
9888 strtab_section->data + sym->st_name);
9889 goto found;
9894 /* did not find any info: */
9895 fprintf(stderr, " ???\n");
9896 return;
9897 found:
9898 if (last_func_name[0] != '\0') {
9899 fprintf(stderr, " %s()", last_func_name);
9901 if (incl_index > 0) {
9902 fprintf(stderr, " (%s:%d",
9903 incl_files[incl_index - 1], last_line_num);
9904 for(i = incl_index - 2; i >= 0; i--)
9905 fprintf(stderr, ", included from %s", incl_files[i]);
9906 fprintf(stderr, ")");
9908 fprintf(stderr, "\n");
9911 #if !defined(_WIN32) && !defined(CONFIG_TCCBOOT)
9913 #ifdef __i386__
9915 /* fix for glibc 2.1 */
9916 #ifndef REG_EIP
9917 #define REG_EIP EIP
9918 #define REG_EBP EBP
9919 #endif
9921 /* return the PC at frame level 'level'. Return non zero if not found */
9922 static int rt_get_caller_pc(unsigned long *paddr,
9923 ucontext_t *uc, int level)
9925 unsigned long fp;
9926 int i;
9928 if (level == 0) {
9929 #if defined(__FreeBSD__)
9930 *paddr = uc->uc_mcontext.mc_eip;
9931 #elif defined(__dietlibc__)
9932 *paddr = uc->uc_mcontext.eip;
9933 #else
9934 *paddr = uc->uc_mcontext.gregs[REG_EIP];
9935 #endif
9936 return 0;
9937 } else {
9938 #if defined(__FreeBSD__)
9939 fp = uc->uc_mcontext.mc_ebp;
9940 #elif defined(__dietlibc__)
9941 fp = uc->uc_mcontext.ebp;
9942 #else
9943 fp = uc->uc_mcontext.gregs[REG_EBP];
9944 #endif
9945 for(i=1;i<level;i++) {
9946 /* XXX: check address validity with program info */
9947 if (fp <= 0x1000 || fp >= 0xc0000000)
9948 return -1;
9949 fp = ((unsigned long *)fp)[0];
9951 *paddr = ((unsigned long *)fp)[1];
9952 return 0;
9955 #else
9957 #warning add arch specific rt_get_caller_pc()
9959 static int rt_get_caller_pc(unsigned long *paddr,
9960 ucontext_t *uc, int level)
9962 return -1;
9964 #endif
9966 /* emit a run time error at position 'pc' */
9967 void rt_error(ucontext_t *uc, const char *fmt, ...)
9969 va_list ap;
9970 unsigned long pc;
9971 int i;
9973 va_start(ap, fmt);
9974 fprintf(stderr, "Runtime error: ");
9975 vfprintf(stderr, fmt, ap);
9976 fprintf(stderr, "\n");
9977 for(i=0;i<num_callers;i++) {
9978 if (rt_get_caller_pc(&pc, uc, i) < 0)
9979 break;
9980 if (i == 0)
9981 fprintf(stderr, "at ");
9982 else
9983 fprintf(stderr, "by ");
9984 rt_printline(pc);
9986 exit(255);
9987 va_end(ap);
9990 /* signal handler for fatal errors */
9991 static void sig_error(int signum, siginfo_t *siginf, void *puc)
9993 ucontext_t *uc = puc;
9995 switch(signum) {
9996 case SIGFPE:
9997 switch(siginf->si_code) {
9998 case FPE_INTDIV:
9999 case FPE_FLTDIV:
10000 rt_error(uc, "division by zero");
10001 break;
10002 default:
10003 rt_error(uc, "floating point exception");
10004 break;
10006 break;
10007 case SIGBUS:
10008 case SIGSEGV:
10009 if (rt_bound_error_msg && *rt_bound_error_msg)
10010 rt_error(uc, *rt_bound_error_msg);
10011 else
10012 rt_error(uc, "dereferencing invalid pointer");
10013 break;
10014 case SIGILL:
10015 rt_error(uc, "illegal instruction");
10016 break;
10017 case SIGABRT:
10018 rt_error(uc, "abort() called");
10019 break;
10020 default:
10021 rt_error(uc, "caught signal %d", signum);
10022 break;
10024 exit(255);
10026 #endif
10028 /* do all relocations (needed before using tcc_get_symbol()) */
10029 int tcc_relocate(TCCState *s1)
10031 Section *s;
10032 int i;
10034 s1->nb_errors = 0;
10036 #ifdef TCC_TARGET_PE
10037 pe_add_runtime(s1);
10038 #else
10039 tcc_add_runtime(s1);
10040 #endif
10042 relocate_common_syms();
10044 tcc_add_linker_symbols(s1);
10045 #ifndef TCC_TARGET_PE
10046 build_got_entries(s1);
10047 #endif
10048 /* compute relocation address : section are relocated in place. We
10049 also alloc the bss space */
10050 for(i = 1; i < s1->nb_sections; i++) {
10051 s = s1->sections[i];
10052 if (s->sh_flags & SHF_ALLOC) {
10053 if (s->sh_type == SHT_NOBITS)
10054 s->data = tcc_mallocz(s->data_offset);
10055 s->sh_addr = (unsigned long)s->data;
10059 relocate_syms(s1, 1);
10061 if (s1->nb_errors != 0)
10062 return -1;
10064 /* relocate each section */
10065 for(i = 1; i < s1->nb_sections; i++) {
10066 s = s1->sections[i];
10067 if (s->reloc)
10068 relocate_section(s1, s);
10071 /* mark executable sections as executable in memory */
10072 for(i = 1; i < s1->nb_sections; i++) {
10073 s = s1->sections[i];
10074 if ((s->sh_flags & (SHF_ALLOC | SHF_EXECINSTR)) ==
10075 (SHF_ALLOC | SHF_EXECINSTR))
10076 set_pages_executable(s->data, s->data_offset);
10078 return 0;
10081 /* launch the compiled program with the given arguments */
10082 int tcc_run(TCCState *s1, int argc, char **argv)
10084 int (*prog_main)(int, char **);
10086 if (tcc_relocate(s1) < 0)
10087 return -1;
10089 prog_main = tcc_get_symbol_err(s1, "main");
10091 if (do_debug) {
10092 #if defined(_WIN32) || defined(CONFIG_TCCBOOT)
10093 error("debug mode currently not available for Windows");
10094 #else
10095 struct sigaction sigact;
10096 /* install TCC signal handlers to print debug info on fatal
10097 runtime errors */
10098 sigact.sa_flags = SA_SIGINFO | SA_RESETHAND;
10099 sigact.sa_sigaction = sig_error;
10100 sigemptyset(&sigact.sa_mask);
10101 sigaction(SIGFPE, &sigact, NULL);
10102 sigaction(SIGILL, &sigact, NULL);
10103 sigaction(SIGSEGV, &sigact, NULL);
10104 sigaction(SIGBUS, &sigact, NULL);
10105 sigaction(SIGABRT, &sigact, NULL);
10106 #endif
10109 #ifdef CONFIG_TCC_BCHECK
10110 if (do_bounds_check) {
10111 void (*bound_init)(void);
10113 /* set error function */
10114 rt_bound_error_msg = (void *)tcc_get_symbol_err(s1,
10115 "__bound_error_msg");
10117 /* XXX: use .init section so that it also work in binary ? */
10118 bound_init = (void *)tcc_get_symbol_err(s1, "__bound_init");
10119 bound_init();
10121 #endif
10122 return (*prog_main)(argc, argv);
10125 void tcc_memstats(void)
10127 #ifdef MEM_DEBUG
10128 printf("memory in use: %d\n", mem_cur_size);
10129 #endif
10132 static void tcc_cleanup(void)
10134 int i, n;
10136 if (NULL == tcc_state)
10137 return;
10138 tcc_state = NULL;
10140 /* free -D defines */
10141 free_defines(NULL);
10143 /* free tokens */
10144 n = tok_ident - TOK_IDENT;
10145 for(i = 0; i < n; i++)
10146 tcc_free(table_ident[i]);
10147 tcc_free(table_ident);
10149 /* free sym_pools */
10150 dynarray_reset(&sym_pools, &nb_sym_pools);
10151 /* string buffer */
10152 cstr_free(&tokcstr);
10153 /* reset symbol stack */
10154 sym_free_first = NULL;
10155 /* cleanup from error/setjmp */
10156 macro_ptr = NULL;
10159 TCCState *tcc_new(void)
10161 const char *p, *r;
10162 TCCState *s;
10163 TokenSym *ts;
10164 int i, c;
10166 tcc_cleanup();
10168 s = tcc_mallocz(sizeof(TCCState));
10169 if (!s)
10170 return NULL;
10171 tcc_state = s;
10172 s->output_type = TCC_OUTPUT_MEMORY;
10174 /* init isid table */
10175 for(i=CH_EOF;i<256;i++)
10176 isidnum_table[i-CH_EOF] = isid(i) || isnum(i);
10178 /* add all tokens */
10179 table_ident = NULL;
10180 memset(hash_ident, 0, TOK_HASH_SIZE * sizeof(TokenSym *));
10182 tok_ident = TOK_IDENT;
10183 p = tcc_keywords;
10184 while (*p) {
10185 r = p;
10186 for(;;) {
10187 c = *r++;
10188 if (c == '\0')
10189 break;
10191 ts = tok_alloc(p, r - p - 1);
10192 p = r;
10195 /* we add dummy defines for some special macros to speed up tests
10196 and to have working defined() */
10197 define_push(TOK___LINE__, MACRO_OBJ, NULL, NULL);
10198 define_push(TOK___FILE__, MACRO_OBJ, NULL, NULL);
10199 define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL);
10200 define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL);
10202 /* standard defines */
10203 tcc_define_symbol(s, "__STDC__", NULL);
10204 tcc_define_symbol(s, "__STDC_VERSION__", "199901L");
10205 #if defined(TCC_TARGET_I386)
10206 tcc_define_symbol(s, "__i386__", NULL);
10207 #endif
10208 #if defined(TCC_TARGET_ARM)
10209 tcc_define_symbol(s, "__ARM_ARCH_4__", NULL);
10210 tcc_define_symbol(s, "__arm_elf__", NULL);
10211 tcc_define_symbol(s, "__arm_elf", NULL);
10212 tcc_define_symbol(s, "arm_elf", NULL);
10213 tcc_define_symbol(s, "__arm__", NULL);
10214 tcc_define_symbol(s, "__arm", NULL);
10215 tcc_define_symbol(s, "arm", NULL);
10216 tcc_define_symbol(s, "__APCS_32__", NULL);
10217 #endif
10218 #ifdef TCC_TARGET_PE
10219 tcc_define_symbol(s, "_WIN32", NULL);
10220 #else
10221 tcc_define_symbol(s, "__unix__", NULL);
10222 tcc_define_symbol(s, "__unix", NULL);
10223 #if defined(__linux)
10224 tcc_define_symbol(s, "__linux__", NULL);
10225 tcc_define_symbol(s, "__linux", NULL);
10226 #endif
10227 #endif
10228 /* tiny C specific defines */
10229 tcc_define_symbol(s, "__TINYC__", NULL);
10231 /* tiny C & gcc defines */
10232 tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned int");
10233 tcc_define_symbol(s, "__PTRDIFF_TYPE__", "int");
10234 #ifdef TCC_TARGET_PE
10235 tcc_define_symbol(s, "__WCHAR_TYPE__", "unsigned short");
10236 #else
10237 tcc_define_symbol(s, "__WCHAR_TYPE__", "int");
10238 #endif
10240 #ifndef TCC_TARGET_PE
10241 /* default library paths */
10242 tcc_add_library_path(s, CONFIG_SYSROOT "/usr/local/lib");
10243 tcc_add_library_path(s, CONFIG_SYSROOT "/usr/lib");
10244 tcc_add_library_path(s, CONFIG_SYSROOT "/lib");
10245 #endif
10247 /* no section zero */
10248 dynarray_add((void ***)&s->sections, &s->nb_sections, NULL);
10250 /* create standard sections */
10251 text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
10252 data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
10253 bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
10255 /* symbols are always generated for linking stage */
10256 symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0,
10257 ".strtab",
10258 ".hashtab", SHF_PRIVATE);
10259 strtab_section = symtab_section->link;
10261 /* private symbol table for dynamic symbols */
10262 s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE,
10263 ".dynstrtab",
10264 ".dynhashtab", SHF_PRIVATE);
10265 s->alacarte_link = 1;
10267 #ifdef CHAR_IS_UNSIGNED
10268 s->char_is_unsigned = 1;
10269 #endif
10270 #if defined(TCC_TARGET_PE) && 0
10271 /* XXX: currently the PE linker is not ready to support that */
10272 s->leading_underscore = 1;
10273 #endif
10274 return s;
10277 void tcc_delete(TCCState *s1)
10279 int i;
10281 tcc_cleanup();
10283 /* free all sections */
10284 free_section(s1->dynsymtab_section);
10286 for(i = 1; i < s1->nb_sections; i++)
10287 free_section(s1->sections[i]);
10288 tcc_free(s1->sections);
10290 /* free any loaded DLLs */
10291 for ( i = 0; i < s1->nb_loaded_dlls; i++)
10293 DLLReference *ref = s1->loaded_dlls[i];
10294 if ( ref->handle )
10295 dlclose(ref->handle);
10298 /* free loaded dlls array */
10299 dynarray_reset(&s1->loaded_dlls, &s1->nb_loaded_dlls);
10301 /* free library paths */
10302 dynarray_reset(&s1->library_paths, &s1->nb_library_paths);
10304 /* free include paths */
10305 dynarray_reset(&s1->cached_includes, &s1->nb_cached_includes);
10306 dynarray_reset(&s1->include_paths, &s1->nb_include_paths);
10307 dynarray_reset(&s1->sysinclude_paths, &s1->nb_sysinclude_paths);
10309 tcc_free(s1);
10312 int tcc_add_include_path(TCCState *s1, const char *pathname)
10314 char *pathname1;
10316 pathname1 = tcc_strdup(pathname);
10317 dynarray_add((void ***)&s1->include_paths, &s1->nb_include_paths, pathname1);
10318 return 0;
10321 int tcc_add_sysinclude_path(TCCState *s1, const char *pathname)
10323 char *pathname1;
10325 pathname1 = tcc_strdup(pathname);
10326 dynarray_add((void ***)&s1->sysinclude_paths, &s1->nb_sysinclude_paths, pathname1);
10327 return 0;
10330 static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
10332 const char *ext;
10333 ElfW(Ehdr) ehdr;
10334 int fd, ret;
10335 BufferedFile *saved_file;
10337 /* find source file type with extension */
10338 ext = tcc_fileextension(filename);
10339 if (ext[0])
10340 ext++;
10342 /* open the file */
10343 saved_file = file;
10344 file = tcc_open(s1, filename);
10345 if (!file) {
10346 if (flags & AFF_PRINT_ERROR) {
10347 error_noabort("file '%s' not found", filename);
10349 ret = -1;
10350 goto fail1;
10353 if (flags & AFF_PREPROCESS) {
10354 ret = tcc_preprocess(s1);
10355 } else if (!ext[0] || !strcmp(ext, "c")) {
10356 /* C file assumed */
10357 ret = tcc_compile(s1);
10358 } else
10359 #ifdef CONFIG_TCC_ASM
10360 if (!strcmp(ext, "S")) {
10361 /* preprocessed assembler */
10362 ret = tcc_assemble(s1, 1);
10363 } else if (!strcmp(ext, "s")) {
10364 /* non preprocessed assembler */
10365 ret = tcc_assemble(s1, 0);
10366 } else
10367 #endif
10368 #ifdef TCC_TARGET_PE
10369 if (!strcmp(ext, "def")) {
10370 ret = pe_load_def_file(s1, file->fd);
10371 } else
10372 #endif
10374 fd = file->fd;
10375 /* assume executable format: auto guess file type */
10376 ret = read(fd, &ehdr, sizeof(ehdr));
10377 lseek(fd, 0, SEEK_SET);
10378 if (ret <= 0) {
10379 error_noabort("could not read header");
10380 goto fail;
10381 } else if (ret != sizeof(ehdr)) {
10382 goto try_load_script;
10385 if (ehdr.e_ident[0] == ELFMAG0 &&
10386 ehdr.e_ident[1] == ELFMAG1 &&
10387 ehdr.e_ident[2] == ELFMAG2 &&
10388 ehdr.e_ident[3] == ELFMAG3) {
10389 file->line_num = 0; /* do not display line number if error */
10390 if (ehdr.e_type == ET_REL) {
10391 ret = tcc_load_object_file(s1, fd, 0);
10392 } else if (ehdr.e_type == ET_DYN) {
10393 if (s1->output_type == TCC_OUTPUT_MEMORY) {
10394 #ifdef TCC_TARGET_PE
10395 ret = -1;
10396 #else
10397 void *h;
10398 h = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY);
10399 if (h)
10400 ret = 0;
10401 else
10402 ret = -1;
10403 #endif
10404 } else {
10405 ret = tcc_load_dll(s1, fd, filename,
10406 (flags & AFF_REFERENCED_DLL) != 0);
10408 } else {
10409 error_noabort("unrecognized ELF file");
10410 goto fail;
10412 } else if (memcmp((char *)&ehdr, ARMAG, 8) == 0) {
10413 file->line_num = 0; /* do not display line number if error */
10414 ret = tcc_load_archive(s1, fd);
10415 } else
10416 #ifdef TCC_TARGET_COFF
10417 if (*(uint16_t *)(&ehdr) == COFF_C67_MAGIC) {
10418 ret = tcc_load_coff(s1, fd);
10419 } else
10420 #endif
10421 #ifdef TCC_TARGET_PE
10422 if (pe_test_res_file(&ehdr, ret)) {
10423 ret = pe_load_res_file(s1, fd);
10424 } else
10425 #endif
10427 /* as GNU ld, consider it is an ld script if not recognized */
10428 try_load_script:
10429 ret = tcc_load_ldscript(s1);
10430 if (ret < 0) {
10431 error_noabort("unrecognized file type");
10432 goto fail;
10436 the_end:
10437 tcc_close(file);
10438 fail1:
10439 file = saved_file;
10440 return ret;
10441 fail:
10442 ret = -1;
10443 goto the_end;
10446 int tcc_add_file(TCCState *s, const char *filename)
10448 return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR);
10451 int tcc_add_library_path(TCCState *s, const char *pathname)
10453 char *pathname1;
10455 pathname1 = tcc_strdup(pathname);
10456 dynarray_add((void ***)&s->library_paths, &s->nb_library_paths, pathname1);
10457 return 0;
10460 /* find and load a dll. Return non zero if not found */
10461 /* XXX: add '-rpath' option support ? */
10462 static int tcc_add_dll(TCCState *s, const char *filename, int flags)
10464 char buf[1024];
10465 int i;
10467 for(i = 0; i < s->nb_library_paths; i++) {
10468 snprintf(buf, sizeof(buf), "%s/%s",
10469 s->library_paths[i], filename);
10470 if (tcc_add_file_internal(s, buf, flags) == 0)
10471 return 0;
10473 return -1;
10476 /* the library name is the same as the argument of the '-l' option */
10477 int tcc_add_library(TCCState *s, const char *libraryname)
10479 char buf[1024];
10480 int i;
10482 /* first we look for the dynamic library if not static linking */
10483 if (!s->static_link) {
10484 #ifdef TCC_TARGET_PE
10485 snprintf(buf, sizeof(buf), "%s.def", libraryname);
10486 #else
10487 snprintf(buf, sizeof(buf), "lib%s.so", libraryname);
10488 #endif
10489 if (tcc_add_dll(s, buf, 0) == 0)
10490 return 0;
10493 /* then we look for the static library */
10494 for(i = 0; i < s->nb_library_paths; i++) {
10495 snprintf(buf, sizeof(buf), "%s/lib%s.a",
10496 s->library_paths[i], libraryname);
10497 if (tcc_add_file_internal(s, buf, 0) == 0)
10498 return 0;
10500 return -1;
10503 int tcc_add_symbol(TCCState *s, const char *name, unsigned long val)
10505 add_elf_sym(symtab_section, val, 0,
10506 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
10507 SHN_ABS, name);
10508 return 0;
10511 int tcc_set_output_type(TCCState *s, int output_type)
10513 char buf[1024];
10515 s->output_type = output_type;
10517 if (!s->nostdinc) {
10518 /* default include paths */
10519 /* XXX: reverse order needed if -isystem support */
10520 #ifndef TCC_TARGET_PE
10521 tcc_add_sysinclude_path(s, CONFIG_SYSROOT "/usr/local/include");
10522 tcc_add_sysinclude_path(s, CONFIG_SYSROOT "/usr/include");
10523 #endif
10524 snprintf(buf, sizeof(buf), "%s/include", tcc_lib_path);
10525 tcc_add_sysinclude_path(s, buf);
10526 #ifdef TCC_TARGET_PE
10527 snprintf(buf, sizeof(buf), "%s/include/winapi", tcc_lib_path);
10528 tcc_add_sysinclude_path(s, buf);
10529 #endif
10532 /* if bound checking, then add corresponding sections */
10533 #ifdef CONFIG_TCC_BCHECK
10534 if (do_bounds_check) {
10535 /* define symbol */
10536 tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL);
10537 /* create bounds sections */
10538 bounds_section = new_section(s, ".bounds",
10539 SHT_PROGBITS, SHF_ALLOC);
10540 lbounds_section = new_section(s, ".lbounds",
10541 SHT_PROGBITS, SHF_ALLOC);
10543 #endif
10545 if (s->char_is_unsigned) {
10546 tcc_define_symbol(s, "__CHAR_UNSIGNED__", NULL);
10549 /* add debug sections */
10550 if (do_debug) {
10551 /* stab symbols */
10552 stab_section = new_section(s, ".stab", SHT_PROGBITS, 0);
10553 stab_section->sh_entsize = sizeof(Stab_Sym);
10554 stabstr_section = new_section(s, ".stabstr", SHT_STRTAB, 0);
10555 put_elf_str(stabstr_section, "");
10556 stab_section->link = stabstr_section;
10557 /* put first entry */
10558 put_stabs("", 0, 0, 0, 0);
10561 /* add libc crt1/crti objects */
10562 #ifndef TCC_TARGET_PE
10563 if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) &&
10564 !s->nostdlib) {
10565 if (output_type != TCC_OUTPUT_DLL)
10566 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crt1.o");
10567 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crti.o");
10569 #endif
10571 #ifdef TCC_TARGET_PE
10572 snprintf(buf, sizeof(buf), "%s/lib", tcc_lib_path);
10573 tcc_add_library_path(s, buf);
10574 #endif
10576 return 0;
10579 #define WD_ALL 0x0001 /* warning is activated when using -Wall */
10580 #define FD_INVERT 0x0002 /* invert value before storing */
10582 typedef struct FlagDef {
10583 uint16_t offset;
10584 uint16_t flags;
10585 const char *name;
10586 } FlagDef;
10588 static const FlagDef warning_defs[] = {
10589 { offsetof(TCCState, warn_unsupported), 0, "unsupported" },
10590 { offsetof(TCCState, warn_write_strings), 0, "write-strings" },
10591 { offsetof(TCCState, warn_error), 0, "error" },
10592 { offsetof(TCCState, warn_implicit_function_declaration), WD_ALL,
10593 "implicit-function-declaration" },
10596 static int set_flag(TCCState *s, const FlagDef *flags, int nb_flags,
10597 const char *name, int value)
10599 int i;
10600 const FlagDef *p;
10601 const char *r;
10603 r = name;
10604 if (r[0] == 'n' && r[1] == 'o' && r[2] == '-') {
10605 r += 3;
10606 value = !value;
10608 for(i = 0, p = flags; i < nb_flags; i++, p++) {
10609 if (!strcmp(r, p->name))
10610 goto found;
10612 return -1;
10613 found:
10614 if (p->flags & FD_INVERT)
10615 value = !value;
10616 *(int *)((uint8_t *)s + p->offset) = value;
10617 return 0;
10621 /* set/reset a warning */
10622 int tcc_set_warning(TCCState *s, const char *warning_name, int value)
10624 int i;
10625 const FlagDef *p;
10627 if (!strcmp(warning_name, "all")) {
10628 for(i = 0, p = warning_defs; i < countof(warning_defs); i++, p++) {
10629 if (p->flags & WD_ALL)
10630 *(int *)((uint8_t *)s + p->offset) = 1;
10632 return 0;
10633 } else {
10634 return set_flag(s, warning_defs, countof(warning_defs),
10635 warning_name, value);
10639 static const FlagDef flag_defs[] = {
10640 { offsetof(TCCState, char_is_unsigned), 0, "unsigned-char" },
10641 { offsetof(TCCState, char_is_unsigned), FD_INVERT, "signed-char" },
10642 { offsetof(TCCState, nocommon), FD_INVERT, "common" },
10643 { offsetof(TCCState, leading_underscore), 0, "leading-underscore" },
10646 /* set/reset a flag */
10647 int tcc_set_flag(TCCState *s, const char *flag_name, int value)
10649 return set_flag(s, flag_defs, countof(flag_defs),
10650 flag_name, value);
10653 #if !defined(LIBTCC)
10655 static int64_t getclock_us(void)
10657 #ifdef _WIN32
10658 struct _timeb tb;
10659 _ftime(&tb);
10660 return (tb.time * 1000LL + tb.millitm) * 1000LL;
10661 #else
10662 struct timeval tv;
10663 gettimeofday(&tv, NULL);
10664 return tv.tv_sec * 1000000LL + tv.tv_usec;
10665 #endif
10668 void help(void)
10670 printf("tcc version " TCC_VERSION " - Tiny C Compiler - Copyright (C) 2001-2006 Fabrice Bellard\n"
10671 "usage: tcc [-v] [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
10672 " [-Wwarn] [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-soname name]\n"
10673 " [-static] [infile1 infile2...] [-run infile args...]\n"
10674 "\n"
10675 "General options:\n"
10676 " -v display current version, increase verbosity\n"
10677 " -c compile only - generate an object file\n"
10678 " -o outfile set output filename\n"
10679 " -Bdir set tcc internal library path\n"
10680 " -bench output compilation statistics\n"
10681 " -run run compiled source\n"
10682 " -fflag set or reset (with 'no-' prefix) 'flag' (see man page)\n"
10683 " -Wwarning set or reset (with 'no-' prefix) 'warning' (see man page)\n"
10684 " -w disable all warnings\n"
10685 "Preprocessor options:\n"
10686 " -E preprocess only\n"
10687 " -Idir add include path 'dir'\n"
10688 " -Dsym[=val] define 'sym' with value 'val'\n"
10689 " -Usym undefine 'sym'\n"
10690 "Linker options:\n"
10691 " -Ldir add library path 'dir'\n"
10692 " -llib link with dynamic or static library 'lib'\n"
10693 " -shared generate a shared library\n"
10694 " -soname set name for shared library to be used at runtime\n"
10695 " -static static linking\n"
10696 " -rdynamic export all global symbols to dynamic linker\n"
10697 " -r generate (relocatable) object file\n"
10698 "Debugger options:\n"
10699 " -g generate runtime debug info\n"
10700 #ifdef CONFIG_TCC_BCHECK
10701 " -b compile with built-in memory and bounds checker (implies -g)\n"
10702 #endif
10703 " -bt N show N callers in stack traces\n"
10707 #define TCC_OPTION_HAS_ARG 0x0001
10708 #define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
10710 typedef struct TCCOption {
10711 const char *name;
10712 uint16_t index;
10713 uint16_t flags;
10714 } TCCOption;
10716 enum {
10717 TCC_OPTION_HELP,
10718 TCC_OPTION_I,
10719 TCC_OPTION_D,
10720 TCC_OPTION_U,
10721 TCC_OPTION_L,
10722 TCC_OPTION_B,
10723 TCC_OPTION_l,
10724 TCC_OPTION_bench,
10725 TCC_OPTION_bt,
10726 TCC_OPTION_b,
10727 TCC_OPTION_g,
10728 TCC_OPTION_c,
10729 TCC_OPTION_static,
10730 TCC_OPTION_shared,
10731 TCC_OPTION_soname,
10732 TCC_OPTION_o,
10733 TCC_OPTION_r,
10734 TCC_OPTION_Wl,
10735 TCC_OPTION_W,
10736 TCC_OPTION_O,
10737 TCC_OPTION_m,
10738 TCC_OPTION_f,
10739 TCC_OPTION_nostdinc,
10740 TCC_OPTION_nostdlib,
10741 TCC_OPTION_print_search_dirs,
10742 TCC_OPTION_rdynamic,
10743 TCC_OPTION_run,
10744 TCC_OPTION_v,
10745 TCC_OPTION_w,
10746 TCC_OPTION_pipe,
10747 TCC_OPTION_E,
10750 static const TCCOption tcc_options[] = {
10751 { "h", TCC_OPTION_HELP, 0 },
10752 { "?", TCC_OPTION_HELP, 0 },
10753 { "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG },
10754 { "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG },
10755 { "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG },
10756 { "L", TCC_OPTION_L, TCC_OPTION_HAS_ARG },
10757 { "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG },
10758 { "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10759 { "bench", TCC_OPTION_bench, 0 },
10760 { "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG },
10761 #ifdef CONFIG_TCC_BCHECK
10762 { "b", TCC_OPTION_b, 0 },
10763 #endif
10764 { "g", TCC_OPTION_g, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10765 { "c", TCC_OPTION_c, 0 },
10766 { "static", TCC_OPTION_static, 0 },
10767 { "shared", TCC_OPTION_shared, 0 },
10768 { "soname", TCC_OPTION_soname, TCC_OPTION_HAS_ARG },
10769 { "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG },
10770 { "run", TCC_OPTION_run, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10771 { "rdynamic", TCC_OPTION_rdynamic, 0 },
10772 { "r", TCC_OPTION_r, 0 },
10773 { "Wl,", TCC_OPTION_Wl, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10774 { "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10775 { "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10776 { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG },
10777 { "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10778 { "nostdinc", TCC_OPTION_nostdinc, 0 },
10779 { "nostdlib", TCC_OPTION_nostdlib, 0 },
10780 { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 },
10781 { "v", TCC_OPTION_v, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10782 { "w", TCC_OPTION_w, 0 },
10783 { "pipe", TCC_OPTION_pipe, 0},
10784 { "E", TCC_OPTION_E, 0},
10785 { NULL },
10788 /* convert 'str' into an array of space separated strings */
10789 static int expand_args(char ***pargv, const char *str)
10791 const char *s1;
10792 char **argv, *arg;
10793 int argc, len;
10795 argc = 0;
10796 argv = NULL;
10797 for(;;) {
10798 while (is_space(*str))
10799 str++;
10800 if (*str == '\0')
10801 break;
10802 s1 = str;
10803 while (*str != '\0' && !is_space(*str))
10804 str++;
10805 len = str - s1;
10806 arg = tcc_malloc(len + 1);
10807 memcpy(arg, s1, len);
10808 arg[len] = '\0';
10809 dynarray_add((void ***)&argv, &argc, arg);
10811 *pargv = argv;
10812 return argc;
10815 static char **files;
10816 static int nb_files, nb_libraries;
10817 static int multiple_files;
10818 static int print_search_dirs;
10819 static int output_type;
10820 static int reloc_output;
10821 static const char *outfile;
10823 int parse_args(TCCState *s, int argc, char **argv)
10825 int optind;
10826 const TCCOption *popt;
10827 const char *optarg, *p1, *r1;
10828 char *r;
10830 optind = 0;
10831 while (optind < argc) {
10833 r = argv[optind++];
10834 if (r[0] != '-' || r[1] == '\0') {
10835 /* add a new file */
10836 dynarray_add((void ***)&files, &nb_files, r);
10837 if (!multiple_files) {
10838 optind--;
10839 /* argv[0] will be this file */
10840 break;
10842 } else {
10843 /* find option in table (match only the first chars */
10844 popt = tcc_options;
10845 for(;;) {
10846 p1 = popt->name;
10847 if (p1 == NULL)
10848 error("invalid option -- '%s'", r);
10849 r1 = r + 1;
10850 for(;;) {
10851 if (*p1 == '\0')
10852 goto option_found;
10853 if (*r1 != *p1)
10854 break;
10855 p1++;
10856 r1++;
10858 popt++;
10860 option_found:
10861 if (popt->flags & TCC_OPTION_HAS_ARG) {
10862 if (*r1 != '\0' || (popt->flags & TCC_OPTION_NOSEP)) {
10863 optarg = r1;
10864 } else {
10865 if (optind >= argc)
10866 error("argument to '%s' is missing", r);
10867 optarg = argv[optind++];
10869 } else {
10870 if (*r1 != '\0')
10871 return 0;
10872 optarg = NULL;
10875 switch(popt->index) {
10876 case TCC_OPTION_HELP:
10877 return 0;
10879 case TCC_OPTION_I:
10880 if (tcc_add_include_path(s, optarg) < 0)
10881 error("too many include paths");
10882 break;
10883 case TCC_OPTION_D:
10885 char *sym, *value;
10886 sym = (char *)optarg;
10887 value = strchr(sym, '=');
10888 if (value) {
10889 *value = '\0';
10890 value++;
10892 tcc_define_symbol(s, sym, value);
10894 break;
10895 case TCC_OPTION_U:
10896 tcc_undefine_symbol(s, optarg);
10897 break;
10898 case TCC_OPTION_L:
10899 tcc_add_library_path(s, optarg);
10900 break;
10901 case TCC_OPTION_B:
10902 /* set tcc utilities path (mainly for tcc development) */
10903 tcc_lib_path = optarg;
10904 break;
10905 case TCC_OPTION_l:
10906 dynarray_add((void ***)&files, &nb_files, r);
10907 nb_libraries++;
10908 break;
10909 case TCC_OPTION_bench:
10910 do_bench = 1;
10911 break;
10912 case TCC_OPTION_bt:
10913 num_callers = atoi(optarg);
10914 break;
10915 #ifdef CONFIG_TCC_BCHECK
10916 case TCC_OPTION_b:
10917 do_bounds_check = 1;
10918 do_debug = 1;
10919 break;
10920 #endif
10921 case TCC_OPTION_g:
10922 do_debug = 1;
10923 break;
10924 case TCC_OPTION_c:
10925 multiple_files = 1;
10926 output_type = TCC_OUTPUT_OBJ;
10927 break;
10928 case TCC_OPTION_static:
10929 s->static_link = 1;
10930 break;
10931 case TCC_OPTION_shared:
10932 output_type = TCC_OUTPUT_DLL;
10933 break;
10934 case TCC_OPTION_soname:
10935 s->soname = optarg;
10936 break;
10937 case TCC_OPTION_o:
10938 multiple_files = 1;
10939 outfile = optarg;
10940 break;
10941 case TCC_OPTION_r:
10942 /* generate a .o merging several output files */
10943 reloc_output = 1;
10944 output_type = TCC_OUTPUT_OBJ;
10945 break;
10946 case TCC_OPTION_nostdinc:
10947 s->nostdinc = 1;
10948 break;
10949 case TCC_OPTION_nostdlib:
10950 s->nostdlib = 1;
10951 break;
10952 case TCC_OPTION_print_search_dirs:
10953 print_search_dirs = 1;
10954 break;
10955 case TCC_OPTION_run:
10957 int argc1;
10958 char **argv1;
10959 argc1 = expand_args(&argv1, optarg);
10960 if (argc1 > 0) {
10961 parse_args(s, argc1, argv1);
10963 multiple_files = 0;
10964 output_type = TCC_OUTPUT_MEMORY;
10966 break;
10967 case TCC_OPTION_v:
10968 do {
10969 if (0 == verbose++)
10970 printf("tcc version %s\n", TCC_VERSION);
10971 } while (*optarg++ == 'v');
10972 break;
10973 case TCC_OPTION_f:
10974 if (tcc_set_flag(s, optarg, 1) < 0 && s->warn_unsupported)
10975 goto unsupported_option;
10976 break;
10977 case TCC_OPTION_W:
10978 if (tcc_set_warning(s, optarg, 1) < 0 &&
10979 s->warn_unsupported)
10980 goto unsupported_option;
10981 break;
10982 case TCC_OPTION_w:
10983 s->warn_none = 1;
10984 break;
10985 case TCC_OPTION_rdynamic:
10986 s->rdynamic = 1;
10987 break;
10988 case TCC_OPTION_Wl:
10990 const char *p;
10991 if (strstart(optarg, "-Ttext,", &p)) {
10992 s->text_addr = strtoul(p, NULL, 16);
10993 s->has_text_addr = 1;
10994 } else if (strstart(optarg, "--oformat,", &p)) {
10995 if (strstart(p, "elf32-", NULL)) {
10996 s->output_format = TCC_OUTPUT_FORMAT_ELF;
10997 } else if (!strcmp(p, "binary")) {
10998 s->output_format = TCC_OUTPUT_FORMAT_BINARY;
10999 } else
11000 #ifdef TCC_TARGET_COFF
11001 if (!strcmp(p, "coff")) {
11002 s->output_format = TCC_OUTPUT_FORMAT_COFF;
11003 } else
11004 #endif
11006 error("target %s not found", p);
11008 } else {
11009 error("unsupported linker option '%s'", optarg);
11012 break;
11013 case TCC_OPTION_E:
11014 output_type = TCC_OUTPUT_PREPROCESS;
11015 break;
11016 default:
11017 if (s->warn_unsupported) {
11018 unsupported_option:
11019 warning("unsupported option '%s'", r);
11021 break;
11025 return optind + 1;
11028 int main(int argc, char **argv)
11030 int i;
11031 TCCState *s;
11032 int nb_objfiles, ret, optind;
11033 char objfilename[1024];
11034 int64_t start_time = 0;
11036 #ifdef _WIN32
11037 tcc_lib_path = w32_tcc_lib_path();
11038 #endif
11040 s = tcc_new();
11041 output_type = TCC_OUTPUT_EXE;
11042 outfile = NULL;
11043 multiple_files = 1;
11044 files = NULL;
11045 nb_files = 0;
11046 nb_libraries = 0;
11047 reloc_output = 0;
11048 print_search_dirs = 0;
11049 ret = 0;
11051 optind = parse_args(s, argc - 1, argv + 1);
11052 if (print_search_dirs) {
11053 /* enough for Linux kernel */
11054 printf("install: %s/\n", tcc_lib_path);
11055 return 0;
11057 if (optind == 0 || nb_files == 0) {
11058 if (optind && verbose)
11059 return 0;
11060 help();
11061 return 1;
11064 nb_objfiles = nb_files - nb_libraries;
11066 /* if outfile provided without other options, we output an
11067 executable */
11068 if (outfile && output_type == TCC_OUTPUT_MEMORY)
11069 output_type = TCC_OUTPUT_EXE;
11071 /* check -c consistency : only single file handled. XXX: checks file type */
11072 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
11073 /* accepts only a single input file */
11074 if (nb_objfiles != 1)
11075 error("cannot specify multiple files with -c");
11076 if (nb_libraries != 0)
11077 error("cannot specify libraries with -c");
11081 if (output_type == TCC_OUTPUT_PREPROCESS) {
11082 if (!outfile) {
11083 s->outfile = stdout;
11084 } else {
11085 s->outfile = fopen(outfile, "w");
11086 if (!s->outfile)
11087 error("could not open '%s", outfile);
11089 } else if (output_type != TCC_OUTPUT_MEMORY) {
11090 if (!outfile) {
11091 /* compute default outfile name */
11092 char *ext;
11093 const char *name =
11094 strcmp(files[0], "-") == 0 ? "a" : tcc_basename(files[0]);
11095 pstrcpy(objfilename, sizeof(objfilename), name);
11096 ext = tcc_fileextension(objfilename);
11097 #ifdef TCC_TARGET_PE
11098 if (output_type == TCC_OUTPUT_DLL)
11099 strcpy(ext, ".dll");
11100 else
11101 if (output_type == TCC_OUTPUT_EXE)
11102 strcpy(ext, ".exe");
11103 else
11104 #endif
11105 if (output_type == TCC_OUTPUT_OBJ && !reloc_output && *ext)
11106 strcpy(ext, ".o");
11107 else
11108 pstrcpy(objfilename, sizeof(objfilename), "a.out");
11109 outfile = objfilename;
11113 if (do_bench) {
11114 start_time = getclock_us();
11117 tcc_set_output_type(s, output_type);
11119 /* compile or add each files or library */
11120 for(i = 0; i < nb_files && ret == 0; i++) {
11121 const char *filename;
11123 filename = files[i];
11124 if (output_type == TCC_OUTPUT_PREPROCESS) {
11125 if (tcc_add_file_internal(s, filename,
11126 AFF_PRINT_ERROR | AFF_PREPROCESS) < 0)
11127 ret = 1;
11128 } else if (filename[0] == '-' && filename[1]) {
11129 if (tcc_add_library(s, filename + 2) < 0)
11130 error("cannot find %s", filename);
11131 } else {
11132 if (1 == verbose)
11133 printf("-> %s\n", filename);
11134 if (tcc_add_file(s, filename) < 0)
11135 ret = 1;
11139 /* free all files */
11140 tcc_free(files);
11142 if (ret)
11143 goto the_end;
11145 if (do_bench) {
11146 double total_time;
11147 total_time = (double)(getclock_us() - start_time) / 1000000.0;
11148 if (total_time < 0.001)
11149 total_time = 0.001;
11150 if (total_bytes < 1)
11151 total_bytes = 1;
11152 printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
11153 tok_ident - TOK_IDENT, total_lines, total_bytes,
11154 total_time, (int)(total_lines / total_time),
11155 total_bytes / total_time / 1000000.0);
11158 if (s->output_type == TCC_OUTPUT_PREPROCESS) {
11159 if (outfile)
11160 fclose(s->outfile);
11161 } else if (s->output_type == TCC_OUTPUT_MEMORY) {
11162 ret = tcc_run(s, argc - optind, argv + optind);
11163 } else
11164 ret = tcc_output_file(s, outfile) ? 1 : 0;
11165 the_end:
11166 /* XXX: cannot do it with bound checking because of the malloc hooks */
11167 if (!do_bounds_check)
11168 tcc_delete(s);
11170 #ifdef MEM_DEBUG
11171 if (do_bench) {
11172 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size, mem_max_size);
11174 #endif
11175 return ret;
11178 #endif