One more s/int/long/
[tinycc.git] / tcc.c
blob13da161c977b1b0fecc587928dfba9e7c0164baa
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 long r; /* associated register */
188 long 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, long 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, (long)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, (long)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_builtin_frame_address:
7604 CType type;
7605 next();
7606 skip('(');
7607 if (tok != TOK_CINT) {
7608 error("__builtin_frame_address only takes integers");
7610 if (tokc.i != 0) {
7611 error("TCC only supports __builtin_frame_address(0)");
7613 next();
7614 skip(')');
7615 type.t = VT_VOID;
7616 mk_pointer(&type);
7617 vset(&type, VT_LOCAL, 0);
7619 break;
7620 case TOK_INC:
7621 case TOK_DEC:
7622 t = tok;
7623 next();
7624 unary();
7625 inc(0, t);
7626 break;
7627 case '-':
7628 next();
7629 vpushi(0);
7630 unary();
7631 gen_op('-');
7632 break;
7633 case TOK_LAND:
7634 if (!gnu_ext)
7635 goto tok_identifier;
7636 next();
7637 /* allow to take the address of a label */
7638 if (tok < TOK_UIDENT)
7639 expect("label identifier");
7640 s = label_find(tok);
7641 if (!s) {
7642 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
7643 } else {
7644 if (s->r == LABEL_DECLARED)
7645 s->r = LABEL_FORWARD;
7647 if (!s->type.t) {
7648 s->type.t = VT_VOID;
7649 mk_pointer(&s->type);
7650 s->type.t |= VT_STATIC;
7652 vset(&s->type, VT_CONST | VT_SYM, 0);
7653 vtop->sym = s;
7654 next();
7655 break;
7656 default:
7657 tok_identifier:
7658 t = tok;
7659 next();
7660 if (t < TOK_UIDENT)
7661 expect("identifier");
7662 s = sym_find(t);
7663 if (!s) {
7664 if (tok != '(')
7665 error("'%s' undeclared", get_tok_str(t, NULL));
7666 /* for simple function calls, we tolerate undeclared
7667 external reference to int() function */
7668 if (tcc_state->warn_implicit_function_declaration)
7669 warning("implicit declaration of function '%s'",
7670 get_tok_str(t, NULL));
7671 s = external_global_sym(t, &func_old_type, 0);
7673 if ((s->type.t & (VT_STATIC | VT_INLINE | VT_BTYPE)) ==
7674 (VT_STATIC | VT_INLINE | VT_FUNC)) {
7675 /* if referencing an inline function, then we generate a
7676 symbol to it if not already done. It will have the
7677 effect to generate code for it at the end of the
7678 compilation unit. Inline function as always
7679 generated in the text section. */
7680 if (!s->c)
7681 put_extern_sym(s, text_section, 0, 0);
7682 r = VT_SYM | VT_CONST;
7683 } else {
7684 r = s->r;
7686 vset(&s->type, r, s->c);
7687 /* if forward reference, we must point to s */
7688 if (vtop->r & VT_SYM) {
7689 vtop->sym = s;
7690 vtop->c.ul = 0;
7692 break;
7695 /* post operations */
7696 while (1) {
7697 if (tok == TOK_INC || tok == TOK_DEC) {
7698 inc(1, tok);
7699 next();
7700 } else if (tok == '.' || tok == TOK_ARROW) {
7701 /* field */
7702 if (tok == TOK_ARROW)
7703 indir();
7704 test_lvalue();
7705 gaddrof();
7706 next();
7707 /* expect pointer on structure */
7708 if ((vtop->type.t & VT_BTYPE) != VT_STRUCT)
7709 expect("struct or union");
7710 s = vtop->type.ref;
7711 /* find field */
7712 tok |= SYM_FIELD;
7713 while ((s = s->next) != NULL) {
7714 if (s->v == tok)
7715 break;
7717 if (!s)
7718 error("field not found: %s", get_tok_str(tok & ~SYM_FIELD, NULL));
7719 /* add field offset to pointer */
7720 vtop->type = char_pointer_type; /* change type to 'char *' */
7721 vpushi(s->c);
7722 gen_op('+');
7723 /* change type to field type, and set to lvalue */
7724 vtop->type = s->type;
7725 /* an array is never an lvalue */
7726 if (!(vtop->type.t & VT_ARRAY)) {
7727 vtop->r |= lvalue_type(vtop->type.t);
7728 /* if bound checking, the referenced pointer must be checked */
7729 if (do_bounds_check)
7730 vtop->r |= VT_MUSTBOUND;
7732 next();
7733 } else if (tok == '[') {
7734 next();
7735 gexpr();
7736 gen_op('+');
7737 indir();
7738 skip(']');
7739 } else if (tok == '(') {
7740 SValue ret;
7741 Sym *sa;
7742 int nb_args;
7744 /* function call */
7745 if ((vtop->type.t & VT_BTYPE) != VT_FUNC) {
7746 /* pointer test (no array accepted) */
7747 if ((vtop->type.t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
7748 vtop->type = *pointed_type(&vtop->type);
7749 if ((vtop->type.t & VT_BTYPE) != VT_FUNC)
7750 goto error_func;
7751 } else {
7752 error_func:
7753 expect("function pointer");
7755 } else {
7756 vtop->r &= ~VT_LVAL; /* no lvalue */
7758 /* get return type */
7759 s = vtop->type.ref;
7760 next();
7761 sa = s->next; /* first parameter */
7762 nb_args = 0;
7763 ret.r2 = VT_CONST;
7764 /* compute first implicit argument if a structure is returned */
7765 if ((s->type.t & VT_BTYPE) == VT_STRUCT) {
7766 /* get some space for the returned structure */
7767 size = type_size(&s->type, &align);
7768 loc = (loc - size) & -align;
7769 ret.type = s->type;
7770 ret.r = VT_LOCAL | VT_LVAL;
7771 /* pass it as 'int' to avoid structure arg passing
7772 problems */
7773 vseti(VT_LOCAL, loc);
7774 ret.c = vtop->c;
7775 nb_args++;
7776 } else {
7777 ret.type = s->type;
7778 /* return in register */
7779 if (is_float(ret.type.t)) {
7780 ret.r = REG_FRET;
7781 } else {
7782 if ((ret.type.t & VT_BTYPE) == VT_LLONG)
7783 ret.r2 = REG_LRET;
7784 ret.r = REG_IRET;
7786 ret.c.i = 0;
7788 if (tok != ')') {
7789 for(;;) {
7790 expr_eq();
7791 gfunc_param_typed(s, sa);
7792 nb_args++;
7793 if (sa)
7794 sa = sa->next;
7795 if (tok == ')')
7796 break;
7797 skip(',');
7800 if (sa)
7801 error("too few arguments to function");
7802 skip(')');
7803 if (!nocode_wanted) {
7804 gfunc_call(nb_args);
7805 } else {
7806 vtop -= (nb_args + 1);
7808 /* return value */
7809 vsetc(&ret.type, ret.r, &ret.c);
7810 vtop->r2 = ret.r2;
7811 } else {
7812 break;
7817 static void uneq(void)
7819 int t;
7821 unary();
7822 if (tok == '=' ||
7823 (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
7824 tok == TOK_A_XOR || tok == TOK_A_OR ||
7825 tok == TOK_A_SHL || tok == TOK_A_SAR) {
7826 test_lvalue();
7827 t = tok;
7828 next();
7829 if (t == '=') {
7830 expr_eq();
7831 } else {
7832 vdup();
7833 expr_eq();
7834 gen_op(t & 0x7f);
7836 vstore();
7840 static void expr_prod(void)
7842 int t;
7844 uneq();
7845 while (tok == '*' || tok == '/' || tok == '%') {
7846 t = tok;
7847 next();
7848 uneq();
7849 gen_op(t);
7853 static void expr_sum(void)
7855 int t;
7857 expr_prod();
7858 while (tok == '+' || tok == '-') {
7859 t = tok;
7860 next();
7861 expr_prod();
7862 gen_op(t);
7866 static void expr_shift(void)
7868 int t;
7870 expr_sum();
7871 while (tok == TOK_SHL || tok == TOK_SAR) {
7872 t = tok;
7873 next();
7874 expr_sum();
7875 gen_op(t);
7879 static void expr_cmp(void)
7881 int t;
7883 expr_shift();
7884 while ((tok >= TOK_ULE && tok <= TOK_GT) ||
7885 tok == TOK_ULT || tok == TOK_UGE) {
7886 t = tok;
7887 next();
7888 expr_shift();
7889 gen_op(t);
7893 static void expr_cmpeq(void)
7895 int t;
7897 expr_cmp();
7898 while (tok == TOK_EQ || tok == TOK_NE) {
7899 t = tok;
7900 next();
7901 expr_cmp();
7902 gen_op(t);
7906 static void expr_and(void)
7908 expr_cmpeq();
7909 while (tok == '&') {
7910 next();
7911 expr_cmpeq();
7912 gen_op('&');
7916 static void expr_xor(void)
7918 expr_and();
7919 while (tok == '^') {
7920 next();
7921 expr_and();
7922 gen_op('^');
7926 static void expr_or(void)
7928 expr_xor();
7929 while (tok == '|') {
7930 next();
7931 expr_xor();
7932 gen_op('|');
7936 /* XXX: fix this mess */
7937 static void expr_land_const(void)
7939 expr_or();
7940 while (tok == TOK_LAND) {
7941 next();
7942 expr_or();
7943 gen_op(TOK_LAND);
7947 /* XXX: fix this mess */
7948 static void expr_lor_const(void)
7950 expr_land_const();
7951 while (tok == TOK_LOR) {
7952 next();
7953 expr_land_const();
7954 gen_op(TOK_LOR);
7958 /* only used if non constant */
7959 static void expr_land(void)
7961 int t;
7963 expr_or();
7964 if (tok == TOK_LAND) {
7965 t = 0;
7966 save_regs(1);
7967 for(;;) {
7968 t = gtst(1, t);
7969 if (tok != TOK_LAND) {
7970 vseti(VT_JMPI, t);
7971 break;
7973 next();
7974 expr_or();
7979 static void expr_lor(void)
7981 int t;
7983 expr_land();
7984 if (tok == TOK_LOR) {
7985 t = 0;
7986 save_regs(1);
7987 for(;;) {
7988 t = gtst(0, t);
7989 if (tok != TOK_LOR) {
7990 vseti(VT_JMP, t);
7991 break;
7993 next();
7994 expr_land();
7999 /* XXX: better constant handling */
8000 static void expr_eq(void)
8002 int tt, u, r1, r2, rc, t1, t2, bt1, bt2;
8003 SValue sv;
8004 CType type, type1, type2;
8006 if (const_wanted) {
8007 expr_lor_const();
8008 if (tok == '?') {
8009 CType boolean;
8010 int c;
8011 boolean.t = VT_BOOL;
8012 vdup();
8013 gen_cast(&boolean);
8014 c = vtop->c.i;
8015 vpop();
8016 next();
8017 if (tok != ':' || !gnu_ext) {
8018 vpop();
8019 gexpr();
8021 if (!c)
8022 vpop();
8023 skip(':');
8024 expr_eq();
8025 if (c)
8026 vpop();
8028 } else {
8029 expr_lor();
8030 if (tok == '?') {
8031 next();
8032 if (vtop != vstack) {
8033 /* needed to avoid having different registers saved in
8034 each branch */
8035 if (is_float(vtop->type.t))
8036 rc = RC_FLOAT;
8037 else
8038 rc = RC_INT;
8039 gv(rc);
8040 save_regs(1);
8042 if (tok == ':' && gnu_ext) {
8043 gv_dup();
8044 tt = gtst(1, 0);
8045 } else {
8046 tt = gtst(1, 0);
8047 gexpr();
8049 type1 = vtop->type;
8050 sv = *vtop; /* save value to handle it later */
8051 vtop--; /* no vpop so that FP stack is not flushed */
8052 skip(':');
8053 u = gjmp(0);
8054 gsym(tt);
8055 expr_eq();
8056 type2 = vtop->type;
8058 t1 = type1.t;
8059 bt1 = t1 & VT_BTYPE;
8060 t2 = type2.t;
8061 bt2 = t2 & VT_BTYPE;
8062 /* cast operands to correct type according to ISOC rules */
8063 if (is_float(bt1) || is_float(bt2)) {
8064 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
8065 type.t = VT_LDOUBLE;
8066 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
8067 type.t = VT_DOUBLE;
8068 } else {
8069 type.t = VT_FLOAT;
8071 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
8072 /* cast to biggest op */
8073 type.t = VT_LLONG;
8074 /* convert to unsigned if it does not fit in a long long */
8075 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
8076 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
8077 type.t |= VT_UNSIGNED;
8078 } else if (bt1 == VT_PTR || bt2 == VT_PTR) {
8079 /* XXX: test pointer compatibility */
8080 type = type1;
8081 } else if (bt1 == VT_FUNC || bt2 == VT_FUNC) {
8082 /* XXX: test function pointer compatibility */
8083 type = type1;
8084 } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
8085 /* XXX: test structure compatibility */
8086 type = type1;
8087 } else if (bt1 == VT_VOID || bt2 == VT_VOID) {
8088 /* NOTE: as an extension, we accept void on only one side */
8089 type.t = VT_VOID;
8090 } else {
8091 /* integer operations */
8092 type.t = VT_INT;
8093 /* convert to unsigned if it does not fit in an integer */
8094 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
8095 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
8096 type.t |= VT_UNSIGNED;
8099 /* now we convert second operand */
8100 gen_cast(&type);
8101 if (VT_STRUCT == (vtop->type.t & VT_BTYPE))
8102 gaddrof();
8103 rc = RC_INT;
8104 if (is_float(type.t)) {
8105 rc = RC_FLOAT;
8106 } else if ((type.t & VT_BTYPE) == VT_LLONG) {
8107 /* for long longs, we use fixed registers to avoid having
8108 to handle a complicated move */
8109 rc = RC_IRET;
8112 r2 = gv(rc);
8113 /* this is horrible, but we must also convert first
8114 operand */
8115 tt = gjmp(0);
8116 gsym(u);
8117 /* put again first value and cast it */
8118 *vtop = sv;
8119 gen_cast(&type);
8120 if (VT_STRUCT == (vtop->type.t & VT_BTYPE))
8121 gaddrof();
8122 r1 = gv(rc);
8123 move_reg(r2, r1);
8124 vtop->r = r2;
8125 gsym(tt);
8130 static void gexpr(void)
8132 while (1) {
8133 expr_eq();
8134 if (tok != ',')
8135 break;
8136 vpop();
8137 next();
8141 /* parse an expression and return its type without any side effect. */
8142 static void expr_type(CType *type)
8144 int saved_nocode_wanted;
8146 saved_nocode_wanted = nocode_wanted;
8147 nocode_wanted = 1;
8148 gexpr();
8149 *type = vtop->type;
8150 vpop();
8151 nocode_wanted = saved_nocode_wanted;
8154 /* parse a unary expression and return its type without any side
8155 effect. */
8156 static void unary_type(CType *type)
8158 int a;
8160 a = nocode_wanted;
8161 nocode_wanted = 1;
8162 unary();
8163 *type = vtop->type;
8164 vpop();
8165 nocode_wanted = a;
8168 /* parse a constant expression and return value in vtop. */
8169 static void expr_const1(void)
8171 int a;
8172 a = const_wanted;
8173 const_wanted = 1;
8174 expr_eq();
8175 const_wanted = a;
8178 /* parse an integer constant and return its value. */
8179 static int expr_const(void)
8181 int c;
8182 expr_const1();
8183 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
8184 expect("constant expression");
8185 c = vtop->c.i;
8186 vpop();
8187 return c;
8190 /* return the label token if current token is a label, otherwise
8191 return zero */
8192 static int is_label(void)
8194 int last_tok;
8196 /* fast test first */
8197 if (tok < TOK_UIDENT)
8198 return 0;
8199 /* no need to save tokc because tok is an identifier */
8200 last_tok = tok;
8201 next();
8202 if (tok == ':') {
8203 next();
8204 return last_tok;
8205 } else {
8206 unget_tok(last_tok);
8207 return 0;
8211 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
8212 int case_reg, int is_expr)
8214 int a, b, c, d;
8215 Sym *s;
8217 /* generate line number info */
8218 if (do_debug &&
8219 (last_line_num != file->line_num || last_ind != ind)) {
8220 put_stabn(N_SLINE, 0, file->line_num, ind - func_ind);
8221 last_ind = ind;
8222 last_line_num = file->line_num;
8225 if (is_expr) {
8226 /* default return value is (void) */
8227 vpushi(0);
8228 vtop->type.t = VT_VOID;
8231 if (tok == TOK_IF) {
8232 /* if test */
8233 next();
8234 skip('(');
8235 gexpr();
8236 skip(')');
8237 a = gtst(1, 0);
8238 block(bsym, csym, case_sym, def_sym, case_reg, 0);
8239 c = tok;
8240 if (c == TOK_ELSE) {
8241 next();
8242 d = gjmp(0);
8243 gsym(a);
8244 block(bsym, csym, case_sym, def_sym, case_reg, 0);
8245 gsym(d); /* patch else jmp */
8246 } else
8247 gsym(a);
8248 } else if (tok == TOK_WHILE) {
8249 next();
8250 d = ind;
8251 skip('(');
8252 gexpr();
8253 skip(')');
8254 a = gtst(1, 0);
8255 b = 0;
8256 block(&a, &b, case_sym, def_sym, case_reg, 0);
8257 gjmp_addr(d);
8258 gsym(a);
8259 gsym_addr(b, d);
8260 } else if (tok == '{') {
8261 Sym *llabel;
8263 next();
8264 /* record local declaration stack position */
8265 s = local_stack;
8266 llabel = local_label_stack;
8267 /* handle local labels declarations */
8268 if (tok == TOK_LABEL) {
8269 next();
8270 for(;;) {
8271 if (tok < TOK_UIDENT)
8272 expect("label identifier");
8273 label_push(&local_label_stack, tok, LABEL_DECLARED);
8274 next();
8275 if (tok == ',') {
8276 next();
8277 } else {
8278 skip(';');
8279 break;
8283 while (tok != '}') {
8284 decl(VT_LOCAL);
8285 if (tok != '}') {
8286 if (is_expr)
8287 vpop();
8288 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
8291 /* pop locally defined labels */
8292 label_pop(&local_label_stack, llabel);
8293 /* pop locally defined symbols */
8294 if(is_expr) {
8295 /* XXX: this solution makes only valgrind happy...
8296 triggered by gcc.c-torture/execute/20000917-1.c */
8297 Sym *p;
8298 switch(vtop->type.t & VT_BTYPE) {
8299 case VT_PTR:
8300 case VT_STRUCT:
8301 case VT_ENUM:
8302 case VT_FUNC:
8303 for(p=vtop->type.ref;p;p=p->prev)
8304 if(p->prev==s)
8305 error("unsupported expression type");
8308 sym_pop(&local_stack, s);
8309 next();
8310 } else if (tok == TOK_RETURN) {
8311 next();
8312 if (tok != ';') {
8313 gexpr();
8314 gen_assign_cast(&func_vt);
8315 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
8316 CType type;
8317 /* if returning structure, must copy it to implicit
8318 first pointer arg location */
8319 #ifdef TCC_ARM_EABI
8320 int align, size;
8321 size = type_size(&func_vt,&align);
8322 if(size <= 4)
8324 if((vtop->r != (VT_LOCAL | VT_LVAL) || (vtop->c.i & 3))
8325 && (align & 3))
8327 int addr;
8328 loc = (loc - size) & -4;
8329 addr = loc;
8330 type = func_vt;
8331 vset(&type, VT_LOCAL | VT_LVAL, addr);
8332 vswap();
8333 vstore();
8334 vset(&int_type, VT_LOCAL | VT_LVAL, addr);
8336 vtop->type = int_type;
8337 gv(RC_IRET);
8338 } else {
8339 #endif
8340 type = func_vt;
8341 mk_pointer(&type);
8342 vset(&type, VT_LOCAL | VT_LVAL, func_vc);
8343 indir();
8344 vswap();
8345 /* copy structure value to pointer */
8346 vstore();
8347 #ifdef TCC_ARM_EABI
8349 #endif
8350 } else if (is_float(func_vt.t)) {
8351 gv(RC_FRET);
8352 } else {
8353 gv(RC_IRET);
8355 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
8357 skip(';');
8358 rsym = gjmp(rsym); /* jmp */
8359 } else if (tok == TOK_BREAK) {
8360 /* compute jump */
8361 if (!bsym)
8362 error("cannot break");
8363 *bsym = gjmp(*bsym);
8364 next();
8365 skip(';');
8366 } else if (tok == TOK_CONTINUE) {
8367 /* compute jump */
8368 if (!csym)
8369 error("cannot continue");
8370 *csym = gjmp(*csym);
8371 next();
8372 skip(';');
8373 } else if (tok == TOK_FOR) {
8374 int e;
8375 next();
8376 skip('(');
8377 if (tok != ';') {
8378 gexpr();
8379 vpop();
8381 skip(';');
8382 d = ind;
8383 c = ind;
8384 a = 0;
8385 b = 0;
8386 if (tok != ';') {
8387 gexpr();
8388 a = gtst(1, 0);
8390 skip(';');
8391 if (tok != ')') {
8392 e = gjmp(0);
8393 c = ind;
8394 gexpr();
8395 vpop();
8396 gjmp_addr(d);
8397 gsym(e);
8399 skip(')');
8400 block(&a, &b, case_sym, def_sym, case_reg, 0);
8401 gjmp_addr(c);
8402 gsym(a);
8403 gsym_addr(b, c);
8404 } else
8405 if (tok == TOK_DO) {
8406 next();
8407 a = 0;
8408 b = 0;
8409 d = ind;
8410 block(&a, &b, case_sym, def_sym, case_reg, 0);
8411 skip(TOK_WHILE);
8412 skip('(');
8413 gsym(b);
8414 gexpr();
8415 c = gtst(0, 0);
8416 gsym_addr(c, d);
8417 skip(')');
8418 gsym(a);
8419 skip(';');
8420 } else
8421 if (tok == TOK_SWITCH) {
8422 next();
8423 skip('(');
8424 gexpr();
8425 /* XXX: other types than integer */
8426 case_reg = gv(RC_INT);
8427 vpop();
8428 skip(')');
8429 a = 0;
8430 b = gjmp(0); /* jump to first case */
8431 c = 0;
8432 block(&a, csym, &b, &c, case_reg, 0);
8433 /* if no default, jmp after switch */
8434 if (c == 0)
8435 c = ind;
8436 /* default label */
8437 gsym_addr(b, c);
8438 /* break label */
8439 gsym(a);
8440 } else
8441 if (tok == TOK_CASE) {
8442 int v1, v2;
8443 if (!case_sym)
8444 expect("switch");
8445 next();
8446 v1 = expr_const();
8447 v2 = v1;
8448 if (gnu_ext && tok == TOK_DOTS) {
8449 next();
8450 v2 = expr_const();
8451 if (v2 < v1)
8452 warning("empty case range");
8454 /* since a case is like a label, we must skip it with a jmp */
8455 b = gjmp(0);
8456 gsym(*case_sym);
8457 vseti(case_reg, 0);
8458 vpushi(v1);
8459 if (v1 == v2) {
8460 gen_op(TOK_EQ);
8461 *case_sym = gtst(1, 0);
8462 } else {
8463 gen_op(TOK_GE);
8464 *case_sym = gtst(1, 0);
8465 vseti(case_reg, 0);
8466 vpushi(v2);
8467 gen_op(TOK_LE);
8468 *case_sym = gtst(1, *case_sym);
8470 gsym(b);
8471 skip(':');
8472 is_expr = 0;
8473 goto block_after_label;
8474 } else
8475 if (tok == TOK_DEFAULT) {
8476 next();
8477 skip(':');
8478 if (!def_sym)
8479 expect("switch");
8480 if (*def_sym)
8481 error("too many 'default'");
8482 *def_sym = ind;
8483 is_expr = 0;
8484 goto block_after_label;
8485 } else
8486 if (tok == TOK_GOTO) {
8487 next();
8488 if (tok == '*' && gnu_ext) {
8489 /* computed goto */
8490 next();
8491 gexpr();
8492 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
8493 expect("pointer");
8494 ggoto();
8495 } else if (tok >= TOK_UIDENT) {
8496 s = label_find(tok);
8497 /* put forward definition if needed */
8498 if (!s) {
8499 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
8500 } else {
8501 if (s->r == LABEL_DECLARED)
8502 s->r = LABEL_FORWARD;
8504 /* label already defined */
8505 if (s->r & LABEL_FORWARD)
8506 s->next = (void *)gjmp((long)s->next);
8507 else
8508 gjmp_addr((long)s->next);
8509 next();
8510 } else {
8511 expect("label identifier");
8513 skip(';');
8514 } else if (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3) {
8515 asm_instr();
8516 } else {
8517 b = is_label();
8518 if (b) {
8519 /* label case */
8520 s = label_find(b);
8521 if (s) {
8522 if (s->r == LABEL_DEFINED)
8523 error("duplicate label '%s'", get_tok_str(s->v, NULL));
8524 gsym((long)s->next);
8525 s->r = LABEL_DEFINED;
8526 } else {
8527 s = label_push(&global_label_stack, b, LABEL_DEFINED);
8529 s->next = (void *)ind;
8530 /* we accept this, but it is a mistake */
8531 block_after_label:
8532 if (tok == '}') {
8533 warning("deprecated use of label at end of compound statement");
8534 } else {
8535 if (is_expr)
8536 vpop();
8537 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
8539 } else {
8540 /* expression case */
8541 if (tok != ';') {
8542 if (is_expr) {
8543 vpop();
8544 gexpr();
8545 } else {
8546 gexpr();
8547 vpop();
8550 skip(';');
8555 /* t is the array or struct type. c is the array or struct
8556 address. cur_index/cur_field is the pointer to the current
8557 value. 'size_only' is true if only size info is needed (only used
8558 in arrays) */
8559 static void decl_designator(CType *type, Section *sec, unsigned long c,
8560 int *cur_index, Sym **cur_field,
8561 int size_only)
8563 Sym *s, *f;
8564 int notfirst, index, index_last, align, l, nb_elems, elem_size;
8565 CType type1;
8567 notfirst = 0;
8568 elem_size = 0;
8569 nb_elems = 1;
8570 if (gnu_ext && (l = is_label()) != 0)
8571 goto struct_field;
8572 while (tok == '[' || tok == '.') {
8573 if (tok == '[') {
8574 if (!(type->t & VT_ARRAY))
8575 expect("array type");
8576 s = type->ref;
8577 next();
8578 index = expr_const();
8579 if (index < 0 || (s->c >= 0 && index >= s->c))
8580 expect("invalid index");
8581 if (tok == TOK_DOTS && gnu_ext) {
8582 next();
8583 index_last = expr_const();
8584 if (index_last < 0 ||
8585 (s->c >= 0 && index_last >= s->c) ||
8586 index_last < index)
8587 expect("invalid index");
8588 } else {
8589 index_last = index;
8591 skip(']');
8592 if (!notfirst)
8593 *cur_index = index_last;
8594 type = pointed_type(type);
8595 elem_size = type_size(type, &align);
8596 c += index * elem_size;
8597 /* NOTE: we only support ranges for last designator */
8598 nb_elems = index_last - index + 1;
8599 if (nb_elems != 1) {
8600 notfirst = 1;
8601 break;
8603 } else {
8604 next();
8605 l = tok;
8606 next();
8607 struct_field:
8608 if ((type->t & VT_BTYPE) != VT_STRUCT)
8609 expect("struct/union type");
8610 s = type->ref;
8611 l |= SYM_FIELD;
8612 f = s->next;
8613 while (f) {
8614 if (f->v == l)
8615 break;
8616 f = f->next;
8618 if (!f)
8619 expect("field");
8620 if (!notfirst)
8621 *cur_field = f;
8622 /* XXX: fix this mess by using explicit storage field */
8623 type1 = f->type;
8624 type1.t |= (type->t & ~VT_TYPE);
8625 type = &type1;
8626 c += f->c;
8628 notfirst = 1;
8630 if (notfirst) {
8631 if (tok == '=') {
8632 next();
8633 } else {
8634 if (!gnu_ext)
8635 expect("=");
8637 } else {
8638 if (type->t & VT_ARRAY) {
8639 index = *cur_index;
8640 type = pointed_type(type);
8641 c += index * type_size(type, &align);
8642 } else {
8643 f = *cur_field;
8644 if (!f)
8645 error("too many field init");
8646 /* XXX: fix this mess by using explicit storage field */
8647 type1 = f->type;
8648 type1.t |= (type->t & ~VT_TYPE);
8649 type = &type1;
8650 c += f->c;
8653 decl_initializer(type, sec, c, 0, size_only);
8655 /* XXX: make it more general */
8656 if (!size_only && nb_elems > 1) {
8657 unsigned long c_end;
8658 uint8_t *src, *dst;
8659 int i;
8661 if (!sec)
8662 error("range init not supported yet for dynamic storage");
8663 c_end = c + nb_elems * elem_size;
8664 if (c_end > sec->data_allocated)
8665 section_realloc(sec, c_end);
8666 src = sec->data + c;
8667 dst = src;
8668 for(i = 1; i < nb_elems; i++) {
8669 dst += elem_size;
8670 memcpy(dst, src, elem_size);
8675 #define EXPR_VAL 0
8676 #define EXPR_CONST 1
8677 #define EXPR_ANY 2
8679 /* store a value or an expression directly in global data or in local array */
8680 static void init_putv(CType *type, Section *sec, unsigned long c,
8681 int v, int expr_type)
8683 int saved_global_expr, bt, bit_pos, bit_size;
8684 void *ptr;
8685 unsigned long long bit_mask;
8686 CType dtype;
8688 switch(expr_type) {
8689 case EXPR_VAL:
8690 vpushi(v);
8691 break;
8692 case EXPR_CONST:
8693 /* compound literals must be allocated globally in this case */
8694 saved_global_expr = global_expr;
8695 global_expr = 1;
8696 expr_const1();
8697 global_expr = saved_global_expr;
8698 /* NOTE: symbols are accepted */
8699 if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST)
8700 error("initializer element is not constant");
8701 break;
8702 case EXPR_ANY:
8703 expr_eq();
8704 break;
8707 dtype = *type;
8708 dtype.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
8710 if (sec) {
8711 /* XXX: not portable */
8712 /* XXX: generate error if incorrect relocation */
8713 gen_assign_cast(&dtype);
8714 bt = type->t & VT_BTYPE;
8715 ptr = sec->data + c;
8716 /* XXX: make code faster ? */
8717 if (!(type->t & VT_BITFIELD)) {
8718 bit_pos = 0;
8719 bit_size = 32;
8720 bit_mask = -1LL;
8721 } else {
8722 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
8723 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
8724 bit_mask = (1LL << bit_size) - 1;
8726 if ((vtop->r & VT_SYM) &&
8727 (bt == VT_BYTE ||
8728 bt == VT_SHORT ||
8729 bt == VT_DOUBLE ||
8730 bt == VT_LDOUBLE ||
8731 bt == VT_LLONG ||
8732 (bt == VT_INT && bit_size != 32)))
8733 error("initializer element is not computable at load time");
8734 switch(bt) {
8735 case VT_BOOL:
8736 vtop->c.i = (vtop->c.i != 0);
8737 case VT_BYTE:
8738 *(char *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8739 break;
8740 case VT_SHORT:
8741 *(short *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8742 break;
8743 case VT_DOUBLE:
8744 *(double *)ptr = vtop->c.d;
8745 break;
8746 case VT_LDOUBLE:
8747 *(long double *)ptr = vtop->c.ld;
8748 break;
8749 case VT_LLONG:
8750 *(long long *)ptr |= (vtop->c.ll & bit_mask) << bit_pos;
8751 break;
8752 default:
8753 if (vtop->r & VT_SYM) {
8754 greloc(sec, vtop->sym, c, R_DATA_32);
8756 *(int *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8757 break;
8759 vtop--;
8760 } else {
8761 vset(&dtype, VT_LOCAL|VT_LVAL, c);
8762 vswap();
8763 vstore();
8764 vpop();
8768 /* put zeros for variable based init */
8769 static void init_putz(CType *t, Section *sec, unsigned long c, int size)
8771 if (sec) {
8772 /* nothing to do because globals are already set to zero */
8773 } else {
8774 vpush_global_sym(&func_old_type, TOK_memset);
8775 vseti(VT_LOCAL, c);
8776 vpushi(0);
8777 vpushi(size);
8778 gfunc_call(3);
8782 /* 't' contains the type and storage info. 'c' is the offset of the
8783 object in section 'sec'. If 'sec' is NULL, it means stack based
8784 allocation. 'first' is true if array '{' must be read (multi
8785 dimension implicit array init handling). 'size_only' is true if
8786 size only evaluation is wanted (only for arrays). */
8787 static void decl_initializer(CType *type, Section *sec, unsigned long c,
8788 int first, int size_only)
8790 int index, array_length, n, no_oblock, nb, parlevel, i;
8791 int size1, align1, expr_type;
8792 Sym *s, *f;
8793 CType *t1;
8795 if (type->t & VT_ARRAY) {
8796 s = type->ref;
8797 n = s->c;
8798 array_length = 0;
8799 t1 = pointed_type(type);
8800 size1 = type_size(t1, &align1);
8802 no_oblock = 1;
8803 if ((first && tok != TOK_LSTR && tok != TOK_STR) ||
8804 tok == '{') {
8805 skip('{');
8806 no_oblock = 0;
8809 /* only parse strings here if correct type (otherwise: handle
8810 them as ((w)char *) expressions */
8811 if ((tok == TOK_LSTR &&
8812 #ifdef TCC_TARGET_PE
8813 (t1->t & VT_BTYPE) == VT_SHORT && (t1->t & VT_UNSIGNED)
8814 #else
8815 (t1->t & VT_BTYPE) == VT_INT
8816 #endif
8817 ) || (tok == TOK_STR && (t1->t & VT_BTYPE) == VT_BYTE)) {
8818 while (tok == TOK_STR || tok == TOK_LSTR) {
8819 int cstr_len, ch;
8820 CString *cstr;
8822 cstr = tokc.cstr;
8823 /* compute maximum number of chars wanted */
8824 if (tok == TOK_STR)
8825 cstr_len = cstr->size;
8826 else
8827 cstr_len = cstr->size / sizeof(nwchar_t);
8828 cstr_len--;
8829 nb = cstr_len;
8830 if (n >= 0 && nb > (n - array_length))
8831 nb = n - array_length;
8832 if (!size_only) {
8833 if (cstr_len > nb)
8834 warning("initializer-string for array is too long");
8835 /* in order to go faster for common case (char
8836 string in global variable, we handle it
8837 specifically */
8838 if (sec && tok == TOK_STR && size1 == 1) {
8839 memcpy(sec->data + c + array_length, cstr->data, nb);
8840 } else {
8841 for(i=0;i<nb;i++) {
8842 if (tok == TOK_STR)
8843 ch = ((unsigned char *)cstr->data)[i];
8844 else
8845 ch = ((nwchar_t *)cstr->data)[i];
8846 init_putv(t1, sec, c + (array_length + i) * size1,
8847 ch, EXPR_VAL);
8851 array_length += nb;
8852 next();
8854 /* only add trailing zero if enough storage (no
8855 warning in this case since it is standard) */
8856 if (n < 0 || array_length < n) {
8857 if (!size_only) {
8858 init_putv(t1, sec, c + (array_length * size1), 0, EXPR_VAL);
8860 array_length++;
8862 } else {
8863 index = 0;
8864 while (tok != '}') {
8865 decl_designator(type, sec, c, &index, NULL, size_only);
8866 if (n >= 0 && index >= n)
8867 error("index too large");
8868 /* must put zero in holes (note that doing it that way
8869 ensures that it even works with designators) */
8870 if (!size_only && array_length < index) {
8871 init_putz(t1, sec, c + array_length * size1,
8872 (index - array_length) * size1);
8874 index++;
8875 if (index > array_length)
8876 array_length = index;
8877 /* special test for multi dimensional arrays (may not
8878 be strictly correct if designators are used at the
8879 same time) */
8880 if (index >= n && no_oblock)
8881 break;
8882 if (tok == '}')
8883 break;
8884 skip(',');
8887 if (!no_oblock)
8888 skip('}');
8889 /* put zeros at the end */
8890 if (!size_only && n >= 0 && array_length < n) {
8891 init_putz(t1, sec, c + array_length * size1,
8892 (n - array_length) * size1);
8894 /* patch type size if needed */
8895 if (n < 0)
8896 s->c = array_length;
8897 } else if ((type->t & VT_BTYPE) == VT_STRUCT &&
8898 (sec || !first || tok == '{')) {
8899 int par_count;
8901 /* NOTE: the previous test is a specific case for automatic
8902 struct/union init */
8903 /* XXX: union needs only one init */
8905 /* XXX: this test is incorrect for local initializers
8906 beginning with ( without {. It would be much more difficult
8907 to do it correctly (ideally, the expression parser should
8908 be used in all cases) */
8909 par_count = 0;
8910 if (tok == '(') {
8911 AttributeDef ad1;
8912 CType type1;
8913 next();
8914 while (tok == '(') {
8915 par_count++;
8916 next();
8918 if (!parse_btype(&type1, &ad1))
8919 expect("cast");
8920 type_decl(&type1, &ad1, &n, TYPE_ABSTRACT);
8921 #if 0
8922 if (!is_assignable_types(type, &type1))
8923 error("invalid type for cast");
8924 #endif
8925 skip(')');
8927 no_oblock = 1;
8928 if (first || tok == '{') {
8929 skip('{');
8930 no_oblock = 0;
8932 s = type->ref;
8933 f = s->next;
8934 array_length = 0;
8935 index = 0;
8936 n = s->c;
8937 while (tok != '}') {
8938 decl_designator(type, sec, c, NULL, &f, size_only);
8939 index = f->c;
8940 if (!size_only && array_length < index) {
8941 init_putz(type, sec, c + array_length,
8942 index - array_length);
8944 index = index + type_size(&f->type, &align1);
8945 if (index > array_length)
8946 array_length = index;
8947 f = f->next;
8948 if (no_oblock && f == NULL)
8949 break;
8950 if (tok == '}')
8951 break;
8952 skip(',');
8954 /* put zeros at the end */
8955 if (!size_only && array_length < n) {
8956 init_putz(type, sec, c + array_length,
8957 n - array_length);
8959 if (!no_oblock)
8960 skip('}');
8961 while (par_count) {
8962 skip(')');
8963 par_count--;
8965 } else if (tok == '{') {
8966 next();
8967 decl_initializer(type, sec, c, first, size_only);
8968 skip('}');
8969 } else if (size_only) {
8970 /* just skip expression */
8971 parlevel = 0;
8972 while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
8973 tok != -1) {
8974 if (tok == '(')
8975 parlevel++;
8976 else if (tok == ')')
8977 parlevel--;
8978 next();
8980 } else {
8981 /* currently, we always use constant expression for globals
8982 (may change for scripting case) */
8983 expr_type = EXPR_CONST;
8984 if (!sec)
8985 expr_type = EXPR_ANY;
8986 init_putv(type, sec, c, 0, expr_type);
8990 /* parse an initializer for type 't' if 'has_init' is non zero, and
8991 allocate space in local or global data space ('r' is either
8992 VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
8993 variable 'v' of scope 'scope' is declared before initializers are
8994 parsed. If 'v' is zero, then a reference to the new object is put
8995 in the value stack. If 'has_init' is 2, a special parsing is done
8996 to handle string constants. */
8997 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
8998 int has_init, int v, int scope)
9000 int size, align, addr, data_offset;
9001 int level;
9002 ParseState saved_parse_state;
9003 TokenString init_str;
9004 Section *sec;
9006 size = type_size(type, &align);
9007 /* If unknown size, we must evaluate it before
9008 evaluating initializers because
9009 initializers can generate global data too
9010 (e.g. string pointers or ISOC99 compound
9011 literals). It also simplifies local
9012 initializers handling */
9013 tok_str_new(&init_str);
9014 if (size < 0) {
9015 if (!has_init)
9016 error("unknown type size");
9017 /* get all init string */
9018 if (has_init == 2) {
9019 /* only get strings */
9020 while (tok == TOK_STR || tok == TOK_LSTR) {
9021 tok_str_add_tok(&init_str);
9022 next();
9024 } else {
9025 level = 0;
9026 while (level > 0 || (tok != ',' && tok != ';')) {
9027 if (tok < 0)
9028 error("unexpected end of file in initializer");
9029 tok_str_add_tok(&init_str);
9030 if (tok == '{')
9031 level++;
9032 else if (tok == '}') {
9033 if (level == 0)
9034 break;
9035 level--;
9037 next();
9040 tok_str_add(&init_str, -1);
9041 tok_str_add(&init_str, 0);
9043 /* compute size */
9044 save_parse_state(&saved_parse_state);
9046 macro_ptr = init_str.str;
9047 next();
9048 decl_initializer(type, NULL, 0, 1, 1);
9049 /* prepare second initializer parsing */
9050 macro_ptr = init_str.str;
9051 next();
9053 /* if still unknown size, error */
9054 size = type_size(type, &align);
9055 if (size < 0)
9056 error("unknown type size");
9058 /* take into account specified alignment if bigger */
9059 if (ad->aligned) {
9060 if (ad->aligned > align)
9061 align = ad->aligned;
9062 } else if (ad->packed) {
9063 align = 1;
9065 if ((r & VT_VALMASK) == VT_LOCAL) {
9066 sec = NULL;
9067 if (do_bounds_check && (type->t & VT_ARRAY))
9068 loc--;
9069 loc = (loc - size) & -align;
9070 addr = loc;
9071 /* handles bounds */
9072 /* XXX: currently, since we do only one pass, we cannot track
9073 '&' operators, so we add only arrays */
9074 if (do_bounds_check && (type->t & VT_ARRAY)) {
9075 unsigned long *bounds_ptr;
9076 /* add padding between regions */
9077 loc--;
9078 /* then add local bound info */
9079 bounds_ptr = section_ptr_add(lbounds_section, 2 * sizeof(unsigned long));
9080 bounds_ptr[0] = addr;
9081 bounds_ptr[1] = size;
9083 if (v) {
9084 /* local variable */
9085 sym_push(v, type, r, addr);
9086 } else {
9087 /* push local reference */
9088 vset(type, r, addr);
9090 } else {
9091 Sym *sym;
9093 sym = NULL;
9094 if (v && scope == VT_CONST) {
9095 /* see if the symbol was already defined */
9096 sym = sym_find(v);
9097 if (sym) {
9098 if (!is_compatible_types(&sym->type, type))
9099 error("incompatible types for redefinition of '%s'",
9100 get_tok_str(v, NULL));
9101 if (sym->type.t & VT_EXTERN) {
9102 /* if the variable is extern, it was not allocated */
9103 sym->type.t &= ~VT_EXTERN;
9104 /* set array size if it was ommited in extern
9105 declaration */
9106 if ((sym->type.t & VT_ARRAY) &&
9107 sym->type.ref->c < 0 &&
9108 type->ref->c >= 0)
9109 sym->type.ref->c = type->ref->c;
9110 } else {
9111 /* we accept several definitions of the same
9112 global variable. this is tricky, because we
9113 must play with the SHN_COMMON type of the symbol */
9114 /* XXX: should check if the variable was already
9115 initialized. It is incorrect to initialized it
9116 twice */
9117 /* no init data, we won't add more to the symbol */
9118 if (!has_init)
9119 goto no_alloc;
9124 /* allocate symbol in corresponding section */
9125 sec = ad->section;
9126 if (!sec) {
9127 if (has_init)
9128 sec = data_section;
9129 else if (tcc_state->nocommon)
9130 sec = bss_section;
9132 if (sec) {
9133 data_offset = sec->data_offset;
9134 data_offset = (data_offset + align - 1) & -align;
9135 addr = data_offset;
9136 /* very important to increment global pointer at this time
9137 because initializers themselves can create new initializers */
9138 data_offset += size;
9139 /* add padding if bound check */
9140 if (do_bounds_check)
9141 data_offset++;
9142 sec->data_offset = data_offset;
9143 /* allocate section space to put the data */
9144 if (sec->sh_type != SHT_NOBITS &&
9145 data_offset > sec->data_allocated)
9146 section_realloc(sec, data_offset);
9147 /* align section if needed */
9148 if (align > sec->sh_addralign)
9149 sec->sh_addralign = align;
9150 } else {
9151 addr = 0; /* avoid warning */
9154 if (v) {
9155 if (scope != VT_CONST || !sym) {
9156 sym = sym_push(v, type, r | VT_SYM, 0);
9158 /* update symbol definition */
9159 if (sec) {
9160 put_extern_sym(sym, sec, addr, size);
9161 } else {
9162 ElfW(Sym) *esym;
9163 /* put a common area */
9164 put_extern_sym(sym, NULL, align, size);
9165 /* XXX: find a nicer way */
9166 esym = &((ElfW(Sym) *)symtab_section->data)[sym->c];
9167 esym->st_shndx = SHN_COMMON;
9169 } else {
9170 CValue cval;
9172 /* push global reference */
9173 sym = get_sym_ref(type, sec, addr, size);
9174 cval.ul = 0;
9175 vsetc(type, VT_CONST | VT_SYM, &cval);
9176 vtop->sym = sym;
9179 /* handles bounds now because the symbol must be defined
9180 before for the relocation */
9181 if (do_bounds_check) {
9182 unsigned long *bounds_ptr;
9184 greloc(bounds_section, sym, bounds_section->data_offset, R_DATA_32);
9185 /* then add global bound info */
9186 bounds_ptr = section_ptr_add(bounds_section, 2 * sizeof(long));
9187 bounds_ptr[0] = 0; /* relocated */
9188 bounds_ptr[1] = size;
9191 if (has_init) {
9192 decl_initializer(type, sec, addr, 1, 0);
9193 /* restore parse state if needed */
9194 if (init_str.str) {
9195 tok_str_free(init_str.str);
9196 restore_parse_state(&saved_parse_state);
9199 no_alloc: ;
9202 void put_func_debug(Sym *sym)
9204 char buf[512];
9206 /* stabs info */
9207 /* XXX: we put here a dummy type */
9208 snprintf(buf, sizeof(buf), "%s:%c1",
9209 funcname, sym->type.t & VT_STATIC ? 'f' : 'F');
9210 put_stabs_r(buf, N_FUN, 0, file->line_num, 0,
9211 cur_text_section, sym->c);
9212 /* //gr gdb wants a line at the function */
9213 put_stabn(N_SLINE, 0, file->line_num, 0);
9214 last_ind = 0;
9215 last_line_num = 0;
9218 /* parse an old style function declaration list */
9219 /* XXX: check multiple parameter */
9220 static void func_decl_list(Sym *func_sym)
9222 AttributeDef ad;
9223 int v;
9224 Sym *s;
9225 CType btype, type;
9227 /* parse each declaration */
9228 while (tok != '{' && tok != ';' && tok != ',' && tok != TOK_EOF) {
9229 if (!parse_btype(&btype, &ad))
9230 expect("declaration list");
9231 if (((btype.t & VT_BTYPE) == VT_ENUM ||
9232 (btype.t & VT_BTYPE) == VT_STRUCT) &&
9233 tok == ';') {
9234 /* we accept no variable after */
9235 } else {
9236 for(;;) {
9237 type = btype;
9238 type_decl(&type, &ad, &v, TYPE_DIRECT);
9239 /* find parameter in function parameter list */
9240 s = func_sym->next;
9241 while (s != NULL) {
9242 if ((s->v & ~SYM_FIELD) == v)
9243 goto found;
9244 s = s->next;
9246 error("declaration for parameter '%s' but no such parameter",
9247 get_tok_str(v, NULL));
9248 found:
9249 /* check that no storage specifier except 'register' was given */
9250 if (type.t & VT_STORAGE)
9251 error("storage class specified for '%s'", get_tok_str(v, NULL));
9252 convert_parameter_type(&type);
9253 /* we can add the type (NOTE: it could be local to the function) */
9254 s->type = type;
9255 /* accept other parameters */
9256 if (tok == ',')
9257 next();
9258 else
9259 break;
9262 skip(';');
9266 /* parse a function defined by symbol 'sym' and generate its code in
9267 'cur_text_section' */
9268 static void gen_function(Sym *sym)
9270 int saved_nocode_wanted = nocode_wanted;
9271 nocode_wanted = 0;
9272 ind = cur_text_section->data_offset;
9273 /* NOTE: we patch the symbol size later */
9274 put_extern_sym(sym, cur_text_section, ind, 0);
9275 funcname = get_tok_str(sym->v, NULL);
9276 func_ind = ind;
9277 /* put debug symbol */
9278 if (do_debug)
9279 put_func_debug(sym);
9280 /* push a dummy symbol to enable local sym storage */
9281 sym_push2(&local_stack, SYM_FIELD, 0, 0);
9282 gfunc_prolog(&sym->type);
9283 rsym = 0;
9284 block(NULL, NULL, NULL, NULL, 0, 0);
9285 gsym(rsym);
9286 gfunc_epilog();
9287 cur_text_section->data_offset = ind;
9288 label_pop(&global_label_stack, NULL);
9289 sym_pop(&local_stack, NULL); /* reset local stack */
9290 /* end of function */
9291 /* patch symbol size */
9292 ((ElfW(Sym) *)symtab_section->data)[sym->c].st_size =
9293 ind - func_ind;
9294 if (do_debug) {
9295 put_stabn(N_FUN, 0, 0, ind - func_ind);
9297 /* It's better to crash than to generate wrong code */
9298 cur_text_section = NULL;
9299 funcname = ""; /* for safety */
9300 func_vt.t = VT_VOID; /* for safety */
9301 ind = 0; /* for safety */
9302 nocode_wanted = saved_nocode_wanted;
9305 static void gen_inline_functions(void)
9307 Sym *sym;
9308 CType *type;
9309 int *str, inline_generated;
9311 /* iterate while inline function are referenced */
9312 for(;;) {
9313 inline_generated = 0;
9314 for(sym = global_stack; sym != NULL; sym = sym->prev) {
9315 type = &sym->type;
9316 if (((type->t & VT_BTYPE) == VT_FUNC) &&
9317 (type->t & (VT_STATIC | VT_INLINE)) ==
9318 (VT_STATIC | VT_INLINE) &&
9319 sym->c != 0) {
9320 /* the function was used: generate its code and
9321 convert it to a normal function */
9322 str = INLINE_DEF(sym->r);
9323 sym->r = VT_SYM | VT_CONST;
9324 sym->type.t &= ~VT_INLINE;
9326 macro_ptr = str;
9327 next();
9328 cur_text_section = text_section;
9329 gen_function(sym);
9330 macro_ptr = NULL; /* fail safe */
9332 tok_str_free(str);
9333 inline_generated = 1;
9336 if (!inline_generated)
9337 break;
9340 /* free all remaining inline function tokens */
9341 for(sym = global_stack; sym != NULL; sym = sym->prev) {
9342 type = &sym->type;
9343 if (((type->t & VT_BTYPE) == VT_FUNC) &&
9344 (type->t & (VT_STATIC | VT_INLINE)) ==
9345 (VT_STATIC | VT_INLINE)) {
9346 //gr printf("sym %d %s\n", sym->r, get_tok_str(sym->v, NULL));
9347 if (sym->r == (VT_SYM | VT_CONST)) //gr beware!
9348 continue;
9349 str = INLINE_DEF(sym->r);
9350 tok_str_free(str);
9351 sym->r = 0; /* fail safe */
9356 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
9357 static void decl(int l)
9359 int v, has_init, r;
9360 CType type, btype;
9361 Sym *sym;
9362 AttributeDef ad;
9364 while (1) {
9365 if (!parse_btype(&btype, &ad)) {
9366 /* skip redundant ';' */
9367 /* XXX: find more elegant solution */
9368 if (tok == ';') {
9369 next();
9370 continue;
9372 if (l == VT_CONST &&
9373 (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3)) {
9374 /* global asm block */
9375 asm_global_instr();
9376 continue;
9378 /* special test for old K&R protos without explicit int
9379 type. Only accepted when defining global data */
9380 if (l == VT_LOCAL || tok < TOK_DEFINE)
9381 break;
9382 btype.t = VT_INT;
9384 if (((btype.t & VT_BTYPE) == VT_ENUM ||
9385 (btype.t & VT_BTYPE) == VT_STRUCT) &&
9386 tok == ';') {
9387 /* we accept no variable after */
9388 next();
9389 continue;
9391 while (1) { /* iterate thru each declaration */
9392 type = btype;
9393 type_decl(&type, &ad, &v, TYPE_DIRECT);
9394 #if 0
9396 char buf[500];
9397 type_to_str(buf, sizeof(buf), t, get_tok_str(v, NULL));
9398 printf("type = '%s'\n", buf);
9400 #endif
9401 if ((type.t & VT_BTYPE) == VT_FUNC) {
9402 /* if old style function prototype, we accept a
9403 declaration list */
9404 sym = type.ref;
9405 if (sym->c == FUNC_OLD)
9406 func_decl_list(sym);
9409 if (tok == '{') {
9410 if (l == VT_LOCAL)
9411 error("cannot use local functions");
9412 if ((type.t & VT_BTYPE) != VT_FUNC)
9413 expect("function definition");
9415 /* reject abstract declarators in function definition */
9416 sym = type.ref;
9417 while ((sym = sym->next) != NULL)
9418 if (!(sym->v & ~SYM_FIELD))
9419 expect("identifier");
9421 /* XXX: cannot do better now: convert extern line to static inline */
9422 if ((type.t & (VT_EXTERN | VT_INLINE)) == (VT_EXTERN | VT_INLINE))
9423 type.t = (type.t & ~VT_EXTERN) | VT_STATIC;
9425 sym = sym_find(v);
9426 if (sym) {
9427 if ((sym->type.t & VT_BTYPE) != VT_FUNC)
9428 goto func_error1;
9429 /* specific case: if not func_call defined, we put
9430 the one of the prototype */
9431 /* XXX: should have default value */
9432 r = sym->type.ref->r;
9433 if (FUNC_CALL(r) != FUNC_CDECL
9434 && FUNC_CALL(type.ref->r) == FUNC_CDECL)
9435 FUNC_CALL(type.ref->r) = FUNC_CALL(r);
9436 if (FUNC_EXPORT(r))
9437 FUNC_EXPORT(type.ref->r) = 1;
9439 if (!is_compatible_types(&sym->type, &type)) {
9440 func_error1:
9441 error("incompatible types for redefinition of '%s'",
9442 get_tok_str(v, NULL));
9444 /* if symbol is already defined, then put complete type */
9445 sym->type = type;
9446 } else {
9447 /* put function symbol */
9448 sym = global_identifier_push(v, type.t, 0);
9449 sym->type.ref = type.ref;
9452 /* static inline functions are just recorded as a kind
9453 of macro. Their code will be emitted at the end of
9454 the compilation unit only if they are used */
9455 if ((type.t & (VT_INLINE | VT_STATIC)) ==
9456 (VT_INLINE | VT_STATIC)) {
9457 TokenString func_str;
9458 int block_level;
9460 tok_str_new(&func_str);
9462 block_level = 0;
9463 for(;;) {
9464 int t;
9465 if (tok == TOK_EOF)
9466 error("unexpected end of file");
9467 tok_str_add_tok(&func_str);
9468 t = tok;
9469 next();
9470 if (t == '{') {
9471 block_level++;
9472 } else if (t == '}') {
9473 block_level--;
9474 if (block_level == 0)
9475 break;
9478 tok_str_add(&func_str, -1);
9479 tok_str_add(&func_str, 0);
9480 INLINE_DEF(sym->r) = func_str.str;
9481 } else {
9482 /* compute text section */
9483 cur_text_section = ad.section;
9484 if (!cur_text_section)
9485 cur_text_section = text_section;
9486 sym->r = VT_SYM | VT_CONST;
9487 gen_function(sym);
9489 break;
9490 } else {
9491 if (btype.t & VT_TYPEDEF) {
9492 /* save typedefed type */
9493 /* XXX: test storage specifiers ? */
9494 sym = sym_push(v, &type, 0, 0);
9495 sym->type.t |= VT_TYPEDEF;
9496 } else if ((type.t & VT_BTYPE) == VT_FUNC) {
9497 /* external function definition */
9498 /* specific case for func_call attribute */
9499 if (ad.func_attr)
9500 type.ref->r = ad.func_attr;
9501 external_sym(v, &type, 0);
9502 } else {
9503 /* not lvalue if array */
9504 r = 0;
9505 if (!(type.t & VT_ARRAY))
9506 r |= lvalue_type(type.t);
9507 has_init = (tok == '=');
9508 if ((btype.t & VT_EXTERN) ||
9509 ((type.t & VT_ARRAY) && (type.t & VT_STATIC) &&
9510 !has_init && l == VT_CONST && type.ref->c < 0)) {
9511 /* external variable */
9512 /* NOTE: as GCC, uninitialized global static
9513 arrays of null size are considered as
9514 extern */
9515 external_sym(v, &type, r);
9516 } else {
9517 type.t |= (btype.t & VT_STATIC); /* Retain "static". */
9518 if (type.t & VT_STATIC)
9519 r |= VT_CONST;
9520 else
9521 r |= l;
9522 if (has_init)
9523 next();
9524 decl_initializer_alloc(&type, &ad, r,
9525 has_init, v, l);
9528 if (tok != ',') {
9529 skip(';');
9530 break;
9532 next();
9538 /* better than nothing, but needs extension to handle '-E' option
9539 correctly too */
9540 static void preprocess_init(TCCState *s1)
9542 s1->include_stack_ptr = s1->include_stack;
9543 /* XXX: move that before to avoid having to initialize
9544 file->ifdef_stack_ptr ? */
9545 s1->ifdef_stack_ptr = s1->ifdef_stack;
9546 file->ifdef_stack_ptr = s1->ifdef_stack_ptr;
9548 /* XXX: not ANSI compliant: bound checking says error */
9549 vtop = vstack - 1;
9550 s1->pack_stack[0] = 0;
9551 s1->pack_stack_ptr = s1->pack_stack;
9554 /* compile the C file opened in 'file'. Return non zero if errors. */
9555 static int tcc_compile(TCCState *s1)
9557 Sym *define_start;
9558 char buf[512];
9559 volatile int section_sym;
9561 #ifdef INC_DEBUG
9562 printf("%s: **** new file\n", file->filename);
9563 #endif
9564 preprocess_init(s1);
9566 cur_text_section = NULL;
9567 funcname = "";
9568 anon_sym = SYM_FIRST_ANOM;
9570 /* file info: full path + filename */
9571 section_sym = 0; /* avoid warning */
9572 if (do_debug) {
9573 section_sym = put_elf_sym(symtab_section, 0, 0,
9574 ELFW(ST_INFO)(STB_LOCAL, STT_SECTION), 0,
9575 text_section->sh_num, NULL);
9576 getcwd(buf, sizeof(buf));
9577 #ifdef _WIN32
9578 normalize_slashes(buf);
9579 #endif
9580 pstrcat(buf, sizeof(buf), "/");
9581 put_stabs_r(buf, N_SO, 0, 0,
9582 text_section->data_offset, text_section, section_sym);
9583 put_stabs_r(file->filename, N_SO, 0, 0,
9584 text_section->data_offset, text_section, section_sym);
9586 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
9587 symbols can be safely used */
9588 put_elf_sym(symtab_section, 0, 0,
9589 ELFW(ST_INFO)(STB_LOCAL, STT_FILE), 0,
9590 SHN_ABS, file->filename);
9592 /* define some often used types */
9593 int_type.t = VT_INT;
9595 char_pointer_type.t = VT_BYTE;
9596 mk_pointer(&char_pointer_type);
9598 func_old_type.t = VT_FUNC;
9599 func_old_type.ref = sym_push(SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD);
9601 #if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)
9602 float_type.t = VT_FLOAT;
9603 double_type.t = VT_DOUBLE;
9605 func_float_type.t = VT_FUNC;
9606 func_float_type.ref = sym_push(SYM_FIELD, &float_type, FUNC_CDECL, FUNC_OLD);
9607 func_double_type.t = VT_FUNC;
9608 func_double_type.ref = sym_push(SYM_FIELD, &double_type, FUNC_CDECL, FUNC_OLD);
9609 #endif
9611 #if 0
9612 /* define 'void *alloca(unsigned int)' builtin function */
9614 Sym *s1;
9616 p = anon_sym++;
9617 sym = sym_push(p, mk_pointer(VT_VOID), FUNC_CDECL, FUNC_NEW);
9618 s1 = sym_push(SYM_FIELD, VT_UNSIGNED | VT_INT, 0, 0);
9619 s1->next = NULL;
9620 sym->next = s1;
9621 sym_push(TOK_alloca, VT_FUNC | (p << VT_STRUCT_SHIFT), VT_CONST, 0);
9623 #endif
9625 define_start = define_stack;
9626 nocode_wanted = 1;
9628 if (setjmp(s1->error_jmp_buf) == 0) {
9629 s1->nb_errors = 0;
9630 s1->error_set_jmp_enabled = 1;
9632 ch = file->buf_ptr[0];
9633 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
9634 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM;
9635 next();
9636 decl(VT_CONST);
9637 if (tok != TOK_EOF)
9638 expect("declaration");
9640 /* end of translation unit info */
9641 if (do_debug) {
9642 put_stabs_r(NULL, N_SO, 0, 0,
9643 text_section->data_offset, text_section, section_sym);
9646 s1->error_set_jmp_enabled = 0;
9648 /* reset define stack, but leave -Dsymbols (may be incorrect if
9649 they are undefined) */
9650 free_defines(define_start);
9652 gen_inline_functions();
9654 sym_pop(&global_stack, NULL);
9655 sym_pop(&local_stack, NULL);
9657 return s1->nb_errors != 0 ? -1 : 0;
9660 /* Preprocess the current file */
9661 /* XXX: add line and file infos, add options to preserve spaces */
9662 static int tcc_preprocess(TCCState *s1)
9664 Sym *define_start;
9665 BufferedFile *file_ref;
9666 int token_seen, line_ref;
9668 preprocess_init(s1);
9669 define_start = define_stack;
9670 ch = file->buf_ptr[0];
9672 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
9673 parse_flags = PARSE_FLAG_ASM_COMMENTS | PARSE_FLAG_PREPROCESS |
9674 PARSE_FLAG_LINEFEED;
9676 token_seen = 0;
9677 line_ref = 0;
9678 file_ref = NULL;
9680 for (;;) {
9681 next();
9682 if (tok == TOK_EOF) {
9683 break;
9684 } else if (tok == TOK_LINEFEED) {
9685 if (!token_seen)
9686 continue;
9687 ++line_ref;
9688 token_seen = 0;
9689 } else if (token_seen) {
9690 fputc(' ', s1->outfile);
9691 } else {
9692 int d = file->line_num - line_ref;
9693 if (file != file_ref || d < 0 || d >= 8)
9694 fprintf(s1->outfile, "# %d \"%s\"\n", file->line_num, file->filename);
9695 else
9696 while (d)
9697 fputs("\n", s1->outfile), --d;
9698 line_ref = (file_ref = file)->line_num;
9699 token_seen = 1;
9701 fputs(get_tok_str(tok, &tokc), s1->outfile);
9703 free_defines(define_start);
9704 return 0;
9707 #ifdef LIBTCC
9708 int tcc_compile_string(TCCState *s, const char *str)
9710 BufferedFile bf1, *bf = &bf1;
9711 int ret, len;
9712 char *buf;
9714 /* init file structure */
9715 bf->fd = -1;
9716 /* XXX: avoid copying */
9717 len = strlen(str);
9718 buf = tcc_malloc(len + 1);
9719 if (!buf)
9720 return -1;
9721 memcpy(buf, str, len);
9722 buf[len] = CH_EOB;
9723 bf->buf_ptr = buf;
9724 bf->buf_end = buf + len;
9725 pstrcpy(bf->filename, sizeof(bf->filename), "<string>");
9726 bf->line_num = 1;
9727 file = bf;
9728 ret = tcc_compile(s);
9729 file = NULL;
9730 tcc_free(buf);
9732 /* currently, no need to close */
9733 return ret;
9735 #endif
9737 /* define a preprocessor symbol. A value can also be provided with the '=' operator */
9738 void tcc_define_symbol(TCCState *s1, const char *sym, const char *value)
9740 BufferedFile bf1, *bf = &bf1;
9742 pstrcpy(bf->buffer, IO_BUF_SIZE, sym);
9743 pstrcat(bf->buffer, IO_BUF_SIZE, " ");
9744 /* default value */
9745 if (!value)
9746 value = "1";
9747 pstrcat(bf->buffer, IO_BUF_SIZE, value);
9749 /* init file structure */
9750 bf->fd = -1;
9751 bf->buf_ptr = bf->buffer;
9752 bf->buf_end = bf->buffer + strlen(bf->buffer);
9753 *bf->buf_end = CH_EOB;
9754 bf->filename[0] = '\0';
9755 bf->line_num = 1;
9756 file = bf;
9758 s1->include_stack_ptr = s1->include_stack;
9760 /* parse with define parser */
9761 ch = file->buf_ptr[0];
9762 next_nomacro();
9763 parse_define();
9764 file = NULL;
9767 /* undefine a preprocessor symbol */
9768 void tcc_undefine_symbol(TCCState *s1, const char *sym)
9770 TokenSym *ts;
9771 Sym *s;
9772 ts = tok_alloc(sym, strlen(sym));
9773 s = define_find(ts->tok);
9774 /* undefine symbol by putting an invalid name */
9775 if (s)
9776 define_undef(s);
9779 #ifdef CONFIG_TCC_ASM
9781 #ifdef TCC_TARGET_I386
9782 #include "i386-asm.c"
9783 #endif
9784 #include "tccasm.c"
9786 #else
9787 static void asm_instr(void)
9789 error("inline asm() not supported");
9791 static void asm_global_instr(void)
9793 error("inline asm() not supported");
9795 #endif
9797 #include "tccelf.c"
9799 #ifdef TCC_TARGET_COFF
9800 #include "tcccoff.c"
9801 #endif
9803 #ifdef TCC_TARGET_PE
9804 #include "tccpe.c"
9805 #endif
9807 /* print the position in the source file of PC value 'pc' by reading
9808 the stabs debug information */
9809 static void rt_printline(unsigned long wanted_pc)
9811 Stab_Sym *sym, *sym_end;
9812 char func_name[128], last_func_name[128];
9813 unsigned long func_addr, last_pc, pc;
9814 const char *incl_files[INCLUDE_STACK_SIZE];
9815 int incl_index, len, last_line_num, i;
9816 const char *str, *p;
9818 fprintf(stderr, "0x%08lx:", wanted_pc);
9820 func_name[0] = '\0';
9821 func_addr = 0;
9822 incl_index = 0;
9823 last_func_name[0] = '\0';
9824 last_pc = 0xffffffff;
9825 last_line_num = 1;
9826 sym = (Stab_Sym *)stab_section->data + 1;
9827 sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset);
9828 while (sym < sym_end) {
9829 switch(sym->n_type) {
9830 /* function start or end */
9831 case N_FUN:
9832 if (sym->n_strx == 0) {
9833 /* we test if between last line and end of function */
9834 pc = sym->n_value + func_addr;
9835 if (wanted_pc >= last_pc && wanted_pc < pc)
9836 goto found;
9837 func_name[0] = '\0';
9838 func_addr = 0;
9839 } else {
9840 str = stabstr_section->data + sym->n_strx;
9841 p = strchr(str, ':');
9842 if (!p) {
9843 pstrcpy(func_name, sizeof(func_name), str);
9844 } else {
9845 len = p - str;
9846 if (len > sizeof(func_name) - 1)
9847 len = sizeof(func_name) - 1;
9848 memcpy(func_name, str, len);
9849 func_name[len] = '\0';
9851 func_addr = sym->n_value;
9853 break;
9854 /* line number info */
9855 case N_SLINE:
9856 pc = sym->n_value + func_addr;
9857 if (wanted_pc >= last_pc && wanted_pc < pc)
9858 goto found;
9859 last_pc = pc;
9860 last_line_num = sym->n_desc;
9861 /* XXX: slow! */
9862 strcpy(last_func_name, func_name);
9863 break;
9864 /* include files */
9865 case N_BINCL:
9866 str = stabstr_section->data + sym->n_strx;
9867 add_incl:
9868 if (incl_index < INCLUDE_STACK_SIZE) {
9869 incl_files[incl_index++] = str;
9871 break;
9872 case N_EINCL:
9873 if (incl_index > 1)
9874 incl_index--;
9875 break;
9876 case N_SO:
9877 if (sym->n_strx == 0) {
9878 incl_index = 0; /* end of translation unit */
9879 } else {
9880 str = stabstr_section->data + sym->n_strx;
9881 /* do not add path */
9882 len = strlen(str);
9883 if (len > 0 && str[len - 1] != '/')
9884 goto add_incl;
9886 break;
9888 sym++;
9891 /* second pass: we try symtab symbols (no line number info) */
9892 incl_index = 0;
9894 ElfW(Sym) *sym, *sym_end;
9895 int type;
9897 sym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset);
9898 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
9899 sym < sym_end;
9900 sym++) {
9901 type = ELFW(ST_TYPE)(sym->st_info);
9902 if (type == STT_FUNC) {
9903 if (wanted_pc >= sym->st_value &&
9904 wanted_pc < sym->st_value + sym->st_size) {
9905 pstrcpy(last_func_name, sizeof(last_func_name),
9906 strtab_section->data + sym->st_name);
9907 goto found;
9912 /* did not find any info: */
9913 fprintf(stderr, " ???\n");
9914 return;
9915 found:
9916 if (last_func_name[0] != '\0') {
9917 fprintf(stderr, " %s()", last_func_name);
9919 if (incl_index > 0) {
9920 fprintf(stderr, " (%s:%d",
9921 incl_files[incl_index - 1], last_line_num);
9922 for(i = incl_index - 2; i >= 0; i--)
9923 fprintf(stderr, ", included from %s", incl_files[i]);
9924 fprintf(stderr, ")");
9926 fprintf(stderr, "\n");
9929 #if !defined(_WIN32) && !defined(CONFIG_TCCBOOT)
9931 #ifdef __i386__
9933 /* fix for glibc 2.1 */
9934 #ifndef REG_EIP
9935 #define REG_EIP EIP
9936 #define REG_EBP EBP
9937 #endif
9939 /* return the PC at frame level 'level'. Return non zero if not found */
9940 static int rt_get_caller_pc(unsigned long *paddr,
9941 ucontext_t *uc, int level)
9943 unsigned long fp;
9944 int i;
9946 if (level == 0) {
9947 #if defined(__FreeBSD__)
9948 *paddr = uc->uc_mcontext.mc_eip;
9949 #elif defined(__dietlibc__)
9950 *paddr = uc->uc_mcontext.eip;
9951 #else
9952 *paddr = uc->uc_mcontext.gregs[REG_EIP];
9953 #endif
9954 return 0;
9955 } else {
9956 #if defined(__FreeBSD__)
9957 fp = uc->uc_mcontext.mc_ebp;
9958 #elif defined(__dietlibc__)
9959 fp = uc->uc_mcontext.ebp;
9960 #else
9961 fp = uc->uc_mcontext.gregs[REG_EBP];
9962 #endif
9963 for(i=1;i<level;i++) {
9964 /* XXX: check address validity with program info */
9965 if (fp <= 0x1000 || fp >= 0xc0000000)
9966 return -1;
9967 fp = ((unsigned long *)fp)[0];
9969 *paddr = ((unsigned long *)fp)[1];
9970 return 0;
9973 #else
9975 #warning add arch specific rt_get_caller_pc()
9977 static int rt_get_caller_pc(unsigned long *paddr,
9978 ucontext_t *uc, int level)
9980 return -1;
9982 #endif
9984 /* emit a run time error at position 'pc' */
9985 void rt_error(ucontext_t *uc, const char *fmt, ...)
9987 va_list ap;
9988 unsigned long pc;
9989 int i;
9991 va_start(ap, fmt);
9992 fprintf(stderr, "Runtime error: ");
9993 vfprintf(stderr, fmt, ap);
9994 fprintf(stderr, "\n");
9995 for(i=0;i<num_callers;i++) {
9996 if (rt_get_caller_pc(&pc, uc, i) < 0)
9997 break;
9998 if (i == 0)
9999 fprintf(stderr, "at ");
10000 else
10001 fprintf(stderr, "by ");
10002 rt_printline(pc);
10004 exit(255);
10005 va_end(ap);
10008 /* signal handler for fatal errors */
10009 static void sig_error(int signum, siginfo_t *siginf, void *puc)
10011 ucontext_t *uc = puc;
10013 switch(signum) {
10014 case SIGFPE:
10015 switch(siginf->si_code) {
10016 case FPE_INTDIV:
10017 case FPE_FLTDIV:
10018 rt_error(uc, "division by zero");
10019 break;
10020 default:
10021 rt_error(uc, "floating point exception");
10022 break;
10024 break;
10025 case SIGBUS:
10026 case SIGSEGV:
10027 if (rt_bound_error_msg && *rt_bound_error_msg)
10028 rt_error(uc, *rt_bound_error_msg);
10029 else
10030 rt_error(uc, "dereferencing invalid pointer");
10031 break;
10032 case SIGILL:
10033 rt_error(uc, "illegal instruction");
10034 break;
10035 case SIGABRT:
10036 rt_error(uc, "abort() called");
10037 break;
10038 default:
10039 rt_error(uc, "caught signal %d", signum);
10040 break;
10042 exit(255);
10044 #endif
10046 /* do all relocations (needed before using tcc_get_symbol()) */
10047 int tcc_relocate(TCCState *s1)
10049 Section *s;
10050 int i;
10052 s1->nb_errors = 0;
10054 #ifdef TCC_TARGET_PE
10055 pe_add_runtime(s1);
10056 #else
10057 tcc_add_runtime(s1);
10058 #endif
10060 relocate_common_syms();
10062 tcc_add_linker_symbols(s1);
10063 #ifndef TCC_TARGET_PE
10064 build_got_entries(s1);
10065 #endif
10066 /* compute relocation address : section are relocated in place. We
10067 also alloc the bss space */
10068 for(i = 1; i < s1->nb_sections; i++) {
10069 s = s1->sections[i];
10070 if (s->sh_flags & SHF_ALLOC) {
10071 if (s->sh_type == SHT_NOBITS)
10072 s->data = tcc_mallocz(s->data_offset);
10073 s->sh_addr = (unsigned long)s->data;
10077 relocate_syms(s1, 1);
10079 if (s1->nb_errors != 0)
10080 return -1;
10082 /* relocate each section */
10083 for(i = 1; i < s1->nb_sections; i++) {
10084 s = s1->sections[i];
10085 if (s->reloc)
10086 relocate_section(s1, s);
10089 /* mark executable sections as executable in memory */
10090 for(i = 1; i < s1->nb_sections; i++) {
10091 s = s1->sections[i];
10092 if ((s->sh_flags & (SHF_ALLOC | SHF_EXECINSTR)) ==
10093 (SHF_ALLOC | SHF_EXECINSTR))
10094 set_pages_executable(s->data, s->data_offset);
10096 return 0;
10099 /* launch the compiled program with the given arguments */
10100 int tcc_run(TCCState *s1, int argc, char **argv)
10102 int (*prog_main)(int, char **);
10104 if (tcc_relocate(s1) < 0)
10105 return -1;
10107 prog_main = tcc_get_symbol_err(s1, "main");
10109 if (do_debug) {
10110 #if defined(_WIN32) || defined(CONFIG_TCCBOOT)
10111 error("debug mode currently not available for Windows");
10112 #else
10113 struct sigaction sigact;
10114 /* install TCC signal handlers to print debug info on fatal
10115 runtime errors */
10116 sigact.sa_flags = SA_SIGINFO | SA_RESETHAND;
10117 sigact.sa_sigaction = sig_error;
10118 sigemptyset(&sigact.sa_mask);
10119 sigaction(SIGFPE, &sigact, NULL);
10120 sigaction(SIGILL, &sigact, NULL);
10121 sigaction(SIGSEGV, &sigact, NULL);
10122 sigaction(SIGBUS, &sigact, NULL);
10123 sigaction(SIGABRT, &sigact, NULL);
10124 #endif
10127 #ifdef CONFIG_TCC_BCHECK
10128 if (do_bounds_check) {
10129 void (*bound_init)(void);
10131 /* set error function */
10132 rt_bound_error_msg = (void *)tcc_get_symbol_err(s1,
10133 "__bound_error_msg");
10135 /* XXX: use .init section so that it also work in binary ? */
10136 bound_init = (void *)tcc_get_symbol_err(s1, "__bound_init");
10137 bound_init();
10139 #endif
10140 return (*prog_main)(argc, argv);
10143 void tcc_memstats(void)
10145 #ifdef MEM_DEBUG
10146 printf("memory in use: %d\n", mem_cur_size);
10147 #endif
10150 static void tcc_cleanup(void)
10152 int i, n;
10154 if (NULL == tcc_state)
10155 return;
10156 tcc_state = NULL;
10158 /* free -D defines */
10159 free_defines(NULL);
10161 /* free tokens */
10162 n = tok_ident - TOK_IDENT;
10163 for(i = 0; i < n; i++)
10164 tcc_free(table_ident[i]);
10165 tcc_free(table_ident);
10167 /* free sym_pools */
10168 dynarray_reset(&sym_pools, &nb_sym_pools);
10169 /* string buffer */
10170 cstr_free(&tokcstr);
10171 /* reset symbol stack */
10172 sym_free_first = NULL;
10173 /* cleanup from error/setjmp */
10174 macro_ptr = NULL;
10177 TCCState *tcc_new(void)
10179 const char *p, *r;
10180 TCCState *s;
10181 TokenSym *ts;
10182 int i, c;
10184 tcc_cleanup();
10186 s = tcc_mallocz(sizeof(TCCState));
10187 if (!s)
10188 return NULL;
10189 tcc_state = s;
10190 s->output_type = TCC_OUTPUT_MEMORY;
10192 /* init isid table */
10193 for(i=CH_EOF;i<256;i++)
10194 isidnum_table[i-CH_EOF] = isid(i) || isnum(i);
10196 /* add all tokens */
10197 table_ident = NULL;
10198 memset(hash_ident, 0, TOK_HASH_SIZE * sizeof(TokenSym *));
10200 tok_ident = TOK_IDENT;
10201 p = tcc_keywords;
10202 while (*p) {
10203 r = p;
10204 for(;;) {
10205 c = *r++;
10206 if (c == '\0')
10207 break;
10209 ts = tok_alloc(p, r - p - 1);
10210 p = r;
10213 /* we add dummy defines for some special macros to speed up tests
10214 and to have working defined() */
10215 define_push(TOK___LINE__, MACRO_OBJ, NULL, NULL);
10216 define_push(TOK___FILE__, MACRO_OBJ, NULL, NULL);
10217 define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL);
10218 define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL);
10220 /* standard defines */
10221 tcc_define_symbol(s, "__STDC__", NULL);
10222 tcc_define_symbol(s, "__STDC_VERSION__", "199901L");
10223 #if defined(TCC_TARGET_I386)
10224 tcc_define_symbol(s, "__i386__", NULL);
10225 #endif
10226 #if defined(TCC_TARGET_ARM)
10227 tcc_define_symbol(s, "__ARM_ARCH_4__", NULL);
10228 tcc_define_symbol(s, "__arm_elf__", NULL);
10229 tcc_define_symbol(s, "__arm_elf", NULL);
10230 tcc_define_symbol(s, "arm_elf", NULL);
10231 tcc_define_symbol(s, "__arm__", NULL);
10232 tcc_define_symbol(s, "__arm", NULL);
10233 tcc_define_symbol(s, "arm", NULL);
10234 tcc_define_symbol(s, "__APCS_32__", NULL);
10235 #endif
10236 #ifdef TCC_TARGET_PE
10237 tcc_define_symbol(s, "_WIN32", NULL);
10238 #else
10239 tcc_define_symbol(s, "__unix__", NULL);
10240 tcc_define_symbol(s, "__unix", NULL);
10241 #if defined(__linux)
10242 tcc_define_symbol(s, "__linux__", NULL);
10243 tcc_define_symbol(s, "__linux", NULL);
10244 #endif
10245 #endif
10246 /* tiny C specific defines */
10247 tcc_define_symbol(s, "__TINYC__", NULL);
10249 /* tiny C & gcc defines */
10250 tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned int");
10251 tcc_define_symbol(s, "__PTRDIFF_TYPE__", "int");
10252 #ifdef TCC_TARGET_PE
10253 tcc_define_symbol(s, "__WCHAR_TYPE__", "unsigned short");
10254 #else
10255 tcc_define_symbol(s, "__WCHAR_TYPE__", "int");
10256 #endif
10258 #ifndef TCC_TARGET_PE
10259 /* default library paths */
10260 tcc_add_library_path(s, CONFIG_SYSROOT "/usr/local/lib");
10261 tcc_add_library_path(s, CONFIG_SYSROOT "/usr/lib");
10262 tcc_add_library_path(s, CONFIG_SYSROOT "/lib");
10263 #endif
10265 /* no section zero */
10266 dynarray_add((void ***)&s->sections, &s->nb_sections, NULL);
10268 /* create standard sections */
10269 text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
10270 data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
10271 bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
10273 /* symbols are always generated for linking stage */
10274 symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0,
10275 ".strtab",
10276 ".hashtab", SHF_PRIVATE);
10277 strtab_section = symtab_section->link;
10279 /* private symbol table for dynamic symbols */
10280 s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE,
10281 ".dynstrtab",
10282 ".dynhashtab", SHF_PRIVATE);
10283 s->alacarte_link = 1;
10285 #ifdef CHAR_IS_UNSIGNED
10286 s->char_is_unsigned = 1;
10287 #endif
10288 #if defined(TCC_TARGET_PE) && 0
10289 /* XXX: currently the PE linker is not ready to support that */
10290 s->leading_underscore = 1;
10291 #endif
10292 return s;
10295 void tcc_delete(TCCState *s1)
10297 int i;
10299 tcc_cleanup();
10301 /* free all sections */
10302 free_section(s1->dynsymtab_section);
10304 for(i = 1; i < s1->nb_sections; i++)
10305 free_section(s1->sections[i]);
10306 tcc_free(s1->sections);
10308 /* free any loaded DLLs */
10309 for ( i = 0; i < s1->nb_loaded_dlls; i++)
10311 DLLReference *ref = s1->loaded_dlls[i];
10312 if ( ref->handle )
10313 dlclose(ref->handle);
10316 /* free loaded dlls array */
10317 dynarray_reset(&s1->loaded_dlls, &s1->nb_loaded_dlls);
10319 /* free library paths */
10320 dynarray_reset(&s1->library_paths, &s1->nb_library_paths);
10322 /* free include paths */
10323 dynarray_reset(&s1->cached_includes, &s1->nb_cached_includes);
10324 dynarray_reset(&s1->include_paths, &s1->nb_include_paths);
10325 dynarray_reset(&s1->sysinclude_paths, &s1->nb_sysinclude_paths);
10327 tcc_free(s1);
10330 int tcc_add_include_path(TCCState *s1, const char *pathname)
10332 char *pathname1;
10334 pathname1 = tcc_strdup(pathname);
10335 dynarray_add((void ***)&s1->include_paths, &s1->nb_include_paths, pathname1);
10336 return 0;
10339 int tcc_add_sysinclude_path(TCCState *s1, const char *pathname)
10341 char *pathname1;
10343 pathname1 = tcc_strdup(pathname);
10344 dynarray_add((void ***)&s1->sysinclude_paths, &s1->nb_sysinclude_paths, pathname1);
10345 return 0;
10348 static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
10350 const char *ext;
10351 ElfW(Ehdr) ehdr;
10352 int fd, ret;
10353 BufferedFile *saved_file;
10355 /* find source file type with extension */
10356 ext = tcc_fileextension(filename);
10357 if (ext[0])
10358 ext++;
10360 /* open the file */
10361 saved_file = file;
10362 file = tcc_open(s1, filename);
10363 if (!file) {
10364 if (flags & AFF_PRINT_ERROR) {
10365 error_noabort("file '%s' not found", filename);
10367 ret = -1;
10368 goto fail1;
10371 if (flags & AFF_PREPROCESS) {
10372 ret = tcc_preprocess(s1);
10373 } else if (!ext[0] || !strcmp(ext, "c")) {
10374 /* C file assumed */
10375 ret = tcc_compile(s1);
10376 } else
10377 #ifdef CONFIG_TCC_ASM
10378 if (!strcmp(ext, "S")) {
10379 /* preprocessed assembler */
10380 ret = tcc_assemble(s1, 1);
10381 } else if (!strcmp(ext, "s")) {
10382 /* non preprocessed assembler */
10383 ret = tcc_assemble(s1, 0);
10384 } else
10385 #endif
10386 #ifdef TCC_TARGET_PE
10387 if (!strcmp(ext, "def")) {
10388 ret = pe_load_def_file(s1, file->fd);
10389 } else
10390 #endif
10392 fd = file->fd;
10393 /* assume executable format: auto guess file type */
10394 ret = read(fd, &ehdr, sizeof(ehdr));
10395 lseek(fd, 0, SEEK_SET);
10396 if (ret <= 0) {
10397 error_noabort("could not read header");
10398 goto fail;
10399 } else if (ret != sizeof(ehdr)) {
10400 goto try_load_script;
10403 if (ehdr.e_ident[0] == ELFMAG0 &&
10404 ehdr.e_ident[1] == ELFMAG1 &&
10405 ehdr.e_ident[2] == ELFMAG2 &&
10406 ehdr.e_ident[3] == ELFMAG3) {
10407 file->line_num = 0; /* do not display line number if error */
10408 if (ehdr.e_type == ET_REL) {
10409 ret = tcc_load_object_file(s1, fd, 0);
10410 } else if (ehdr.e_type == ET_DYN) {
10411 if (s1->output_type == TCC_OUTPUT_MEMORY) {
10412 #ifdef TCC_TARGET_PE
10413 ret = -1;
10414 #else
10415 void *h;
10416 h = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY);
10417 if (h)
10418 ret = 0;
10419 else
10420 ret = -1;
10421 #endif
10422 } else {
10423 ret = tcc_load_dll(s1, fd, filename,
10424 (flags & AFF_REFERENCED_DLL) != 0);
10426 } else {
10427 error_noabort("unrecognized ELF file");
10428 goto fail;
10430 } else if (memcmp((char *)&ehdr, ARMAG, 8) == 0) {
10431 file->line_num = 0; /* do not display line number if error */
10432 ret = tcc_load_archive(s1, fd);
10433 } else
10434 #ifdef TCC_TARGET_COFF
10435 if (*(uint16_t *)(&ehdr) == COFF_C67_MAGIC) {
10436 ret = tcc_load_coff(s1, fd);
10437 } else
10438 #endif
10439 #ifdef TCC_TARGET_PE
10440 if (pe_test_res_file(&ehdr, ret)) {
10441 ret = pe_load_res_file(s1, fd);
10442 } else
10443 #endif
10445 /* as GNU ld, consider it is an ld script if not recognized */
10446 try_load_script:
10447 ret = tcc_load_ldscript(s1);
10448 if (ret < 0) {
10449 error_noabort("unrecognized file type");
10450 goto fail;
10454 the_end:
10455 tcc_close(file);
10456 fail1:
10457 file = saved_file;
10458 return ret;
10459 fail:
10460 ret = -1;
10461 goto the_end;
10464 int tcc_add_file(TCCState *s, const char *filename)
10466 return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR);
10469 int tcc_add_library_path(TCCState *s, const char *pathname)
10471 char *pathname1;
10473 pathname1 = tcc_strdup(pathname);
10474 dynarray_add((void ***)&s->library_paths, &s->nb_library_paths, pathname1);
10475 return 0;
10478 /* find and load a dll. Return non zero if not found */
10479 /* XXX: add '-rpath' option support ? */
10480 static int tcc_add_dll(TCCState *s, const char *filename, int flags)
10482 char buf[1024];
10483 int i;
10485 for(i = 0; i < s->nb_library_paths; i++) {
10486 snprintf(buf, sizeof(buf), "%s/%s",
10487 s->library_paths[i], filename);
10488 if (tcc_add_file_internal(s, buf, flags) == 0)
10489 return 0;
10491 return -1;
10494 /* the library name is the same as the argument of the '-l' option */
10495 int tcc_add_library(TCCState *s, const char *libraryname)
10497 char buf[1024];
10498 int i;
10500 /* first we look for the dynamic library if not static linking */
10501 if (!s->static_link) {
10502 #ifdef TCC_TARGET_PE
10503 snprintf(buf, sizeof(buf), "%s.def", libraryname);
10504 #else
10505 snprintf(buf, sizeof(buf), "lib%s.so", libraryname);
10506 #endif
10507 if (tcc_add_dll(s, buf, 0) == 0)
10508 return 0;
10511 /* then we look for the static library */
10512 for(i = 0; i < s->nb_library_paths; i++) {
10513 snprintf(buf, sizeof(buf), "%s/lib%s.a",
10514 s->library_paths[i], libraryname);
10515 if (tcc_add_file_internal(s, buf, 0) == 0)
10516 return 0;
10518 return -1;
10521 int tcc_add_symbol(TCCState *s, const char *name, unsigned long val)
10523 add_elf_sym(symtab_section, val, 0,
10524 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
10525 SHN_ABS, name);
10526 return 0;
10529 int tcc_set_output_type(TCCState *s, int output_type)
10531 char buf[1024];
10533 s->output_type = output_type;
10535 if (!s->nostdinc) {
10536 /* default include paths */
10537 /* XXX: reverse order needed if -isystem support */
10538 #ifndef TCC_TARGET_PE
10539 tcc_add_sysinclude_path(s, CONFIG_SYSROOT "/usr/local/include");
10540 tcc_add_sysinclude_path(s, CONFIG_SYSROOT "/usr/include");
10541 #endif
10542 snprintf(buf, sizeof(buf), "%s/include", tcc_lib_path);
10543 tcc_add_sysinclude_path(s, buf);
10544 #ifdef TCC_TARGET_PE
10545 snprintf(buf, sizeof(buf), "%s/include/winapi", tcc_lib_path);
10546 tcc_add_sysinclude_path(s, buf);
10547 #endif
10550 /* if bound checking, then add corresponding sections */
10551 #ifdef CONFIG_TCC_BCHECK
10552 if (do_bounds_check) {
10553 /* define symbol */
10554 tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL);
10555 /* create bounds sections */
10556 bounds_section = new_section(s, ".bounds",
10557 SHT_PROGBITS, SHF_ALLOC);
10558 lbounds_section = new_section(s, ".lbounds",
10559 SHT_PROGBITS, SHF_ALLOC);
10561 #endif
10563 if (s->char_is_unsigned) {
10564 tcc_define_symbol(s, "__CHAR_UNSIGNED__", NULL);
10567 /* add debug sections */
10568 if (do_debug) {
10569 /* stab symbols */
10570 stab_section = new_section(s, ".stab", SHT_PROGBITS, 0);
10571 stab_section->sh_entsize = sizeof(Stab_Sym);
10572 stabstr_section = new_section(s, ".stabstr", SHT_STRTAB, 0);
10573 put_elf_str(stabstr_section, "");
10574 stab_section->link = stabstr_section;
10575 /* put first entry */
10576 put_stabs("", 0, 0, 0, 0);
10579 /* add libc crt1/crti objects */
10580 #ifndef TCC_TARGET_PE
10581 if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) &&
10582 !s->nostdlib) {
10583 if (output_type != TCC_OUTPUT_DLL)
10584 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crt1.o");
10585 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crti.o");
10587 #endif
10589 #ifdef TCC_TARGET_PE
10590 snprintf(buf, sizeof(buf), "%s/lib", tcc_lib_path);
10591 tcc_add_library_path(s, buf);
10592 #endif
10594 return 0;
10597 #define WD_ALL 0x0001 /* warning is activated when using -Wall */
10598 #define FD_INVERT 0x0002 /* invert value before storing */
10600 typedef struct FlagDef {
10601 uint16_t offset;
10602 uint16_t flags;
10603 const char *name;
10604 } FlagDef;
10606 static const FlagDef warning_defs[] = {
10607 { offsetof(TCCState, warn_unsupported), 0, "unsupported" },
10608 { offsetof(TCCState, warn_write_strings), 0, "write-strings" },
10609 { offsetof(TCCState, warn_error), 0, "error" },
10610 { offsetof(TCCState, warn_implicit_function_declaration), WD_ALL,
10611 "implicit-function-declaration" },
10614 static int set_flag(TCCState *s, const FlagDef *flags, int nb_flags,
10615 const char *name, int value)
10617 int i;
10618 const FlagDef *p;
10619 const char *r;
10621 r = name;
10622 if (r[0] == 'n' && r[1] == 'o' && r[2] == '-') {
10623 r += 3;
10624 value = !value;
10626 for(i = 0, p = flags; i < nb_flags; i++, p++) {
10627 if (!strcmp(r, p->name))
10628 goto found;
10630 return -1;
10631 found:
10632 if (p->flags & FD_INVERT)
10633 value = !value;
10634 *(int *)((uint8_t *)s + p->offset) = value;
10635 return 0;
10639 /* set/reset a warning */
10640 int tcc_set_warning(TCCState *s, const char *warning_name, int value)
10642 int i;
10643 const FlagDef *p;
10645 if (!strcmp(warning_name, "all")) {
10646 for(i = 0, p = warning_defs; i < countof(warning_defs); i++, p++) {
10647 if (p->flags & WD_ALL)
10648 *(int *)((uint8_t *)s + p->offset) = 1;
10650 return 0;
10651 } else {
10652 return set_flag(s, warning_defs, countof(warning_defs),
10653 warning_name, value);
10657 static const FlagDef flag_defs[] = {
10658 { offsetof(TCCState, char_is_unsigned), 0, "unsigned-char" },
10659 { offsetof(TCCState, char_is_unsigned), FD_INVERT, "signed-char" },
10660 { offsetof(TCCState, nocommon), FD_INVERT, "common" },
10661 { offsetof(TCCState, leading_underscore), 0, "leading-underscore" },
10664 /* set/reset a flag */
10665 int tcc_set_flag(TCCState *s, const char *flag_name, int value)
10667 return set_flag(s, flag_defs, countof(flag_defs),
10668 flag_name, value);
10671 #if !defined(LIBTCC)
10673 static int64_t getclock_us(void)
10675 #ifdef _WIN32
10676 struct _timeb tb;
10677 _ftime(&tb);
10678 return (tb.time * 1000LL + tb.millitm) * 1000LL;
10679 #else
10680 struct timeval tv;
10681 gettimeofday(&tv, NULL);
10682 return tv.tv_sec * 1000000LL + tv.tv_usec;
10683 #endif
10686 void help(void)
10688 printf("tcc version " TCC_VERSION " - Tiny C Compiler - Copyright (C) 2001-2006 Fabrice Bellard\n"
10689 "usage: tcc [-v] [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
10690 " [-Wwarn] [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-soname name]\n"
10691 " [-static] [infile1 infile2...] [-run infile args...]\n"
10692 "\n"
10693 "General options:\n"
10694 " -v display current version, increase verbosity\n"
10695 " -c compile only - generate an object file\n"
10696 " -o outfile set output filename\n"
10697 " -Bdir set tcc internal library path\n"
10698 " -bench output compilation statistics\n"
10699 " -run run compiled source\n"
10700 " -fflag set or reset (with 'no-' prefix) 'flag' (see man page)\n"
10701 " -Wwarning set or reset (with 'no-' prefix) 'warning' (see man page)\n"
10702 " -w disable all warnings\n"
10703 "Preprocessor options:\n"
10704 " -E preprocess only\n"
10705 " -Idir add include path 'dir'\n"
10706 " -Dsym[=val] define 'sym' with value 'val'\n"
10707 " -Usym undefine 'sym'\n"
10708 "Linker options:\n"
10709 " -Ldir add library path 'dir'\n"
10710 " -llib link with dynamic or static library 'lib'\n"
10711 " -shared generate a shared library\n"
10712 " -soname set name for shared library to be used at runtime\n"
10713 " -static static linking\n"
10714 " -rdynamic export all global symbols to dynamic linker\n"
10715 " -r generate (relocatable) object file\n"
10716 "Debugger options:\n"
10717 " -g generate runtime debug info\n"
10718 #ifdef CONFIG_TCC_BCHECK
10719 " -b compile with built-in memory and bounds checker (implies -g)\n"
10720 #endif
10721 " -bt N show N callers in stack traces\n"
10725 #define TCC_OPTION_HAS_ARG 0x0001
10726 #define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
10728 typedef struct TCCOption {
10729 const char *name;
10730 uint16_t index;
10731 uint16_t flags;
10732 } TCCOption;
10734 enum {
10735 TCC_OPTION_HELP,
10736 TCC_OPTION_I,
10737 TCC_OPTION_D,
10738 TCC_OPTION_U,
10739 TCC_OPTION_L,
10740 TCC_OPTION_B,
10741 TCC_OPTION_l,
10742 TCC_OPTION_bench,
10743 TCC_OPTION_bt,
10744 TCC_OPTION_b,
10745 TCC_OPTION_g,
10746 TCC_OPTION_c,
10747 TCC_OPTION_static,
10748 TCC_OPTION_shared,
10749 TCC_OPTION_soname,
10750 TCC_OPTION_o,
10751 TCC_OPTION_r,
10752 TCC_OPTION_Wl,
10753 TCC_OPTION_W,
10754 TCC_OPTION_O,
10755 TCC_OPTION_m,
10756 TCC_OPTION_f,
10757 TCC_OPTION_nostdinc,
10758 TCC_OPTION_nostdlib,
10759 TCC_OPTION_print_search_dirs,
10760 TCC_OPTION_rdynamic,
10761 TCC_OPTION_run,
10762 TCC_OPTION_v,
10763 TCC_OPTION_w,
10764 TCC_OPTION_pipe,
10765 TCC_OPTION_E,
10768 static const TCCOption tcc_options[] = {
10769 { "h", TCC_OPTION_HELP, 0 },
10770 { "?", TCC_OPTION_HELP, 0 },
10771 { "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG },
10772 { "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG },
10773 { "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG },
10774 { "L", TCC_OPTION_L, TCC_OPTION_HAS_ARG },
10775 { "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG },
10776 { "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10777 { "bench", TCC_OPTION_bench, 0 },
10778 { "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG },
10779 #ifdef CONFIG_TCC_BCHECK
10780 { "b", TCC_OPTION_b, 0 },
10781 #endif
10782 { "g", TCC_OPTION_g, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10783 { "c", TCC_OPTION_c, 0 },
10784 { "static", TCC_OPTION_static, 0 },
10785 { "shared", TCC_OPTION_shared, 0 },
10786 { "soname", TCC_OPTION_soname, TCC_OPTION_HAS_ARG },
10787 { "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG },
10788 { "run", TCC_OPTION_run, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10789 { "rdynamic", TCC_OPTION_rdynamic, 0 },
10790 { "r", TCC_OPTION_r, 0 },
10791 { "Wl,", TCC_OPTION_Wl, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10792 { "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10793 { "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10794 { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG },
10795 { "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10796 { "nostdinc", TCC_OPTION_nostdinc, 0 },
10797 { "nostdlib", TCC_OPTION_nostdlib, 0 },
10798 { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 },
10799 { "v", TCC_OPTION_v, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10800 { "w", TCC_OPTION_w, 0 },
10801 { "pipe", TCC_OPTION_pipe, 0},
10802 { "E", TCC_OPTION_E, 0},
10803 { NULL },
10806 /* convert 'str' into an array of space separated strings */
10807 static int expand_args(char ***pargv, const char *str)
10809 const char *s1;
10810 char **argv, *arg;
10811 int argc, len;
10813 argc = 0;
10814 argv = NULL;
10815 for(;;) {
10816 while (is_space(*str))
10817 str++;
10818 if (*str == '\0')
10819 break;
10820 s1 = str;
10821 while (*str != '\0' && !is_space(*str))
10822 str++;
10823 len = str - s1;
10824 arg = tcc_malloc(len + 1);
10825 memcpy(arg, s1, len);
10826 arg[len] = '\0';
10827 dynarray_add((void ***)&argv, &argc, arg);
10829 *pargv = argv;
10830 return argc;
10833 static char **files;
10834 static int nb_files, nb_libraries;
10835 static int multiple_files;
10836 static int print_search_dirs;
10837 static int output_type;
10838 static int reloc_output;
10839 static const char *outfile;
10841 int parse_args(TCCState *s, int argc, char **argv)
10843 int optind;
10844 const TCCOption *popt;
10845 const char *optarg, *p1, *r1;
10846 char *r;
10848 optind = 0;
10849 while (optind < argc) {
10851 r = argv[optind++];
10852 if (r[0] != '-' || r[1] == '\0') {
10853 /* add a new file */
10854 dynarray_add((void ***)&files, &nb_files, r);
10855 if (!multiple_files) {
10856 optind--;
10857 /* argv[0] will be this file */
10858 break;
10860 } else {
10861 /* find option in table (match only the first chars */
10862 popt = tcc_options;
10863 for(;;) {
10864 p1 = popt->name;
10865 if (p1 == NULL)
10866 error("invalid option -- '%s'", r);
10867 r1 = r + 1;
10868 for(;;) {
10869 if (*p1 == '\0')
10870 goto option_found;
10871 if (*r1 != *p1)
10872 break;
10873 p1++;
10874 r1++;
10876 popt++;
10878 option_found:
10879 if (popt->flags & TCC_OPTION_HAS_ARG) {
10880 if (*r1 != '\0' || (popt->flags & TCC_OPTION_NOSEP)) {
10881 optarg = r1;
10882 } else {
10883 if (optind >= argc)
10884 error("argument to '%s' is missing", r);
10885 optarg = argv[optind++];
10887 } else {
10888 if (*r1 != '\0')
10889 return 0;
10890 optarg = NULL;
10893 switch(popt->index) {
10894 case TCC_OPTION_HELP:
10895 return 0;
10897 case TCC_OPTION_I:
10898 if (tcc_add_include_path(s, optarg) < 0)
10899 error("too many include paths");
10900 break;
10901 case TCC_OPTION_D:
10903 char *sym, *value;
10904 sym = (char *)optarg;
10905 value = strchr(sym, '=');
10906 if (value) {
10907 *value = '\0';
10908 value++;
10910 tcc_define_symbol(s, sym, value);
10912 break;
10913 case TCC_OPTION_U:
10914 tcc_undefine_symbol(s, optarg);
10915 break;
10916 case TCC_OPTION_L:
10917 tcc_add_library_path(s, optarg);
10918 break;
10919 case TCC_OPTION_B:
10920 /* set tcc utilities path (mainly for tcc development) */
10921 tcc_lib_path = optarg;
10922 break;
10923 case TCC_OPTION_l:
10924 dynarray_add((void ***)&files, &nb_files, r);
10925 nb_libraries++;
10926 break;
10927 case TCC_OPTION_bench:
10928 do_bench = 1;
10929 break;
10930 case TCC_OPTION_bt:
10931 num_callers = atoi(optarg);
10932 break;
10933 #ifdef CONFIG_TCC_BCHECK
10934 case TCC_OPTION_b:
10935 do_bounds_check = 1;
10936 do_debug = 1;
10937 break;
10938 #endif
10939 case TCC_OPTION_g:
10940 do_debug = 1;
10941 break;
10942 case TCC_OPTION_c:
10943 multiple_files = 1;
10944 output_type = TCC_OUTPUT_OBJ;
10945 break;
10946 case TCC_OPTION_static:
10947 s->static_link = 1;
10948 break;
10949 case TCC_OPTION_shared:
10950 output_type = TCC_OUTPUT_DLL;
10951 break;
10952 case TCC_OPTION_soname:
10953 s->soname = optarg;
10954 break;
10955 case TCC_OPTION_o:
10956 multiple_files = 1;
10957 outfile = optarg;
10958 break;
10959 case TCC_OPTION_r:
10960 /* generate a .o merging several output files */
10961 reloc_output = 1;
10962 output_type = TCC_OUTPUT_OBJ;
10963 break;
10964 case TCC_OPTION_nostdinc:
10965 s->nostdinc = 1;
10966 break;
10967 case TCC_OPTION_nostdlib:
10968 s->nostdlib = 1;
10969 break;
10970 case TCC_OPTION_print_search_dirs:
10971 print_search_dirs = 1;
10972 break;
10973 case TCC_OPTION_run:
10975 int argc1;
10976 char **argv1;
10977 argc1 = expand_args(&argv1, optarg);
10978 if (argc1 > 0) {
10979 parse_args(s, argc1, argv1);
10981 multiple_files = 0;
10982 output_type = TCC_OUTPUT_MEMORY;
10984 break;
10985 case TCC_OPTION_v:
10986 do {
10987 if (0 == verbose++)
10988 printf("tcc version %s\n", TCC_VERSION);
10989 } while (*optarg++ == 'v');
10990 break;
10991 case TCC_OPTION_f:
10992 if (tcc_set_flag(s, optarg, 1) < 0 && s->warn_unsupported)
10993 goto unsupported_option;
10994 break;
10995 case TCC_OPTION_W:
10996 if (tcc_set_warning(s, optarg, 1) < 0 &&
10997 s->warn_unsupported)
10998 goto unsupported_option;
10999 break;
11000 case TCC_OPTION_w:
11001 s->warn_none = 1;
11002 break;
11003 case TCC_OPTION_rdynamic:
11004 s->rdynamic = 1;
11005 break;
11006 case TCC_OPTION_Wl:
11008 const char *p;
11009 if (strstart(optarg, "-Ttext,", &p)) {
11010 s->text_addr = strtoul(p, NULL, 16);
11011 s->has_text_addr = 1;
11012 } else if (strstart(optarg, "--oformat,", &p)) {
11013 if (strstart(p, "elf32-", NULL)) {
11014 s->output_format = TCC_OUTPUT_FORMAT_ELF;
11015 } else if (!strcmp(p, "binary")) {
11016 s->output_format = TCC_OUTPUT_FORMAT_BINARY;
11017 } else
11018 #ifdef TCC_TARGET_COFF
11019 if (!strcmp(p, "coff")) {
11020 s->output_format = TCC_OUTPUT_FORMAT_COFF;
11021 } else
11022 #endif
11024 error("target %s not found", p);
11026 } else {
11027 error("unsupported linker option '%s'", optarg);
11030 break;
11031 case TCC_OPTION_E:
11032 output_type = TCC_OUTPUT_PREPROCESS;
11033 break;
11034 default:
11035 if (s->warn_unsupported) {
11036 unsupported_option:
11037 warning("unsupported option '%s'", r);
11039 break;
11043 return optind + 1;
11046 int main(int argc, char **argv)
11048 int i;
11049 TCCState *s;
11050 int nb_objfiles, ret, optind;
11051 char objfilename[1024];
11052 int64_t start_time = 0;
11054 #ifdef _WIN32
11055 tcc_lib_path = w32_tcc_lib_path();
11056 #endif
11058 s = tcc_new();
11059 output_type = TCC_OUTPUT_EXE;
11060 outfile = NULL;
11061 multiple_files = 1;
11062 files = NULL;
11063 nb_files = 0;
11064 nb_libraries = 0;
11065 reloc_output = 0;
11066 print_search_dirs = 0;
11067 ret = 0;
11069 optind = parse_args(s, argc - 1, argv + 1);
11070 if (print_search_dirs) {
11071 /* enough for Linux kernel */
11072 printf("install: %s/\n", tcc_lib_path);
11073 return 0;
11075 if (optind == 0 || nb_files == 0) {
11076 if (optind && verbose)
11077 return 0;
11078 help();
11079 return 1;
11082 nb_objfiles = nb_files - nb_libraries;
11084 /* if outfile provided without other options, we output an
11085 executable */
11086 if (outfile && output_type == TCC_OUTPUT_MEMORY)
11087 output_type = TCC_OUTPUT_EXE;
11089 /* check -c consistency : only single file handled. XXX: checks file type */
11090 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
11091 /* accepts only a single input file */
11092 if (nb_objfiles != 1)
11093 error("cannot specify multiple files with -c");
11094 if (nb_libraries != 0)
11095 error("cannot specify libraries with -c");
11099 if (output_type == TCC_OUTPUT_PREPROCESS) {
11100 if (!outfile) {
11101 s->outfile = stdout;
11102 } else {
11103 s->outfile = fopen(outfile, "w");
11104 if (!s->outfile)
11105 error("could not open '%s", outfile);
11107 } else if (output_type != TCC_OUTPUT_MEMORY) {
11108 if (!outfile) {
11109 /* compute default outfile name */
11110 char *ext;
11111 const char *name =
11112 strcmp(files[0], "-") == 0 ? "a" : tcc_basename(files[0]);
11113 pstrcpy(objfilename, sizeof(objfilename), name);
11114 ext = tcc_fileextension(objfilename);
11115 #ifdef TCC_TARGET_PE
11116 if (output_type == TCC_OUTPUT_DLL)
11117 strcpy(ext, ".dll");
11118 else
11119 if (output_type == TCC_OUTPUT_EXE)
11120 strcpy(ext, ".exe");
11121 else
11122 #endif
11123 if (output_type == TCC_OUTPUT_OBJ && !reloc_output && *ext)
11124 strcpy(ext, ".o");
11125 else
11126 pstrcpy(objfilename, sizeof(objfilename), "a.out");
11127 outfile = objfilename;
11131 if (do_bench) {
11132 start_time = getclock_us();
11135 tcc_set_output_type(s, output_type);
11137 /* compile or add each files or library */
11138 for(i = 0; i < nb_files && ret == 0; i++) {
11139 const char *filename;
11141 filename = files[i];
11142 if (output_type == TCC_OUTPUT_PREPROCESS) {
11143 if (tcc_add_file_internal(s, filename,
11144 AFF_PRINT_ERROR | AFF_PREPROCESS) < 0)
11145 ret = 1;
11146 } else if (filename[0] == '-' && filename[1]) {
11147 if (tcc_add_library(s, filename + 2) < 0)
11148 error("cannot find %s", filename);
11149 } else {
11150 if (1 == verbose)
11151 printf("-> %s\n", filename);
11152 if (tcc_add_file(s, filename) < 0)
11153 ret = 1;
11157 /* free all files */
11158 tcc_free(files);
11160 if (ret)
11161 goto the_end;
11163 if (do_bench) {
11164 double total_time;
11165 total_time = (double)(getclock_us() - start_time) / 1000000.0;
11166 if (total_time < 0.001)
11167 total_time = 0.001;
11168 if (total_bytes < 1)
11169 total_bytes = 1;
11170 printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
11171 tok_ident - TOK_IDENT, total_lines, total_bytes,
11172 total_time, (int)(total_lines / total_time),
11173 total_bytes / total_time / 1000000.0);
11176 if (s->output_type == TCC_OUTPUT_PREPROCESS) {
11177 if (outfile)
11178 fclose(s->outfile);
11179 } else if (s->output_type == TCC_OUTPUT_MEMORY) {
11180 ret = tcc_run(s, argc - optind, argv + optind);
11181 } else
11182 ret = tcc_output_file(s, outfile) ? 1 : 0;
11183 the_end:
11184 /* XXX: cannot do it with bound checking because of the malloc hooks */
11185 if (!do_bounds_check)
11186 tcc_delete(s);
11188 #ifdef MEM_DEBUG
11189 if (do_bench) {
11190 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size, mem_max_size);
11192 #endif
11193 return ret;
11196 #endif