mark executable sections as executable when running in memory
[tinycc.git] / tcc.c
blobc281cedc522f974e00d949b1530ec77d62e157a9
1 /*
2 * TCC - Tiny C Compiler
3 *
4 * Copyright (c) 2001-2004 Fabrice Bellard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #define _GNU_SOURCE
21 #include "config.h"
23 #ifdef CONFIG_TCCBOOT
25 #include "tccboot.h"
26 #define CONFIG_TCC_STATIC
28 #else
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <stdarg.h>
33 #include <string.h>
34 #include <errno.h>
35 #include <math.h>
36 #include <unistd.h>
37 #include <signal.h>
38 #include <fcntl.h>
39 #include <setjmp.h>
40 #include <time.h>
41 #ifdef WIN32
42 #include <sys/timeb.h>
43 #include <windows.h>
44 #endif
45 #ifndef WIN32
46 #include <sys/time.h>
47 #include <sys/ucontext.h>
48 #include <sys/mman.h>
49 #endif
51 #endif /* !CONFIG_TCCBOOT */
53 #ifndef PAGESIZE
54 #define PAGESIZE 4096
55 #endif
57 #include "elf.h"
58 #include "stab.h"
60 #ifndef O_BINARY
61 #define O_BINARY 0
62 #endif
64 #include "libtcc.h"
66 /* parser debug */
67 //#define PARSE_DEBUG
68 /* preprocessor debug */
69 //#define PP_DEBUG
70 /* include file debug */
71 //#define INC_DEBUG
73 //#define MEM_DEBUG
75 /* assembler debug */
76 //#define ASM_DEBUG
78 /* target selection */
79 //#define TCC_TARGET_I386 /* i386 code generator */
80 //#define TCC_TARGET_ARM /* ARMv4 code generator */
81 //#define TCC_TARGET_C67 /* TMS320C67xx code generator */
83 /* default target is I386 */
84 #if !defined(TCC_TARGET_I386) && !defined(TCC_TARGET_ARM) && \
85 !defined(TCC_TARGET_C67)
86 #define TCC_TARGET_I386
87 #endif
89 #if !defined(WIN32) && !defined(TCC_UCLIBC) && !defined(TCC_TARGET_ARM) && \
90 !defined(TCC_TARGET_C67)
91 #define CONFIG_TCC_BCHECK /* enable bound checking code */
92 #endif
94 #if defined(WIN32) && !defined(TCC_TARGET_PE)
95 #define CONFIG_TCC_STATIC
96 #endif
98 /* define it to include assembler support */
99 #if !defined(TCC_TARGET_ARM) && !defined(TCC_TARGET_C67)
100 #define CONFIG_TCC_ASM
101 #endif
103 /* object format selection */
104 #if defined(TCC_TARGET_C67)
105 #define TCC_TARGET_COFF
106 #endif
108 #define FALSE 0
109 #define false 0
110 #define TRUE 1
111 #define true 1
112 typedef int BOOL;
114 /* path to find crt1.o, crti.o and crtn.o. Only needed when generating
115 executables or dlls */
116 #define CONFIG_TCC_CRT_PREFIX "/usr/lib"
118 #define INCLUDE_STACK_SIZE 32
119 #define IFDEF_STACK_SIZE 64
120 #define VSTACK_SIZE 256
121 #define STRING_MAX_SIZE 1024
122 #define PACK_STACK_SIZE 8
124 #define TOK_HASH_SIZE 8192 /* must be a power of two */
125 #define TOK_ALLOC_INCR 512 /* must be a power of two */
126 #define TOK_MAX_SIZE 4 /* token max size in int unit when stored in string */
128 /* token symbol management */
129 typedef struct TokenSym {
130 struct TokenSym *hash_next;
131 struct Sym *sym_define; /* direct pointer to define */
132 struct Sym *sym_label; /* direct pointer to label */
133 struct Sym *sym_struct; /* direct pointer to structure */
134 struct Sym *sym_identifier; /* direct pointer to identifier */
135 int tok; /* token number */
136 int len;
137 char str[1];
138 } TokenSym;
140 typedef struct CString {
141 int size; /* size in bytes */
142 void *data; /* either 'char *' or 'int *' */
143 int size_allocated;
144 void *data_allocated; /* if non NULL, data has been malloced */
145 } CString;
147 /* type definition */
148 typedef struct CType {
149 int t;
150 struct Sym *ref;
151 } CType;
153 /* constant value */
154 typedef union CValue {
155 long double ld;
156 double d;
157 float f;
158 int i;
159 unsigned int ui;
160 unsigned int ul; /* address (should be unsigned long on 64 bit cpu) */
161 long long ll;
162 unsigned long long ull;
163 struct CString *cstr;
164 void *ptr;
165 int tab[1];
166 } CValue;
168 /* value on stack */
169 typedef struct SValue {
170 CType type; /* type */
171 unsigned short r; /* register + flags */
172 unsigned short r2; /* second register, used for 'long long'
173 type. If not used, set to VT_CONST */
174 CValue c; /* constant, if VT_CONST */
175 struct Sym *sym; /* symbol, if (VT_SYM | VT_CONST) */
176 } SValue;
178 /* symbol management */
179 typedef struct Sym {
180 int v; /* symbol token */
181 int r; /* associated register */
182 int c; /* associated number */
183 CType type; /* associated type */
184 struct Sym *next; /* next related symbol */
185 struct Sym *prev; /* prev symbol in stack */
186 struct Sym *prev_tok; /* previous symbol for this token */
187 } Sym;
189 /* section definition */
190 /* XXX: use directly ELF structure for parameters ? */
191 /* special flag to indicate that the section should not be linked to
192 the other ones */
193 #define SHF_PRIVATE 0x80000000
195 typedef struct Section {
196 unsigned long data_offset; /* current data offset */
197 unsigned char *data; /* section data */
198 unsigned long data_allocated; /* used for realloc() handling */
199 int sh_name; /* elf section name (only used during output) */
200 int sh_num; /* elf section number */
201 int sh_type; /* elf section type */
202 int sh_flags; /* elf section flags */
203 int sh_info; /* elf section info */
204 int sh_addralign; /* elf section alignment */
205 int sh_entsize; /* elf entry size */
206 unsigned long sh_size; /* section size (only used during output) */
207 unsigned long sh_addr; /* address at which the section is relocated */
208 unsigned long sh_offset; /* file offset */
209 int nb_hashed_syms; /* used to resize the hash table */
210 struct Section *link; /* link to another section */
211 struct Section *reloc; /* corresponding section for relocation, if any */
212 struct Section *hash; /* hash table for symbols */
213 struct Section *next;
214 char name[1]; /* section name */
215 } Section;
217 typedef struct DLLReference {
218 int level;
219 char name[1];
220 } DLLReference;
222 /* GNUC attribute definition */
223 typedef struct AttributeDef {
224 int aligned;
225 int packed;
226 Section *section;
227 unsigned char func_call; /* FUNC_CDECL, FUNC_STDCALL, FUNC_FASTCALLx */
228 unsigned char dllexport;
229 } AttributeDef;
231 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
232 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
233 #define SYM_FIRST_ANOM 0x10000000 /* first anonymous sym */
235 /* stored in 'Sym.c' field */
236 #define FUNC_NEW 1 /* ansi function prototype */
237 #define FUNC_OLD 2 /* old function prototype */
238 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
240 /* stored in 'Sym.r' field */
241 #define FUNC_CDECL 0 /* standard c call */
242 #define FUNC_STDCALL 1 /* pascal c call */
243 #define FUNC_FASTCALL1 2 /* first param in %eax */
244 #define FUNC_FASTCALL2 3 /* first parameters in %eax, %edx */
245 #define FUNC_FASTCALL3 4 /* first parameter in %eax, %edx, %ecx */
247 /* field 'Sym.t' for macros */
248 #define MACRO_OBJ 0 /* object like macro */
249 #define MACRO_FUNC 1 /* function like macro */
251 /* field 'Sym.r' for C labels */
252 #define LABEL_DEFINED 0 /* label is defined */
253 #define LABEL_FORWARD 1 /* label is forward defined */
254 #define LABEL_DECLARED 2 /* label is declared but never used */
256 /* type_decl() types */
257 #define TYPE_ABSTRACT 1 /* type without variable */
258 #define TYPE_DIRECT 2 /* type with variable */
260 #define IO_BUF_SIZE 8192
262 typedef struct BufferedFile {
263 uint8_t *buf_ptr;
264 uint8_t *buf_end;
265 int fd;
266 int line_num; /* current line number - here to simplify code */
267 int ifndef_macro; /* #ifndef macro / #endif search */
268 int ifndef_macro_saved; /* saved ifndef_macro */
269 int *ifdef_stack_ptr; /* ifdef_stack value at the start of the file */
270 char inc_type; /* type of include */
271 char inc_filename[512]; /* filename specified by the user */
272 char filename[1024]; /* current filename - here to simplify code */
273 unsigned char buffer[IO_BUF_SIZE + 1]; /* extra size for CH_EOB char */
274 } BufferedFile;
276 #define CH_EOB '\\' /* end of buffer or '\0' char in file */
277 #define CH_EOF (-1) /* end of file */
279 /* parsing state (used to save parser state to reparse part of the
280 source several times) */
281 typedef struct ParseState {
282 int *macro_ptr;
283 int line_num;
284 int tok;
285 CValue tokc;
286 } ParseState;
288 /* used to record tokens */
289 typedef struct TokenString {
290 int *str;
291 int len;
292 int allocated_len;
293 int last_line_num;
294 } TokenString;
296 /* include file cache, used to find files faster and also to eliminate
297 inclusion if the include file is protected by #ifndef ... #endif */
298 typedef struct CachedInclude {
299 int ifndef_macro;
300 int hash_next; /* -1 if none */
301 char type; /* '"' or '>' to give include type */
302 char filename[1]; /* path specified in #include */
303 } CachedInclude;
305 #define CACHED_INCLUDES_HASH_SIZE 512
307 /* parser */
308 static struct BufferedFile *file;
309 static int ch, tok;
310 static CValue tokc;
311 static CString tokcstr; /* current parsed string, if any */
312 /* additional informations about token */
313 static int tok_flags;
314 #define TOK_FLAG_BOL 0x0001 /* beginning of line before */
315 #define TOK_FLAG_BOF 0x0002 /* beginning of file before */
316 #define TOK_FLAG_ENDIF 0x0004 /* a endif was found matching starting #ifdef */
318 static int *macro_ptr, *macro_ptr_allocated;
319 static int *unget_saved_macro_ptr;
320 static int unget_saved_buffer[TOK_MAX_SIZE + 1];
321 static int unget_buffer_enabled;
322 static int parse_flags;
323 #define PARSE_FLAG_PREPROCESS 0x0001 /* activate preprocessing */
324 #define PARSE_FLAG_TOK_NUM 0x0002 /* return numbers instead of TOK_PPNUM */
325 #define PARSE_FLAG_LINEFEED 0x0004 /* line feed is returned as a
326 token. line feed is also
327 returned at eof */
328 #define PARSE_FLAG_ASM_COMMENTS 0x0008 /* '#' can be used for line comment */
330 static Section *text_section, *data_section, *bss_section; /* predefined sections */
331 static Section *cur_text_section; /* current section where function code is
332 generated */
333 #ifdef CONFIG_TCC_ASM
334 static Section *last_text_section; /* to handle .previous asm directive */
335 #endif
336 /* bound check related sections */
337 static Section *bounds_section; /* contains global data bound description */
338 static Section *lbounds_section; /* contains local data bound description */
339 /* symbol sections */
340 static Section *symtab_section, *strtab_section;
342 /* debug sections */
343 static Section *stab_section, *stabstr_section;
345 /* loc : local variable index
346 ind : output code index
347 rsym: return symbol
348 anon_sym: anonymous symbol index
350 static int rsym, anon_sym, ind, loc;
351 /* expression generation modifiers */
352 static int const_wanted; /* true if constant wanted */
353 static int nocode_wanted; /* true if no code generation wanted for an expression */
354 static int global_expr; /* true if compound literals must be allocated
355 globally (used during initializers parsing */
356 static CType func_vt; /* current function return type (used by return
357 instruction) */
358 static int func_vc;
359 static int last_line_num, last_ind, func_ind; /* debug last line number and pc */
360 static int tok_ident;
361 static TokenSym **table_ident;
362 static TokenSym *hash_ident[TOK_HASH_SIZE];
363 static char token_buf[STRING_MAX_SIZE + 1];
364 static char *funcname;
365 static Sym *global_stack, *local_stack;
366 static Sym *define_stack;
367 static Sym *global_label_stack, *local_label_stack;
368 /* symbol allocator */
369 #define SYM_POOL_NB (8192 / sizeof(Sym))
370 static Sym *sym_free_first;
372 static SValue vstack[VSTACK_SIZE], *vtop;
373 /* some predefined types */
374 static CType char_pointer_type, func_old_type, int_type;
375 /* true if isid(c) || isnum(c) */
376 static unsigned char isidnum_table[256];
378 /* compile with debug symbol (and use them if error during execution) */
379 static int do_debug = 0;
381 /* compile with built-in memory and bounds checker */
382 static int do_bounds_check = 0;
384 /* display benchmark infos */
385 #if !defined(LIBTCC)
386 static int do_bench = 0;
387 #endif
388 static int total_lines;
389 static int total_bytes;
391 /* use GNU C extensions */
392 static int gnu_ext = 1;
394 /* use Tiny C extensions */
395 static int tcc_ext = 1;
397 /* max number of callers shown if error */
398 static int num_callers = 6;
399 static const char **rt_bound_error_msg;
401 /* XXX: get rid of this ASAP */
402 static struct TCCState *tcc_state;
404 /* give the path of the tcc libraries */
405 static const char *tcc_lib_path = CONFIG_TCCDIR;
407 struct TCCState {
408 int output_type;
410 BufferedFile **include_stack_ptr;
411 int *ifdef_stack_ptr;
413 /* include file handling */
414 char **include_paths;
415 int nb_include_paths;
416 char **sysinclude_paths;
417 int nb_sysinclude_paths;
418 CachedInclude **cached_includes;
419 int nb_cached_includes;
421 char **library_paths;
422 int nb_library_paths;
424 /* array of all loaded dlls (including those referenced by loaded
425 dlls) */
426 DLLReference **loaded_dlls;
427 int nb_loaded_dlls;
429 /* sections */
430 Section **sections;
431 int nb_sections; /* number of sections, including first dummy section */
433 /* got handling */
434 Section *got;
435 Section *plt;
436 unsigned long *got_offsets;
437 int nb_got_offsets;
438 /* give the correspondance from symtab indexes to dynsym indexes */
439 int *symtab_to_dynsym;
441 /* temporary dynamic symbol sections (for dll loading) */
442 Section *dynsymtab_section;
443 /* exported dynamic symbol section */
444 Section *dynsym;
446 int nostdinc; /* if true, no standard headers are added */
447 int nostdlib; /* if true, no standard libraries are added */
449 int nocommon; /* if true, do not use common symbols for .bss data */
451 /* if true, static linking is performed */
452 int static_link;
454 /* if true, all symbols are exported */
455 int rdynamic;
457 /* if true, only link in referenced objects from archive */
458 int alacarte_link;
460 /* address of text section */
461 unsigned long text_addr;
462 int has_text_addr;
464 /* output format, see TCC_OUTPUT_FORMAT_xxx */
465 int output_format;
467 /* C language options */
468 int char_is_unsigned;
469 int leading_underscore;
471 /* warning switches */
472 int warn_write_strings;
473 int warn_unsupported;
474 int warn_error;
475 int warn_none;
476 int warn_implicit_function_declaration;
478 /* error handling */
479 void *error_opaque;
480 void (*error_func)(void *opaque, const char *msg);
481 int error_set_jmp_enabled;
482 jmp_buf error_jmp_buf;
483 int nb_errors;
485 /* tiny assembler state */
486 Sym *asm_labels;
488 /* see include_stack_ptr */
489 BufferedFile *include_stack[INCLUDE_STACK_SIZE];
491 /* see ifdef_stack_ptr */
492 int ifdef_stack[IFDEF_STACK_SIZE];
494 /* see cached_includes */
495 int cached_includes_hash[CACHED_INCLUDES_HASH_SIZE];
497 /* pack stack */
498 int pack_stack[PACK_STACK_SIZE];
499 int *pack_stack_ptr;
502 /* The current value can be: */
503 #define VT_VALMASK 0x00ff
504 #define VT_CONST 0x00f0 /* constant in vc
505 (must be first non register value) */
506 #define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */
507 #define VT_LOCAL 0x00f2 /* offset on stack */
508 #define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */
509 #define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */
510 #define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */
511 #define VT_LVAL 0x0100 /* var is an lvalue */
512 #define VT_SYM 0x0200 /* a symbol value is added */
513 #define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for
514 char/short stored in integer registers) */
515 #define VT_MUSTBOUND 0x0800 /* bound checking must be done before
516 dereferencing value */
517 #define VT_BOUNDED 0x8000 /* value is bounded. The address of the
518 bounding function call point is in vc */
519 #define VT_LVAL_BYTE 0x1000 /* lvalue is a byte */
520 #define VT_LVAL_SHORT 0x2000 /* lvalue is a short */
521 #define VT_LVAL_UNSIGNED 0x4000 /* lvalue is unsigned */
522 #define VT_LVAL_TYPE (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)
524 /* types */
525 #define VT_INT 0 /* integer type */
526 #define VT_BYTE 1 /* signed byte type */
527 #define VT_SHORT 2 /* short type */
528 #define VT_VOID 3 /* void type */
529 #define VT_PTR 4 /* pointer */
530 #define VT_ENUM 5 /* enum definition */
531 #define VT_FUNC 6 /* function type */
532 #define VT_STRUCT 7 /* struct/union definition */
533 #define VT_FLOAT 8 /* IEEE float */
534 #define VT_DOUBLE 9 /* IEEE double */
535 #define VT_LDOUBLE 10 /* IEEE long double */
536 #define VT_BOOL 11 /* ISOC99 boolean type */
537 #define VT_LLONG 12 /* 64 bit integer */
538 #define VT_LONG 13 /* long integer (NEVER USED as type, only
539 during parsing) */
540 #define VT_BTYPE 0x000f /* mask for basic type */
541 #define VT_UNSIGNED 0x0010 /* unsigned type */
542 #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
543 #define VT_BITFIELD 0x0040 /* bitfield modifier */
544 #define VT_CONSTANT 0x0800 /* const modifier */
545 #define VT_VOLATILE 0x1000 /* volatile modifier */
546 #define VT_SIGNED 0x2000 /* signed type */
548 /* storage */
549 #define VT_EXTERN 0x00000080 /* extern definition */
550 #define VT_STATIC 0x00000100 /* static variable */
551 #define VT_TYPEDEF 0x00000200 /* typedef definition */
552 #define VT_INLINE 0x00000400 /* inline definition */
554 #define VT_STRUCT_SHIFT 16 /* shift for bitfield shift values */
556 /* type mask (except storage) */
557 #define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE)
558 #define VT_TYPE (~(VT_STORAGE))
560 /* token values */
562 /* warning: the following compare tokens depend on i386 asm code */
563 #define TOK_ULT 0x92
564 #define TOK_UGE 0x93
565 #define TOK_EQ 0x94
566 #define TOK_NE 0x95
567 #define TOK_ULE 0x96
568 #define TOK_UGT 0x97
569 #define TOK_LT 0x9c
570 #define TOK_GE 0x9d
571 #define TOK_LE 0x9e
572 #define TOK_GT 0x9f
574 #define TOK_LAND 0xa0
575 #define TOK_LOR 0xa1
577 #define TOK_DEC 0xa2
578 #define TOK_MID 0xa3 /* inc/dec, to void constant */
579 #define TOK_INC 0xa4
580 #define TOK_UDIV 0xb0 /* unsigned division */
581 #define TOK_UMOD 0xb1 /* unsigned modulo */
582 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
583 #define TOK_CINT 0xb3 /* number in tokc */
584 #define TOK_CCHAR 0xb4 /* char constant in tokc */
585 #define TOK_STR 0xb5 /* pointer to string in tokc */
586 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
587 #define TOK_LCHAR 0xb7
588 #define TOK_LSTR 0xb8
589 #define TOK_CFLOAT 0xb9 /* float constant */
590 #define TOK_LINENUM 0xba /* line number info */
591 #define TOK_CDOUBLE 0xc0 /* double constant */
592 #define TOK_CLDOUBLE 0xc1 /* long double constant */
593 #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
594 #define TOK_ADDC1 0xc3 /* add with carry generation */
595 #define TOK_ADDC2 0xc4 /* add with carry use */
596 #define TOK_SUBC1 0xc5 /* add with carry generation */
597 #define TOK_SUBC2 0xc6 /* add with carry use */
598 #define TOK_CUINT 0xc8 /* unsigned int constant */
599 #define TOK_CLLONG 0xc9 /* long long constant */
600 #define TOK_CULLONG 0xca /* unsigned long long constant */
601 #define TOK_ARROW 0xcb
602 #define TOK_DOTS 0xcc /* three dots */
603 #define TOK_SHR 0xcd /* unsigned shift right */
604 #define TOK_PPNUM 0xce /* preprocessor number */
606 #define TOK_SHL 0x01 /* shift left */
607 #define TOK_SAR 0x02 /* signed shift right */
609 /* assignement operators : normal operator or 0x80 */
610 #define TOK_A_MOD 0xa5
611 #define TOK_A_AND 0xa6
612 #define TOK_A_MUL 0xaa
613 #define TOK_A_ADD 0xab
614 #define TOK_A_SUB 0xad
615 #define TOK_A_DIV 0xaf
616 #define TOK_A_XOR 0xde
617 #define TOK_A_OR 0xfc
618 #define TOK_A_SHL 0x81
619 #define TOK_A_SAR 0x82
621 #ifndef offsetof
622 #define offsetof(type, field) ((size_t) &((type *)0)->field)
623 #endif
625 #ifndef countof
626 #define countof(tab) (sizeof(tab) / sizeof((tab)[0]))
627 #endif
629 /* WARNING: the content of this string encodes token numbers */
630 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";
632 #define TOK_EOF (-1) /* end of file */
633 #define TOK_LINEFEED 10 /* line feed */
635 /* all identificators and strings have token above that */
636 #define TOK_IDENT 256
638 /* only used for i386 asm opcodes definitions */
639 #define DEF_ASM(x) DEF(TOK_ASM_ ## x, #x)
641 #define DEF_BWL(x) \
642 DEF(TOK_ASM_ ## x ## b, #x "b") \
643 DEF(TOK_ASM_ ## x ## w, #x "w") \
644 DEF(TOK_ASM_ ## x ## l, #x "l") \
645 DEF(TOK_ASM_ ## x, #x)
647 #define DEF_WL(x) \
648 DEF(TOK_ASM_ ## x ## w, #x "w") \
649 DEF(TOK_ASM_ ## x ## l, #x "l") \
650 DEF(TOK_ASM_ ## x, #x)
652 #define DEF_FP1(x) \
653 DEF(TOK_ASM_ ## f ## x ## s, "f" #x "s") \
654 DEF(TOK_ASM_ ## fi ## x ## l, "fi" #x "l") \
655 DEF(TOK_ASM_ ## f ## x ## l, "f" #x "l") \
656 DEF(TOK_ASM_ ## fi ## x ## s, "fi" #x "s")
658 #define DEF_FP(x) \
659 DEF(TOK_ASM_ ## f ## x, "f" #x ) \
660 DEF(TOK_ASM_ ## f ## x ## p, "f" #x "p") \
661 DEF_FP1(x)
663 #define DEF_ASMTEST(x) \
664 DEF_ASM(x ## o) \
665 DEF_ASM(x ## no) \
666 DEF_ASM(x ## b) \
667 DEF_ASM(x ## c) \
668 DEF_ASM(x ## nae) \
669 DEF_ASM(x ## nb) \
670 DEF_ASM(x ## nc) \
671 DEF_ASM(x ## ae) \
672 DEF_ASM(x ## e) \
673 DEF_ASM(x ## z) \
674 DEF_ASM(x ## ne) \
675 DEF_ASM(x ## nz) \
676 DEF_ASM(x ## be) \
677 DEF_ASM(x ## na) \
678 DEF_ASM(x ## nbe) \
679 DEF_ASM(x ## a) \
680 DEF_ASM(x ## s) \
681 DEF_ASM(x ## ns) \
682 DEF_ASM(x ## p) \
683 DEF_ASM(x ## pe) \
684 DEF_ASM(x ## np) \
685 DEF_ASM(x ## po) \
686 DEF_ASM(x ## l) \
687 DEF_ASM(x ## nge) \
688 DEF_ASM(x ## nl) \
689 DEF_ASM(x ## ge) \
690 DEF_ASM(x ## le) \
691 DEF_ASM(x ## ng) \
692 DEF_ASM(x ## nle) \
693 DEF_ASM(x ## g)
695 #define TOK_ASM_int TOK_INT
697 enum tcc_token {
698 TOK_LAST = TOK_IDENT - 1,
699 #define DEF(id, str) id,
700 #include "tcctok.h"
701 #undef DEF
704 static const char tcc_keywords[] =
705 #define DEF(id, str) str "\0"
706 #include "tcctok.h"
707 #undef DEF
710 #define TOK_UIDENT TOK_DEFINE
712 #ifdef WIN32
713 int __stdcall GetModuleFileNameA(void *, char *, int);
714 void *__stdcall GetProcAddress(void *, const char *);
715 void *__stdcall GetModuleHandleA(const char *);
716 void *__stdcall LoadLibraryA(const char *);
717 int __stdcall FreeConsole(void);
719 #define snprintf _snprintf
720 #define vsnprintf _vsnprintf
721 #ifndef __GNUC__
722 #define strtold (long double)strtod
723 #define strtof (float)strtod
724 #define strtoll (long long)strtol
725 #endif
726 #elif defined(TCC_UCLIBC) || defined(__FreeBSD__)
727 /* currently incorrect */
728 long double strtold(const char *nptr, char **endptr)
730 return (long double)strtod(nptr, endptr);
732 float strtof(const char *nptr, char **endptr)
734 return (float)strtod(nptr, endptr);
736 #else
737 /* XXX: need to define this to use them in non ISOC99 context */
738 extern float strtof (const char *__nptr, char **__endptr);
739 extern long double strtold (const char *__nptr, char **__endptr);
740 #endif
742 static char *pstrcpy(char *buf, int buf_size, const char *s);
743 static char *pstrcat(char *buf, int buf_size, const char *s);
744 static const char *tcc_basename(const char *name);
746 static void next(void);
747 static void next_nomacro(void);
748 static void parse_expr_type(CType *type);
749 static void expr_type(CType *type);
750 static void unary_type(CType *type);
751 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
752 int case_reg, int is_expr);
753 static int expr_const(void);
754 static void expr_eq(void);
755 static void gexpr(void);
756 static void gen_inline_functions(void);
757 static void decl(int l);
758 static void decl_initializer(CType *type, Section *sec, unsigned long c,
759 int first, int size_only);
760 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
761 int has_init, int v, int scope);
762 int gv(int rc);
763 void gv2(int rc1, int rc2);
764 void move_reg(int r, int s);
765 void save_regs(int n);
766 void save_reg(int r);
767 void vpop(void);
768 void vswap(void);
769 void vdup(void);
770 int get_reg(int rc);
771 int get_reg_ex(int rc,int rc2);
773 struct macro_level {
774 struct macro_level *prev;
775 int *p;
778 static void macro_subst(TokenString *tok_str, Sym **nested_list,
779 const int *macro_str, struct macro_level **can_read_stream);
780 void gen_op(int op);
781 void force_charshort_cast(int t);
782 static void gen_cast(CType *type);
783 void vstore(void);
784 static Sym *sym_find(int v);
785 static Sym *sym_push(int v, CType *type, int r, int c);
787 /* type handling */
788 static int type_size(CType *type, int *a);
789 static inline CType *pointed_type(CType *type);
790 static int pointed_size(CType *type);
791 static int lvalue_type(int t);
792 static int parse_btype(CType *type, AttributeDef *ad);
793 static void type_decl(CType *type, AttributeDef *ad, int *v, int td);
794 static int is_compatible_types(CType *type1, CType *type2);
796 int ieee_finite(double d);
797 void error(const char *fmt, ...);
798 void vpushi(int v);
799 void vrott(int n);
800 void vnrott(int n);
801 void lexpand_nr(void);
802 static void vpush_global_sym(CType *type, int v);
803 void vset(CType *type, int r, int v);
804 void type_to_str(char *buf, int buf_size,
805 CType *type, const char *varstr);
806 char *get_tok_str(int v, CValue *cv);
807 static Sym *get_sym_ref(CType *type, Section *sec,
808 unsigned long offset, unsigned long size);
809 static Sym *external_global_sym(int v, CType *type, int r);
811 /* section generation */
812 static void section_realloc(Section *sec, unsigned long new_size);
813 static void *section_ptr_add(Section *sec, unsigned long size);
814 static void put_extern_sym(Sym *sym, Section *section,
815 unsigned long value, unsigned long size);
816 static void greloc(Section *s, Sym *sym, unsigned long addr, int type);
817 static int put_elf_str(Section *s, const char *sym);
818 static int put_elf_sym(Section *s,
819 unsigned long value, unsigned long size,
820 int info, int other, int shndx, const char *name);
821 static int add_elf_sym(Section *s, unsigned long value, unsigned long size,
822 int info, int other, int sh_num, const char *name);
823 static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
824 int type, int symbol);
825 static void put_stabs(const char *str, int type, int other, int desc,
826 unsigned long value);
827 static void put_stabs_r(const char *str, int type, int other, int desc,
828 unsigned long value, Section *sec, int sym_index);
829 static void put_stabn(int type, int other, int desc, int value);
830 static void put_stabd(int type, int other, int desc);
831 static int tcc_add_dll(TCCState *s, const char *filename, int flags);
833 #define AFF_PRINT_ERROR 0x0001 /* print error if file not found */
834 #define AFF_REFERENCED_DLL 0x0002 /* load a referenced dll from another dll */
835 static int tcc_add_file_internal(TCCState *s, const char *filename, int flags);
837 /* tcccoff.c */
838 int tcc_output_coff(TCCState *s1, FILE *f);
840 /* tccpe.c */
841 void *resolve_sym(TCCState *s1, const char *sym, int type);
842 int pe_load_def_file(struct TCCState *s1, FILE *fp);
843 void pe_setup_paths(struct TCCState *s1, int *p_output_type, const char **p_outfile, char *first_file);
844 unsigned long pe_add_runtime(struct TCCState *s1);
845 int tcc_output_pe(struct TCCState *s1, const char *filename);
847 /* tccasm.c */
849 #ifdef CONFIG_TCC_ASM
851 typedef struct ExprValue {
852 uint32_t v;
853 Sym *sym;
854 } ExprValue;
856 #define MAX_ASM_OPERANDS 30
858 typedef struct ASMOperand {
859 int id; /* GCC 3 optionnal identifier (0 if number only supported */
860 char *constraint;
861 char asm_str[16]; /* computed asm string for operand */
862 SValue *vt; /* C value of the expression */
863 int ref_index; /* if >= 0, gives reference to a output constraint */
864 int input_index; /* if >= 0, gives reference to an input constraint */
865 int priority; /* priority, used to assign registers */
866 int reg; /* if >= 0, register number used for this operand */
867 int is_llong; /* true if double register value */
868 int is_memory; /* true if memory operand */
869 int is_rw; /* for '+' modifier */
870 } ASMOperand;
872 static void asm_expr(TCCState *s1, ExprValue *pe);
873 static int asm_int_expr(TCCState *s1);
874 static int find_constraint(ASMOperand *operands, int nb_operands,
875 const char *name, const char **pp);
877 static int tcc_assemble(TCCState *s1, int do_preprocess);
879 #endif
881 static void asm_instr(void);
882 static void asm_global_instr(void);
884 /* true if float/double/long double type */
885 static inline int is_float(int t)
887 int bt;
888 bt = t & VT_BTYPE;
889 return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT;
892 #ifdef TCC_TARGET_I386
893 #include "i386-gen.c"
894 #endif
896 #ifdef TCC_TARGET_ARM
897 #include "arm-gen.c"
898 #endif
900 #ifdef TCC_TARGET_C67
901 #include "c67-gen.c"
902 #endif
904 #ifdef CONFIG_TCC_STATIC
906 #define RTLD_LAZY 0x001
907 #define RTLD_NOW 0x002
908 #define RTLD_GLOBAL 0x100
909 #define RTLD_DEFAULT NULL
911 /* dummy function for profiling */
912 void *dlopen(const char *filename, int flag)
914 return NULL;
917 const char *dlerror(void)
919 return "error";
922 typedef struct TCCSyms {
923 char *str;
924 void *ptr;
925 } TCCSyms;
927 #define TCCSYM(a) { #a, &a, },
929 /* add the symbol you want here if no dynamic linking is done */
930 static TCCSyms tcc_syms[] = {
931 #if !defined(CONFIG_TCCBOOT)
932 TCCSYM(printf)
933 TCCSYM(fprintf)
934 TCCSYM(fopen)
935 TCCSYM(fclose)
936 #endif
937 { NULL, NULL },
940 void *resolve_sym(TCCState *s1, const char *symbol, int type)
942 TCCSyms *p;
943 p = tcc_syms;
944 while (p->str != NULL) {
945 if (!strcmp(p->str, symbol))
946 return p->ptr;
947 p++;
949 return NULL;
952 #elif !defined(WIN32)
954 #include <dlfcn.h>
956 void *resolve_sym(TCCState *s1, const char *sym, int type)
958 return dlsym(RTLD_DEFAULT, sym);
961 #endif
963 /********************************************************/
965 /* we use our own 'finite' function to avoid potential problems with
966 non standard math libs */
967 /* XXX: endianness dependent */
968 int ieee_finite(double d)
970 int *p = (int *)&d;
971 return ((unsigned)((p[1] | 0x800fffff) + 1)) >> 31;
974 /* copy a string and truncate it. */
975 static char *pstrcpy(char *buf, int buf_size, const char *s)
977 char *q, *q_end;
978 int c;
980 if (buf_size > 0) {
981 q = buf;
982 q_end = buf + buf_size - 1;
983 while (q < q_end) {
984 c = *s++;
985 if (c == '\0')
986 break;
987 *q++ = c;
989 *q = '\0';
991 return buf;
994 /* strcat and truncate. */
995 static char *pstrcat(char *buf, int buf_size, const char *s)
997 int len;
998 len = strlen(buf);
999 if (len < buf_size)
1000 pstrcpy(buf + len, buf_size - len, s);
1001 return buf;
1004 static int strstart(const char *str, const char *val, const char **ptr)
1006 const char *p, *q;
1007 p = str;
1008 q = val;
1009 while (*q != '\0') {
1010 if (*p != *q)
1011 return 0;
1012 p++;
1013 q++;
1015 if (ptr)
1016 *ptr = p;
1017 return 1;
1020 /* memory management */
1021 #ifdef MEM_DEBUG
1022 int mem_cur_size;
1023 int mem_max_size;
1024 #endif
1026 static inline void tcc_free(void *ptr)
1028 #ifdef MEM_DEBUG
1029 mem_cur_size -= malloc_usable_size(ptr);
1030 #endif
1031 free(ptr);
1034 static void *tcc_malloc(unsigned long size)
1036 void *ptr;
1037 ptr = malloc(size);
1038 if (!ptr && size)
1039 error("memory full");
1040 #ifdef MEM_DEBUG
1041 mem_cur_size += malloc_usable_size(ptr);
1042 if (mem_cur_size > mem_max_size)
1043 mem_max_size = mem_cur_size;
1044 #endif
1045 return ptr;
1048 static void *tcc_mallocz(unsigned long size)
1050 void *ptr;
1051 ptr = tcc_malloc(size);
1052 memset(ptr, 0, size);
1053 return ptr;
1056 static inline void *tcc_realloc(void *ptr, unsigned long size)
1058 void *ptr1;
1059 #ifdef MEM_DEBUG
1060 mem_cur_size -= malloc_usable_size(ptr);
1061 #endif
1062 ptr1 = realloc(ptr, size);
1063 #ifdef MEM_DEBUG
1064 /* NOTE: count not correct if alloc error, but not critical */
1065 mem_cur_size += malloc_usable_size(ptr1);
1066 if (mem_cur_size > mem_max_size)
1067 mem_max_size = mem_cur_size;
1068 #endif
1069 return ptr1;
1072 static char *tcc_strdup(const char *str)
1074 char *ptr;
1075 ptr = tcc_malloc(strlen(str) + 1);
1076 strcpy(ptr, str);
1077 return ptr;
1080 #define free(p) use_tcc_free(p)
1081 #define malloc(s) use_tcc_malloc(s)
1082 #define realloc(p, s) use_tcc_realloc(p, s)
1084 static void dynarray_add(void ***ptab, int *nb_ptr, void *data)
1086 int nb, nb_alloc;
1087 void **pp;
1089 nb = *nb_ptr;
1090 pp = *ptab;
1091 /* every power of two we double array size */
1092 if ((nb & (nb - 1)) == 0) {
1093 if (!nb)
1094 nb_alloc = 1;
1095 else
1096 nb_alloc = nb * 2;
1097 pp = tcc_realloc(pp, nb_alloc * sizeof(void *));
1098 if (!pp)
1099 error("memory full");
1100 *ptab = pp;
1102 pp[nb++] = data;
1103 *nb_ptr = nb;
1106 /* symbol allocator */
1107 static Sym *__sym_malloc(void)
1109 Sym *sym_pool, *sym, *last_sym;
1110 int i;
1112 sym_pool = tcc_malloc(SYM_POOL_NB * sizeof(Sym));
1114 last_sym = sym_free_first;
1115 sym = sym_pool;
1116 for(i = 0; i < SYM_POOL_NB; i++) {
1117 sym->next = last_sym;
1118 last_sym = sym;
1119 sym++;
1121 sym_free_first = last_sym;
1122 return last_sym;
1125 static inline Sym *sym_malloc(void)
1127 Sym *sym;
1128 sym = sym_free_first;
1129 if (!sym)
1130 sym = __sym_malloc();
1131 sym_free_first = sym->next;
1132 return sym;
1135 static inline void sym_free(Sym *sym)
1137 sym->next = sym_free_first;
1138 sym_free_first = sym;
1141 Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags)
1143 Section *sec;
1145 sec = tcc_mallocz(sizeof(Section) + strlen(name));
1146 strcpy(sec->name, name);
1147 sec->sh_type = sh_type;
1148 sec->sh_flags = sh_flags;
1149 switch(sh_type) {
1150 case SHT_HASH:
1151 case SHT_REL:
1152 case SHT_DYNSYM:
1153 case SHT_SYMTAB:
1154 case SHT_DYNAMIC:
1155 sec->sh_addralign = 4;
1156 break;
1157 case SHT_STRTAB:
1158 sec->sh_addralign = 1;
1159 break;
1160 default:
1161 sec->sh_addralign = 32; /* default conservative alignment */
1162 break;
1165 /* only add section if not private */
1166 if (!(sh_flags & SHF_PRIVATE)) {
1167 sec->sh_num = s1->nb_sections;
1168 dynarray_add((void ***)&s1->sections, &s1->nb_sections, sec);
1170 return sec;
1173 static void free_section(Section *s)
1175 tcc_free(s->data);
1176 tcc_free(s);
1179 /* realloc section and set its content to zero */
1180 static void section_realloc(Section *sec, unsigned long new_size)
1182 unsigned long size;
1183 unsigned char *data;
1185 size = sec->data_allocated;
1186 if (size == 0)
1187 size = 1;
1188 while (size < new_size)
1189 size = size * 2;
1190 data = tcc_realloc(sec->data, size);
1191 if (!data)
1192 error("memory full");
1193 memset(data + sec->data_allocated, 0, size - sec->data_allocated);
1194 sec->data = data;
1195 sec->data_allocated = size;
1198 /* reserve at least 'size' bytes in section 'sec' from
1199 sec->data_offset. */
1200 static void *section_ptr_add(Section *sec, unsigned long size)
1202 unsigned long offset, offset1;
1204 offset = sec->data_offset;
1205 offset1 = offset + size;
1206 if (offset1 > sec->data_allocated)
1207 section_realloc(sec, offset1);
1208 sec->data_offset = offset1;
1209 return sec->data + offset;
1212 /* return a reference to a section, and create it if it does not
1213 exists */
1214 Section *find_section(TCCState *s1, const char *name)
1216 Section *sec;
1217 int i;
1218 for(i = 1; i < s1->nb_sections; i++) {
1219 sec = s1->sections[i];
1220 if (!strcmp(name, sec->name))
1221 return sec;
1223 /* sections are created as PROGBITS */
1224 return new_section(s1, name, SHT_PROGBITS, SHF_ALLOC);
1227 #define SECTION_ABS ((void *)1)
1229 /* update sym->c so that it points to an external symbol in section
1230 'section' with value 'value' */
1231 static void put_extern_sym2(Sym *sym, Section *section,
1232 unsigned long value, unsigned long size,
1233 int can_add_underscore)
1235 int sym_type, sym_bind, sh_num, info;
1236 Elf32_Sym *esym;
1237 const char *name;
1238 char buf1[256];
1240 if (section == NULL)
1241 sh_num = SHN_UNDEF;
1242 else if (section == SECTION_ABS)
1243 sh_num = SHN_ABS;
1244 else
1245 sh_num = section->sh_num;
1246 if (!sym->c) {
1247 if ((sym->type.t & VT_BTYPE) == VT_FUNC)
1248 sym_type = STT_FUNC;
1249 else
1250 sym_type = STT_OBJECT;
1251 if (sym->type.t & VT_STATIC)
1252 sym_bind = STB_LOCAL;
1253 else
1254 sym_bind = STB_GLOBAL;
1256 name = get_tok_str(sym->v, NULL);
1257 #ifdef CONFIG_TCC_BCHECK
1258 if (do_bounds_check) {
1259 char buf[32];
1261 /* XXX: avoid doing that for statics ? */
1262 /* if bound checking is activated, we change some function
1263 names by adding the "__bound" prefix */
1264 switch(sym->v) {
1265 #if 0
1266 /* XXX: we rely only on malloc hooks */
1267 case TOK_malloc:
1268 case TOK_free:
1269 case TOK_realloc:
1270 case TOK_memalign:
1271 case TOK_calloc:
1272 #endif
1273 case TOK_memcpy:
1274 case TOK_memmove:
1275 case TOK_memset:
1276 case TOK_strlen:
1277 case TOK_strcpy:
1278 strcpy(buf, "__bound_");
1279 strcat(buf, name);
1280 name = buf;
1281 break;
1284 #endif
1285 if (tcc_state->leading_underscore && can_add_underscore) {
1286 buf1[0] = '_';
1287 pstrcpy(buf1 + 1, sizeof(buf1) - 1, name);
1288 name = buf1;
1290 info = ELF32_ST_INFO(sym_bind, sym_type);
1291 sym->c = add_elf_sym(symtab_section, value, size, info, 0, sh_num, name);
1292 } else {
1293 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
1294 esym->st_value = value;
1295 esym->st_size = size;
1296 esym->st_shndx = sh_num;
1300 static void put_extern_sym(Sym *sym, Section *section,
1301 unsigned long value, unsigned long size)
1303 put_extern_sym2(sym, section, value, size, 1);
1306 /* add a new relocation entry to symbol 'sym' in section 's' */
1307 static void greloc(Section *s, Sym *sym, unsigned long offset, int type)
1309 if (!sym->c)
1310 put_extern_sym(sym, NULL, 0, 0);
1311 /* now we can add ELF relocation info */
1312 put_elf_reloc(symtab_section, s, offset, type, sym->c);
1315 static inline int isid(int c)
1317 return (c >= 'a' && c <= 'z') ||
1318 (c >= 'A' && c <= 'Z') ||
1319 c == '_';
1322 static inline int isnum(int c)
1324 return c >= '0' && c <= '9';
1327 static inline int isoct(int c)
1329 return c >= '0' && c <= '7';
1332 static inline int toup(int c)
1334 if (c >= 'a' && c <= 'z')
1335 return c - 'a' + 'A';
1336 else
1337 return c;
1340 static void strcat_vprintf(char *buf, int buf_size, const char *fmt, va_list ap)
1342 int len;
1343 len = strlen(buf);
1344 vsnprintf(buf + len, buf_size - len, fmt, ap);
1347 static void strcat_printf(char *buf, int buf_size, const char *fmt, ...)
1349 va_list ap;
1350 va_start(ap, fmt);
1351 strcat_vprintf(buf, buf_size, fmt, ap);
1352 va_end(ap);
1355 void error1(TCCState *s1, int is_warning, const char *fmt, va_list ap)
1357 char buf[2048];
1358 BufferedFile **f;
1360 buf[0] = '\0';
1361 if (file) {
1362 for(f = s1->include_stack; f < s1->include_stack_ptr; f++)
1363 strcat_printf(buf, sizeof(buf), "In file included from %s:%d:\n",
1364 (*f)->filename, (*f)->line_num);
1365 if (file->line_num > 0) {
1366 strcat_printf(buf, sizeof(buf),
1367 "%s:%d: ", file->filename, file->line_num);
1368 } else {
1369 strcat_printf(buf, sizeof(buf),
1370 "%s: ", file->filename);
1372 } else {
1373 strcat_printf(buf, sizeof(buf),
1374 "tcc: ");
1376 if (is_warning)
1377 strcat_printf(buf, sizeof(buf), "warning: ");
1378 strcat_vprintf(buf, sizeof(buf), fmt, ap);
1380 if (!s1->error_func) {
1381 /* default case: stderr */
1382 fprintf(stderr, "%s\n", buf);
1383 } else {
1384 s1->error_func(s1->error_opaque, buf);
1386 if (!is_warning || s1->warn_error)
1387 s1->nb_errors++;
1390 #ifdef LIBTCC
1391 void tcc_set_error_func(TCCState *s, void *error_opaque,
1392 void (*error_func)(void *opaque, const char *msg))
1394 s->error_opaque = error_opaque;
1395 s->error_func = error_func;
1397 #endif
1399 /* error without aborting current compilation */
1400 void error_noabort(const char *fmt, ...)
1402 TCCState *s1 = tcc_state;
1403 va_list ap;
1405 va_start(ap, fmt);
1406 error1(s1, 0, fmt, ap);
1407 va_end(ap);
1410 void error(const char *fmt, ...)
1412 TCCState *s1 = tcc_state;
1413 va_list ap;
1415 va_start(ap, fmt);
1416 error1(s1, 0, fmt, ap);
1417 va_end(ap);
1418 /* better than nothing: in some cases, we accept to handle errors */
1419 if (s1->error_set_jmp_enabled) {
1420 longjmp(s1->error_jmp_buf, 1);
1421 } else {
1422 /* XXX: eliminate this someday */
1423 exit(1);
1427 void expect(const char *msg)
1429 error("%s expected", msg);
1432 void warning(const char *fmt, ...)
1434 TCCState *s1 = tcc_state;
1435 va_list ap;
1437 if (s1->warn_none)
1438 return;
1440 va_start(ap, fmt);
1441 error1(s1, 1, fmt, ap);
1442 va_end(ap);
1445 void skip(int c)
1447 if (tok != c)
1448 error("'%c' expected", c);
1449 next();
1452 static void test_lvalue(void)
1454 if (!(vtop->r & VT_LVAL))
1455 expect("lvalue");
1458 /* allocate a new token */
1459 static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len)
1461 TokenSym *ts, **ptable;
1462 int i;
1464 if (tok_ident >= SYM_FIRST_ANOM)
1465 error("memory full");
1467 /* expand token table if needed */
1468 i = tok_ident - TOK_IDENT;
1469 if ((i % TOK_ALLOC_INCR) == 0) {
1470 ptable = tcc_realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *));
1471 if (!ptable)
1472 error("memory full");
1473 table_ident = ptable;
1476 ts = tcc_malloc(sizeof(TokenSym) + len);
1477 table_ident[i] = ts;
1478 ts->tok = tok_ident++;
1479 ts->sym_define = NULL;
1480 ts->sym_label = NULL;
1481 ts->sym_struct = NULL;
1482 ts->sym_identifier = NULL;
1483 ts->len = len;
1484 ts->hash_next = NULL;
1485 memcpy(ts->str, str, len);
1486 ts->str[len] = '\0';
1487 *pts = ts;
1488 return ts;
1491 #define TOK_HASH_INIT 1
1492 #define TOK_HASH_FUNC(h, c) ((h) * 263 + (c))
1494 /* find a token and add it if not found */
1495 static TokenSym *tok_alloc(const char *str, int len)
1497 TokenSym *ts, **pts;
1498 int i;
1499 unsigned int h;
1501 h = TOK_HASH_INIT;
1502 for(i=0;i<len;i++)
1503 h = TOK_HASH_FUNC(h, ((unsigned char *)str)[i]);
1504 h &= (TOK_HASH_SIZE - 1);
1506 pts = &hash_ident[h];
1507 for(;;) {
1508 ts = *pts;
1509 if (!ts)
1510 break;
1511 if (ts->len == len && !memcmp(ts->str, str, len))
1512 return ts;
1513 pts = &(ts->hash_next);
1515 return tok_alloc_new(pts, str, len);
1518 /* CString handling */
1520 static void cstr_realloc(CString *cstr, int new_size)
1522 int size;
1523 void *data;
1525 size = cstr->size_allocated;
1526 if (size == 0)
1527 size = 8; /* no need to allocate a too small first string */
1528 while (size < new_size)
1529 size = size * 2;
1530 data = tcc_realloc(cstr->data_allocated, size);
1531 if (!data)
1532 error("memory full");
1533 cstr->data_allocated = data;
1534 cstr->size_allocated = size;
1535 cstr->data = data;
1538 /* add a byte */
1539 static inline void cstr_ccat(CString *cstr, int ch)
1541 int size;
1542 size = cstr->size + 1;
1543 if (size > cstr->size_allocated)
1544 cstr_realloc(cstr, size);
1545 ((unsigned char *)cstr->data)[size - 1] = ch;
1546 cstr->size = size;
1549 static void cstr_cat(CString *cstr, const char *str)
1551 int c;
1552 for(;;) {
1553 c = *str;
1554 if (c == '\0')
1555 break;
1556 cstr_ccat(cstr, c);
1557 str++;
1561 /* add a wide char */
1562 static void cstr_wccat(CString *cstr, int ch)
1564 int size;
1565 size = cstr->size + sizeof(int);
1566 if (size > cstr->size_allocated)
1567 cstr_realloc(cstr, size);
1568 *(int *)(((unsigned char *)cstr->data) + size - sizeof(int)) = ch;
1569 cstr->size = size;
1572 static void cstr_new(CString *cstr)
1574 memset(cstr, 0, sizeof(CString));
1577 /* free string and reset it to NULL */
1578 static void cstr_free(CString *cstr)
1580 tcc_free(cstr->data_allocated);
1581 cstr_new(cstr);
1584 #define cstr_reset(cstr) cstr_free(cstr)
1586 /* XXX: unicode ? */
1587 static void add_char(CString *cstr, int c)
1589 if (c == '\'' || c == '\"' || c == '\\') {
1590 /* XXX: could be more precise if char or string */
1591 cstr_ccat(cstr, '\\');
1593 if (c >= 32 && c <= 126) {
1594 cstr_ccat(cstr, c);
1595 } else {
1596 cstr_ccat(cstr, '\\');
1597 if (c == '\n') {
1598 cstr_ccat(cstr, 'n');
1599 } else {
1600 cstr_ccat(cstr, '0' + ((c >> 6) & 7));
1601 cstr_ccat(cstr, '0' + ((c >> 3) & 7));
1602 cstr_ccat(cstr, '0' + (c & 7));
1607 /* XXX: buffer overflow */
1608 /* XXX: float tokens */
1609 char *get_tok_str(int v, CValue *cv)
1611 static char buf[STRING_MAX_SIZE + 1];
1612 static CString cstr_buf;
1613 CString *cstr;
1614 unsigned char *q;
1615 char *p;
1616 int i, len;
1618 /* NOTE: to go faster, we give a fixed buffer for small strings */
1619 cstr_reset(&cstr_buf);
1620 cstr_buf.data = buf;
1621 cstr_buf.size_allocated = sizeof(buf);
1622 p = buf;
1624 switch(v) {
1625 case TOK_CINT:
1626 case TOK_CUINT:
1627 /* XXX: not quite exact, but only useful for testing */
1628 sprintf(p, "%u", cv->ui);
1629 break;
1630 case TOK_CLLONG:
1631 case TOK_CULLONG:
1632 /* XXX: not quite exact, but only useful for testing */
1633 sprintf(p, "%Lu", cv->ull);
1634 break;
1635 case TOK_CCHAR:
1636 case TOK_LCHAR:
1637 cstr_ccat(&cstr_buf, '\'');
1638 add_char(&cstr_buf, cv->i);
1639 cstr_ccat(&cstr_buf, '\'');
1640 cstr_ccat(&cstr_buf, '\0');
1641 break;
1642 case TOK_PPNUM:
1643 cstr = cv->cstr;
1644 len = cstr->size - 1;
1645 for(i=0;i<len;i++)
1646 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1647 cstr_ccat(&cstr_buf, '\0');
1648 break;
1649 case TOK_STR:
1650 case TOK_LSTR:
1651 cstr = cv->cstr;
1652 cstr_ccat(&cstr_buf, '\"');
1653 if (v == TOK_STR) {
1654 len = cstr->size - 1;
1655 for(i=0;i<len;i++)
1656 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1657 } else {
1658 len = (cstr->size / sizeof(int)) - 1;
1659 for(i=0;i<len;i++)
1660 add_char(&cstr_buf, ((int *)cstr->data)[i]);
1662 cstr_ccat(&cstr_buf, '\"');
1663 cstr_ccat(&cstr_buf, '\0');
1664 break;
1665 case TOK_LT:
1666 v = '<';
1667 goto addv;
1668 case TOK_GT:
1669 v = '>';
1670 goto addv;
1671 case TOK_A_SHL:
1672 return strcpy(p, "<<=");
1673 case TOK_A_SAR:
1674 return strcpy(p, ">>=");
1675 default:
1676 if (v < TOK_IDENT) {
1677 /* search in two bytes table */
1678 q = tok_two_chars;
1679 while (*q) {
1680 if (q[2] == v) {
1681 *p++ = q[0];
1682 *p++ = q[1];
1683 *p = '\0';
1684 return buf;
1686 q += 3;
1688 addv:
1689 *p++ = v;
1690 *p = '\0';
1691 } else if (v < tok_ident) {
1692 return table_ident[v - TOK_IDENT]->str;
1693 } else if (v >= SYM_FIRST_ANOM) {
1694 /* special name for anonymous symbol */
1695 sprintf(p, "L.%u", v - SYM_FIRST_ANOM);
1696 } else {
1697 /* should never happen */
1698 return NULL;
1700 break;
1702 return cstr_buf.data;
1705 /* push, without hashing */
1706 static Sym *sym_push2(Sym **ps, int v, int t, int c)
1708 Sym *s;
1709 s = sym_malloc();
1710 s->v = v;
1711 s->type.t = t;
1712 s->c = c;
1713 s->next = NULL;
1714 /* add in stack */
1715 s->prev = *ps;
1716 *ps = s;
1717 return s;
1720 /* find a symbol and return its associated structure. 's' is the top
1721 of the symbol stack */
1722 static Sym *sym_find2(Sym *s, int v)
1724 while (s) {
1725 if (s->v == v)
1726 return s;
1727 s = s->prev;
1729 return NULL;
1732 /* structure lookup */
1733 static inline Sym *struct_find(int v)
1735 v -= TOK_IDENT;
1736 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1737 return NULL;
1738 return table_ident[v]->sym_struct;
1741 /* find an identifier */
1742 static inline Sym *sym_find(int v)
1744 v -= TOK_IDENT;
1745 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1746 return NULL;
1747 return table_ident[v]->sym_identifier;
1750 /* push a given symbol on the symbol stack */
1751 static Sym *sym_push(int v, CType *type, int r, int c)
1753 Sym *s, **ps;
1754 TokenSym *ts;
1756 if (local_stack)
1757 ps = &local_stack;
1758 else
1759 ps = &global_stack;
1760 s = sym_push2(ps, v, type->t, c);
1761 s->type.ref = type->ref;
1762 s->r = r;
1763 /* don't record fields or anonymous symbols */
1764 /* XXX: simplify */
1765 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1766 /* record symbol in token array */
1767 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1768 if (v & SYM_STRUCT)
1769 ps = &ts->sym_struct;
1770 else
1771 ps = &ts->sym_identifier;
1772 s->prev_tok = *ps;
1773 *ps = s;
1775 return s;
1778 /* push a global identifier */
1779 static Sym *global_identifier_push(int v, int t, int c)
1781 Sym *s, **ps;
1782 s = sym_push2(&global_stack, v, t, c);
1783 /* don't record anonymous symbol */
1784 if (v < SYM_FIRST_ANOM) {
1785 ps = &table_ident[v - TOK_IDENT]->sym_identifier;
1786 /* modify the top most local identifier, so that
1787 sym_identifier will point to 's' when popped */
1788 while (*ps != NULL)
1789 ps = &(*ps)->prev_tok;
1790 s->prev_tok = NULL;
1791 *ps = s;
1793 return s;
1796 /* pop symbols until top reaches 'b' */
1797 static void sym_pop(Sym **ptop, Sym *b)
1799 Sym *s, *ss, **ps;
1800 TokenSym *ts;
1801 int v;
1803 s = *ptop;
1804 while(s != b) {
1805 ss = s->prev;
1806 v = s->v;
1807 /* remove symbol in token array */
1808 /* XXX: simplify */
1809 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1810 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1811 if (v & SYM_STRUCT)
1812 ps = &ts->sym_struct;
1813 else
1814 ps = &ts->sym_identifier;
1815 *ps = s->prev_tok;
1817 sym_free(s);
1818 s = ss;
1820 *ptop = b;
1823 /* I/O layer */
1825 BufferedFile *tcc_open(TCCState *s1, const char *filename)
1827 int fd;
1828 BufferedFile *bf;
1830 fd = open(filename, O_RDONLY | O_BINARY);
1831 if (fd < 0)
1832 return NULL;
1833 bf = tcc_malloc(sizeof(BufferedFile));
1834 if (!bf) {
1835 close(fd);
1836 return NULL;
1838 bf->fd = fd;
1839 bf->buf_ptr = bf->buffer;
1840 bf->buf_end = bf->buffer;
1841 bf->buffer[0] = CH_EOB; /* put eob symbol */
1842 pstrcpy(bf->filename, sizeof(bf->filename), filename);
1843 bf->line_num = 1;
1844 bf->ifndef_macro = 0;
1845 bf->ifdef_stack_ptr = s1->ifdef_stack_ptr;
1846 // printf("opening '%s'\n", filename);
1847 return bf;
1850 void tcc_close(BufferedFile *bf)
1852 total_lines += bf->line_num;
1853 close(bf->fd);
1854 tcc_free(bf);
1857 /* fill input buffer and peek next char */
1858 static int tcc_peekc_slow(BufferedFile *bf)
1860 int len;
1861 /* only tries to read if really end of buffer */
1862 if (bf->buf_ptr >= bf->buf_end) {
1863 if (bf->fd != -1) {
1864 #if defined(PARSE_DEBUG)
1865 len = 8;
1866 #else
1867 len = IO_BUF_SIZE;
1868 #endif
1869 len = read(bf->fd, bf->buffer, len);
1870 if (len < 0)
1871 len = 0;
1872 } else {
1873 len = 0;
1875 total_bytes += len;
1876 bf->buf_ptr = bf->buffer;
1877 bf->buf_end = bf->buffer + len;
1878 *bf->buf_end = CH_EOB;
1880 if (bf->buf_ptr < bf->buf_end) {
1881 return bf->buf_ptr[0];
1882 } else {
1883 bf->buf_ptr = bf->buf_end;
1884 return CH_EOF;
1888 /* return the current character, handling end of block if necessary
1889 (but not stray) */
1890 static int handle_eob(void)
1892 return tcc_peekc_slow(file);
1895 /* read next char from current input file and handle end of input buffer */
1896 static inline void inp(void)
1898 ch = *(++(file->buf_ptr));
1899 /* end of buffer/file handling */
1900 if (ch == CH_EOB)
1901 ch = handle_eob();
1904 /* handle '\[\r]\n' */
1905 static void handle_stray(void)
1907 while (ch == '\\') {
1908 inp();
1909 if (ch == '\n') {
1910 file->line_num++;
1911 inp();
1912 } else if (ch == '\r') {
1913 inp();
1914 if (ch != '\n')
1915 goto fail;
1916 file->line_num++;
1917 inp();
1918 } else {
1919 fail:
1920 error("stray '\\' in program");
1925 /* skip the stray and handle the \\n case. Output an error if
1926 incorrect char after the stray */
1927 static int handle_stray1(uint8_t *p)
1929 int c;
1931 if (p >= file->buf_end) {
1932 file->buf_ptr = p;
1933 c = handle_eob();
1934 p = file->buf_ptr;
1935 if (c == '\\')
1936 goto parse_stray;
1937 } else {
1938 parse_stray:
1939 file->buf_ptr = p;
1940 ch = *p;
1941 handle_stray();
1942 p = file->buf_ptr;
1943 c = *p;
1945 return c;
1948 /* handle just the EOB case, but not stray */
1949 #define PEEKC_EOB(c, p)\
1951 p++;\
1952 c = *p;\
1953 if (c == '\\') {\
1954 file->buf_ptr = p;\
1955 c = handle_eob();\
1956 p = file->buf_ptr;\
1960 /* handle the complicated stray case */
1961 #define PEEKC(c, p)\
1963 p++;\
1964 c = *p;\
1965 if (c == '\\') {\
1966 c = handle_stray1(p);\
1967 p = file->buf_ptr;\
1971 /* input with '\[\r]\n' handling. Note that this function cannot
1972 handle other characters after '\', so you cannot call it inside
1973 strings or comments */
1974 static void minp(void)
1976 inp();
1977 if (ch == '\\')
1978 handle_stray();
1982 /* single line C++ comments */
1983 static uint8_t *parse_line_comment(uint8_t *p)
1985 int c;
1987 p++;
1988 for(;;) {
1989 c = *p;
1990 redo:
1991 if (c == '\n' || c == CH_EOF) {
1992 break;
1993 } else if (c == '\\') {
1994 file->buf_ptr = p;
1995 c = handle_eob();
1996 p = file->buf_ptr;
1997 if (c == '\\') {
1998 PEEKC_EOB(c, p);
1999 if (c == '\n') {
2000 file->line_num++;
2001 PEEKC_EOB(c, p);
2002 } else if (c == '\r') {
2003 PEEKC_EOB(c, p);
2004 if (c == '\n') {
2005 file->line_num++;
2006 PEEKC_EOB(c, p);
2009 } else {
2010 goto redo;
2012 } else {
2013 p++;
2016 return p;
2019 /* C comments */
2020 static uint8_t *parse_comment(uint8_t *p)
2022 int c;
2024 p++;
2025 for(;;) {
2026 /* fast skip loop */
2027 for(;;) {
2028 c = *p;
2029 if (c == '\n' || c == '*' || c == '\\')
2030 break;
2031 p++;
2032 c = *p;
2033 if (c == '\n' || c == '*' || c == '\\')
2034 break;
2035 p++;
2037 /* now we can handle all the cases */
2038 if (c == '\n') {
2039 file->line_num++;
2040 p++;
2041 } else if (c == '*') {
2042 p++;
2043 for(;;) {
2044 c = *p;
2045 if (c == '*') {
2046 p++;
2047 } else if (c == '/') {
2048 goto end_of_comment;
2049 } else if (c == '\\') {
2050 file->buf_ptr = p;
2051 c = handle_eob();
2052 p = file->buf_ptr;
2053 if (c == '\\') {
2054 /* skip '\[\r]\n', otherwise just skip the stray */
2055 while (c == '\\') {
2056 PEEKC_EOB(c, p);
2057 if (c == '\n') {
2058 file->line_num++;
2059 PEEKC_EOB(c, p);
2060 } else if (c == '\r') {
2061 PEEKC_EOB(c, p);
2062 if (c == '\n') {
2063 file->line_num++;
2064 PEEKC_EOB(c, p);
2066 } else {
2067 goto after_star;
2071 } else {
2072 break;
2075 after_star: ;
2076 } else {
2077 /* stray, eob or eof */
2078 file->buf_ptr = p;
2079 c = handle_eob();
2080 p = file->buf_ptr;
2081 if (c == CH_EOF) {
2082 error("unexpected end of file in comment");
2083 } else if (c == '\\') {
2084 p++;
2088 end_of_comment:
2089 p++;
2090 return p;
2093 #define cinp minp
2095 /* space exlcuding newline */
2096 static inline int is_space(int ch)
2098 return ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f' || ch == '\r';
2101 static inline void skip_spaces(void)
2103 while (is_space(ch))
2104 cinp();
2107 /* parse a string without interpreting escapes */
2108 static uint8_t *parse_pp_string(uint8_t *p,
2109 int sep, CString *str)
2111 int c;
2112 p++;
2113 for(;;) {
2114 c = *p;
2115 if (c == sep) {
2116 break;
2117 } else if (c == '\\') {
2118 file->buf_ptr = p;
2119 c = handle_eob();
2120 p = file->buf_ptr;
2121 if (c == CH_EOF) {
2122 unterminated_string:
2123 /* XXX: indicate line number of start of string */
2124 error("missing terminating %c character", sep);
2125 } else if (c == '\\') {
2126 /* escape : just skip \[\r]\n */
2127 PEEKC_EOB(c, p);
2128 if (c == '\n') {
2129 file->line_num++;
2130 p++;
2131 } else if (c == '\r') {
2132 PEEKC_EOB(c, p);
2133 if (c != '\n')
2134 expect("'\n' after '\r'");
2135 file->line_num++;
2136 p++;
2137 } else if (c == CH_EOF) {
2138 goto unterminated_string;
2139 } else {
2140 if (str) {
2141 cstr_ccat(str, '\\');
2142 cstr_ccat(str, c);
2144 p++;
2147 } else if (c == '\n') {
2148 file->line_num++;
2149 goto add_char;
2150 } else if (c == '\r') {
2151 PEEKC_EOB(c, p);
2152 if (c != '\n') {
2153 if (str)
2154 cstr_ccat(str, '\r');
2155 } else {
2156 file->line_num++;
2157 goto add_char;
2159 } else {
2160 add_char:
2161 if (str)
2162 cstr_ccat(str, c);
2163 p++;
2166 p++;
2167 return p;
2170 /* skip block of text until #else, #elif or #endif. skip also pairs of
2171 #if/#endif */
2172 void preprocess_skip(void)
2174 int a, start_of_line, c;
2175 uint8_t *p;
2177 p = file->buf_ptr;
2178 start_of_line = 1;
2179 a = 0;
2180 for(;;) {
2181 redo_no_start:
2182 c = *p;
2183 switch(c) {
2184 case ' ':
2185 case '\t':
2186 case '\f':
2187 case '\v':
2188 case '\r':
2189 p++;
2190 goto redo_no_start;
2191 case '\n':
2192 start_of_line = 1;
2193 file->line_num++;
2194 p++;
2195 goto redo_no_start;
2196 case '\\':
2197 file->buf_ptr = p;
2198 c = handle_eob();
2199 if (c == CH_EOF) {
2200 expect("#endif");
2201 } else if (c == '\\') {
2202 /* XXX: incorrect: should not give an error */
2203 ch = file->buf_ptr[0];
2204 handle_stray();
2206 p = file->buf_ptr;
2207 goto redo_no_start;
2208 /* skip strings */
2209 case '\"':
2210 case '\'':
2211 p = parse_pp_string(p, c, NULL);
2212 break;
2213 /* skip comments */
2214 case '/':
2215 file->buf_ptr = p;
2216 ch = *p;
2217 minp();
2218 p = file->buf_ptr;
2219 if (ch == '*') {
2220 p = parse_comment(p);
2221 } else if (ch == '/') {
2222 p = parse_line_comment(p);
2224 break;
2226 case '#':
2227 p++;
2228 if (start_of_line) {
2229 file->buf_ptr = p;
2230 next_nomacro();
2231 p = file->buf_ptr;
2232 if (a == 0 &&
2233 (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
2234 goto the_end;
2235 if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
2236 a++;
2237 else if (tok == TOK_ENDIF)
2238 a--;
2240 break;
2241 default:
2242 p++;
2243 break;
2245 start_of_line = 0;
2247 the_end: ;
2248 file->buf_ptr = p;
2251 /* ParseState handling */
2253 /* XXX: currently, no include file info is stored. Thus, we cannot display
2254 accurate messages if the function or data definition spans multiple
2255 files */
2257 /* save current parse state in 's' */
2258 void save_parse_state(ParseState *s)
2260 s->line_num = file->line_num;
2261 s->macro_ptr = macro_ptr;
2262 s->tok = tok;
2263 s->tokc = tokc;
2266 /* restore parse state from 's' */
2267 void restore_parse_state(ParseState *s)
2269 file->line_num = s->line_num;
2270 macro_ptr = s->macro_ptr;
2271 tok = s->tok;
2272 tokc = s->tokc;
2275 /* return the number of additional 'ints' necessary to store the
2276 token */
2277 static inline int tok_ext_size(int t)
2279 switch(t) {
2280 /* 4 bytes */
2281 case TOK_CINT:
2282 case TOK_CUINT:
2283 case TOK_CCHAR:
2284 case TOK_LCHAR:
2285 case TOK_CFLOAT:
2286 case TOK_LINENUM:
2287 return 1;
2288 case TOK_STR:
2289 case TOK_LSTR:
2290 case TOK_PPNUM:
2291 error("unsupported token");
2292 return 1;
2293 case TOK_CDOUBLE:
2294 case TOK_CLLONG:
2295 case TOK_CULLONG:
2296 return 2;
2297 case TOK_CLDOUBLE:
2298 return LDOUBLE_SIZE / 4;
2299 default:
2300 return 0;
2304 /* token string handling */
2306 static inline void tok_str_new(TokenString *s)
2308 s->str = NULL;
2309 s->len = 0;
2310 s->allocated_len = 0;
2311 s->last_line_num = -1;
2314 static void tok_str_free(int *str)
2316 tcc_free(str);
2319 static int *tok_str_realloc(TokenString *s)
2321 int *str, len;
2323 if (s->allocated_len == 0) {
2324 len = 8;
2325 } else {
2326 len = s->allocated_len * 2;
2328 str = tcc_realloc(s->str, len * sizeof(int));
2329 if (!str)
2330 error("memory full");
2331 s->allocated_len = len;
2332 s->str = str;
2333 return str;
2336 static void tok_str_add(TokenString *s, int t)
2338 int len, *str;
2340 len = s->len;
2341 str = s->str;
2342 if (len >= s->allocated_len)
2343 str = tok_str_realloc(s);
2344 str[len++] = t;
2345 s->len = len;
2348 static void tok_str_add2(TokenString *s, int t, CValue *cv)
2350 int len, *str;
2352 len = s->len;
2353 str = s->str;
2355 /* allocate space for worst case */
2356 if (len + TOK_MAX_SIZE > s->allocated_len)
2357 str = tok_str_realloc(s);
2358 str[len++] = t;
2359 switch(t) {
2360 case TOK_CINT:
2361 case TOK_CUINT:
2362 case TOK_CCHAR:
2363 case TOK_LCHAR:
2364 case TOK_CFLOAT:
2365 case TOK_LINENUM:
2366 str[len++] = cv->tab[0];
2367 break;
2368 case TOK_PPNUM:
2369 case TOK_STR:
2370 case TOK_LSTR:
2372 int nb_words;
2373 CString *cstr;
2375 nb_words = (sizeof(CString) + cv->cstr->size + 3) >> 2;
2376 while ((len + nb_words) > s->allocated_len)
2377 str = tok_str_realloc(s);
2378 cstr = (CString *)(str + len);
2379 cstr->data = NULL;
2380 cstr->size = cv->cstr->size;
2381 cstr->data_allocated = NULL;
2382 cstr->size_allocated = cstr->size;
2383 memcpy((char *)cstr + sizeof(CString),
2384 cv->cstr->data, cstr->size);
2385 len += nb_words;
2387 break;
2388 case TOK_CDOUBLE:
2389 case TOK_CLLONG:
2390 case TOK_CULLONG:
2391 #if LDOUBLE_SIZE == 8
2392 case TOK_CLDOUBLE:
2393 #endif
2394 str[len++] = cv->tab[0];
2395 str[len++] = cv->tab[1];
2396 break;
2397 #if LDOUBLE_SIZE == 12
2398 case TOK_CLDOUBLE:
2399 str[len++] = cv->tab[0];
2400 str[len++] = cv->tab[1];
2401 str[len++] = cv->tab[2];
2402 #elif LDOUBLE_SIZE != 8
2403 #error add long double size support
2404 #endif
2405 break;
2406 default:
2407 break;
2409 s->len = len;
2412 /* add the current parse token in token string 's' */
2413 static void tok_str_add_tok(TokenString *s)
2415 CValue cval;
2417 /* save line number info */
2418 if (file->line_num != s->last_line_num) {
2419 s->last_line_num = file->line_num;
2420 cval.i = s->last_line_num;
2421 tok_str_add2(s, TOK_LINENUM, &cval);
2423 tok_str_add2(s, tok, &tokc);
2426 #if LDOUBLE_SIZE == 12
2427 #define LDOUBLE_GET(p, cv) \
2428 cv.tab[0] = p[0]; \
2429 cv.tab[1] = p[1]; \
2430 cv.tab[2] = p[2];
2431 #elif LDOUBLE_SIZE == 8
2432 #define LDOUBLE_GET(p, cv) \
2433 cv.tab[0] = p[0]; \
2434 cv.tab[1] = p[1];
2435 #else
2436 #error add long double size support
2437 #endif
2440 /* get a token from an integer array and increment pointer
2441 accordingly. we code it as a macro to avoid pointer aliasing. */
2442 #define TOK_GET(t, p, cv) \
2444 t = *p++; \
2445 switch(t) { \
2446 case TOK_CINT: \
2447 case TOK_CUINT: \
2448 case TOK_CCHAR: \
2449 case TOK_LCHAR: \
2450 case TOK_CFLOAT: \
2451 case TOK_LINENUM: \
2452 cv.tab[0] = *p++; \
2453 break; \
2454 case TOK_STR: \
2455 case TOK_LSTR: \
2456 case TOK_PPNUM: \
2457 cv.cstr = (CString *)p; \
2458 cv.cstr->data = (char *)p + sizeof(CString);\
2459 p += (sizeof(CString) + cv.cstr->size + 3) >> 2;\
2460 break; \
2461 case TOK_CDOUBLE: \
2462 case TOK_CLLONG: \
2463 case TOK_CULLONG: \
2464 cv.tab[0] = p[0]; \
2465 cv.tab[1] = p[1]; \
2466 p += 2; \
2467 break; \
2468 case TOK_CLDOUBLE: \
2469 LDOUBLE_GET(p, cv); \
2470 p += LDOUBLE_SIZE / 4; \
2471 break; \
2472 default: \
2473 break; \
2477 /* defines handling */
2478 static inline void define_push(int v, int macro_type, int *str, Sym *first_arg)
2480 Sym *s;
2482 s = sym_push2(&define_stack, v, macro_type, (int)str);
2483 s->next = first_arg;
2484 table_ident[v - TOK_IDENT]->sym_define = s;
2487 /* undefined a define symbol. Its name is just set to zero */
2488 static void define_undef(Sym *s)
2490 int v;
2491 v = s->v;
2492 if (v >= TOK_IDENT && v < tok_ident)
2493 table_ident[v - TOK_IDENT]->sym_define = NULL;
2494 s->v = 0;
2497 static inline Sym *define_find(int v)
2499 v -= TOK_IDENT;
2500 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2501 return NULL;
2502 return table_ident[v]->sym_define;
2505 /* free define stack until top reaches 'b' */
2506 static void free_defines(Sym *b)
2508 Sym *top, *top1;
2509 int v;
2511 top = define_stack;
2512 while (top != b) {
2513 top1 = top->prev;
2514 /* do not free args or predefined defines */
2515 if (top->c)
2516 tok_str_free((int *)top->c);
2517 v = top->v;
2518 if (v >= TOK_IDENT && v < tok_ident)
2519 table_ident[v - TOK_IDENT]->sym_define = NULL;
2520 sym_free(top);
2521 top = top1;
2523 define_stack = b;
2526 /* label lookup */
2527 static Sym *label_find(int v)
2529 v -= TOK_IDENT;
2530 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2531 return NULL;
2532 return table_ident[v]->sym_label;
2535 static Sym *label_push(Sym **ptop, int v, int flags)
2537 Sym *s, **ps;
2538 s = sym_push2(ptop, v, 0, 0);
2539 s->r = flags;
2540 ps = &table_ident[v - TOK_IDENT]->sym_label;
2541 if (ptop == &global_label_stack) {
2542 /* modify the top most local identifier, so that
2543 sym_identifier will point to 's' when popped */
2544 while (*ps != NULL)
2545 ps = &(*ps)->prev_tok;
2547 s->prev_tok = *ps;
2548 *ps = s;
2549 return s;
2552 /* pop labels until element last is reached. Look if any labels are
2553 undefined. Define symbols if '&&label' was used. */
2554 static void label_pop(Sym **ptop, Sym *slast)
2556 Sym *s, *s1;
2557 for(s = *ptop; s != slast; s = s1) {
2558 s1 = s->prev;
2559 if (s->r == LABEL_DECLARED) {
2560 warning("label '%s' declared but not used", get_tok_str(s->v, NULL));
2561 } else if (s->r == LABEL_FORWARD) {
2562 error("label '%s' used but not defined",
2563 get_tok_str(s->v, NULL));
2564 } else {
2565 if (s->c) {
2566 /* define corresponding symbol. A size of
2567 1 is put. */
2568 put_extern_sym(s, cur_text_section, (long)s->next, 1);
2571 /* remove label */
2572 table_ident[s->v - TOK_IDENT]->sym_label = s->prev_tok;
2573 sym_free(s);
2575 *ptop = slast;
2578 /* eval an expression for #if/#elif */
2579 static int expr_preprocess(void)
2581 int c, t;
2582 TokenString str;
2584 tok_str_new(&str);
2585 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2586 next(); /* do macro subst */
2587 if (tok == TOK_DEFINED) {
2588 next_nomacro();
2589 t = tok;
2590 if (t == '(')
2591 next_nomacro();
2592 c = define_find(tok) != 0;
2593 if (t == '(')
2594 next_nomacro();
2595 tok = TOK_CINT;
2596 tokc.i = c;
2597 } else if (tok >= TOK_IDENT) {
2598 /* if undefined macro */
2599 tok = TOK_CINT;
2600 tokc.i = 0;
2602 tok_str_add_tok(&str);
2604 tok_str_add(&str, -1); /* simulate end of file */
2605 tok_str_add(&str, 0);
2606 /* now evaluate C constant expression */
2607 macro_ptr = str.str;
2608 next();
2609 c = expr_const();
2610 macro_ptr = NULL;
2611 tok_str_free(str.str);
2612 return c != 0;
2615 #if defined(PARSE_DEBUG) || defined(PP_DEBUG)
2616 static void tok_print(int *str)
2618 int t;
2619 CValue cval;
2621 while (1) {
2622 TOK_GET(t, str, cval);
2623 if (!t)
2624 break;
2625 printf(" %s", get_tok_str(t, &cval));
2627 printf("\n");
2629 #endif
2631 /* parse after #define */
2632 static void parse_define(void)
2634 Sym *s, *first, **ps;
2635 int v, t, varg, is_vaargs, c;
2636 TokenString str;
2638 v = tok;
2639 if (v < TOK_IDENT)
2640 error("invalid macro name '%s'", get_tok_str(tok, &tokc));
2641 /* XXX: should check if same macro (ANSI) */
2642 first = NULL;
2643 t = MACRO_OBJ;
2644 /* '(' must be just after macro definition for MACRO_FUNC */
2645 c = file->buf_ptr[0];
2646 if (c == '\\')
2647 c = handle_stray1(file->buf_ptr);
2648 if (c == '(') {
2649 next_nomacro();
2650 next_nomacro();
2651 ps = &first;
2652 while (tok != ')') {
2653 varg = tok;
2654 next_nomacro();
2655 is_vaargs = 0;
2656 if (varg == TOK_DOTS) {
2657 varg = TOK___VA_ARGS__;
2658 is_vaargs = 1;
2659 } else if (tok == TOK_DOTS && gnu_ext) {
2660 is_vaargs = 1;
2661 next_nomacro();
2663 if (varg < TOK_IDENT)
2664 error("badly punctuated parameter list");
2665 s = sym_push2(&define_stack, varg | SYM_FIELD, is_vaargs, 0);
2666 *ps = s;
2667 ps = &s->next;
2668 if (tok != ',')
2669 break;
2670 next_nomacro();
2672 t = MACRO_FUNC;
2674 tok_str_new(&str);
2675 next_nomacro();
2676 /* EOF testing necessary for '-D' handling */
2677 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2678 tok_str_add2(&str, tok, &tokc);
2679 next_nomacro();
2681 tok_str_add(&str, 0);
2682 #ifdef PP_DEBUG
2683 printf("define %s %d: ", get_tok_str(v, NULL), t);
2684 tok_print(str.str);
2685 #endif
2686 define_push(v, t, str.str, first);
2689 static inline int hash_cached_include(int type, const char *filename)
2691 const unsigned char *s;
2692 unsigned int h;
2694 h = TOK_HASH_INIT;
2695 h = TOK_HASH_FUNC(h, type);
2696 s = filename;
2697 while (*s) {
2698 h = TOK_HASH_FUNC(h, *s);
2699 s++;
2701 h &= (CACHED_INCLUDES_HASH_SIZE - 1);
2702 return h;
2705 /* XXX: use a token or a hash table to accelerate matching ? */
2706 static CachedInclude *search_cached_include(TCCState *s1,
2707 int type, const char *filename)
2709 CachedInclude *e;
2710 int i, h;
2711 h = hash_cached_include(type, filename);
2712 i = s1->cached_includes_hash[h];
2713 for(;;) {
2714 if (i == 0)
2715 break;
2716 e = s1->cached_includes[i - 1];
2717 if (e->type == type && !strcmp(e->filename, filename))
2718 return e;
2719 i = e->hash_next;
2721 return NULL;
2724 static inline void add_cached_include(TCCState *s1, int type,
2725 const char *filename, int ifndef_macro)
2727 CachedInclude *e;
2728 int h;
2730 if (search_cached_include(s1, type, filename))
2731 return;
2732 #ifdef INC_DEBUG
2733 printf("adding cached '%s' %s\n", filename, get_tok_str(ifndef_macro, NULL));
2734 #endif
2735 e = tcc_malloc(sizeof(CachedInclude) + strlen(filename));
2736 if (!e)
2737 return;
2738 e->type = type;
2739 strcpy(e->filename, filename);
2740 e->ifndef_macro = ifndef_macro;
2741 dynarray_add((void ***)&s1->cached_includes, &s1->nb_cached_includes, e);
2742 /* add in hash table */
2743 h = hash_cached_include(type, filename);
2744 e->hash_next = s1->cached_includes_hash[h];
2745 s1->cached_includes_hash[h] = s1->nb_cached_includes;
2748 static void pragma_parse(TCCState *s1)
2750 int val;
2752 next();
2753 if (tok == TOK_pack) {
2755 This may be:
2756 #pragma pack(1) // set
2757 #pragma pack() // reset to default
2758 #pragma pack(push,1) // push & set
2759 #pragma pack(pop) // restore previous
2761 next();
2762 skip('(');
2763 if (tok == TOK_ASM_pop) {
2764 next();
2765 if (s1->pack_stack_ptr <= s1->pack_stack) {
2766 stk_error:
2767 error("out of pack stack");
2769 s1->pack_stack_ptr--;
2770 } else {
2771 val = 0;
2772 if (tok != ')') {
2773 if (tok == TOK_ASM_push) {
2774 next();
2775 if (s1->pack_stack_ptr >= s1->pack_stack + PACK_STACK_SIZE - 1)
2776 goto stk_error;
2777 s1->pack_stack_ptr++;
2778 skip(',');
2780 if (tok != TOK_CINT) {
2781 pack_error:
2782 error("invalid pack pragma");
2784 val = tokc.i;
2785 if (val < 1 || val > 16 || (val & (val - 1)) != 0)
2786 goto pack_error;
2787 next();
2789 *s1->pack_stack_ptr = val;
2790 skip(')');
2795 /* is_bof is true if first non space token at beginning of file */
2796 static void preprocess(int is_bof)
2798 TCCState *s1 = tcc_state;
2799 int size, i, c, n, saved_parse_flags;
2800 char buf[1024], *q, *p;
2801 char buf1[1024];
2802 BufferedFile *f;
2803 Sym *s;
2804 CachedInclude *e;
2806 saved_parse_flags = parse_flags;
2807 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM |
2808 PARSE_FLAG_LINEFEED;
2809 next_nomacro();
2810 redo:
2811 switch(tok) {
2812 case TOK_DEFINE:
2813 next_nomacro();
2814 parse_define();
2815 break;
2816 case TOK_UNDEF:
2817 next_nomacro();
2818 s = define_find(tok);
2819 /* undefine symbol by putting an invalid name */
2820 if (s)
2821 define_undef(s);
2822 break;
2823 case TOK_INCLUDE:
2824 case TOK_INCLUDE_NEXT:
2825 ch = file->buf_ptr[0];
2826 /* XXX: incorrect if comments : use next_nomacro with a special mode */
2827 skip_spaces();
2828 if (ch == '<') {
2829 c = '>';
2830 goto read_name;
2831 } else if (ch == '\"') {
2832 c = ch;
2833 read_name:
2834 /* XXX: better stray handling */
2835 minp();
2836 q = buf;
2837 while (ch != c && ch != '\n' && ch != CH_EOF) {
2838 if ((q - buf) < sizeof(buf) - 1)
2839 *q++ = ch;
2840 minp();
2842 *q = '\0';
2843 minp();
2844 #if 0
2845 /* eat all spaces and comments after include */
2846 /* XXX: slightly incorrect */
2847 while (ch1 != '\n' && ch1 != CH_EOF)
2848 inp();
2849 #endif
2850 } else {
2851 /* computed #include : either we have only strings or
2852 we have anything enclosed in '<>' */
2853 next();
2854 buf[0] = '\0';
2855 if (tok == TOK_STR) {
2856 while (tok != TOK_LINEFEED) {
2857 if (tok != TOK_STR) {
2858 include_syntax:
2859 error("'#include' expects \"FILENAME\" or <FILENAME>");
2861 pstrcat(buf, sizeof(buf), (char *)tokc.cstr->data);
2862 next();
2864 c = '\"';
2865 } else {
2866 int len;
2867 while (tok != TOK_LINEFEED) {
2868 pstrcat(buf, sizeof(buf), get_tok_str(tok, &tokc));
2869 next();
2871 len = strlen(buf);
2872 /* check syntax and remove '<>' */
2873 if (len < 2 || buf[0] != '<' || buf[len - 1] != '>')
2874 goto include_syntax;
2875 memmove(buf, buf + 1, len - 2);
2876 buf[len - 2] = '\0';
2877 c = '>';
2881 e = search_cached_include(s1, c, buf);
2882 if (e && define_find(e->ifndef_macro)) {
2883 /* no need to parse the include because the 'ifndef macro'
2884 is defined */
2885 #ifdef INC_DEBUG
2886 printf("%s: skipping %s\n", file->filename, buf);
2887 #endif
2888 } else {
2889 if (c == '\"') {
2890 /* first search in current dir if "header.h" */
2891 size = 0;
2892 p = strrchr(file->filename, '/');
2893 if (p)
2894 size = p + 1 - file->filename;
2895 if (size > sizeof(buf1) - 1)
2896 size = sizeof(buf1) - 1;
2897 memcpy(buf1, file->filename, size);
2898 buf1[size] = '\0';
2899 pstrcat(buf1, sizeof(buf1), buf);
2900 f = tcc_open(s1, buf1);
2901 if (f) {
2902 if (tok == TOK_INCLUDE_NEXT)
2903 tok = TOK_INCLUDE;
2904 else
2905 goto found;
2908 if (s1->include_stack_ptr >= s1->include_stack + INCLUDE_STACK_SIZE)
2909 error("#include recursion too deep");
2910 /* now search in all the include paths */
2911 n = s1->nb_include_paths + s1->nb_sysinclude_paths;
2912 for(i = 0; i < n; i++) {
2913 const char *path;
2914 if (i < s1->nb_include_paths)
2915 path = s1->include_paths[i];
2916 else
2917 path = s1->sysinclude_paths[i - s1->nb_include_paths];
2918 pstrcpy(buf1, sizeof(buf1), path);
2919 pstrcat(buf1, sizeof(buf1), "/");
2920 pstrcat(buf1, sizeof(buf1), buf);
2921 f = tcc_open(s1, buf1);
2922 if (f) {
2923 if (tok == TOK_INCLUDE_NEXT)
2924 tok = TOK_INCLUDE;
2925 else
2926 goto found;
2929 error("include file '%s' not found", buf);
2930 f = NULL;
2931 found:
2932 #ifdef INC_DEBUG
2933 printf("%s: including %s\n", file->filename, buf1);
2934 #endif
2935 f->inc_type = c;
2936 pstrcpy(f->inc_filename, sizeof(f->inc_filename), buf);
2937 /* push current file in stack */
2938 /* XXX: fix current line init */
2939 *s1->include_stack_ptr++ = file;
2940 file = f;
2941 /* add include file debug info */
2942 if (do_debug) {
2943 put_stabs(file->filename, N_BINCL, 0, 0, 0);
2945 tok_flags |= TOK_FLAG_BOF | TOK_FLAG_BOL;
2946 ch = file->buf_ptr[0];
2947 goto the_end;
2949 break;
2950 case TOK_IFNDEF:
2951 c = 1;
2952 goto do_ifdef;
2953 case TOK_IF:
2954 c = expr_preprocess();
2955 goto do_if;
2956 case TOK_IFDEF:
2957 c = 0;
2958 do_ifdef:
2959 next_nomacro();
2960 if (tok < TOK_IDENT)
2961 error("invalid argument for '#if%sdef'", c ? "n" : "");
2962 if (is_bof) {
2963 if (c) {
2964 #ifdef INC_DEBUG
2965 printf("#ifndef %s\n", get_tok_str(tok, NULL));
2966 #endif
2967 file->ifndef_macro = tok;
2970 c = (define_find(tok) != 0) ^ c;
2971 do_if:
2972 if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE)
2973 error("memory full");
2974 *s1->ifdef_stack_ptr++ = c;
2975 goto test_skip;
2976 case TOK_ELSE:
2977 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
2978 error("#else without matching #if");
2979 if (s1->ifdef_stack_ptr[-1] & 2)
2980 error("#else after #else");
2981 c = (s1->ifdef_stack_ptr[-1] ^= 3);
2982 goto test_skip;
2983 case TOK_ELIF:
2984 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
2985 error("#elif without matching #if");
2986 c = s1->ifdef_stack_ptr[-1];
2987 if (c > 1)
2988 error("#elif after #else");
2989 /* last #if/#elif expression was true: we skip */
2990 if (c == 1)
2991 goto skip;
2992 c = expr_preprocess();
2993 s1->ifdef_stack_ptr[-1] = c;
2994 test_skip:
2995 if (!(c & 1)) {
2996 skip:
2997 preprocess_skip();
2998 is_bof = 0;
2999 goto redo;
3001 break;
3002 case TOK_ENDIF:
3003 if (s1->ifdef_stack_ptr <= file->ifdef_stack_ptr)
3004 error("#endif without matching #if");
3005 s1->ifdef_stack_ptr--;
3006 /* '#ifndef macro' was at the start of file. Now we check if
3007 an '#endif' is exactly at the end of file */
3008 if (file->ifndef_macro &&
3009 s1->ifdef_stack_ptr == file->ifdef_stack_ptr) {
3010 file->ifndef_macro_saved = file->ifndef_macro;
3011 /* need to set to zero to avoid false matches if another
3012 #ifndef at middle of file */
3013 file->ifndef_macro = 0;
3014 while (tok != TOK_LINEFEED)
3015 next_nomacro();
3016 tok_flags |= TOK_FLAG_ENDIF;
3017 goto the_end;
3019 break;
3020 case TOK_LINE:
3021 next();
3022 if (tok != TOK_CINT)
3023 error("#line");
3024 file->line_num = tokc.i - 1; /* the line number will be incremented after */
3025 next();
3026 if (tok != TOK_LINEFEED) {
3027 if (tok != TOK_STR)
3028 error("#line");
3029 pstrcpy(file->filename, sizeof(file->filename),
3030 (char *)tokc.cstr->data);
3032 break;
3033 case TOK_ERROR:
3034 case TOK_WARNING:
3035 c = tok;
3036 ch = file->buf_ptr[0];
3037 skip_spaces();
3038 q = buf;
3039 while (ch != '\n' && ch != CH_EOF) {
3040 if ((q - buf) < sizeof(buf) - 1)
3041 *q++ = ch;
3042 minp();
3044 *q = '\0';
3045 if (c == TOK_ERROR)
3046 error("#error %s", buf);
3047 else
3048 warning("#warning %s", buf);
3049 break;
3050 case TOK_PRAGMA:
3051 pragma_parse(s1);
3052 break;
3053 default:
3054 if (tok == TOK_LINEFEED || tok == '!' || tok == TOK_CINT) {
3055 /* '!' is ignored to allow C scripts. numbers are ignored
3056 to emulate cpp behaviour */
3057 } else {
3058 if (!(saved_parse_flags & PARSE_FLAG_ASM_COMMENTS))
3059 error("invalid preprocessing directive #%s", get_tok_str(tok, &tokc));
3061 break;
3063 /* ignore other preprocess commands or #! for C scripts */
3064 while (tok != TOK_LINEFEED)
3065 next_nomacro();
3066 the_end:
3067 parse_flags = saved_parse_flags;
3070 /* evaluate escape codes in a string. */
3071 static void parse_escape_string(CString *outstr, const uint8_t *buf, int is_long)
3073 int c, n;
3074 const uint8_t *p;
3076 p = buf;
3077 for(;;) {
3078 c = *p;
3079 if (c == '\0')
3080 break;
3081 if (c == '\\') {
3082 p++;
3083 /* escape */
3084 c = *p;
3085 switch(c) {
3086 case '0': case '1': case '2': case '3':
3087 case '4': case '5': case '6': case '7':
3088 /* at most three octal digits */
3089 n = c - '0';
3090 p++;
3091 c = *p;
3092 if (isoct(c)) {
3093 n = n * 8 + c - '0';
3094 p++;
3095 c = *p;
3096 if (isoct(c)) {
3097 n = n * 8 + c - '0';
3098 p++;
3101 c = n;
3102 goto add_char_nonext;
3103 case 'x':
3104 p++;
3105 n = 0;
3106 for(;;) {
3107 c = *p;
3108 if (c >= 'a' && c <= 'f')
3109 c = c - 'a' + 10;
3110 else if (c >= 'A' && c <= 'F')
3111 c = c - 'A' + 10;
3112 else if (isnum(c))
3113 c = c - '0';
3114 else
3115 break;
3116 n = n * 16 + c;
3117 p++;
3119 c = n;
3120 goto add_char_nonext;
3121 case 'a':
3122 c = '\a';
3123 break;
3124 case 'b':
3125 c = '\b';
3126 break;
3127 case 'f':
3128 c = '\f';
3129 break;
3130 case 'n':
3131 c = '\n';
3132 break;
3133 case 'r':
3134 c = '\r';
3135 break;
3136 case 't':
3137 c = '\t';
3138 break;
3139 case 'v':
3140 c = '\v';
3141 break;
3142 case 'e':
3143 if (!gnu_ext)
3144 goto invalid_escape;
3145 c = 27;
3146 break;
3147 case '\'':
3148 case '\"':
3149 case '\\':
3150 case '?':
3151 break;
3152 default:
3153 invalid_escape:
3154 if (c >= '!' && c <= '~')
3155 warning("unknown escape sequence: \'\\%c\'", c);
3156 else
3157 warning("unknown escape sequence: \'\\x%x\'", c);
3158 break;
3161 p++;
3162 add_char_nonext:
3163 if (!is_long)
3164 cstr_ccat(outstr, c);
3165 else
3166 cstr_wccat(outstr, c);
3168 /* add a trailing '\0' */
3169 if (!is_long)
3170 cstr_ccat(outstr, '\0');
3171 else
3172 cstr_wccat(outstr, '\0');
3175 /* we use 64 bit numbers */
3176 #define BN_SIZE 2
3178 /* bn = (bn << shift) | or_val */
3179 void bn_lshift(unsigned int *bn, int shift, int or_val)
3181 int i;
3182 unsigned int v;
3183 for(i=0;i<BN_SIZE;i++) {
3184 v = bn[i];
3185 bn[i] = (v << shift) | or_val;
3186 or_val = v >> (32 - shift);
3190 void bn_zero(unsigned int *bn)
3192 int i;
3193 for(i=0;i<BN_SIZE;i++) {
3194 bn[i] = 0;
3198 /* parse number in null terminated string 'p' and return it in the
3199 current token */
3200 void parse_number(const char *p)
3202 int b, t, shift, frac_bits, s, exp_val, ch;
3203 char *q;
3204 unsigned int bn[BN_SIZE];
3205 double d;
3207 /* number */
3208 q = token_buf;
3209 ch = *p++;
3210 t = ch;
3211 ch = *p++;
3212 *q++ = t;
3213 b = 10;
3214 if (t == '.') {
3215 goto float_frac_parse;
3216 } else if (t == '0') {
3217 if (ch == 'x' || ch == 'X') {
3218 q--;
3219 ch = *p++;
3220 b = 16;
3221 } else if (tcc_ext && (ch == 'b' || ch == 'B')) {
3222 q--;
3223 ch = *p++;
3224 b = 2;
3227 /* parse all digits. cannot check octal numbers at this stage
3228 because of floating point constants */
3229 while (1) {
3230 if (ch >= 'a' && ch <= 'f')
3231 t = ch - 'a' + 10;
3232 else if (ch >= 'A' && ch <= 'F')
3233 t = ch - 'A' + 10;
3234 else if (isnum(ch))
3235 t = ch - '0';
3236 else
3237 break;
3238 if (t >= b)
3239 break;
3240 if (q >= token_buf + STRING_MAX_SIZE) {
3241 num_too_long:
3242 error("number too long");
3244 *q++ = ch;
3245 ch = *p++;
3247 if (ch == '.' ||
3248 ((ch == 'e' || ch == 'E') && b == 10) ||
3249 ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
3250 if (b != 10) {
3251 /* NOTE: strtox should support that for hexa numbers, but
3252 non ISOC99 libcs do not support it, so we prefer to do
3253 it by hand */
3254 /* hexadecimal or binary floats */
3255 /* XXX: handle overflows */
3256 *q = '\0';
3257 if (b == 16)
3258 shift = 4;
3259 else
3260 shift = 2;
3261 bn_zero(bn);
3262 q = token_buf;
3263 while (1) {
3264 t = *q++;
3265 if (t == '\0') {
3266 break;
3267 } else if (t >= 'a') {
3268 t = t - 'a' + 10;
3269 } else if (t >= 'A') {
3270 t = t - 'A' + 10;
3271 } else {
3272 t = t - '0';
3274 bn_lshift(bn, shift, t);
3276 frac_bits = 0;
3277 if (ch == '.') {
3278 ch = *p++;
3279 while (1) {
3280 t = ch;
3281 if (t >= 'a' && t <= 'f') {
3282 t = t - 'a' + 10;
3283 } else if (t >= 'A' && t <= 'F') {
3284 t = t - 'A' + 10;
3285 } else if (t >= '0' && t <= '9') {
3286 t = t - '0';
3287 } else {
3288 break;
3290 if (t >= b)
3291 error("invalid digit");
3292 bn_lshift(bn, shift, t);
3293 frac_bits += shift;
3294 ch = *p++;
3297 if (ch != 'p' && ch != 'P')
3298 expect("exponent");
3299 ch = *p++;
3300 s = 1;
3301 exp_val = 0;
3302 if (ch == '+') {
3303 ch = *p++;
3304 } else if (ch == '-') {
3305 s = -1;
3306 ch = *p++;
3308 if (ch < '0' || ch > '9')
3309 expect("exponent digits");
3310 while (ch >= '0' && ch <= '9') {
3311 exp_val = exp_val * 10 + ch - '0';
3312 ch = *p++;
3314 exp_val = exp_val * s;
3316 /* now we can generate the number */
3317 /* XXX: should patch directly float number */
3318 d = (double)bn[1] * 4294967296.0 + (double)bn[0];
3319 d = ldexp(d, exp_val - frac_bits);
3320 t = toup(ch);
3321 if (t == 'F') {
3322 ch = *p++;
3323 tok = TOK_CFLOAT;
3324 /* float : should handle overflow */
3325 tokc.f = (float)d;
3326 } else if (t == 'L') {
3327 ch = *p++;
3328 tok = TOK_CLDOUBLE;
3329 /* XXX: not large enough */
3330 tokc.ld = (long double)d;
3331 } else {
3332 tok = TOK_CDOUBLE;
3333 tokc.d = d;
3335 } else {
3336 /* decimal floats */
3337 if (ch == '.') {
3338 if (q >= token_buf + STRING_MAX_SIZE)
3339 goto num_too_long;
3340 *q++ = ch;
3341 ch = *p++;
3342 float_frac_parse:
3343 while (ch >= '0' && ch <= '9') {
3344 if (q >= token_buf + STRING_MAX_SIZE)
3345 goto num_too_long;
3346 *q++ = ch;
3347 ch = *p++;
3350 if (ch == 'e' || ch == 'E') {
3351 if (q >= token_buf + STRING_MAX_SIZE)
3352 goto num_too_long;
3353 *q++ = ch;
3354 ch = *p++;
3355 if (ch == '-' || ch == '+') {
3356 if (q >= token_buf + STRING_MAX_SIZE)
3357 goto num_too_long;
3358 *q++ = ch;
3359 ch = *p++;
3361 if (ch < '0' || ch > '9')
3362 expect("exponent digits");
3363 while (ch >= '0' && ch <= '9') {
3364 if (q >= token_buf + STRING_MAX_SIZE)
3365 goto num_too_long;
3366 *q++ = ch;
3367 ch = *p++;
3370 *q = '\0';
3371 t = toup(ch);
3372 errno = 0;
3373 if (t == 'F') {
3374 ch = *p++;
3375 tok = TOK_CFLOAT;
3376 tokc.f = strtof(token_buf, NULL);
3377 } else if (t == 'L') {
3378 ch = *p++;
3379 tok = TOK_CLDOUBLE;
3380 tokc.ld = strtold(token_buf, NULL);
3381 } else {
3382 tok = TOK_CDOUBLE;
3383 tokc.d = strtod(token_buf, NULL);
3386 } else {
3387 unsigned long long n, n1;
3388 int lcount, ucount;
3390 /* integer number */
3391 *q = '\0';
3392 q = token_buf;
3393 if (b == 10 && *q == '0') {
3394 b = 8;
3395 q++;
3397 n = 0;
3398 while(1) {
3399 t = *q++;
3400 /* no need for checks except for base 10 / 8 errors */
3401 if (t == '\0') {
3402 break;
3403 } else if (t >= 'a') {
3404 t = t - 'a' + 10;
3405 } else if (t >= 'A') {
3406 t = t - 'A' + 10;
3407 } else {
3408 t = t - '0';
3409 if (t >= b)
3410 error("invalid digit");
3412 n1 = n;
3413 n = n * b + t;
3414 /* detect overflow */
3415 /* XXX: this test is not reliable */
3416 if (n < n1)
3417 error("integer constant overflow");
3420 /* XXX: not exactly ANSI compliant */
3421 if ((n & 0xffffffff00000000LL) != 0) {
3422 if ((n >> 63) != 0)
3423 tok = TOK_CULLONG;
3424 else
3425 tok = TOK_CLLONG;
3426 } else if (n > 0x7fffffff) {
3427 tok = TOK_CUINT;
3428 } else {
3429 tok = TOK_CINT;
3431 lcount = 0;
3432 ucount = 0;
3433 for(;;) {
3434 t = toup(ch);
3435 if (t == 'L') {
3436 if (lcount >= 2)
3437 error("three 'l's in integer constant");
3438 lcount++;
3439 if (lcount == 2) {
3440 if (tok == TOK_CINT)
3441 tok = TOK_CLLONG;
3442 else if (tok == TOK_CUINT)
3443 tok = TOK_CULLONG;
3445 ch = *p++;
3446 } else if (t == 'U') {
3447 if (ucount >= 1)
3448 error("two 'u's in integer constant");
3449 ucount++;
3450 if (tok == TOK_CINT)
3451 tok = TOK_CUINT;
3452 else if (tok == TOK_CLLONG)
3453 tok = TOK_CULLONG;
3454 ch = *p++;
3455 } else {
3456 break;
3459 if (tok == TOK_CINT || tok == TOK_CUINT)
3460 tokc.ui = n;
3461 else
3462 tokc.ull = n;
3467 #define PARSE2(c1, tok1, c2, tok2) \
3468 case c1: \
3469 PEEKC(c, p); \
3470 if (c == c2) { \
3471 p++; \
3472 tok = tok2; \
3473 } else { \
3474 tok = tok1; \
3476 break;
3478 /* return next token without macro substitution */
3479 static inline void next_nomacro1(void)
3481 int t, c, is_long;
3482 TokenSym *ts;
3483 uint8_t *p, *p1;
3484 unsigned int h;
3486 p = file->buf_ptr;
3487 redo_no_start:
3488 c = *p;
3489 switch(c) {
3490 case ' ':
3491 case '\t':
3492 case '\f':
3493 case '\v':
3494 case '\r':
3495 p++;
3496 goto redo_no_start;
3498 case '\\':
3499 /* first look if it is in fact an end of buffer */
3500 if (p >= file->buf_end) {
3501 file->buf_ptr = p;
3502 handle_eob();
3503 p = file->buf_ptr;
3504 if (p >= file->buf_end)
3505 goto parse_eof;
3506 else
3507 goto redo_no_start;
3508 } else {
3509 file->buf_ptr = p;
3510 ch = *p;
3511 handle_stray();
3512 p = file->buf_ptr;
3513 goto redo_no_start;
3515 parse_eof:
3517 TCCState *s1 = tcc_state;
3518 if (parse_flags & PARSE_FLAG_LINEFEED) {
3519 tok = TOK_LINEFEED;
3520 } else if (s1->include_stack_ptr == s1->include_stack ||
3521 !(parse_flags & PARSE_FLAG_PREPROCESS)) {
3522 /* no include left : end of file. */
3523 tok = TOK_EOF;
3524 } else {
3525 /* pop include file */
3527 /* test if previous '#endif' was after a #ifdef at
3528 start of file */
3529 if (tok_flags & TOK_FLAG_ENDIF) {
3530 #ifdef INC_DEBUG
3531 printf("#endif %s\n", get_tok_str(file->ifndef_macro_saved, NULL));
3532 #endif
3533 add_cached_include(s1, file->inc_type, file->inc_filename,
3534 file->ifndef_macro_saved);
3537 /* add end of include file debug info */
3538 if (do_debug) {
3539 put_stabd(N_EINCL, 0, 0);
3541 /* pop include stack */
3542 tcc_close(file);
3543 s1->include_stack_ptr--;
3544 file = *s1->include_stack_ptr;
3545 p = file->buf_ptr;
3546 goto redo_no_start;
3549 break;
3551 case '\n':
3552 if (parse_flags & PARSE_FLAG_LINEFEED) {
3553 tok = TOK_LINEFEED;
3554 } else {
3555 file->line_num++;
3556 tok_flags |= TOK_FLAG_BOL;
3557 p++;
3558 goto redo_no_start;
3560 break;
3562 case '#':
3563 /* XXX: simplify */
3564 PEEKC(c, p);
3565 if ((tok_flags & TOK_FLAG_BOL) &&
3566 (parse_flags & PARSE_FLAG_PREPROCESS)) {
3567 file->buf_ptr = p;
3568 preprocess(tok_flags & TOK_FLAG_BOF);
3569 p = file->buf_ptr;
3570 goto redo_no_start;
3571 } else {
3572 if (c == '#') {
3573 p++;
3574 tok = TOK_TWOSHARPS;
3575 } else {
3576 if (parse_flags & PARSE_FLAG_ASM_COMMENTS) {
3577 p = parse_line_comment(p - 1);
3578 goto redo_no_start;
3579 } else {
3580 tok = '#';
3584 break;
3586 case 'a': case 'b': case 'c': case 'd':
3587 case 'e': case 'f': case 'g': case 'h':
3588 case 'i': case 'j': case 'k': case 'l':
3589 case 'm': case 'n': case 'o': case 'p':
3590 case 'q': case 'r': case 's': case 't':
3591 case 'u': case 'v': case 'w': case 'x':
3592 case 'y': case 'z':
3593 case 'A': case 'B': case 'C': case 'D':
3594 case 'E': case 'F': case 'G': case 'H':
3595 case 'I': case 'J': case 'K':
3596 case 'M': case 'N': case 'O': case 'P':
3597 case 'Q': case 'R': case 'S': case 'T':
3598 case 'U': case 'V': case 'W': case 'X':
3599 case 'Y': case 'Z':
3600 case '_':
3601 parse_ident_fast:
3602 p1 = p;
3603 h = TOK_HASH_INIT;
3604 h = TOK_HASH_FUNC(h, c);
3605 p++;
3606 for(;;) {
3607 c = *p;
3608 if (!isidnum_table[c])
3609 break;
3610 h = TOK_HASH_FUNC(h, c);
3611 p++;
3613 if (c != '\\') {
3614 TokenSym **pts;
3615 int len;
3617 /* fast case : no stray found, so we have the full token
3618 and we have already hashed it */
3619 len = p - p1;
3620 h &= (TOK_HASH_SIZE - 1);
3621 pts = &hash_ident[h];
3622 for(;;) {
3623 ts = *pts;
3624 if (!ts)
3625 break;
3626 if (ts->len == len && !memcmp(ts->str, p1, len))
3627 goto token_found;
3628 pts = &(ts->hash_next);
3630 ts = tok_alloc_new(pts, p1, len);
3631 token_found: ;
3632 } else {
3633 /* slower case */
3634 cstr_reset(&tokcstr);
3636 while (p1 < p) {
3637 cstr_ccat(&tokcstr, *p1);
3638 p1++;
3640 p--;
3641 PEEKC(c, p);
3642 parse_ident_slow:
3643 while (isidnum_table[c]) {
3644 cstr_ccat(&tokcstr, c);
3645 PEEKC(c, p);
3647 ts = tok_alloc(tokcstr.data, tokcstr.size);
3649 tok = ts->tok;
3650 break;
3651 case 'L':
3652 t = p[1];
3653 if (t != '\\' && t != '\'' && t != '\"') {
3654 /* fast case */
3655 goto parse_ident_fast;
3656 } else {
3657 PEEKC(c, p);
3658 if (c == '\'' || c == '\"') {
3659 is_long = 1;
3660 goto str_const;
3661 } else {
3662 cstr_reset(&tokcstr);
3663 cstr_ccat(&tokcstr, 'L');
3664 goto parse_ident_slow;
3667 break;
3668 case '0': case '1': case '2': case '3':
3669 case '4': case '5': case '6': case '7':
3670 case '8': case '9':
3672 cstr_reset(&tokcstr);
3673 /* after the first digit, accept digits, alpha, '.' or sign if
3674 prefixed by 'eEpP' */
3675 parse_num:
3676 for(;;) {
3677 t = c;
3678 cstr_ccat(&tokcstr, c);
3679 PEEKC(c, p);
3680 if (!(isnum(c) || isid(c) || c == '.' ||
3681 ((c == '+' || c == '-') &&
3682 (t == 'e' || t == 'E' || t == 'p' || t == 'P'))))
3683 break;
3685 /* We add a trailing '\0' to ease parsing */
3686 cstr_ccat(&tokcstr, '\0');
3687 tokc.cstr = &tokcstr;
3688 tok = TOK_PPNUM;
3689 break;
3690 case '.':
3691 /* special dot handling because it can also start a number */
3692 PEEKC(c, p);
3693 if (isnum(c)) {
3694 cstr_reset(&tokcstr);
3695 cstr_ccat(&tokcstr, '.');
3696 goto parse_num;
3697 } else if (c == '.') {
3698 PEEKC(c, p);
3699 if (c != '.')
3700 expect("'.'");
3701 PEEKC(c, p);
3702 tok = TOK_DOTS;
3703 } else {
3704 tok = '.';
3706 break;
3707 case '\'':
3708 case '\"':
3709 is_long = 0;
3710 str_const:
3712 CString str;
3713 int sep;
3715 sep = c;
3717 /* parse the string */
3718 cstr_new(&str);
3719 p = parse_pp_string(p, sep, &str);
3720 cstr_ccat(&str, '\0');
3722 /* eval the escape (should be done as TOK_PPNUM) */
3723 cstr_reset(&tokcstr);
3724 parse_escape_string(&tokcstr, str.data, is_long);
3725 cstr_free(&str);
3727 if (sep == '\'') {
3728 int char_size;
3729 /* XXX: make it portable */
3730 if (!is_long)
3731 char_size = 1;
3732 else
3733 char_size = sizeof(int);
3734 if (tokcstr.size <= char_size)
3735 error("empty character constant");
3736 if (tokcstr.size > 2 * char_size)
3737 warning("multi-character character constant");
3738 if (!is_long) {
3739 tokc.i = *(int8_t *)tokcstr.data;
3740 tok = TOK_CCHAR;
3741 } else {
3742 tokc.i = *(int *)tokcstr.data;
3743 tok = TOK_LCHAR;
3745 } else {
3746 tokc.cstr = &tokcstr;
3747 if (!is_long)
3748 tok = TOK_STR;
3749 else
3750 tok = TOK_LSTR;
3753 break;
3755 case '<':
3756 PEEKC(c, p);
3757 if (c == '=') {
3758 p++;
3759 tok = TOK_LE;
3760 } else if (c == '<') {
3761 PEEKC(c, p);
3762 if (c == '=') {
3763 p++;
3764 tok = TOK_A_SHL;
3765 } else {
3766 tok = TOK_SHL;
3768 } else {
3769 tok = TOK_LT;
3771 break;
3773 case '>':
3774 PEEKC(c, p);
3775 if (c == '=') {
3776 p++;
3777 tok = TOK_GE;
3778 } else if (c == '>') {
3779 PEEKC(c, p);
3780 if (c == '=') {
3781 p++;
3782 tok = TOK_A_SAR;
3783 } else {
3784 tok = TOK_SAR;
3786 } else {
3787 tok = TOK_GT;
3789 break;
3791 case '&':
3792 PEEKC(c, p);
3793 if (c == '&') {
3794 p++;
3795 tok = TOK_LAND;
3796 } else if (c == '=') {
3797 p++;
3798 tok = TOK_A_AND;
3799 } else {
3800 tok = '&';
3802 break;
3804 case '|':
3805 PEEKC(c, p);
3806 if (c == '|') {
3807 p++;
3808 tok = TOK_LOR;
3809 } else if (c == '=') {
3810 p++;
3811 tok = TOK_A_OR;
3812 } else {
3813 tok = '|';
3815 break;
3817 case '+':
3818 PEEKC(c, p);
3819 if (c == '+') {
3820 p++;
3821 tok = TOK_INC;
3822 } else if (c == '=') {
3823 p++;
3824 tok = TOK_A_ADD;
3825 } else {
3826 tok = '+';
3828 break;
3830 case '-':
3831 PEEKC(c, p);
3832 if (c == '-') {
3833 p++;
3834 tok = TOK_DEC;
3835 } else if (c == '=') {
3836 p++;
3837 tok = TOK_A_SUB;
3838 } else if (c == '>') {
3839 p++;
3840 tok = TOK_ARROW;
3841 } else {
3842 tok = '-';
3844 break;
3846 PARSE2('!', '!', '=', TOK_NE)
3847 PARSE2('=', '=', '=', TOK_EQ)
3848 PARSE2('*', '*', '=', TOK_A_MUL)
3849 PARSE2('%', '%', '=', TOK_A_MOD)
3850 PARSE2('^', '^', '=', TOK_A_XOR)
3852 /* comments or operator */
3853 case '/':
3854 PEEKC(c, p);
3855 if (c == '*') {
3856 p = parse_comment(p);
3857 goto redo_no_start;
3858 } else if (c == '/') {
3859 p = parse_line_comment(p);
3860 goto redo_no_start;
3861 } else if (c == '=') {
3862 p++;
3863 tok = TOK_A_DIV;
3864 } else {
3865 tok = '/';
3867 break;
3869 /* simple tokens */
3870 case '(':
3871 case ')':
3872 case '[':
3873 case ']':
3874 case '{':
3875 case '}':
3876 case ',':
3877 case ';':
3878 case ':':
3879 case '?':
3880 case '~':
3881 case '$': /* only used in assembler */
3882 case '@': /* dito */
3883 tok = c;
3884 p++;
3885 break;
3886 default:
3887 error("unrecognized character \\x%02x", c);
3888 break;
3890 file->buf_ptr = p;
3891 tok_flags = 0;
3892 #if defined(PARSE_DEBUG)
3893 printf("token = %s\n", get_tok_str(tok, &tokc));
3894 #endif
3897 /* return next token without macro substitution. Can read input from
3898 macro_ptr buffer */
3899 static void next_nomacro(void)
3901 if (macro_ptr) {
3902 redo:
3903 tok = *macro_ptr;
3904 if (tok) {
3905 TOK_GET(tok, macro_ptr, tokc);
3906 if (tok == TOK_LINENUM) {
3907 file->line_num = tokc.i;
3908 goto redo;
3911 } else {
3912 next_nomacro1();
3916 /* substitute args in macro_str and return allocated string */
3917 static int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
3919 int *st, last_tok, t, notfirst;
3920 Sym *s;
3921 CValue cval;
3922 TokenString str;
3923 CString cstr;
3925 tok_str_new(&str);
3926 last_tok = 0;
3927 while(1) {
3928 TOK_GET(t, macro_str, cval);
3929 if (!t)
3930 break;
3931 if (t == '#') {
3932 /* stringize */
3933 TOK_GET(t, macro_str, cval);
3934 if (!t)
3935 break;
3936 s = sym_find2(args, t);
3937 if (s) {
3938 cstr_new(&cstr);
3939 st = (int *)s->c;
3940 notfirst = 0;
3941 while (*st) {
3942 if (notfirst)
3943 cstr_ccat(&cstr, ' ');
3944 TOK_GET(t, st, cval);
3945 cstr_cat(&cstr, get_tok_str(t, &cval));
3946 notfirst = 1;
3948 cstr_ccat(&cstr, '\0');
3949 #ifdef PP_DEBUG
3950 printf("stringize: %s\n", (char *)cstr.data);
3951 #endif
3952 /* add string */
3953 cval.cstr = &cstr;
3954 tok_str_add2(&str, TOK_STR, &cval);
3955 cstr_free(&cstr);
3956 } else {
3957 tok_str_add2(&str, t, &cval);
3959 } else if (t >= TOK_IDENT) {
3960 s = sym_find2(args, t);
3961 if (s) {
3962 st = (int *)s->c;
3963 /* if '##' is present before or after, no arg substitution */
3964 if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) {
3965 /* special case for var arg macros : ## eats the
3966 ',' if empty VA_ARGS variable. */
3967 /* XXX: test of the ',' is not 100%
3968 reliable. should fix it to avoid security
3969 problems */
3970 if (gnu_ext && s->type.t &&
3971 last_tok == TOK_TWOSHARPS &&
3972 str.len >= 2 && str.str[str.len - 2] == ',') {
3973 if (*st == 0) {
3974 /* suppress ',' '##' */
3975 str.len -= 2;
3976 } else {
3977 /* suppress '##' and add variable */
3978 str.len--;
3979 goto add_var;
3981 } else {
3982 int t1;
3983 add_var:
3984 for(;;) {
3985 TOK_GET(t1, st, cval);
3986 if (!t1)
3987 break;
3988 tok_str_add2(&str, t1, &cval);
3991 } else {
3992 /* NOTE: the stream cannot be read when macro
3993 substituing an argument */
3994 macro_subst(&str, nested_list, st, NULL);
3996 } else {
3997 tok_str_add(&str, t);
3999 } else {
4000 tok_str_add2(&str, t, &cval);
4002 last_tok = t;
4004 tok_str_add(&str, 0);
4005 return str.str;
4008 static char const ab_month_name[12][4] =
4010 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
4011 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
4014 /* do macro substitution of current token with macro 's' and add
4015 result to (tok_str,tok_len). 'nested_list' is the list of all
4016 macros we got inside to avoid recursing. Return non zero if no
4017 substitution needs to be done */
4018 static int macro_subst_tok(TokenString *tok_str,
4019 Sym **nested_list, Sym *s, struct macro_level **can_read_stream)
4021 Sym *args, *sa, *sa1;
4022 int mstr_allocated, parlevel, *mstr, t, t1;
4023 TokenString str;
4024 char *cstrval;
4025 CValue cval;
4026 CString cstr;
4027 char buf[32];
4029 /* if symbol is a macro, prepare substitution */
4030 /* special macros */
4031 if (tok == TOK___LINE__) {
4032 snprintf(buf, sizeof(buf), "%d", file->line_num);
4033 cstrval = buf;
4034 t1 = TOK_PPNUM;
4035 goto add_cstr1;
4036 } else if (tok == TOK___FILE__) {
4037 cstrval = file->filename;
4038 goto add_cstr;
4039 } else if (tok == TOK___DATE__ || tok == TOK___TIME__) {
4040 time_t ti;
4041 struct tm *tm;
4043 time(&ti);
4044 tm = localtime(&ti);
4045 if (tok == TOK___DATE__) {
4046 snprintf(buf, sizeof(buf), "%s %2d %d",
4047 ab_month_name[tm->tm_mon], tm->tm_mday, tm->tm_year + 1900);
4048 } else {
4049 snprintf(buf, sizeof(buf), "%02d:%02d:%02d",
4050 tm->tm_hour, tm->tm_min, tm->tm_sec);
4052 cstrval = buf;
4053 add_cstr:
4054 t1 = TOK_STR;
4055 add_cstr1:
4056 cstr_new(&cstr);
4057 cstr_cat(&cstr, cstrval);
4058 cstr_ccat(&cstr, '\0');
4059 cval.cstr = &cstr;
4060 tok_str_add2(tok_str, t1, &cval);
4061 cstr_free(&cstr);
4062 } else {
4063 mstr = (int *)s->c;
4064 mstr_allocated = 0;
4065 if (s->type.t == MACRO_FUNC) {
4066 /* NOTE: we do not use next_nomacro to avoid eating the
4067 next token. XXX: find better solution */
4068 redo:
4069 if (macro_ptr) {
4070 t = *macro_ptr;
4071 if (t == 0 && can_read_stream) {
4072 /* end of macro stream: we must look at the token
4073 after in the file */
4074 struct macro_level *ml = *can_read_stream;
4075 macro_ptr = NULL;
4076 if (ml)
4078 macro_ptr = ml->p;
4079 ml->p = NULL;
4080 *can_read_stream = ml -> prev;
4082 goto redo;
4084 } else {
4085 /* XXX: incorrect with comments */
4086 ch = file->buf_ptr[0];
4087 while (is_space(ch) || ch == '\n')
4088 cinp();
4089 t = ch;
4091 if (t != '(') /* no macro subst */
4092 return -1;
4094 /* argument macro */
4095 next_nomacro();
4096 next_nomacro();
4097 args = NULL;
4098 sa = s->next;
4099 /* NOTE: empty args are allowed, except if no args */
4100 for(;;) {
4101 /* handle '()' case */
4102 if (!args && !sa && tok == ')')
4103 break;
4104 if (!sa)
4105 error("macro '%s' used with too many args",
4106 get_tok_str(s->v, 0));
4107 tok_str_new(&str);
4108 parlevel = 0;
4109 /* NOTE: non zero sa->t indicates VA_ARGS */
4110 while ((parlevel > 0 ||
4111 (tok != ')' &&
4112 (tok != ',' || sa->type.t))) &&
4113 tok != -1) {
4114 if (tok == '(')
4115 parlevel++;
4116 else if (tok == ')')
4117 parlevel--;
4118 tok_str_add2(&str, tok, &tokc);
4119 next_nomacro();
4121 tok_str_add(&str, 0);
4122 sym_push2(&args, sa->v & ~SYM_FIELD, sa->type.t, (int)str.str);
4123 sa = sa->next;
4124 if (tok == ')') {
4125 /* special case for gcc var args: add an empty
4126 var arg argument if it is omitted */
4127 if (sa && sa->type.t && gnu_ext)
4128 continue;
4129 else
4130 break;
4132 if (tok != ',')
4133 expect(",");
4134 next_nomacro();
4136 if (sa) {
4137 error("macro '%s' used with too few args",
4138 get_tok_str(s->v, 0));
4141 /* now subst each arg */
4142 mstr = macro_arg_subst(nested_list, mstr, args);
4143 /* free memory */
4144 sa = args;
4145 while (sa) {
4146 sa1 = sa->prev;
4147 tok_str_free((int *)sa->c);
4148 sym_free(sa);
4149 sa = sa1;
4151 mstr_allocated = 1;
4153 sym_push2(nested_list, s->v, 0, 0);
4154 macro_subst(tok_str, nested_list, mstr, can_read_stream);
4155 /* pop nested defined symbol */
4156 sa1 = *nested_list;
4157 *nested_list = sa1->prev;
4158 sym_free(sa1);
4159 if (mstr_allocated)
4160 tok_str_free(mstr);
4162 return 0;
4165 /* handle the '##' operator. Return NULL if no '##' seen. Otherwise
4166 return the resulting string (which must be freed). */
4167 static inline int *macro_twosharps(const int *macro_str)
4169 TokenSym *ts;
4170 const int *macro_ptr1, *start_macro_ptr, *ptr, *saved_macro_ptr;
4171 int t;
4172 const char *p1, *p2;
4173 CValue cval;
4174 TokenString macro_str1;
4175 CString cstr;
4177 start_macro_ptr = macro_str;
4178 /* we search the first '##' */
4179 for(;;) {
4180 macro_ptr1 = macro_str;
4181 TOK_GET(t, macro_str, cval);
4182 /* nothing more to do if end of string */
4183 if (t == 0)
4184 return NULL;
4185 if (*macro_str == TOK_TWOSHARPS)
4186 break;
4189 /* we saw '##', so we need more processing to handle it */
4190 cstr_new(&cstr);
4191 tok_str_new(&macro_str1);
4192 tok = t;
4193 tokc = cval;
4195 /* add all tokens seen so far */
4196 for(ptr = start_macro_ptr; ptr < macro_ptr1;) {
4197 TOK_GET(t, ptr, cval);
4198 tok_str_add2(&macro_str1, t, &cval);
4200 saved_macro_ptr = macro_ptr;
4201 /* XXX: get rid of the use of macro_ptr here */
4202 macro_ptr = (int *)macro_str;
4203 for(;;) {
4204 while (*macro_ptr == TOK_TWOSHARPS) {
4205 macro_ptr++;
4206 macro_ptr1 = macro_ptr;
4207 t = *macro_ptr;
4208 if (t) {
4209 TOK_GET(t, macro_ptr, cval);
4210 /* We concatenate the two tokens if we have an
4211 identifier or a preprocessing number */
4212 cstr_reset(&cstr);
4213 p1 = get_tok_str(tok, &tokc);
4214 cstr_cat(&cstr, p1);
4215 p2 = get_tok_str(t, &cval);
4216 cstr_cat(&cstr, p2);
4217 cstr_ccat(&cstr, '\0');
4219 if ((tok >= TOK_IDENT || tok == TOK_PPNUM) &&
4220 (t >= TOK_IDENT || t == TOK_PPNUM)) {
4221 if (tok == TOK_PPNUM) {
4222 /* if number, then create a number token */
4223 /* NOTE: no need to allocate because
4224 tok_str_add2() does it */
4225 tokc.cstr = &cstr;
4226 } else {
4227 /* if identifier, we must do a test to
4228 validate we have a correct identifier */
4229 if (t == TOK_PPNUM) {
4230 const char *p;
4231 int c;
4233 p = p2;
4234 for(;;) {
4235 c = *p;
4236 if (c == '\0')
4237 break;
4238 p++;
4239 if (!isnum(c) && !isid(c))
4240 goto error_pasting;
4243 ts = tok_alloc(cstr.data, strlen(cstr.data));
4244 tok = ts->tok; /* modify current token */
4246 } else {
4247 const char *str = cstr.data;
4248 const unsigned char *q;
4250 /* we look for a valid token */
4251 /* XXX: do more extensive checks */
4252 if (!strcmp(str, ">>=")) {
4253 tok = TOK_A_SAR;
4254 } else if (!strcmp(str, "<<=")) {
4255 tok = TOK_A_SHL;
4256 } else if (strlen(str) == 2) {
4257 /* search in two bytes table */
4258 q = tok_two_chars;
4259 for(;;) {
4260 if (!*q)
4261 goto error_pasting;
4262 if (q[0] == str[0] && q[1] == str[1])
4263 break;
4264 q += 3;
4266 tok = q[2];
4267 } else {
4268 error_pasting:
4269 /* NOTE: because get_tok_str use a static buffer,
4270 we must save it */
4271 cstr_reset(&cstr);
4272 p1 = get_tok_str(tok, &tokc);
4273 cstr_cat(&cstr, p1);
4274 cstr_ccat(&cstr, '\0');
4275 p2 = get_tok_str(t, &cval);
4276 warning("pasting \"%s\" and \"%s\" does not give a valid preprocessing token", cstr.data, p2);
4277 /* cannot merge tokens: just add them separately */
4278 tok_str_add2(&macro_str1, tok, &tokc);
4279 /* XXX: free associated memory ? */
4280 tok = t;
4281 tokc = cval;
4286 tok_str_add2(&macro_str1, tok, &tokc);
4287 next_nomacro();
4288 if (tok == 0)
4289 break;
4291 macro_ptr = (int *)saved_macro_ptr;
4292 cstr_free(&cstr);
4293 tok_str_add(&macro_str1, 0);
4294 return macro_str1.str;
4298 /* do macro substitution of macro_str and add result to
4299 (tok_str,tok_len). 'nested_list' is the list of all macros we got
4300 inside to avoid recursing. */
4301 static void macro_subst(TokenString *tok_str, Sym **nested_list,
4302 const int *macro_str, struct macro_level ** can_read_stream)
4304 Sym *s;
4305 int *macro_str1;
4306 const int *ptr;
4307 int t, ret;
4308 CValue cval;
4309 struct macro_level ml;
4311 /* first scan for '##' operator handling */
4312 ptr = macro_str;
4313 macro_str1 = macro_twosharps(ptr);
4314 if (macro_str1)
4315 ptr = macro_str1;
4316 while (1) {
4317 /* NOTE: ptr == NULL can only happen if tokens are read from
4318 file stream due to a macro function call */
4319 if (ptr == NULL)
4320 break;
4321 TOK_GET(t, ptr, cval);
4322 if (t == 0)
4323 break;
4324 s = define_find(t);
4325 if (s != NULL) {
4326 /* if nested substitution, do nothing */
4327 if (sym_find2(*nested_list, t))
4328 goto no_subst;
4329 ml.p = macro_ptr;
4330 if (can_read_stream)
4331 ml.prev = *can_read_stream, *can_read_stream = &ml;
4332 macro_ptr = (int *)ptr;
4333 tok = t;
4334 ret = macro_subst_tok(tok_str, nested_list, s, can_read_stream);
4335 ptr = (int *)macro_ptr;
4336 macro_ptr = ml.p;
4337 if (can_read_stream && *can_read_stream == &ml)
4338 *can_read_stream = ml.prev;
4339 if (ret != 0)
4340 goto no_subst;
4341 } else {
4342 no_subst:
4343 tok_str_add2(tok_str, t, &cval);
4346 if (macro_str1)
4347 tok_str_free(macro_str1);
4350 /* return next token with macro substitution */
4351 static void next(void)
4353 Sym *nested_list, *s;
4354 TokenString str;
4355 struct macro_level *ml;
4357 redo:
4358 next_nomacro();
4359 if (!macro_ptr) {
4360 /* if not reading from macro substituted string, then try
4361 to substitute macros */
4362 if (tok >= TOK_IDENT &&
4363 (parse_flags & PARSE_FLAG_PREPROCESS)) {
4364 s = define_find(tok);
4365 if (s) {
4366 /* we have a macro: we try to substitute */
4367 tok_str_new(&str);
4368 nested_list = NULL;
4369 ml = NULL;
4370 if (macro_subst_tok(&str, &nested_list, s, &ml) == 0) {
4371 /* substitution done, NOTE: maybe empty */
4372 tok_str_add(&str, 0);
4373 macro_ptr = str.str;
4374 macro_ptr_allocated = str.str;
4375 goto redo;
4379 } else {
4380 if (tok == 0) {
4381 /* end of macro or end of unget buffer */
4382 if (unget_buffer_enabled) {
4383 macro_ptr = unget_saved_macro_ptr;
4384 unget_buffer_enabled = 0;
4385 } else {
4386 /* end of macro string: free it */
4387 tok_str_free(macro_ptr_allocated);
4388 macro_ptr = NULL;
4390 goto redo;
4394 /* convert preprocessor tokens into C tokens */
4395 if (tok == TOK_PPNUM &&
4396 (parse_flags & PARSE_FLAG_TOK_NUM)) {
4397 parse_number((char *)tokc.cstr->data);
4401 /* push back current token and set current token to 'last_tok'. Only
4402 identifier case handled for labels. */
4403 static inline void unget_tok(int last_tok)
4405 int i, n;
4406 int *q;
4407 unget_saved_macro_ptr = macro_ptr;
4408 unget_buffer_enabled = 1;
4409 q = unget_saved_buffer;
4410 macro_ptr = q;
4411 *q++ = tok;
4412 n = tok_ext_size(tok) - 1;
4413 for(i=0;i<n;i++)
4414 *q++ = tokc.tab[i];
4415 *q = 0; /* end of token string */
4416 tok = last_tok;
4420 void swap(int *p, int *q)
4422 int t;
4423 t = *p;
4424 *p = *q;
4425 *q = t;
4428 void vsetc(CType *type, int r, CValue *vc)
4430 int v;
4432 if (vtop >= vstack + (VSTACK_SIZE - 1))
4433 error("memory full");
4434 /* cannot let cpu flags if other instruction are generated. Also
4435 avoid leaving VT_JMP anywhere except on the top of the stack
4436 because it would complicate the code generator. */
4437 if (vtop >= vstack) {
4438 v = vtop->r & VT_VALMASK;
4439 if (v == VT_CMP || (v & ~1) == VT_JMP)
4440 gv(RC_INT);
4442 vtop++;
4443 vtop->type = *type;
4444 vtop->r = r;
4445 vtop->r2 = VT_CONST;
4446 vtop->c = *vc;
4449 /* push integer constant */
4450 void vpushi(int v)
4452 CValue cval;
4453 cval.i = v;
4454 vsetc(&int_type, VT_CONST, &cval);
4457 /* Return a static symbol pointing to a section */
4458 static Sym *get_sym_ref(CType *type, Section *sec,
4459 unsigned long offset, unsigned long size)
4461 int v;
4462 Sym *sym;
4464 v = anon_sym++;
4465 sym = global_identifier_push(v, type->t | VT_STATIC, 0);
4466 sym->type.ref = type->ref;
4467 sym->r = VT_CONST | VT_SYM;
4468 put_extern_sym(sym, sec, offset, size);
4469 return sym;
4472 /* push a reference to a section offset by adding a dummy symbol */
4473 static void vpush_ref(CType *type, Section *sec, unsigned long offset, unsigned long size)
4475 CValue cval;
4477 cval.ul = 0;
4478 vsetc(type, VT_CONST | VT_SYM, &cval);
4479 vtop->sym = get_sym_ref(type, sec, offset, size);
4482 /* define a new external reference to a symbol 'v' of type 'u' */
4483 static Sym *external_global_sym(int v, CType *type, int r)
4485 Sym *s;
4487 s = sym_find(v);
4488 if (!s) {
4489 /* push forward reference */
4490 s = global_identifier_push(v, type->t | VT_EXTERN, 0);
4491 s->type.ref = type->ref;
4492 s->r = r | VT_CONST | VT_SYM;
4494 return s;
4497 /* define a new external reference to a symbol 'v' of type 'u' */
4498 static Sym *external_sym(int v, CType *type, int r)
4500 Sym *s;
4502 s = sym_find(v);
4503 if (!s) {
4504 /* push forward reference */
4505 s = sym_push(v, type, r | VT_CONST | VT_SYM, 0);
4506 s->type.t |= VT_EXTERN;
4507 } else {
4508 if (!is_compatible_types(&s->type, type))
4509 error("incompatible types for redefinition of '%s'",
4510 get_tok_str(v, NULL));
4512 return s;
4515 /* push a reference to global symbol v */
4516 static void vpush_global_sym(CType *type, int v)
4518 Sym *sym;
4519 CValue cval;
4521 sym = external_global_sym(v, type, 0);
4522 cval.ul = 0;
4523 vsetc(type, VT_CONST | VT_SYM, &cval);
4524 vtop->sym = sym;
4527 void vset(CType *type, int r, int v)
4529 CValue cval;
4531 cval.i = v;
4532 vsetc(type, r, &cval);
4535 void vseti(int r, int v)
4537 CType type;
4538 type.t = VT_INT;
4539 vset(&type, r, v);
4542 void vswap(void)
4544 SValue tmp;
4546 tmp = vtop[0];
4547 vtop[0] = vtop[-1];
4548 vtop[-1] = tmp;
4551 void vpushv(SValue *v)
4553 if (vtop >= vstack + (VSTACK_SIZE - 1))
4554 error("memory full");
4555 vtop++;
4556 *vtop = *v;
4559 void vdup(void)
4561 vpushv(vtop);
4564 /* save r to the memory stack, and mark it as being free */
4565 void save_reg(int r)
4567 int l, saved, size, align;
4568 SValue *p, sv;
4569 CType *type;
4571 /* modify all stack values */
4572 saved = 0;
4573 l = 0;
4574 for(p=vstack;p<=vtop;p++) {
4575 if ((p->r & VT_VALMASK) == r ||
4576 (p->r2 & VT_VALMASK) == r) {
4577 /* must save value on stack if not already done */
4578 if (!saved) {
4579 /* NOTE: must reload 'r' because r might be equal to r2 */
4580 r = p->r & VT_VALMASK;
4581 /* store register in the stack */
4582 type = &p->type;
4583 if ((p->r & VT_LVAL) ||
4584 (!is_float(type->t) && (type->t & VT_BTYPE) != VT_LLONG))
4585 type = &int_type;
4586 size = type_size(type, &align);
4587 loc = (loc - size) & -align;
4588 sv.type.t = type->t;
4589 sv.r = VT_LOCAL | VT_LVAL;
4590 sv.c.ul = loc;
4591 store(r, &sv);
4592 #ifdef TCC_TARGET_I386
4593 /* x86 specific: need to pop fp register ST0 if saved */
4594 if (r == TREG_ST0) {
4595 o(0xd9dd); /* fstp %st(1) */
4597 #endif
4598 /* special long long case */
4599 if ((type->t & VT_BTYPE) == VT_LLONG) {
4600 sv.c.ul += 4;
4601 store(p->r2, &sv);
4603 l = loc;
4604 saved = 1;
4606 /* mark that stack entry as being saved on the stack */
4607 if (p->r & VT_LVAL) {
4608 /* also clear the bounded flag because the
4609 relocation address of the function was stored in
4610 p->c.ul */
4611 p->r = (p->r & ~(VT_VALMASK | VT_BOUNDED)) | VT_LLOCAL;
4612 } else {
4613 p->r = lvalue_type(p->type.t) | VT_LOCAL;
4615 p->r2 = VT_CONST;
4616 p->c.ul = l;
4621 /* find a register of class 'rc2' with at most one reference on stack.
4622 * If none, call get_reg(rc) */
4623 int get_reg_ex(int rc, int rc2)
4625 int r;
4626 SValue *p;
4628 for(r=0;r<NB_REGS;r++) {
4629 if (reg_classes[r] & rc2) {
4630 int n;
4631 n=0;
4632 for(p = vstack; p <= vtop; p++) {
4633 if ((p->r & VT_VALMASK) == r ||
4634 (p->r2 & VT_VALMASK) == r)
4635 n++;
4637 if (n <= 1)
4638 return r;
4641 return get_reg(rc);
4644 /* find a free register of class 'rc'. If none, save one register */
4645 int get_reg(int rc)
4647 int r;
4648 SValue *p;
4650 /* find a free register */
4651 for(r=0;r<NB_REGS;r++) {
4652 if (reg_classes[r] & rc) {
4653 for(p=vstack;p<=vtop;p++) {
4654 if ((p->r & VT_VALMASK) == r ||
4655 (p->r2 & VT_VALMASK) == r)
4656 goto notfound;
4658 return r;
4660 notfound: ;
4663 /* no register left : free the first one on the stack (VERY
4664 IMPORTANT to start from the bottom to ensure that we don't
4665 spill registers used in gen_opi()) */
4666 for(p=vstack;p<=vtop;p++) {
4667 r = p->r & VT_VALMASK;
4668 if (r < VT_CONST && (reg_classes[r] & rc))
4669 goto save_found;
4670 /* also look at second register (if long long) */
4671 r = p->r2 & VT_VALMASK;
4672 if (r < VT_CONST && (reg_classes[r] & rc)) {
4673 save_found:
4674 save_reg(r);
4675 return r;
4678 /* Should never comes here */
4679 return -1;
4682 /* save registers up to (vtop - n) stack entry */
4683 void save_regs(int n)
4685 int r;
4686 SValue *p, *p1;
4687 p1 = vtop - n;
4688 for(p = vstack;p <= p1; p++) {
4689 r = p->r & VT_VALMASK;
4690 if (r < VT_CONST) {
4691 save_reg(r);
4696 /* move register 's' to 'r', and flush previous value of r to memory
4697 if needed */
4698 void move_reg(int r, int s)
4700 SValue sv;
4702 if (r != s) {
4703 save_reg(r);
4704 sv.type.t = VT_INT;
4705 sv.r = s;
4706 sv.c.ul = 0;
4707 load(r, &sv);
4711 /* get address of vtop (vtop MUST BE an lvalue) */
4712 void gaddrof(void)
4714 vtop->r &= ~VT_LVAL;
4715 /* tricky: if saved lvalue, then we can go back to lvalue */
4716 if ((vtop->r & VT_VALMASK) == VT_LLOCAL)
4717 vtop->r = (vtop->r & ~(VT_VALMASK | VT_LVAL_TYPE)) | VT_LOCAL | VT_LVAL;
4720 #ifdef CONFIG_TCC_BCHECK
4721 /* generate lvalue bound code */
4722 void gbound(void)
4724 int lval_type;
4725 CType type1;
4727 vtop->r &= ~VT_MUSTBOUND;
4728 /* if lvalue, then use checking code before dereferencing */
4729 if (vtop->r & VT_LVAL) {
4730 /* if not VT_BOUNDED value, then make one */
4731 if (!(vtop->r & VT_BOUNDED)) {
4732 lval_type = vtop->r & (VT_LVAL_TYPE | VT_LVAL);
4733 /* must save type because we must set it to int to get pointer */
4734 type1 = vtop->type;
4735 vtop->type.t = VT_INT;
4736 gaddrof();
4737 vpushi(0);
4738 gen_bounded_ptr_add();
4739 vtop->r |= lval_type;
4740 vtop->type = type1;
4742 /* then check for dereferencing */
4743 gen_bounded_ptr_deref();
4746 #endif
4748 /* store vtop a register belonging to class 'rc'. lvalues are
4749 converted to values. Cannot be used if cannot be converted to
4750 register value (such as structures). */
4751 int gv(int rc)
4753 int r, r2, rc2, bit_pos, bit_size, size, align, i;
4754 unsigned long long ll;
4756 /* NOTE: get_reg can modify vstack[] */
4757 if (vtop->type.t & VT_BITFIELD) {
4758 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
4759 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
4760 /* remove bit field info to avoid loops */
4761 vtop->type.t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
4762 /* generate shifts */
4763 vpushi(32 - (bit_pos + bit_size));
4764 gen_op(TOK_SHL);
4765 vpushi(32 - bit_size);
4766 /* NOTE: transformed to SHR if unsigned */
4767 gen_op(TOK_SAR);
4768 r = gv(rc);
4769 } else {
4770 if (is_float(vtop->type.t) &&
4771 (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4772 Sym *sym;
4773 int *ptr;
4774 unsigned long offset;
4776 /* XXX: unify with initializers handling ? */
4777 /* CPUs usually cannot use float constants, so we store them
4778 generically in data segment */
4779 size = type_size(&vtop->type, &align);
4780 offset = (data_section->data_offset + align - 1) & -align;
4781 data_section->data_offset = offset;
4782 /* XXX: not portable yet */
4783 ptr = section_ptr_add(data_section, size);
4784 size = size >> 2;
4785 for(i=0;i<size;i++)
4786 ptr[i] = vtop->c.tab[i];
4787 sym = get_sym_ref(&vtop->type, data_section, offset, size << 2);
4788 vtop->r |= VT_LVAL | VT_SYM;
4789 vtop->sym = sym;
4790 vtop->c.ul = 0;
4792 #ifdef CONFIG_TCC_BCHECK
4793 if (vtop->r & VT_MUSTBOUND)
4794 gbound();
4795 #endif
4797 r = vtop->r & VT_VALMASK;
4798 /* need to reload if:
4799 - constant
4800 - lvalue (need to dereference pointer)
4801 - already a register, but not in the right class */
4802 if (r >= VT_CONST ||
4803 (vtop->r & VT_LVAL) ||
4804 !(reg_classes[r] & rc) ||
4805 ((vtop->type.t & VT_BTYPE) == VT_LLONG &&
4806 !(reg_classes[vtop->r2] & rc))) {
4807 r = get_reg(rc);
4808 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
4809 /* two register type load : expand to two words
4810 temporarily */
4811 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4812 /* load constant */
4813 ll = vtop->c.ull;
4814 vtop->c.ui = ll; /* first word */
4815 load(r, vtop);
4816 vtop->r = r; /* save register value */
4817 vpushi(ll >> 32); /* second word */
4818 } else if (r >= VT_CONST || /* XXX: test to VT_CONST incorrect ? */
4819 (vtop->r & VT_LVAL)) {
4820 /* We do not want to modifier the long long
4821 pointer here, so the safest (and less
4822 efficient) is to save all the other registers
4823 in the stack. XXX: totally inefficient. */
4824 save_regs(1);
4825 /* load from memory */
4826 load(r, vtop);
4827 vdup();
4828 vtop[-1].r = r; /* save register value */
4829 /* increment pointer to get second word */
4830 vtop->type.t = VT_INT;
4831 gaddrof();
4832 vpushi(4);
4833 gen_op('+');
4834 vtop->r |= VT_LVAL;
4835 } else {
4836 /* move registers */
4837 load(r, vtop);
4838 vdup();
4839 vtop[-1].r = r; /* save register value */
4840 vtop->r = vtop[-1].r2;
4842 /* allocate second register */
4843 rc2 = RC_INT;
4844 if (rc == RC_IRET)
4845 rc2 = RC_LRET;
4846 r2 = get_reg(rc2);
4847 load(r2, vtop);
4848 vpop();
4849 /* write second register */
4850 vtop->r2 = r2;
4851 } else if ((vtop->r & VT_LVAL) && !is_float(vtop->type.t)) {
4852 int t1, t;
4853 /* lvalue of scalar type : need to use lvalue type
4854 because of possible cast */
4855 t = vtop->type.t;
4856 t1 = t;
4857 /* compute memory access type */
4858 if (vtop->r & VT_LVAL_BYTE)
4859 t = VT_BYTE;
4860 else if (vtop->r & VT_LVAL_SHORT)
4861 t = VT_SHORT;
4862 if (vtop->r & VT_LVAL_UNSIGNED)
4863 t |= VT_UNSIGNED;
4864 vtop->type.t = t;
4865 load(r, vtop);
4866 /* restore wanted type */
4867 vtop->type.t = t1;
4868 } else {
4869 /* one register type load */
4870 load(r, vtop);
4873 vtop->r = r;
4874 #ifdef TCC_TARGET_C67
4875 /* uses register pairs for doubles */
4876 if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE)
4877 vtop->r2 = r+1;
4878 #endif
4880 return r;
4883 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
4884 void gv2(int rc1, int rc2)
4886 int v;
4888 /* generate more generic register first. But VT_JMP or VT_CMP
4889 values must be generated first in all cases to avoid possible
4890 reload errors */
4891 v = vtop[0].r & VT_VALMASK;
4892 if (v != VT_CMP && (v & ~1) != VT_JMP && rc1 <= rc2) {
4893 vswap();
4894 gv(rc1);
4895 vswap();
4896 gv(rc2);
4897 /* test if reload is needed for first register */
4898 if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
4899 vswap();
4900 gv(rc1);
4901 vswap();
4903 } else {
4904 gv(rc2);
4905 vswap();
4906 gv(rc1);
4907 vswap();
4908 /* test if reload is needed for first register */
4909 if ((vtop[0].r & VT_VALMASK) >= VT_CONST) {
4910 gv(rc2);
4915 /* expand long long on stack in two int registers */
4916 void lexpand(void)
4918 int u;
4920 u = vtop->type.t & VT_UNSIGNED;
4921 gv(RC_INT);
4922 vdup();
4923 vtop[0].r = vtop[-1].r2;
4924 vtop[0].r2 = VT_CONST;
4925 vtop[-1].r2 = VT_CONST;
4926 vtop[0].type.t = VT_INT | u;
4927 vtop[-1].type.t = VT_INT | u;
4930 #ifdef TCC_TARGET_ARM
4931 /* expand long long on stack */
4932 void lexpand_nr(void)
4934 int u,v;
4936 u = vtop->type.t & VT_UNSIGNED;
4937 vdup();
4938 vtop->r2 = VT_CONST;
4939 vtop->type.t = VT_INT | u;
4940 v=vtop[-1].r & (VT_VALMASK | VT_LVAL);
4941 if (v == VT_CONST) {
4942 vtop[-1].c.ui = vtop->c.ull;
4943 vtop->c.ui = vtop->c.ull >> 32;
4944 vtop->r = VT_CONST;
4945 } else if (v == (VT_LVAL|VT_CONST) || v == (VT_LVAL|VT_LOCAL)) {
4946 vtop->c.ui += 4;
4947 vtop->r = vtop[-1].r;
4948 } else if (v > VT_CONST) {
4949 vtop--;
4950 lexpand();
4951 } else
4952 vtop->r = vtop[-1].r2;
4953 vtop[-1].r2 = VT_CONST;
4954 vtop[-1].type.t = VT_INT | u;
4956 #endif
4958 /* build a long long from two ints */
4959 void lbuild(int t)
4961 gv2(RC_INT, RC_INT);
4962 vtop[-1].r2 = vtop[0].r;
4963 vtop[-1].type.t = t;
4964 vpop();
4967 /* rotate n first stack elements to the bottom
4968 I1 ... In -> I2 ... In I1 [top is right]
4970 void vrotb(int n)
4972 int i;
4973 SValue tmp;
4975 tmp = vtop[-n + 1];
4976 for(i=-n+1;i!=0;i++)
4977 vtop[i] = vtop[i+1];
4978 vtop[0] = tmp;
4981 /* rotate n first stack elements to the top
4982 I1 ... In -> In I1 ... I(n-1) [top is right]
4984 void vrott(int n)
4986 int i;
4987 SValue tmp;
4989 tmp = vtop[0];
4990 for(i = 0;i < n - 1; i++)
4991 vtop[-i] = vtop[-i - 1];
4992 vtop[-n + 1] = tmp;
4995 #ifdef TCC_TARGET_ARM
4996 /* like vrott but in other direction
4997 In ... I1 -> I(n-1) ... I1 In [top is right]
4999 void vnrott(int n)
5001 int i;
5002 SValue tmp;
5004 tmp = vtop[-n + 1];
5005 for(i = n - 1; i > 0; i--)
5006 vtop[-i] = vtop[-i + 1];
5007 vtop[0] = tmp;
5009 #endif
5011 /* pop stack value */
5012 void vpop(void)
5014 int v;
5015 v = vtop->r & VT_VALMASK;
5016 #ifdef TCC_TARGET_I386
5017 /* for x86, we need to pop the FP stack */
5018 if (v == TREG_ST0 && !nocode_wanted) {
5019 o(0xd9dd); /* fstp %st(1) */
5020 } else
5021 #endif
5022 if (v == VT_JMP || v == VT_JMPI) {
5023 /* need to put correct jump if && or || without test */
5024 gsym(vtop->c.ul);
5026 vtop--;
5029 /* convert stack entry to register and duplicate its value in another
5030 register */
5031 void gv_dup(void)
5033 int rc, t, r, r1;
5034 SValue sv;
5036 t = vtop->type.t;
5037 if ((t & VT_BTYPE) == VT_LLONG) {
5038 lexpand();
5039 gv_dup();
5040 vswap();
5041 vrotb(3);
5042 gv_dup();
5043 vrotb(4);
5044 /* stack: H L L1 H1 */
5045 lbuild(t);
5046 vrotb(3);
5047 vrotb(3);
5048 vswap();
5049 lbuild(t);
5050 vswap();
5051 } else {
5052 /* duplicate value */
5053 rc = RC_INT;
5054 sv.type.t = VT_INT;
5055 if (is_float(t)) {
5056 rc = RC_FLOAT;
5057 sv.type.t = t;
5059 r = gv(rc);
5060 r1 = get_reg(rc);
5061 sv.r = r;
5062 sv.c.ul = 0;
5063 load(r1, &sv); /* move r to r1 */
5064 vdup();
5065 /* duplicates value */
5066 vtop->r = r1;
5070 /* generate CPU independent (unsigned) long long operations */
5071 void gen_opl(int op)
5073 int t, a, b, op1, c, i;
5074 int func;
5075 SValue tmp;
5077 switch(op) {
5078 case '/':
5079 case TOK_PDIV:
5080 func = TOK___divdi3;
5081 goto gen_func;
5082 case TOK_UDIV:
5083 func = TOK___udivdi3;
5084 goto gen_func;
5085 case '%':
5086 func = TOK___moddi3;
5087 goto gen_func;
5088 case TOK_UMOD:
5089 func = TOK___umoddi3;
5090 gen_func:
5091 /* call generic long long function */
5092 vpush_global_sym(&func_old_type, func);
5093 vrott(3);
5094 gfunc_call(2);
5095 vpushi(0);
5096 vtop->r = REG_IRET;
5097 vtop->r2 = REG_LRET;
5098 break;
5099 case '^':
5100 case '&':
5101 case '|':
5102 case '*':
5103 case '+':
5104 case '-':
5105 t = vtop->type.t;
5106 vswap();
5107 lexpand();
5108 vrotb(3);
5109 lexpand();
5110 /* stack: L1 H1 L2 H2 */
5111 tmp = vtop[0];
5112 vtop[0] = vtop[-3];
5113 vtop[-3] = tmp;
5114 tmp = vtop[-2];
5115 vtop[-2] = vtop[-3];
5116 vtop[-3] = tmp;
5117 vswap();
5118 /* stack: H1 H2 L1 L2 */
5119 if (op == '*') {
5120 vpushv(vtop - 1);
5121 vpushv(vtop - 1);
5122 gen_op(TOK_UMULL);
5123 lexpand();
5124 /* stack: H1 H2 L1 L2 ML MH */
5125 for(i=0;i<4;i++)
5126 vrotb(6);
5127 /* stack: ML MH H1 H2 L1 L2 */
5128 tmp = vtop[0];
5129 vtop[0] = vtop[-2];
5130 vtop[-2] = tmp;
5131 /* stack: ML MH H1 L2 H2 L1 */
5132 gen_op('*');
5133 vrotb(3);
5134 vrotb(3);
5135 gen_op('*');
5136 /* stack: ML MH M1 M2 */
5137 gen_op('+');
5138 gen_op('+');
5139 } else if (op == '+' || op == '-') {
5140 /* XXX: add non carry method too (for MIPS or alpha) */
5141 if (op == '+')
5142 op1 = TOK_ADDC1;
5143 else
5144 op1 = TOK_SUBC1;
5145 gen_op(op1);
5146 /* stack: H1 H2 (L1 op L2) */
5147 vrotb(3);
5148 vrotb(3);
5149 gen_op(op1 + 1); /* TOK_xxxC2 */
5150 } else {
5151 gen_op(op);
5152 /* stack: H1 H2 (L1 op L2) */
5153 vrotb(3);
5154 vrotb(3);
5155 /* stack: (L1 op L2) H1 H2 */
5156 gen_op(op);
5157 /* stack: (L1 op L2) (H1 op H2) */
5159 /* stack: L H */
5160 lbuild(t);
5161 break;
5162 case TOK_SAR:
5163 case TOK_SHR:
5164 case TOK_SHL:
5165 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
5166 t = vtop[-1].type.t;
5167 vswap();
5168 lexpand();
5169 vrotb(3);
5170 /* stack: L H shift */
5171 c = (int)vtop->c.i;
5172 /* constant: simpler */
5173 /* NOTE: all comments are for SHL. the other cases are
5174 done by swaping words */
5175 vpop();
5176 if (op != TOK_SHL)
5177 vswap();
5178 if (c >= 32) {
5179 /* stack: L H */
5180 vpop();
5181 if (c > 32) {
5182 vpushi(c - 32);
5183 gen_op(op);
5185 if (op != TOK_SAR) {
5186 vpushi(0);
5187 } else {
5188 gv_dup();
5189 vpushi(31);
5190 gen_op(TOK_SAR);
5192 vswap();
5193 } else {
5194 vswap();
5195 gv_dup();
5196 /* stack: H L L */
5197 vpushi(c);
5198 gen_op(op);
5199 vswap();
5200 vpushi(32 - c);
5201 if (op == TOK_SHL)
5202 gen_op(TOK_SHR);
5203 else
5204 gen_op(TOK_SHL);
5205 vrotb(3);
5206 /* stack: L L H */
5207 vpushi(c);
5208 if (op == TOK_SHL)
5209 gen_op(TOK_SHL);
5210 else
5211 gen_op(TOK_SHR);
5212 gen_op('|');
5214 if (op != TOK_SHL)
5215 vswap();
5216 lbuild(t);
5217 } else {
5218 /* XXX: should provide a faster fallback on x86 ? */
5219 switch(op) {
5220 case TOK_SAR:
5221 func = TOK___sardi3;
5222 goto gen_func;
5223 case TOK_SHR:
5224 func = TOK___shrdi3;
5225 goto gen_func;
5226 case TOK_SHL:
5227 func = TOK___shldi3;
5228 goto gen_func;
5231 break;
5232 default:
5233 /* compare operations */
5234 t = vtop->type.t;
5235 vswap();
5236 lexpand();
5237 vrotb(3);
5238 lexpand();
5239 /* stack: L1 H1 L2 H2 */
5240 tmp = vtop[-1];
5241 vtop[-1] = vtop[-2];
5242 vtop[-2] = tmp;
5243 /* stack: L1 L2 H1 H2 */
5244 /* compare high */
5245 op1 = op;
5246 /* when values are equal, we need to compare low words. since
5247 the jump is inverted, we invert the test too. */
5248 if (op1 == TOK_LT)
5249 op1 = TOK_LE;
5250 else if (op1 == TOK_GT)
5251 op1 = TOK_GE;
5252 else if (op1 == TOK_ULT)
5253 op1 = TOK_ULE;
5254 else if (op1 == TOK_UGT)
5255 op1 = TOK_UGE;
5256 a = 0;
5257 b = 0;
5258 gen_op(op1);
5259 if (op1 != TOK_NE) {
5260 a = gtst(1, 0);
5262 if (op != TOK_EQ) {
5263 /* generate non equal test */
5264 /* XXX: NOT PORTABLE yet */
5265 if (a == 0) {
5266 b = gtst(0, 0);
5267 } else {
5268 #if defined(TCC_TARGET_I386)
5269 b = psym(0x850f, 0);
5270 #elif defined(TCC_TARGET_ARM)
5271 b = ind;
5272 o(0x1A000000 | encbranch(ind, 0, 1));
5273 #elif defined(TCC_TARGET_C67)
5274 error("not implemented");
5275 #else
5276 #error not supported
5277 #endif
5280 /* compare low. Always unsigned */
5281 op1 = op;
5282 if (op1 == TOK_LT)
5283 op1 = TOK_ULT;
5284 else if (op1 == TOK_LE)
5285 op1 = TOK_ULE;
5286 else if (op1 == TOK_GT)
5287 op1 = TOK_UGT;
5288 else if (op1 == TOK_GE)
5289 op1 = TOK_UGE;
5290 gen_op(op1);
5291 a = gtst(1, a);
5292 gsym(b);
5293 vseti(VT_JMPI, a);
5294 break;
5298 /* handle integer constant optimizations and various machine
5299 independent opt */
5300 void gen_opic(int op)
5302 int fc, c1, c2, n;
5303 SValue *v1, *v2;
5305 v1 = vtop - 1;
5306 v2 = vtop;
5307 /* currently, we cannot do computations with forward symbols */
5308 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5309 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5310 if (c1 && c2) {
5311 fc = v2->c.i;
5312 switch(op) {
5313 case '+': v1->c.i += fc; break;
5314 case '-': v1->c.i -= fc; break;
5315 case '&': v1->c.i &= fc; break;
5316 case '^': v1->c.i ^= fc; break;
5317 case '|': v1->c.i |= fc; break;
5318 case '*': v1->c.i *= fc; break;
5320 case TOK_PDIV:
5321 case '/':
5322 case '%':
5323 case TOK_UDIV:
5324 case TOK_UMOD:
5325 /* if division by zero, generate explicit division */
5326 if (fc == 0) {
5327 if (const_wanted)
5328 error("division by zero in constant");
5329 goto general_case;
5331 switch(op) {
5332 default: v1->c.i /= fc; break;
5333 case '%': v1->c.i %= fc; break;
5334 case TOK_UDIV: v1->c.i = (unsigned)v1->c.i / fc; break;
5335 case TOK_UMOD: v1->c.i = (unsigned)v1->c.i % fc; break;
5337 break;
5338 case TOK_SHL: v1->c.i <<= fc; break;
5339 case TOK_SHR: v1->c.i = (unsigned)v1->c.i >> fc; break;
5340 case TOK_SAR: v1->c.i >>= fc; break;
5341 /* tests */
5342 case TOK_ULT: v1->c.i = (unsigned)v1->c.i < (unsigned)fc; break;
5343 case TOK_UGE: v1->c.i = (unsigned)v1->c.i >= (unsigned)fc; break;
5344 case TOK_EQ: v1->c.i = v1->c.i == fc; break;
5345 case TOK_NE: v1->c.i = v1->c.i != fc; break;
5346 case TOK_ULE: v1->c.i = (unsigned)v1->c.i <= (unsigned)fc; break;
5347 case TOK_UGT: v1->c.i = (unsigned)v1->c.i > (unsigned)fc; break;
5348 case TOK_LT: v1->c.i = v1->c.i < fc; break;
5349 case TOK_GE: v1->c.i = v1->c.i >= fc; break;
5350 case TOK_LE: v1->c.i = v1->c.i <= fc; break;
5351 case TOK_GT: v1->c.i = v1->c.i > fc; break;
5352 /* logical */
5353 case TOK_LAND: v1->c.i = v1->c.i && fc; break;
5354 case TOK_LOR: v1->c.i = v1->c.i || fc; break;
5355 default:
5356 goto general_case;
5358 vtop--;
5359 } else {
5360 /* if commutative ops, put c2 as constant */
5361 if (c1 && (op == '+' || op == '&' || op == '^' ||
5362 op == '|' || op == '*')) {
5363 vswap();
5364 swap(&c1, &c2);
5366 fc = vtop->c.i;
5367 if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
5368 op == TOK_PDIV) &&
5369 fc == 1) ||
5370 ((op == '+' || op == '-' || op == '|' || op == '^' ||
5371 op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
5372 fc == 0) ||
5373 (op == '&' &&
5374 fc == -1))) {
5375 /* nothing to do */
5376 vtop--;
5377 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
5378 /* try to use shifts instead of muls or divs */
5379 if (fc > 0 && (fc & (fc - 1)) == 0) {
5380 n = -1;
5381 while (fc) {
5382 fc >>= 1;
5383 n++;
5385 vtop->c.i = n;
5386 if (op == '*')
5387 op = TOK_SHL;
5388 else if (op == TOK_PDIV)
5389 op = TOK_SAR;
5390 else
5391 op = TOK_SHR;
5393 goto general_case;
5394 } else if (c2 && (op == '+' || op == '-') &&
5395 (vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) ==
5396 (VT_CONST | VT_SYM)) {
5397 /* symbol + constant case */
5398 if (op == '-')
5399 fc = -fc;
5400 vtop--;
5401 vtop->c.i += fc;
5402 } else {
5403 general_case:
5404 if (!nocode_wanted) {
5405 /* call low level op generator */
5406 gen_opi(op);
5407 } else {
5408 vtop--;
5414 /* generate a floating point operation with constant propagation */
5415 void gen_opif(int op)
5417 int c1, c2;
5418 SValue *v1, *v2;
5419 long double f1, f2;
5421 v1 = vtop - 1;
5422 v2 = vtop;
5423 /* currently, we cannot do computations with forward symbols */
5424 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5425 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5426 if (c1 && c2) {
5427 if (v1->type.t == VT_FLOAT) {
5428 f1 = v1->c.f;
5429 f2 = v2->c.f;
5430 } else if (v1->type.t == VT_DOUBLE) {
5431 f1 = v1->c.d;
5432 f2 = v2->c.d;
5433 } else {
5434 f1 = v1->c.ld;
5435 f2 = v2->c.ld;
5438 /* NOTE: we only do constant propagation if finite number (not
5439 NaN or infinity) (ANSI spec) */
5440 if (!ieee_finite(f1) || !ieee_finite(f2))
5441 goto general_case;
5443 switch(op) {
5444 case '+': f1 += f2; break;
5445 case '-': f1 -= f2; break;
5446 case '*': f1 *= f2; break;
5447 case '/':
5448 if (f2 == 0.0) {
5449 if (const_wanted)
5450 error("division by zero in constant");
5451 goto general_case;
5453 f1 /= f2;
5454 break;
5455 /* XXX: also handles tests ? */
5456 default:
5457 goto general_case;
5459 /* XXX: overflow test ? */
5460 if (v1->type.t == VT_FLOAT) {
5461 v1->c.f = f1;
5462 } else if (v1->type.t == VT_DOUBLE) {
5463 v1->c.d = f1;
5464 } else {
5465 v1->c.ld = f1;
5467 vtop--;
5468 } else {
5469 general_case:
5470 if (!nocode_wanted) {
5471 gen_opf(op);
5472 } else {
5473 vtop--;
5478 static int pointed_size(CType *type)
5480 int align;
5481 return type_size(pointed_type(type), &align);
5484 static inline int is_null_pointer(SValue *p)
5486 if ((p->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
5487 return 0;
5488 return ((p->type.t & VT_BTYPE) == VT_INT && p->c.i == 0) ||
5489 ((p->type.t & VT_BTYPE) == VT_LLONG && p->c.ll == 0);
5492 static inline int is_integer_btype(int bt)
5494 return (bt == VT_BYTE || bt == VT_SHORT ||
5495 bt == VT_INT || bt == VT_LLONG);
5498 /* check types for comparison or substraction of pointers */
5499 static void check_comparison_pointer_types(SValue *p1, SValue *p2, int op)
5501 CType *type1, *type2, tmp_type1, tmp_type2;
5502 int bt1, bt2;
5504 /* null pointers are accepted for all comparisons as gcc */
5505 if (is_null_pointer(p1) || is_null_pointer(p2))
5506 return;
5507 type1 = &p1->type;
5508 type2 = &p2->type;
5509 bt1 = type1->t & VT_BTYPE;
5510 bt2 = type2->t & VT_BTYPE;
5511 /* accept comparison between pointer and integer with a warning */
5512 if ((is_integer_btype(bt1) || is_integer_btype(bt2)) && op != '-') {
5513 warning("comparison between pointer and integer");
5514 return;
5517 /* both must be pointers or implicit function pointers */
5518 if (bt1 == VT_PTR) {
5519 type1 = pointed_type(type1);
5520 } else if (bt1 != VT_FUNC)
5521 goto invalid_operands;
5523 if (bt2 == VT_PTR) {
5524 type2 = pointed_type(type2);
5525 } else if (bt2 != VT_FUNC) {
5526 invalid_operands:
5527 error("invalid operands to binary %s", get_tok_str(op, NULL));
5529 if ((type1->t & VT_BTYPE) == VT_VOID ||
5530 (type2->t & VT_BTYPE) == VT_VOID)
5531 return;
5532 tmp_type1 = *type1;
5533 tmp_type2 = *type2;
5534 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5535 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5536 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
5537 /* gcc-like error if '-' is used */
5538 if (op == '-')
5539 goto invalid_operands;
5540 else
5541 warning("comparison of distinct pointer types lacks a cast");
5545 /* generic gen_op: handles types problems */
5546 void gen_op(int op)
5548 int u, t1, t2, bt1, bt2, t;
5549 CType type1;
5551 t1 = vtop[-1].type.t;
5552 t2 = vtop[0].type.t;
5553 bt1 = t1 & VT_BTYPE;
5554 bt2 = t2 & VT_BTYPE;
5556 if (bt1 == VT_PTR || bt2 == VT_PTR) {
5557 /* at least one operand is a pointer */
5558 /* relationnal op: must be both pointers */
5559 if (op >= TOK_ULT && op <= TOK_GT) {
5560 check_comparison_pointer_types(vtop - 1, vtop, op);
5561 /* pointers are handled are unsigned */
5562 t = VT_INT | VT_UNSIGNED;
5563 goto std_op;
5565 /* if both pointers, then it must be the '-' op */
5566 if (bt1 == VT_PTR && bt2 == VT_PTR) {
5567 if (op != '-')
5568 error("cannot use pointers here");
5569 check_comparison_pointer_types(vtop - 1, vtop, op);
5570 /* XXX: check that types are compatible */
5571 u = pointed_size(&vtop[-1].type);
5572 gen_opic(op);
5573 /* set to integer type */
5574 vtop->type.t = VT_INT;
5575 vpushi(u);
5576 gen_op(TOK_PDIV);
5577 } else {
5578 /* exactly one pointer : must be '+' or '-'. */
5579 if (op != '-' && op != '+')
5580 error("cannot use pointers here");
5581 /* Put pointer as first operand */
5582 if (bt2 == VT_PTR) {
5583 vswap();
5584 swap(&t1, &t2);
5586 type1 = vtop[-1].type;
5587 /* XXX: cast to int ? (long long case) */
5588 vpushi(pointed_size(&vtop[-1].type));
5589 gen_op('*');
5590 #ifdef CONFIG_TCC_BCHECK
5591 /* if evaluating constant expression, no code should be
5592 generated, so no bound check */
5593 if (do_bounds_check && !const_wanted) {
5594 /* if bounded pointers, we generate a special code to
5595 test bounds */
5596 if (op == '-') {
5597 vpushi(0);
5598 vswap();
5599 gen_op('-');
5601 gen_bounded_ptr_add();
5602 } else
5603 #endif
5605 gen_opic(op);
5607 /* put again type if gen_opic() swaped operands */
5608 vtop->type = type1;
5610 } else if (is_float(bt1) || is_float(bt2)) {
5611 /* compute bigger type and do implicit casts */
5612 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
5613 t = VT_LDOUBLE;
5614 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
5615 t = VT_DOUBLE;
5616 } else {
5617 t = VT_FLOAT;
5619 /* floats can only be used for a few operations */
5620 if (op != '+' && op != '-' && op != '*' && op != '/' &&
5621 (op < TOK_ULT || op > TOK_GT))
5622 error("invalid operands for binary operation");
5623 goto std_op;
5624 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
5625 /* cast to biggest op */
5626 t = VT_LLONG;
5627 /* convert to unsigned if it does not fit in a long long */
5628 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
5629 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
5630 t |= VT_UNSIGNED;
5631 goto std_op;
5632 } else {
5633 /* integer operations */
5634 t = VT_INT;
5635 /* convert to unsigned if it does not fit in an integer */
5636 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
5637 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
5638 t |= VT_UNSIGNED;
5639 std_op:
5640 /* XXX: currently, some unsigned operations are explicit, so
5641 we modify them here */
5642 if (t & VT_UNSIGNED) {
5643 if (op == TOK_SAR)
5644 op = TOK_SHR;
5645 else if (op == '/')
5646 op = TOK_UDIV;
5647 else if (op == '%')
5648 op = TOK_UMOD;
5649 else if (op == TOK_LT)
5650 op = TOK_ULT;
5651 else if (op == TOK_GT)
5652 op = TOK_UGT;
5653 else if (op == TOK_LE)
5654 op = TOK_ULE;
5655 else if (op == TOK_GE)
5656 op = TOK_UGE;
5658 vswap();
5659 type1.t = t;
5660 gen_cast(&type1);
5661 vswap();
5662 /* special case for shifts and long long: we keep the shift as
5663 an integer */
5664 if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL)
5665 type1.t = VT_INT;
5666 gen_cast(&type1);
5667 if (is_float(t))
5668 gen_opif(op);
5669 else if ((t & VT_BTYPE) == VT_LLONG)
5670 gen_opl(op);
5671 else
5672 gen_opic(op);
5673 if (op >= TOK_ULT && op <= TOK_GT) {
5674 /* relationnal op: the result is an int */
5675 vtop->type.t = VT_INT;
5676 } else {
5677 vtop->type.t = t;
5682 /* generic itof for unsigned long long case */
5683 void gen_cvt_itof1(int t)
5685 if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
5686 (VT_LLONG | VT_UNSIGNED)) {
5688 if (t == VT_FLOAT)
5689 vpush_global_sym(&func_old_type, TOK___ulltof);
5690 else if (t == VT_DOUBLE)
5691 vpush_global_sym(&func_old_type, TOK___ulltod);
5692 else
5693 vpush_global_sym(&func_old_type, TOK___ulltold);
5694 vrott(2);
5695 gfunc_call(1);
5696 vpushi(0);
5697 vtop->r = REG_FRET;
5698 } else {
5699 gen_cvt_itof(t);
5703 /* generic ftoi for unsigned long long case */
5704 void gen_cvt_ftoi1(int t)
5706 int st;
5708 if (t == (VT_LLONG | VT_UNSIGNED)) {
5709 /* not handled natively */
5710 st = vtop->type.t & VT_BTYPE;
5711 if (st == VT_FLOAT)
5712 vpush_global_sym(&func_old_type, TOK___fixunssfdi);
5713 else if (st == VT_DOUBLE)
5714 vpush_global_sym(&func_old_type, TOK___fixunsdfdi);
5715 else
5716 vpush_global_sym(&func_old_type, TOK___fixunsxfdi);
5717 vrott(2);
5718 gfunc_call(1);
5719 vpushi(0);
5720 vtop->r = REG_IRET;
5721 vtop->r2 = REG_LRET;
5722 } else {
5723 gen_cvt_ftoi(t);
5727 /* force char or short cast */
5728 void force_charshort_cast(int t)
5730 int bits, dbt;
5731 dbt = t & VT_BTYPE;
5732 /* XXX: add optimization if lvalue : just change type and offset */
5733 if (dbt == VT_BYTE)
5734 bits = 8;
5735 else
5736 bits = 16;
5737 if (t & VT_UNSIGNED) {
5738 vpushi((1 << bits) - 1);
5739 gen_op('&');
5740 } else {
5741 bits = 32 - bits;
5742 vpushi(bits);
5743 gen_op(TOK_SHL);
5744 vpushi(bits);
5745 gen_op(TOK_SAR);
5749 /* cast 'vtop' to 'type'. Casting to bitfields is forbidden. */
5750 static void gen_cast(CType *type)
5752 int sbt, dbt, sf, df, c;
5754 /* special delayed cast for char/short */
5755 /* XXX: in some cases (multiple cascaded casts), it may still
5756 be incorrect */
5757 if (vtop->r & VT_MUSTCAST) {
5758 vtop->r &= ~VT_MUSTCAST;
5759 force_charshort_cast(vtop->type.t);
5762 /* bitfields first get cast to ints */
5763 if (vtop->type.t & VT_BITFIELD) {
5764 gv(RC_INT);
5767 dbt = type->t & (VT_BTYPE | VT_UNSIGNED);
5768 sbt = vtop->type.t & (VT_BTYPE | VT_UNSIGNED);
5770 if (sbt != dbt && !nocode_wanted) {
5771 sf = is_float(sbt);
5772 df = is_float(dbt);
5773 c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5774 if (sf && df) {
5775 /* convert from fp to fp */
5776 if (c) {
5777 /* constant case: we can do it now */
5778 /* XXX: in ISOC, cannot do it if error in convert */
5779 if (dbt == VT_FLOAT && sbt == VT_DOUBLE)
5780 vtop->c.f = (float)vtop->c.d;
5781 else if (dbt == VT_FLOAT && sbt == VT_LDOUBLE)
5782 vtop->c.f = (float)vtop->c.ld;
5783 else if (dbt == VT_DOUBLE && sbt == VT_FLOAT)
5784 vtop->c.d = (double)vtop->c.f;
5785 else if (dbt == VT_DOUBLE && sbt == VT_LDOUBLE)
5786 vtop->c.d = (double)vtop->c.ld;
5787 else if (dbt == VT_LDOUBLE && sbt == VT_FLOAT)
5788 vtop->c.ld = (long double)vtop->c.f;
5789 else if (dbt == VT_LDOUBLE && sbt == VT_DOUBLE)
5790 vtop->c.ld = (long double)vtop->c.d;
5791 } else {
5792 /* non constant case: generate code */
5793 gen_cvt_ftof(dbt);
5795 } else if (df) {
5796 /* convert int to fp */
5797 if (c) {
5798 switch(sbt) {
5799 case VT_LLONG | VT_UNSIGNED:
5800 case VT_LLONG:
5801 /* XXX: add const cases for long long */
5802 goto do_itof;
5803 case VT_INT | VT_UNSIGNED:
5804 switch(dbt) {
5805 case VT_FLOAT: vtop->c.f = (float)vtop->c.ui; break;
5806 case VT_DOUBLE: vtop->c.d = (double)vtop->c.ui; break;
5807 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.ui; break;
5809 break;
5810 default:
5811 switch(dbt) {
5812 case VT_FLOAT: vtop->c.f = (float)vtop->c.i; break;
5813 case VT_DOUBLE: vtop->c.d = (double)vtop->c.i; break;
5814 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.i; break;
5816 break;
5818 } else {
5819 do_itof:
5820 #if !defined(TCC_TARGET_ARM)
5821 gen_cvt_itof1(dbt);
5822 #else
5823 gen_cvt_itof(dbt);
5824 #endif
5826 } else if (sf) {
5827 /* convert fp to int */
5828 /* we handle char/short/etc... with generic code */
5829 if (dbt != (VT_INT | VT_UNSIGNED) &&
5830 dbt != (VT_LLONG | VT_UNSIGNED) &&
5831 dbt != VT_LLONG)
5832 dbt = VT_INT;
5833 if (c) {
5834 switch(dbt) {
5835 case VT_LLONG | VT_UNSIGNED:
5836 case VT_LLONG:
5837 /* XXX: add const cases for long long */
5838 goto do_ftoi;
5839 case VT_INT | VT_UNSIGNED:
5840 switch(sbt) {
5841 case VT_FLOAT: vtop->c.ui = (unsigned int)vtop->c.d; break;
5842 case VT_DOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
5843 case VT_LDOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
5845 break;
5846 default:
5847 /* int case */
5848 switch(sbt) {
5849 case VT_FLOAT: vtop->c.i = (int)vtop->c.d; break;
5850 case VT_DOUBLE: vtop->c.i = (int)vtop->c.d; break;
5851 case VT_LDOUBLE: vtop->c.i = (int)vtop->c.d; break;
5853 break;
5855 } else {
5856 do_ftoi:
5857 gen_cvt_ftoi1(dbt);
5859 if (dbt == VT_INT && (type->t & (VT_BTYPE | VT_UNSIGNED)) != dbt) {
5860 /* additional cast for char/short/bool... */
5861 vtop->type.t = dbt;
5862 gen_cast(type);
5864 } else if ((dbt & VT_BTYPE) == VT_LLONG) {
5865 if ((sbt & VT_BTYPE) != VT_LLONG) {
5866 /* scalar to long long */
5867 if (c) {
5868 if (sbt == (VT_INT | VT_UNSIGNED))
5869 vtop->c.ll = vtop->c.ui;
5870 else
5871 vtop->c.ll = vtop->c.i;
5872 } else {
5873 /* machine independent conversion */
5874 gv(RC_INT);
5875 /* generate high word */
5876 if (sbt == (VT_INT | VT_UNSIGNED)) {
5877 vpushi(0);
5878 gv(RC_INT);
5879 } else {
5880 gv_dup();
5881 vpushi(31);
5882 gen_op(TOK_SAR);
5884 /* patch second register */
5885 vtop[-1].r2 = vtop->r;
5886 vpop();
5889 } else if (dbt == VT_BOOL) {
5890 /* scalar to bool */
5891 vpushi(0);
5892 gen_op(TOK_NE);
5893 } else if ((dbt & VT_BTYPE) == VT_BYTE ||
5894 (dbt & VT_BTYPE) == VT_SHORT) {
5895 force_charshort_cast(dbt);
5896 } else if ((dbt & VT_BTYPE) == VT_INT) {
5897 /* scalar to int */
5898 if (sbt == VT_LLONG) {
5899 /* from long long: just take low order word */
5900 lexpand();
5901 vpop();
5903 /* if lvalue and single word type, nothing to do because
5904 the lvalue already contains the real type size (see
5905 VT_LVAL_xxx constants) */
5908 vtop->type = *type;
5911 /* return type size. Put alignment at 'a' */
5912 static int type_size(CType *type, int *a)
5914 Sym *s;
5915 int bt;
5917 bt = type->t & VT_BTYPE;
5918 if (bt == VT_STRUCT) {
5919 /* struct/union */
5920 s = type->ref;
5921 *a = s->r;
5922 return s->c;
5923 } else if (bt == VT_PTR) {
5924 if (type->t & VT_ARRAY) {
5925 s = type->ref;
5926 return type_size(&s->type, a) * s->c;
5927 } else {
5928 *a = PTR_SIZE;
5929 return PTR_SIZE;
5931 } else if (bt == VT_LDOUBLE) {
5932 *a = LDOUBLE_ALIGN;
5933 return LDOUBLE_SIZE;
5934 } else if (bt == VT_DOUBLE || bt == VT_LLONG) {
5935 #ifdef TCC_TARGET_I386
5936 *a = 4;
5937 #else
5938 *a = 8;
5939 #endif
5940 return 8;
5941 } else if (bt == VT_INT || bt == VT_ENUM || bt == VT_FLOAT) {
5942 *a = 4;
5943 return 4;
5944 } else if (bt == VT_SHORT) {
5945 *a = 2;
5946 return 2;
5947 } else {
5948 /* char, void, function, _Bool */
5949 *a = 1;
5950 return 1;
5954 /* return the pointed type of t */
5955 static inline CType *pointed_type(CType *type)
5957 return &type->ref->type;
5960 /* modify type so that its it is a pointer to type. */
5961 static void mk_pointer(CType *type)
5963 Sym *s;
5964 s = sym_push(SYM_FIELD, type, 0, -1);
5965 type->t = VT_PTR | (type->t & ~VT_TYPE);
5966 type->ref = s;
5969 /* compare function types. OLD functions match any new functions */
5970 static int is_compatible_func(CType *type1, CType *type2)
5972 Sym *s1, *s2;
5974 s1 = type1->ref;
5975 s2 = type2->ref;
5976 if (!is_compatible_types(&s1->type, &s2->type))
5977 return 0;
5978 /* check func_call */
5979 if (s1->r != s2->r)
5980 return 0;
5981 /* XXX: not complete */
5982 if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
5983 return 1;
5984 if (s1->c != s2->c)
5985 return 0;
5986 while (s1 != NULL) {
5987 if (s2 == NULL)
5988 return 0;
5989 if (!is_compatible_types(&s1->type, &s2->type))
5990 return 0;
5991 s1 = s1->next;
5992 s2 = s2->next;
5994 if (s2)
5995 return 0;
5996 return 1;
5999 /* return true if type1 and type2 are exactly the same (including
6000 qualifiers).
6002 - enums are not checked as gcc __builtin_types_compatible_p ()
6004 static int is_compatible_types(CType *type1, CType *type2)
6006 int bt1, t1, t2;
6008 t1 = type1->t & VT_TYPE;
6009 t2 = type2->t & VT_TYPE;
6010 /* XXX: bitfields ? */
6011 if (t1 != t2)
6012 return 0;
6013 /* test more complicated cases */
6014 bt1 = t1 & VT_BTYPE;
6015 if (bt1 == VT_PTR) {
6016 type1 = pointed_type(type1);
6017 type2 = pointed_type(type2);
6018 return is_compatible_types(type1, type2);
6019 } else if (bt1 == VT_STRUCT) {
6020 return (type1->ref == type2->ref);
6021 } else if (bt1 == VT_FUNC) {
6022 return is_compatible_func(type1, type2);
6023 } else {
6024 return 1;
6028 /* print a type. If 'varstr' is not NULL, then the variable is also
6029 printed in the type */
6030 /* XXX: union */
6031 /* XXX: add array and function pointers */
6032 void type_to_str(char *buf, int buf_size,
6033 CType *type, const char *varstr)
6035 int bt, v, t;
6036 Sym *s, *sa;
6037 char buf1[256];
6038 const char *tstr;
6040 t = type->t & VT_TYPE;
6041 bt = t & VT_BTYPE;
6042 buf[0] = '\0';
6043 if (t & VT_CONSTANT)
6044 pstrcat(buf, buf_size, "const ");
6045 if (t & VT_VOLATILE)
6046 pstrcat(buf, buf_size, "volatile ");
6047 if (t & VT_UNSIGNED)
6048 pstrcat(buf, buf_size, "unsigned ");
6049 switch(bt) {
6050 case VT_VOID:
6051 tstr = "void";
6052 goto add_tstr;
6053 case VT_BOOL:
6054 tstr = "_Bool";
6055 goto add_tstr;
6056 case VT_BYTE:
6057 tstr = "char";
6058 goto add_tstr;
6059 case VT_SHORT:
6060 tstr = "short";
6061 goto add_tstr;
6062 case VT_INT:
6063 tstr = "int";
6064 goto add_tstr;
6065 case VT_LONG:
6066 tstr = "long";
6067 goto add_tstr;
6068 case VT_LLONG:
6069 tstr = "long long";
6070 goto add_tstr;
6071 case VT_FLOAT:
6072 tstr = "float";
6073 goto add_tstr;
6074 case VT_DOUBLE:
6075 tstr = "double";
6076 goto add_tstr;
6077 case VT_LDOUBLE:
6078 tstr = "long double";
6079 add_tstr:
6080 pstrcat(buf, buf_size, tstr);
6081 break;
6082 case VT_ENUM:
6083 case VT_STRUCT:
6084 if (bt == VT_STRUCT)
6085 tstr = "struct ";
6086 else
6087 tstr = "enum ";
6088 pstrcat(buf, buf_size, tstr);
6089 v = type->ref->v & ~SYM_STRUCT;
6090 if (v >= SYM_FIRST_ANOM)
6091 pstrcat(buf, buf_size, "<anonymous>");
6092 else
6093 pstrcat(buf, buf_size, get_tok_str(v, NULL));
6094 break;
6095 case VT_FUNC:
6096 s = type->ref;
6097 type_to_str(buf, buf_size, &s->type, varstr);
6098 pstrcat(buf, buf_size, "(");
6099 sa = s->next;
6100 while (sa != NULL) {
6101 type_to_str(buf1, sizeof(buf1), &sa->type, NULL);
6102 pstrcat(buf, buf_size, buf1);
6103 sa = sa->next;
6104 if (sa)
6105 pstrcat(buf, buf_size, ", ");
6107 pstrcat(buf, buf_size, ")");
6108 goto no_var;
6109 case VT_PTR:
6110 s = type->ref;
6111 pstrcpy(buf1, sizeof(buf1), "*");
6112 if (varstr)
6113 pstrcat(buf1, sizeof(buf1), varstr);
6114 type_to_str(buf, buf_size, &s->type, buf1);
6115 goto no_var;
6117 if (varstr) {
6118 pstrcat(buf, buf_size, " ");
6119 pstrcat(buf, buf_size, varstr);
6121 no_var: ;
6124 /* verify type compatibility to store vtop in 'dt' type, and generate
6125 casts if needed. */
6126 static void gen_assign_cast(CType *dt)
6128 CType *st, *type1, *type2, tmp_type1, tmp_type2;
6129 char buf1[256], buf2[256];
6130 int dbt, sbt;
6132 st = &vtop->type; /* source type */
6133 dbt = dt->t & VT_BTYPE;
6134 sbt = st->t & VT_BTYPE;
6135 if (dt->t & VT_CONSTANT)
6136 warning("assignment of read-only location");
6137 switch(dbt) {
6138 case VT_PTR:
6139 /* special cases for pointers */
6140 /* '0' can also be a pointer */
6141 if (is_null_pointer(vtop))
6142 goto type_ok;
6143 /* accept implicit pointer to integer cast with warning */
6144 if (is_integer_btype(sbt)) {
6145 warning("assignment makes pointer from integer without a cast");
6146 goto type_ok;
6148 type1 = pointed_type(dt);
6149 /* a function is implicitely a function pointer */
6150 if (sbt == VT_FUNC) {
6151 if ((type1->t & VT_BTYPE) != VT_VOID &&
6152 !is_compatible_types(pointed_type(dt), st))
6153 goto error;
6154 else
6155 goto type_ok;
6157 if (sbt != VT_PTR)
6158 goto error;
6159 type2 = pointed_type(st);
6160 if ((type1->t & VT_BTYPE) == VT_VOID ||
6161 (type2->t & VT_BTYPE) == VT_VOID) {
6162 /* void * can match anything */
6163 } else {
6164 /* exact type match, except for unsigned */
6165 tmp_type1 = *type1;
6166 tmp_type2 = *type2;
6167 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
6168 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
6169 if (!is_compatible_types(&tmp_type1, &tmp_type2))
6170 goto error;
6172 /* check const and volatile */
6173 if ((!(type1->t & VT_CONSTANT) && (type2->t & VT_CONSTANT)) ||
6174 (!(type1->t & VT_VOLATILE) && (type2->t & VT_VOLATILE)))
6175 warning("assignment discards qualifiers from pointer target type");
6176 break;
6177 case VT_BYTE:
6178 case VT_SHORT:
6179 case VT_INT:
6180 case VT_LLONG:
6181 if (sbt == VT_PTR || sbt == VT_FUNC) {
6182 warning("assignment makes integer from pointer without a cast");
6184 /* XXX: more tests */
6185 break;
6186 case VT_STRUCT:
6187 tmp_type1 = *dt;
6188 tmp_type2 = *st;
6189 tmp_type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
6190 tmp_type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
6191 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
6192 error:
6193 type_to_str(buf1, sizeof(buf1), st, NULL);
6194 type_to_str(buf2, sizeof(buf2), dt, NULL);
6195 error("cannot cast '%s' to '%s'", buf1, buf2);
6197 break;
6199 type_ok:
6200 gen_cast(dt);
6203 /* store vtop in lvalue pushed on stack */
6204 void vstore(void)
6206 int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
6208 ft = vtop[-1].type.t;
6209 sbt = vtop->type.t & VT_BTYPE;
6210 dbt = ft & VT_BTYPE;
6211 if (((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
6212 (sbt == VT_INT && dbt == VT_SHORT)) {
6213 /* optimize char/short casts */
6214 delayed_cast = VT_MUSTCAST;
6215 vtop->type.t = ft & VT_TYPE;
6216 /* XXX: factorize */
6217 if (ft & VT_CONSTANT)
6218 warning("assignment of read-only location");
6219 } else {
6220 delayed_cast = 0;
6221 if (!(ft & VT_BITFIELD))
6222 gen_assign_cast(&vtop[-1].type);
6225 if (sbt == VT_STRUCT) {
6226 /* if structure, only generate pointer */
6227 /* structure assignment : generate memcpy */
6228 /* XXX: optimize if small size */
6229 if (!nocode_wanted) {
6230 size = type_size(&vtop->type, &align);
6232 vpush_global_sym(&func_old_type, TOK_memcpy);
6234 /* destination */
6235 vpushv(vtop - 2);
6236 vtop->type.t = VT_INT;
6237 gaddrof();
6238 /* source */
6239 vpushv(vtop - 2);
6240 vtop->type.t = VT_INT;
6241 gaddrof();
6242 /* type size */
6243 vpushi(size);
6244 gfunc_call(3);
6246 vswap();
6247 vpop();
6248 } else {
6249 vswap();
6250 vpop();
6252 /* leave source on stack */
6253 } else if (ft & VT_BITFIELD) {
6254 /* bitfield store handling */
6255 bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
6256 bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
6257 /* remove bit field info to avoid loops */
6258 vtop[-1].type.t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
6260 /* duplicate destination */
6261 vdup();
6262 vtop[-1] = vtop[-2];
6264 /* mask and shift source */
6265 vpushi((1 << bit_size) - 1);
6266 gen_op('&');
6267 vpushi(bit_pos);
6268 gen_op(TOK_SHL);
6269 /* load destination, mask and or with source */
6270 vswap();
6271 vpushi(~(((1 << bit_size) - 1) << bit_pos));
6272 gen_op('&');
6273 gen_op('|');
6274 /* store result */
6275 vstore();
6276 } else {
6277 #ifdef CONFIG_TCC_BCHECK
6278 /* bound check case */
6279 if (vtop[-1].r & VT_MUSTBOUND) {
6280 vswap();
6281 gbound();
6282 vswap();
6284 #endif
6285 if (!nocode_wanted) {
6286 rc = RC_INT;
6287 if (is_float(ft))
6288 rc = RC_FLOAT;
6289 r = gv(rc); /* generate value */
6290 /* if lvalue was saved on stack, must read it */
6291 if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
6292 SValue sv;
6293 t = get_reg(RC_INT);
6294 sv.type.t = VT_INT;
6295 sv.r = VT_LOCAL | VT_LVAL;
6296 sv.c.ul = vtop[-1].c.ul;
6297 load(t, &sv);
6298 vtop[-1].r = t | VT_LVAL;
6300 store(r, vtop - 1);
6301 /* two word case handling : store second register at word + 4 */
6302 if ((ft & VT_BTYPE) == VT_LLONG) {
6303 vswap();
6304 /* convert to int to increment easily */
6305 vtop->type.t = VT_INT;
6306 gaddrof();
6307 vpushi(4);
6308 gen_op('+');
6309 vtop->r |= VT_LVAL;
6310 vswap();
6311 /* XXX: it works because r2 is spilled last ! */
6312 store(vtop->r2, vtop - 1);
6315 vswap();
6316 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
6317 vtop->r |= delayed_cast;
6321 /* post defines POST/PRE add. c is the token ++ or -- */
6322 void inc(int post, int c)
6324 test_lvalue();
6325 vdup(); /* save lvalue */
6326 if (post) {
6327 gv_dup(); /* duplicate value */
6328 vrotb(3);
6329 vrotb(3);
6331 /* add constant */
6332 vpushi(c - TOK_MID);
6333 gen_op('+');
6334 vstore(); /* store value */
6335 if (post)
6336 vpop(); /* if post op, return saved value */
6339 /* Parse GNUC __attribute__ extension. Currently, the following
6340 extensions are recognized:
6341 - aligned(n) : set data/function alignment.
6342 - packed : force data alignment to 1
6343 - section(x) : generate data/code in this section.
6344 - unused : currently ignored, but may be used someday.
6345 - regparm(n) : pass function parameters in registers (i386 only)
6347 static void parse_attribute(AttributeDef *ad)
6349 int t, n;
6351 while (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) {
6352 next();
6353 skip('(');
6354 skip('(');
6355 while (tok != ')') {
6356 if (tok < TOK_IDENT)
6357 expect("attribute name");
6358 t = tok;
6359 next();
6360 switch(t) {
6361 case TOK_SECTION1:
6362 case TOK_SECTION2:
6363 skip('(');
6364 if (tok != TOK_STR)
6365 expect("section name");
6366 ad->section = find_section(tcc_state, (char *)tokc.cstr->data);
6367 next();
6368 skip(')');
6369 break;
6370 case TOK_ALIGNED1:
6371 case TOK_ALIGNED2:
6372 if (tok == '(') {
6373 next();
6374 n = expr_const();
6375 if (n <= 0 || (n & (n - 1)) != 0)
6376 error("alignment must be a positive power of two");
6377 skip(')');
6378 } else {
6379 n = MAX_ALIGN;
6381 ad->aligned = n;
6382 break;
6383 case TOK_PACKED1:
6384 case TOK_PACKED2:
6385 ad->packed = 1;
6386 break;
6387 case TOK_UNUSED1:
6388 case TOK_UNUSED2:
6389 /* currently, no need to handle it because tcc does not
6390 track unused objects */
6391 break;
6392 case TOK_NORETURN1:
6393 case TOK_NORETURN2:
6394 /* currently, no need to handle it because tcc does not
6395 track unused objects */
6396 break;
6397 case TOK_CDECL1:
6398 case TOK_CDECL2:
6399 case TOK_CDECL3:
6400 ad->func_call = FUNC_CDECL;
6401 break;
6402 case TOK_STDCALL1:
6403 case TOK_STDCALL2:
6404 case TOK_STDCALL3:
6405 ad->func_call = FUNC_STDCALL;
6406 break;
6407 #ifdef TCC_TARGET_I386
6408 case TOK_REGPARM1:
6409 case TOK_REGPARM2:
6410 skip('(');
6411 n = expr_const();
6412 if (n > 3)
6413 n = 3;
6414 else if (n < 0)
6415 n = 0;
6416 if (n > 0)
6417 ad->func_call = FUNC_FASTCALL1 + n - 1;
6418 skip(')');
6419 break;
6420 #endif
6421 case TOK_DLLEXPORT:
6422 ad->dllexport = 1;
6423 break;
6424 default:
6425 if (tcc_state->warn_unsupported)
6426 warning("'%s' attribute ignored", get_tok_str(t, NULL));
6427 /* skip parameters */
6428 /* XXX: skip parenthesis too */
6429 if (tok == '(') {
6430 next();
6431 while (tok != ')' && tok != -1)
6432 next();
6433 next();
6435 break;
6437 if (tok != ',')
6438 break;
6439 next();
6441 skip(')');
6442 skip(')');
6446 /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
6447 static void struct_decl(CType *type, int u)
6449 int a, v, size, align, maxalign, c, offset;
6450 int bit_size, bit_pos, bsize, bt, lbit_pos;
6451 Sym *s, *ss, **ps;
6452 AttributeDef ad;
6453 CType type1, btype;
6455 a = tok; /* save decl type */
6456 next();
6457 if (tok != '{') {
6458 v = tok;
6459 next();
6460 /* struct already defined ? return it */
6461 if (v < TOK_IDENT)
6462 expect("struct/union/enum name");
6463 s = struct_find(v);
6464 if (s) {
6465 if (s->type.t != a)
6466 error("invalid type");
6467 goto do_decl;
6469 } else {
6470 v = anon_sym++;
6472 type1.t = a;
6473 /* we put an undefined size for struct/union */
6474 s = sym_push(v | SYM_STRUCT, &type1, 0, -1);
6475 s->r = 0; /* default alignment is zero as gcc */
6476 /* put struct/union/enum name in type */
6477 do_decl:
6478 type->t = u;
6479 type->ref = s;
6481 if (tok == '{') {
6482 next();
6483 if (s->c != -1)
6484 error("struct/union/enum already defined");
6485 /* cannot be empty */
6486 c = 0;
6487 /* non empty enums are not allowed */
6488 if (a == TOK_ENUM) {
6489 for(;;) {
6490 v = tok;
6491 if (v < TOK_UIDENT)
6492 expect("identifier");
6493 next();
6494 if (tok == '=') {
6495 next();
6496 c = expr_const();
6498 /* enum symbols have static storage */
6499 ss = sym_push(v, &int_type, VT_CONST, c);
6500 ss->type.t |= VT_STATIC;
6501 if (tok != ',')
6502 break;
6503 next();
6504 c++;
6505 /* NOTE: we accept a trailing comma */
6506 if (tok == '}')
6507 break;
6509 skip('}');
6510 } else {
6511 maxalign = 1;
6512 ps = &s->next;
6513 bit_pos = 0;
6514 offset = 0;
6515 while (tok != '}') {
6516 parse_btype(&btype, &ad);
6517 while (1) {
6518 bit_size = -1;
6519 v = 0;
6520 type1 = btype;
6521 if (tok != ':') {
6522 type_decl(&type1, &ad, &v, TYPE_DIRECT);
6523 if ((type1.t & VT_BTYPE) == VT_FUNC ||
6524 (type1.t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN | VT_INLINE)))
6525 error("invalid type for '%s'",
6526 get_tok_str(v, NULL));
6528 if (tok == ':') {
6529 next();
6530 bit_size = expr_const();
6531 /* XXX: handle v = 0 case for messages */
6532 if (bit_size < 0)
6533 error("negative width in bit-field '%s'",
6534 get_tok_str(v, NULL));
6535 if (v && bit_size == 0)
6536 error("zero width for bit-field '%s'",
6537 get_tok_str(v, NULL));
6539 size = type_size(&type1, &align);
6540 if (ad.aligned) {
6541 if (align < ad.aligned)
6542 align = ad.aligned;
6543 } else if (ad.packed) {
6544 align = 1;
6545 } else if (*tcc_state->pack_stack_ptr) {
6546 if (align > *tcc_state->pack_stack_ptr)
6547 align = *tcc_state->pack_stack_ptr;
6549 lbit_pos = 0;
6550 if (bit_size >= 0) {
6551 bt = type1.t & VT_BTYPE;
6552 if (bt != VT_INT &&
6553 bt != VT_BYTE &&
6554 bt != VT_SHORT &&
6555 bt != VT_BOOL &&
6556 bt != VT_ENUM)
6557 error("bitfields must have scalar type");
6558 bsize = size * 8;
6559 if (bit_size > bsize) {
6560 error("width of '%s' exceeds its type",
6561 get_tok_str(v, NULL));
6562 } else if (bit_size == bsize) {
6563 /* no need for bit fields */
6564 bit_pos = 0;
6565 } else if (bit_size == 0) {
6566 /* XXX: what to do if only padding in a
6567 structure ? */
6568 /* zero size: means to pad */
6569 if (bit_pos > 0)
6570 bit_pos = bsize;
6571 } else {
6572 /* we do not have enough room ? */
6573 if ((bit_pos + bit_size) > bsize)
6574 bit_pos = 0;
6575 lbit_pos = bit_pos;
6576 /* XXX: handle LSB first */
6577 type1.t |= VT_BITFIELD |
6578 (bit_pos << VT_STRUCT_SHIFT) |
6579 (bit_size << (VT_STRUCT_SHIFT + 6));
6580 bit_pos += bit_size;
6582 } else {
6583 bit_pos = 0;
6585 if (v) {
6586 /* add new memory data only if starting
6587 bit field */
6588 if (lbit_pos == 0) {
6589 if (a == TOK_STRUCT) {
6590 c = (c + align - 1) & -align;
6591 offset = c;
6592 c += size;
6593 } else {
6594 offset = 0;
6595 if (size > c)
6596 c = size;
6598 if (align > maxalign)
6599 maxalign = align;
6601 #if 0
6602 printf("add field %s offset=%d",
6603 get_tok_str(v, NULL), offset);
6604 if (type1.t & VT_BITFIELD) {
6605 printf(" pos=%d size=%d",
6606 (type1.t >> VT_STRUCT_SHIFT) & 0x3f,
6607 (type1.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
6609 printf("\n");
6610 #endif
6611 ss = sym_push(v | SYM_FIELD, &type1, 0, offset);
6612 *ps = ss;
6613 ps = &ss->next;
6615 if (tok == ';' || tok == TOK_EOF)
6616 break;
6617 skip(',');
6619 skip(';');
6621 skip('}');
6622 /* store size and alignment */
6623 s->c = (c + maxalign - 1) & -maxalign;
6624 s->r = maxalign;
6629 /* return 0 if no type declaration. otherwise, return the basic type
6630 and skip it.
6632 static int parse_btype(CType *type, AttributeDef *ad)
6634 int t, u, type_found, typespec_found;
6635 Sym *s;
6636 CType type1;
6638 memset(ad, 0, sizeof(AttributeDef));
6639 type_found = 0;
6640 typespec_found = 0;
6641 t = 0;
6642 while(1) {
6643 switch(tok) {
6644 case TOK_EXTENSION:
6645 /* currently, we really ignore extension */
6646 next();
6647 continue;
6649 /* basic types */
6650 case TOK_CHAR:
6651 u = VT_BYTE;
6652 basic_type:
6653 next();
6654 basic_type1:
6655 if ((t & VT_BTYPE) != 0)
6656 error("too many basic types");
6657 t |= u;
6658 typespec_found = 1;
6659 break;
6660 case TOK_VOID:
6661 u = VT_VOID;
6662 goto basic_type;
6663 case TOK_SHORT:
6664 u = VT_SHORT;
6665 goto basic_type;
6666 case TOK_INT:
6667 next();
6668 typespec_found = 1;
6669 break;
6670 case TOK_LONG:
6671 next();
6672 if ((t & VT_BTYPE) == VT_DOUBLE) {
6673 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6674 } else if ((t & VT_BTYPE) == VT_LONG) {
6675 t = (t & ~VT_BTYPE) | VT_LLONG;
6676 } else {
6677 u = VT_LONG;
6678 goto basic_type1;
6680 break;
6681 case TOK_BOOL:
6682 u = VT_BOOL;
6683 goto basic_type;
6684 case TOK_FLOAT:
6685 u = VT_FLOAT;
6686 goto basic_type;
6687 case TOK_DOUBLE:
6688 next();
6689 if ((t & VT_BTYPE) == VT_LONG) {
6690 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6691 } else {
6692 u = VT_DOUBLE;
6693 goto basic_type1;
6695 break;
6696 case TOK_ENUM:
6697 struct_decl(&type1, VT_ENUM);
6698 basic_type2:
6699 u = type1.t;
6700 type->ref = type1.ref;
6701 goto basic_type1;
6702 case TOK_STRUCT:
6703 case TOK_UNION:
6704 struct_decl(&type1, VT_STRUCT);
6705 goto basic_type2;
6707 /* type modifiers */
6708 case TOK_CONST1:
6709 case TOK_CONST2:
6710 case TOK_CONST3:
6711 t |= VT_CONSTANT;
6712 next();
6713 break;
6714 case TOK_VOLATILE1:
6715 case TOK_VOLATILE2:
6716 case TOK_VOLATILE3:
6717 t |= VT_VOLATILE;
6718 next();
6719 break;
6720 case TOK_SIGNED1:
6721 case TOK_SIGNED2:
6722 case TOK_SIGNED3:
6723 typespec_found = 1;
6724 t |= VT_SIGNED;
6725 next();
6726 break;
6727 case TOK_REGISTER:
6728 case TOK_AUTO:
6729 case TOK_RESTRICT1:
6730 case TOK_RESTRICT2:
6731 case TOK_RESTRICT3:
6732 next();
6733 break;
6734 case TOK_UNSIGNED:
6735 t |= VT_UNSIGNED;
6736 next();
6737 typespec_found = 1;
6738 break;
6740 /* storage */
6741 case TOK_EXTERN:
6742 t |= VT_EXTERN;
6743 next();
6744 break;
6745 case TOK_STATIC:
6746 t |= VT_STATIC;
6747 next();
6748 break;
6749 case TOK_TYPEDEF:
6750 t |= VT_TYPEDEF;
6751 next();
6752 break;
6753 case TOK_INLINE1:
6754 case TOK_INLINE2:
6755 case TOK_INLINE3:
6756 t |= VT_INLINE;
6757 next();
6758 break;
6760 /* GNUC attribute */
6761 case TOK_ATTRIBUTE1:
6762 case TOK_ATTRIBUTE2:
6763 parse_attribute(ad);
6764 break;
6765 /* GNUC typeof */
6766 case TOK_TYPEOF1:
6767 case TOK_TYPEOF2:
6768 case TOK_TYPEOF3:
6769 next();
6770 parse_expr_type(&type1);
6771 goto basic_type2;
6772 default:
6773 if (typespec_found)
6774 goto the_end;
6775 s = sym_find(tok);
6776 if (!s || !(s->type.t & VT_TYPEDEF))
6777 goto the_end;
6778 t |= (s->type.t & ~VT_TYPEDEF);
6779 type->ref = s->type.ref;
6780 next();
6781 break;
6783 type_found = 1;
6785 the_end:
6786 if ((t & (VT_SIGNED|VT_UNSIGNED)) == (VT_SIGNED|VT_UNSIGNED))
6787 error("signed and unsigned modifier");
6788 if (tcc_state->char_is_unsigned) {
6789 if ((t & (VT_SIGNED|VT_UNSIGNED|VT_BTYPE)) == VT_BYTE)
6790 t |= VT_UNSIGNED;
6792 t &= ~VT_SIGNED;
6794 /* long is never used as type */
6795 if ((t & VT_BTYPE) == VT_LONG)
6796 t = (t & ~VT_BTYPE) | VT_INT;
6797 type->t = t;
6798 return type_found;
6801 /* convert a function parameter type (array to pointer and function to
6802 function pointer) */
6803 static inline void convert_parameter_type(CType *pt)
6805 /* remove const and volatile qualifiers (XXX: const could be used
6806 to indicate a const function parameter */
6807 pt->t &= ~(VT_CONSTANT | VT_VOLATILE);
6808 /* array must be transformed to pointer according to ANSI C */
6809 pt->t &= ~VT_ARRAY;
6810 if ((pt->t & VT_BTYPE) == VT_FUNC) {
6811 mk_pointer(pt);
6815 static void post_type(CType *type, AttributeDef *ad)
6817 int n, l, t1;
6818 Sym **plast, *s, *first;
6819 AttributeDef ad1;
6820 CType pt;
6822 if (tok == '(') {
6823 /* function declaration */
6824 next();
6825 l = 0;
6826 first = NULL;
6827 plast = &first;
6828 while (tok != ')') {
6829 /* read param name and compute offset */
6830 if (l != FUNC_OLD) {
6831 if (!parse_btype(&pt, &ad1)) {
6832 if (l) {
6833 error("invalid type");
6834 } else {
6835 l = FUNC_OLD;
6836 goto old_proto;
6839 l = FUNC_NEW;
6840 if ((pt.t & VT_BTYPE) == VT_VOID && tok == ')')
6841 break;
6842 type_decl(&pt, &ad1, &n, TYPE_DIRECT | TYPE_ABSTRACT);
6843 if ((pt.t & VT_BTYPE) == VT_VOID)
6844 error("parameter declared as void");
6845 } else {
6846 old_proto:
6847 n = tok;
6848 pt.t = VT_INT;
6849 next();
6851 convert_parameter_type(&pt);
6852 s = sym_push(n | SYM_FIELD, &pt, 0, 0);
6853 *plast = s;
6854 plast = &s->next;
6855 if (tok == ',') {
6856 next();
6857 if (l == FUNC_NEW && tok == TOK_DOTS) {
6858 l = FUNC_ELLIPSIS;
6859 next();
6860 break;
6864 /* if no parameters, then old type prototype */
6865 if (l == 0)
6866 l = FUNC_OLD;
6867 skip(')');
6868 t1 = type->t & VT_STORAGE;
6869 /* NOTE: const is ignored in returned type as it has a special
6870 meaning in gcc / C++ */
6871 type->t &= ~(VT_STORAGE | VT_CONSTANT);
6872 post_type(type, ad);
6873 /* we push a anonymous symbol which will contain the function prototype */
6874 s = sym_push(SYM_FIELD, type, ad->func_call, l);
6875 s->next = first;
6876 type->t = t1 | VT_FUNC;
6877 type->ref = s;
6878 } else if (tok == '[') {
6879 /* array definition */
6880 next();
6881 n = -1;
6882 if (tok != ']') {
6883 n = expr_const();
6884 if (n < 0)
6885 error("invalid array size");
6887 skip(']');
6888 /* parse next post type */
6889 t1 = type->t & VT_STORAGE;
6890 type->t &= ~VT_STORAGE;
6891 post_type(type, ad);
6893 /* we push a anonymous symbol which will contain the array
6894 element type */
6895 s = sym_push(SYM_FIELD, type, 0, n);
6896 type->t = t1 | VT_ARRAY | VT_PTR;
6897 type->ref = s;
6901 /* Parse a type declaration (except basic type), and return the type
6902 in 'type'. 'td' is a bitmask indicating which kind of type decl is
6903 expected. 'type' should contain the basic type. 'ad' is the
6904 attribute definition of the basic type. It can be modified by
6905 type_decl().
6907 static void type_decl(CType *type, AttributeDef *ad, int *v, int td)
6909 Sym *s;
6910 CType type1, *type2;
6911 int qualifiers;
6913 while (tok == '*') {
6914 qualifiers = 0;
6915 redo:
6916 next();
6917 switch(tok) {
6918 case TOK_CONST1:
6919 case TOK_CONST2:
6920 case TOK_CONST3:
6921 qualifiers |= VT_CONSTANT;
6922 goto redo;
6923 case TOK_VOLATILE1:
6924 case TOK_VOLATILE2:
6925 case TOK_VOLATILE3:
6926 qualifiers |= VT_VOLATILE;
6927 goto redo;
6928 case TOK_RESTRICT1:
6929 case TOK_RESTRICT2:
6930 case TOK_RESTRICT3:
6931 goto redo;
6933 mk_pointer(type);
6934 type->t |= qualifiers;
6937 /* XXX: clarify attribute handling */
6938 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6939 parse_attribute(ad);
6941 /* recursive type */
6942 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
6943 type1.t = 0; /* XXX: same as int */
6944 if (tok == '(') {
6945 next();
6946 /* XXX: this is not correct to modify 'ad' at this point, but
6947 the syntax is not clear */
6948 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6949 parse_attribute(ad);
6950 type_decl(&type1, ad, v, td);
6951 skip(')');
6952 } else {
6953 /* type identifier */
6954 if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
6955 *v = tok;
6956 next();
6957 } else {
6958 if (!(td & TYPE_ABSTRACT))
6959 expect("identifier");
6960 *v = 0;
6963 post_type(type, ad);
6964 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
6965 parse_attribute(ad);
6966 if (!type1.t)
6967 return;
6968 /* append type at the end of type1 */
6969 type2 = &type1;
6970 for(;;) {
6971 s = type2->ref;
6972 type2 = &s->type;
6973 if (!type2->t) {
6974 *type2 = *type;
6975 break;
6978 *type = type1;
6981 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
6982 static int lvalue_type(int t)
6984 int bt, r;
6985 r = VT_LVAL;
6986 bt = t & VT_BTYPE;
6987 if (bt == VT_BYTE || bt == VT_BOOL)
6988 r |= VT_LVAL_BYTE;
6989 else if (bt == VT_SHORT)
6990 r |= VT_LVAL_SHORT;
6991 else
6992 return r;
6993 if (t & VT_UNSIGNED)
6994 r |= VT_LVAL_UNSIGNED;
6995 return r;
6998 /* indirection with full error checking and bound check */
6999 static void indir(void)
7001 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
7002 expect("pointer");
7003 if ((vtop->r & VT_LVAL) && !nocode_wanted)
7004 gv(RC_INT);
7005 vtop->type = *pointed_type(&vtop->type);
7006 /* an array is never an lvalue */
7007 if (!(vtop->type.t & VT_ARRAY)) {
7008 vtop->r |= lvalue_type(vtop->type.t);
7009 /* if bound checking, the referenced pointer must be checked */
7010 if (do_bounds_check)
7011 vtop->r |= VT_MUSTBOUND;
7015 /* pass a parameter to a function and do type checking and casting */
7016 static void gfunc_param_typed(Sym *func, Sym *arg)
7018 int func_type;
7019 CType type;
7021 func_type = func->c;
7022 if (func_type == FUNC_OLD ||
7023 (func_type == FUNC_ELLIPSIS && arg == NULL)) {
7024 /* default casting : only need to convert float to double */
7025 if ((vtop->type.t & VT_BTYPE) == VT_FLOAT) {
7026 type.t = VT_DOUBLE;
7027 gen_cast(&type);
7029 } else if (arg == NULL) {
7030 error("too many arguments to function");
7031 } else {
7032 type = arg->type;
7033 type.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
7034 gen_assign_cast(&type);
7038 /* parse an expression of the form '(type)' or '(expr)' and return its
7039 type */
7040 static void parse_expr_type(CType *type)
7042 int n;
7043 AttributeDef ad;
7045 skip('(');
7046 if (parse_btype(type, &ad)) {
7047 type_decl(type, &ad, &n, TYPE_ABSTRACT);
7048 } else {
7049 expr_type(type);
7051 skip(')');
7054 static void parse_type(CType *type)
7056 AttributeDef ad;
7057 int n;
7059 if (!parse_btype(type, &ad)) {
7060 expect("type");
7062 type_decl(type, &ad, &n, TYPE_ABSTRACT);
7065 static void vpush_tokc(int t)
7067 CType type;
7068 type.t = t;
7069 vsetc(&type, VT_CONST, &tokc);
7072 static void unary(void)
7074 int n, t, align, size, r;
7075 CType type;
7076 Sym *s;
7077 AttributeDef ad;
7079 /* XXX: GCC 2.95.3 does not generate a table although it should be
7080 better here */
7081 tok_next:
7082 switch(tok) {
7083 case TOK_EXTENSION:
7084 next();
7085 goto tok_next;
7086 case TOK_CINT:
7087 case TOK_CCHAR:
7088 case TOK_LCHAR:
7089 vpushi(tokc.i);
7090 next();
7091 break;
7092 case TOK_CUINT:
7093 vpush_tokc(VT_INT | VT_UNSIGNED);
7094 next();
7095 break;
7096 case TOK_CLLONG:
7097 vpush_tokc(VT_LLONG);
7098 next();
7099 break;
7100 case TOK_CULLONG:
7101 vpush_tokc(VT_LLONG | VT_UNSIGNED);
7102 next();
7103 break;
7104 case TOK_CFLOAT:
7105 vpush_tokc(VT_FLOAT);
7106 next();
7107 break;
7108 case TOK_CDOUBLE:
7109 vpush_tokc(VT_DOUBLE);
7110 next();
7111 break;
7112 case TOK_CLDOUBLE:
7113 vpush_tokc(VT_LDOUBLE);
7114 next();
7115 break;
7116 case TOK___FUNCTION__:
7117 if (!gnu_ext)
7118 goto tok_identifier;
7119 /* fall thru */
7120 case TOK___FUNC__:
7122 void *ptr;
7123 int len;
7124 /* special function name identifier */
7125 len = strlen(funcname) + 1;
7126 /* generate char[len] type */
7127 type.t = VT_BYTE;
7128 mk_pointer(&type);
7129 type.t |= VT_ARRAY;
7130 type.ref->c = len;
7131 vpush_ref(&type, data_section, data_section->data_offset, len);
7132 ptr = section_ptr_add(data_section, len);
7133 memcpy(ptr, funcname, len);
7134 next();
7136 break;
7137 case TOK_LSTR:
7138 t = VT_INT;
7139 goto str_init;
7140 case TOK_STR:
7141 /* string parsing */
7142 t = VT_BYTE;
7143 str_init:
7144 if (tcc_state->warn_write_strings)
7145 t |= VT_CONSTANT;
7146 type.t = t;
7147 mk_pointer(&type);
7148 type.t |= VT_ARRAY;
7149 memset(&ad, 0, sizeof(AttributeDef));
7150 decl_initializer_alloc(&type, &ad, VT_CONST, 2, 0, 0);
7151 break;
7152 case '(':
7153 next();
7154 /* cast ? */
7155 if (parse_btype(&type, &ad)) {
7156 type_decl(&type, &ad, &n, TYPE_ABSTRACT);
7157 skip(')');
7158 /* check ISOC99 compound literal */
7159 if (tok == '{') {
7160 /* data is allocated locally by default */
7161 if (global_expr)
7162 r = VT_CONST;
7163 else
7164 r = VT_LOCAL;
7165 /* all except arrays are lvalues */
7166 if (!(type.t & VT_ARRAY))
7167 r |= lvalue_type(type.t);
7168 memset(&ad, 0, sizeof(AttributeDef));
7169 decl_initializer_alloc(&type, &ad, r, 1, 0, 0);
7170 } else {
7171 unary();
7172 gen_cast(&type);
7174 } else if (tok == '{') {
7175 /* save all registers */
7176 save_regs(0);
7177 /* statement expression : we do not accept break/continue
7178 inside as GCC does */
7179 block(NULL, NULL, NULL, NULL, 0, 1);
7180 skip(')');
7181 } else {
7182 gexpr();
7183 skip(')');
7185 break;
7186 case '*':
7187 next();
7188 unary();
7189 indir();
7190 break;
7191 case '&':
7192 next();
7193 unary();
7194 /* functions names must be treated as function pointers,
7195 except for unary '&' and sizeof. Since we consider that
7196 functions are not lvalues, we only have to handle it
7197 there and in function calls. */
7198 /* arrays can also be used although they are not lvalues */
7199 if ((vtop->type.t & VT_BTYPE) != VT_FUNC &&
7200 !(vtop->type.t & VT_ARRAY))
7201 test_lvalue();
7202 mk_pointer(&vtop->type);
7203 gaddrof();
7204 break;
7205 case '!':
7206 next();
7207 unary();
7208 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST)
7209 vtop->c.i = !vtop->c.i;
7210 else if ((vtop->r & VT_VALMASK) == VT_CMP)
7211 vtop->c.i = vtop->c.i ^ 1;
7212 else
7213 vseti(VT_JMP, gtst(1, 0));
7214 break;
7215 case '~':
7216 next();
7217 unary();
7218 vpushi(-1);
7219 gen_op('^');
7220 break;
7221 case '+':
7222 next();
7223 /* in order to force cast, we add zero */
7224 unary();
7225 if ((vtop->type.t & VT_BTYPE) == VT_PTR)
7226 error("pointer not accepted for unary plus");
7227 vpushi(0);
7228 gen_op('+');
7229 break;
7230 case TOK_SIZEOF:
7231 case TOK_ALIGNOF1:
7232 case TOK_ALIGNOF2:
7233 t = tok;
7234 next();
7235 if (tok == '(') {
7236 parse_expr_type(&type);
7237 } else {
7238 unary_type(&type);
7240 size = type_size(&type, &align);
7241 if (t == TOK_SIZEOF) {
7242 if (size < 0)
7243 error("sizeof applied to an incomplete type");
7244 vpushi(size);
7245 } else {
7246 vpushi(align);
7248 break;
7250 case TOK_builtin_types_compatible_p:
7252 CType type1, type2;
7253 next();
7254 skip('(');
7255 parse_type(&type1);
7256 skip(',');
7257 parse_type(&type2);
7258 skip(')');
7259 type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
7260 type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
7261 vpushi(is_compatible_types(&type1, &type2));
7263 break;
7264 case TOK_builtin_constant_p:
7266 int saved_nocode_wanted, res;
7267 next();
7268 skip('(');
7269 saved_nocode_wanted = nocode_wanted;
7270 nocode_wanted = 1;
7271 gexpr();
7272 res = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
7273 vpop();
7274 nocode_wanted = saved_nocode_wanted;
7275 skip(')');
7276 vpushi(res);
7278 break;
7279 case TOK_INC:
7280 case TOK_DEC:
7281 t = tok;
7282 next();
7283 unary();
7284 inc(0, t);
7285 break;
7286 case '-':
7287 next();
7288 vpushi(0);
7289 unary();
7290 gen_op('-');
7291 break;
7292 case TOK_LAND:
7293 if (!gnu_ext)
7294 goto tok_identifier;
7295 next();
7296 /* allow to take the address of a label */
7297 if (tok < TOK_UIDENT)
7298 expect("label identifier");
7299 s = label_find(tok);
7300 if (!s) {
7301 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
7302 } else {
7303 if (s->r == LABEL_DECLARED)
7304 s->r = LABEL_FORWARD;
7306 if (!s->type.t) {
7307 s->type.t = VT_VOID;
7308 mk_pointer(&s->type);
7309 s->type.t |= VT_STATIC;
7311 vset(&s->type, VT_CONST | VT_SYM, 0);
7312 vtop->sym = s;
7313 next();
7314 break;
7315 default:
7316 tok_identifier:
7317 t = tok;
7318 next();
7319 if (t < TOK_UIDENT)
7320 expect("identifier");
7321 s = sym_find(t);
7322 if (!s) {
7323 if (tok != '(')
7324 error("'%s' undeclared", get_tok_str(t, NULL));
7325 /* for simple function calls, we tolerate undeclared
7326 external reference to int() function */
7327 if (tcc_state->warn_implicit_function_declaration)
7328 warning("implicit declaration of function '%s'",
7329 get_tok_str(t, NULL));
7330 s = external_global_sym(t, &func_old_type, 0);
7332 if ((s->type.t & (VT_STATIC | VT_INLINE | VT_BTYPE)) ==
7333 (VT_STATIC | VT_INLINE | VT_FUNC)) {
7334 /* if referencing an inline function, then we generate a
7335 symbol to it if not already done. It will have the
7336 effect to generate code for it at the end of the
7337 compilation unit. Inline function as always
7338 generated in the text section. */
7339 if (!s->c)
7340 put_extern_sym(s, text_section, 0, 0);
7341 r = VT_SYM | VT_CONST;
7342 } else {
7343 r = s->r;
7345 vset(&s->type, r, s->c);
7346 /* if forward reference, we must point to s */
7347 if (vtop->r & VT_SYM) {
7348 vtop->sym = s;
7349 vtop->c.ul = 0;
7351 break;
7354 /* post operations */
7355 while (1) {
7356 if (tok == TOK_INC || tok == TOK_DEC) {
7357 inc(1, tok);
7358 next();
7359 } else if (tok == '.' || tok == TOK_ARROW) {
7360 /* field */
7361 if (tok == TOK_ARROW)
7362 indir();
7363 test_lvalue();
7364 gaddrof();
7365 next();
7366 /* expect pointer on structure */
7367 if ((vtop->type.t & VT_BTYPE) != VT_STRUCT)
7368 expect("struct or union");
7369 s = vtop->type.ref;
7370 /* find field */
7371 tok |= SYM_FIELD;
7372 while ((s = s->next) != NULL) {
7373 if (s->v == tok)
7374 break;
7376 if (!s)
7377 error("field not found");
7378 /* add field offset to pointer */
7379 vtop->type = char_pointer_type; /* change type to 'char *' */
7380 vpushi(s->c);
7381 gen_op('+');
7382 /* change type to field type, and set to lvalue */
7383 vtop->type = s->type;
7384 /* an array is never an lvalue */
7385 if (!(vtop->type.t & VT_ARRAY)) {
7386 vtop->r |= lvalue_type(vtop->type.t);
7387 /* if bound checking, the referenced pointer must be checked */
7388 if (do_bounds_check)
7389 vtop->r |= VT_MUSTBOUND;
7391 next();
7392 } else if (tok == '[') {
7393 next();
7394 gexpr();
7395 gen_op('+');
7396 indir();
7397 skip(']');
7398 } else if (tok == '(') {
7399 SValue ret;
7400 Sym *sa;
7401 int nb_args;
7403 /* function call */
7404 if ((vtop->type.t & VT_BTYPE) != VT_FUNC) {
7405 /* pointer test (no array accepted) */
7406 if ((vtop->type.t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
7407 vtop->type = *pointed_type(&vtop->type);
7408 if ((vtop->type.t & VT_BTYPE) != VT_FUNC)
7409 goto error_func;
7410 } else {
7411 error_func:
7412 expect("function pointer");
7414 } else {
7415 vtop->r &= ~VT_LVAL; /* no lvalue */
7417 /* get return type */
7418 s = vtop->type.ref;
7419 next();
7420 sa = s->next; /* first parameter */
7421 nb_args = 0;
7422 /* compute first implicit argument if a structure is returned */
7423 if ((s->type.t & VT_BTYPE) == VT_STRUCT) {
7424 /* get some space for the returned structure */
7425 size = type_size(&s->type, &align);
7426 loc = (loc - size) & -align;
7427 ret.type = s->type;
7428 ret.r = VT_LOCAL | VT_LVAL;
7429 /* pass it as 'int' to avoid structure arg passing
7430 problems */
7431 vseti(VT_LOCAL, loc);
7432 ret.c = vtop->c;
7433 nb_args++;
7434 } else {
7435 ret.type = s->type;
7436 ret.r2 = VT_CONST;
7437 /* return in register */
7438 if (is_float(ret.type.t)) {
7439 ret.r = REG_FRET;
7440 } else {
7441 if ((ret.type.t & VT_BTYPE) == VT_LLONG)
7442 ret.r2 = REG_LRET;
7443 ret.r = REG_IRET;
7445 ret.c.i = 0;
7447 if (tok != ')') {
7448 for(;;) {
7449 expr_eq();
7450 gfunc_param_typed(s, sa);
7451 nb_args++;
7452 if (sa)
7453 sa = sa->next;
7454 if (tok == ')')
7455 break;
7456 skip(',');
7459 if (sa)
7460 error("too few arguments to function");
7461 skip(')');
7462 if (!nocode_wanted) {
7463 gfunc_call(nb_args);
7464 } else {
7465 vtop -= (nb_args + 1);
7467 /* return value */
7468 vsetc(&ret.type, ret.r, &ret.c);
7469 vtop->r2 = ret.r2;
7470 } else {
7471 break;
7476 static void uneq(void)
7478 int t;
7480 unary();
7481 if (tok == '=' ||
7482 (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
7483 tok == TOK_A_XOR || tok == TOK_A_OR ||
7484 tok == TOK_A_SHL || tok == TOK_A_SAR) {
7485 test_lvalue();
7486 t = tok;
7487 next();
7488 if (t == '=') {
7489 expr_eq();
7490 } else {
7491 vdup();
7492 expr_eq();
7493 gen_op(t & 0x7f);
7495 vstore();
7499 static void expr_prod(void)
7501 int t;
7503 uneq();
7504 while (tok == '*' || tok == '/' || tok == '%') {
7505 t = tok;
7506 next();
7507 uneq();
7508 gen_op(t);
7512 static void expr_sum(void)
7514 int t;
7516 expr_prod();
7517 while (tok == '+' || tok == '-') {
7518 t = tok;
7519 next();
7520 expr_prod();
7521 gen_op(t);
7525 static void expr_shift(void)
7527 int t;
7529 expr_sum();
7530 while (tok == TOK_SHL || tok == TOK_SAR) {
7531 t = tok;
7532 next();
7533 expr_sum();
7534 gen_op(t);
7538 static void expr_cmp(void)
7540 int t;
7542 expr_shift();
7543 while ((tok >= TOK_ULE && tok <= TOK_GT) ||
7544 tok == TOK_ULT || tok == TOK_UGE) {
7545 t = tok;
7546 next();
7547 expr_shift();
7548 gen_op(t);
7552 static void expr_cmpeq(void)
7554 int t;
7556 expr_cmp();
7557 while (tok == TOK_EQ || tok == TOK_NE) {
7558 t = tok;
7559 next();
7560 expr_cmp();
7561 gen_op(t);
7565 static void expr_and(void)
7567 expr_cmpeq();
7568 while (tok == '&') {
7569 next();
7570 expr_cmpeq();
7571 gen_op('&');
7575 static void expr_xor(void)
7577 expr_and();
7578 while (tok == '^') {
7579 next();
7580 expr_and();
7581 gen_op('^');
7585 static void expr_or(void)
7587 expr_xor();
7588 while (tok == '|') {
7589 next();
7590 expr_xor();
7591 gen_op('|');
7595 /* XXX: fix this mess */
7596 static void expr_land_const(void)
7598 expr_or();
7599 while (tok == TOK_LAND) {
7600 next();
7601 expr_or();
7602 gen_op(TOK_LAND);
7606 /* XXX: fix this mess */
7607 static void expr_lor_const(void)
7609 expr_land_const();
7610 while (tok == TOK_LOR) {
7611 next();
7612 expr_land_const();
7613 gen_op(TOK_LOR);
7617 /* only used if non constant */
7618 static void expr_land(void)
7620 int t;
7622 expr_or();
7623 if (tok == TOK_LAND) {
7624 t = 0;
7625 for(;;) {
7626 t = gtst(1, t);
7627 if (tok != TOK_LAND) {
7628 vseti(VT_JMPI, t);
7629 break;
7631 next();
7632 expr_or();
7637 static void expr_lor(void)
7639 int t;
7641 expr_land();
7642 if (tok == TOK_LOR) {
7643 t = 0;
7644 for(;;) {
7645 t = gtst(0, t);
7646 if (tok != TOK_LOR) {
7647 vseti(VT_JMP, t);
7648 break;
7650 next();
7651 expr_land();
7656 /* XXX: better constant handling */
7657 static void expr_eq(void)
7659 int tt, u, r1, r2, rc, t1, t2, bt1, bt2;
7660 SValue sv;
7661 CType type, type1, type2;
7663 if (const_wanted) {
7664 int c1, c;
7665 expr_lor_const();
7666 if (tok == '?') {
7667 c = vtop->c.i;
7668 vpop();
7669 next();
7670 if (tok == ':' && gnu_ext) {
7671 c1 = c;
7672 } else {
7673 gexpr();
7674 c1 = vtop->c.i;
7675 vpop();
7677 skip(':');
7678 expr_eq();
7679 if (c)
7680 vtop->c.i = c1;
7682 } else {
7683 expr_lor();
7684 if (tok == '?') {
7685 next();
7686 if (vtop != vstack) {
7687 /* needed to avoid having different registers saved in
7688 each branch */
7689 if (is_float(vtop->type.t))
7690 rc = RC_FLOAT;
7691 else
7692 rc = RC_INT;
7693 gv(rc);
7694 save_regs(1);
7696 if (tok == ':' && gnu_ext) {
7697 gv_dup();
7698 tt = gtst(1, 0);
7699 } else {
7700 tt = gtst(1, 0);
7701 gexpr();
7703 type1 = vtop->type;
7704 sv = *vtop; /* save value to handle it later */
7705 vtop--; /* no vpop so that FP stack is not flushed */
7706 skip(':');
7707 u = gjmp(0);
7708 gsym(tt);
7709 expr_eq();
7710 type2 = vtop->type;
7712 t1 = type1.t;
7713 bt1 = t1 & VT_BTYPE;
7714 t2 = type2.t;
7715 bt2 = t2 & VT_BTYPE;
7716 /* cast operands to correct type according to ISOC rules */
7717 if (is_float(bt1) || is_float(bt2)) {
7718 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
7719 type.t = VT_LDOUBLE;
7720 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
7721 type.t = VT_DOUBLE;
7722 } else {
7723 type.t = VT_FLOAT;
7725 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
7726 /* cast to biggest op */
7727 type.t = VT_LLONG;
7728 /* convert to unsigned if it does not fit in a long long */
7729 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
7730 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
7731 type.t |= VT_UNSIGNED;
7732 } else if (bt1 == VT_PTR || bt2 == VT_PTR) {
7733 /* XXX: test pointer compatibility */
7734 type = type1;
7735 } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
7736 /* XXX: test structure compatibility */
7737 type = type1;
7738 } else if (bt1 == VT_VOID || bt2 == VT_VOID) {
7739 /* NOTE: as an extension, we accept void on only one side */
7740 type.t = VT_VOID;
7741 } else {
7742 /* integer operations */
7743 type.t = VT_INT;
7744 /* convert to unsigned if it does not fit in an integer */
7745 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
7746 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
7747 type.t |= VT_UNSIGNED;
7750 /* now we convert second operand */
7751 gen_cast(&type);
7752 rc = RC_INT;
7753 if (is_float(type.t)) {
7754 rc = RC_FLOAT;
7755 } else if ((type.t & VT_BTYPE) == VT_LLONG) {
7756 /* for long longs, we use fixed registers to avoid having
7757 to handle a complicated move */
7758 rc = RC_IRET;
7761 r2 = gv(rc);
7762 /* this is horrible, but we must also convert first
7763 operand */
7764 tt = gjmp(0);
7765 gsym(u);
7766 /* put again first value and cast it */
7767 *vtop = sv;
7768 gen_cast(&type);
7769 r1 = gv(rc);
7770 move_reg(r2, r1);
7771 vtop->r = r2;
7772 gsym(tt);
7777 static void gexpr(void)
7779 while (1) {
7780 expr_eq();
7781 if (tok != ',')
7782 break;
7783 vpop();
7784 next();
7788 /* parse an expression and return its type without any side effect. */
7789 static void expr_type(CType *type)
7791 int saved_nocode_wanted;
7793 saved_nocode_wanted = nocode_wanted;
7794 nocode_wanted = 1;
7795 gexpr();
7796 *type = vtop->type;
7797 vpop();
7798 nocode_wanted = saved_nocode_wanted;
7801 /* parse a unary expression and return its type without any side
7802 effect. */
7803 static void unary_type(CType *type)
7805 int a;
7807 a = nocode_wanted;
7808 nocode_wanted = 1;
7809 unary();
7810 *type = vtop->type;
7811 vpop();
7812 nocode_wanted = a;
7815 /* parse a constant expression and return value in vtop. */
7816 static void expr_const1(void)
7818 int a;
7819 a = const_wanted;
7820 const_wanted = 1;
7821 expr_eq();
7822 const_wanted = a;
7825 /* parse an integer constant and return its value. */
7826 static int expr_const(void)
7828 int c;
7829 expr_const1();
7830 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
7831 expect("constant expression");
7832 c = vtop->c.i;
7833 vpop();
7834 return c;
7837 /* return the label token if current token is a label, otherwise
7838 return zero */
7839 static int is_label(void)
7841 int last_tok;
7843 /* fast test first */
7844 if (tok < TOK_UIDENT)
7845 return 0;
7846 /* no need to save tokc because tok is an identifier */
7847 last_tok = tok;
7848 next();
7849 if (tok == ':') {
7850 next();
7851 return last_tok;
7852 } else {
7853 unget_tok(last_tok);
7854 return 0;
7858 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
7859 int case_reg, int is_expr)
7861 int a, b, c, d;
7862 Sym *s;
7864 /* generate line number info */
7865 if (do_debug &&
7866 (last_line_num != file->line_num || last_ind != ind)) {
7867 put_stabn(N_SLINE, 0, file->line_num, ind - func_ind);
7868 last_ind = ind;
7869 last_line_num = file->line_num;
7872 if (is_expr) {
7873 /* default return value is (void) */
7874 vpushi(0);
7875 vtop->type.t = VT_VOID;
7878 if (tok == TOK_IF) {
7879 /* if test */
7880 next();
7881 skip('(');
7882 gexpr();
7883 skip(')');
7884 a = gtst(1, 0);
7885 block(bsym, csym, case_sym, def_sym, case_reg, 0);
7886 c = tok;
7887 if (c == TOK_ELSE) {
7888 next();
7889 d = gjmp(0);
7890 gsym(a);
7891 block(bsym, csym, case_sym, def_sym, case_reg, 0);
7892 gsym(d); /* patch else jmp */
7893 } else
7894 gsym(a);
7895 } else if (tok == TOK_WHILE) {
7896 next();
7897 d = ind;
7898 skip('(');
7899 gexpr();
7900 skip(')');
7901 a = gtst(1, 0);
7902 b = 0;
7903 block(&a, &b, case_sym, def_sym, case_reg, 0);
7904 gjmp_addr(d);
7905 gsym(a);
7906 gsym_addr(b, d);
7907 } else if (tok == '{') {
7908 Sym *llabel;
7910 next();
7911 /* record local declaration stack position */
7912 s = local_stack;
7913 llabel = local_label_stack;
7914 /* handle local labels declarations */
7915 if (tok == TOK_LABEL) {
7916 next();
7917 for(;;) {
7918 if (tok < TOK_UIDENT)
7919 expect("label identifier");
7920 label_push(&local_label_stack, tok, LABEL_DECLARED);
7921 next();
7922 if (tok == ',') {
7923 next();
7924 } else {
7925 skip(';');
7926 break;
7930 while (tok != '}') {
7931 decl(VT_LOCAL);
7932 if (tok != '}') {
7933 if (is_expr)
7934 vpop();
7935 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
7938 /* pop locally defined labels */
7939 label_pop(&local_label_stack, llabel);
7940 /* pop locally defined symbols */
7941 sym_pop(&local_stack, s);
7942 next();
7943 } else if (tok == TOK_RETURN) {
7944 next();
7945 if (tok != ';') {
7946 gexpr();
7947 gen_assign_cast(&func_vt);
7948 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
7949 CType type;
7950 /* if returning structure, must copy it to implicit
7951 first pointer arg location */
7952 type = func_vt;
7953 mk_pointer(&type);
7954 vset(&type, VT_LOCAL | VT_LVAL, func_vc);
7955 indir();
7956 vswap();
7957 /* copy structure value to pointer */
7958 vstore();
7959 } else if (is_float(func_vt.t)) {
7960 gv(RC_FRET);
7961 } else {
7962 gv(RC_IRET);
7964 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
7966 skip(';');
7967 rsym = gjmp(rsym); /* jmp */
7968 } else if (tok == TOK_BREAK) {
7969 /* compute jump */
7970 if (!bsym)
7971 error("cannot break");
7972 *bsym = gjmp(*bsym);
7973 next();
7974 skip(';');
7975 } else if (tok == TOK_CONTINUE) {
7976 /* compute jump */
7977 if (!csym)
7978 error("cannot continue");
7979 *csym = gjmp(*csym);
7980 next();
7981 skip(';');
7982 } else if (tok == TOK_FOR) {
7983 int e;
7984 next();
7985 skip('(');
7986 if (tok != ';') {
7987 gexpr();
7988 vpop();
7990 skip(';');
7991 d = ind;
7992 c = ind;
7993 a = 0;
7994 b = 0;
7995 if (tok != ';') {
7996 gexpr();
7997 a = gtst(1, 0);
7999 skip(';');
8000 if (tok != ')') {
8001 e = gjmp(0);
8002 c = ind;
8003 gexpr();
8004 vpop();
8005 gjmp_addr(d);
8006 gsym(e);
8008 skip(')');
8009 block(&a, &b, case_sym, def_sym, case_reg, 0);
8010 gjmp_addr(c);
8011 gsym(a);
8012 gsym_addr(b, c);
8013 } else
8014 if (tok == TOK_DO) {
8015 next();
8016 a = 0;
8017 b = 0;
8018 d = ind;
8019 block(&a, &b, case_sym, def_sym, case_reg, 0);
8020 skip(TOK_WHILE);
8021 skip('(');
8022 gsym(b);
8023 gexpr();
8024 c = gtst(0, 0);
8025 gsym_addr(c, d);
8026 skip(')');
8027 gsym(a);
8028 skip(';');
8029 } else
8030 if (tok == TOK_SWITCH) {
8031 next();
8032 skip('(');
8033 gexpr();
8034 /* XXX: other types than integer */
8035 case_reg = gv(RC_INT);
8036 vpop();
8037 skip(')');
8038 a = 0;
8039 b = gjmp(0); /* jump to first case */
8040 c = 0;
8041 block(&a, csym, &b, &c, case_reg, 0);
8042 /* if no default, jmp after switch */
8043 if (c == 0)
8044 c = ind;
8045 /* default label */
8046 gsym_addr(b, c);
8047 /* break label */
8048 gsym(a);
8049 } else
8050 if (tok == TOK_CASE) {
8051 int v1, v2;
8052 if (!case_sym)
8053 expect("switch");
8054 next();
8055 v1 = expr_const();
8056 v2 = v1;
8057 if (gnu_ext && tok == TOK_DOTS) {
8058 next();
8059 v2 = expr_const();
8060 if (v2 < v1)
8061 warning("empty case range");
8063 /* since a case is like a label, we must skip it with a jmp */
8064 b = gjmp(0);
8065 gsym(*case_sym);
8066 vseti(case_reg, 0);
8067 vpushi(v1);
8068 if (v1 == v2) {
8069 gen_op(TOK_EQ);
8070 *case_sym = gtst(1, 0);
8071 } else {
8072 gen_op(TOK_GE);
8073 *case_sym = gtst(1, 0);
8074 vseti(case_reg, 0);
8075 vpushi(v2);
8076 gen_op(TOK_LE);
8077 *case_sym = gtst(1, *case_sym);
8079 gsym(b);
8080 skip(':');
8081 is_expr = 0;
8082 goto block_after_label;
8083 } else
8084 if (tok == TOK_DEFAULT) {
8085 next();
8086 skip(':');
8087 if (!def_sym)
8088 expect("switch");
8089 if (*def_sym)
8090 error("too many 'default'");
8091 *def_sym = ind;
8092 is_expr = 0;
8093 goto block_after_label;
8094 } else
8095 if (tok == TOK_GOTO) {
8096 next();
8097 if (tok == '*' && gnu_ext) {
8098 /* computed goto */
8099 next();
8100 gexpr();
8101 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
8102 expect("pointer");
8103 ggoto();
8104 } else if (tok >= TOK_UIDENT) {
8105 s = label_find(tok);
8106 /* put forward definition if needed */
8107 if (!s) {
8108 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
8109 } else {
8110 if (s->r == LABEL_DECLARED)
8111 s->r = LABEL_FORWARD;
8113 /* label already defined */
8114 if (s->r & LABEL_FORWARD)
8115 s->next = (void *)gjmp((long)s->next);
8116 else
8117 gjmp_addr((long)s->next);
8118 next();
8119 } else {
8120 expect("label identifier");
8122 skip(';');
8123 } else if (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3) {
8124 asm_instr();
8125 } else {
8126 b = is_label();
8127 if (b) {
8128 /* label case */
8129 s = label_find(b);
8130 if (s) {
8131 if (s->r == LABEL_DEFINED)
8132 error("duplicate label '%s'", get_tok_str(s->v, NULL));
8133 gsym((long)s->next);
8134 s->r = LABEL_DEFINED;
8135 } else {
8136 s = label_push(&global_label_stack, b, LABEL_DEFINED);
8138 s->next = (void *)ind;
8139 /* we accept this, but it is a mistake */
8140 block_after_label:
8141 if (tok == '}') {
8142 warning("deprecated use of label at end of compound statement");
8143 } else {
8144 if (is_expr)
8145 vpop();
8146 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
8148 } else {
8149 /* expression case */
8150 if (tok != ';') {
8151 if (is_expr) {
8152 vpop();
8153 gexpr();
8154 } else {
8155 gexpr();
8156 vpop();
8159 skip(';');
8164 /* t is the array or struct type. c is the array or struct
8165 address. cur_index/cur_field is the pointer to the current
8166 value. 'size_only' is true if only size info is needed (only used
8167 in arrays) */
8168 static void decl_designator(CType *type, Section *sec, unsigned long c,
8169 int *cur_index, Sym **cur_field,
8170 int size_only)
8172 Sym *s, *f;
8173 int notfirst, index, index_last, align, l, nb_elems, elem_size;
8174 CType type1;
8176 notfirst = 0;
8177 elem_size = 0;
8178 nb_elems = 1;
8179 if (gnu_ext && (l = is_label()) != 0)
8180 goto struct_field;
8181 while (tok == '[' || tok == '.') {
8182 if (tok == '[') {
8183 if (!(type->t & VT_ARRAY))
8184 expect("array type");
8185 s = type->ref;
8186 next();
8187 index = expr_const();
8188 if (index < 0 || (s->c >= 0 && index >= s->c))
8189 expect("invalid index");
8190 if (tok == TOK_DOTS && gnu_ext) {
8191 next();
8192 index_last = expr_const();
8193 if (index_last < 0 ||
8194 (s->c >= 0 && index_last >= s->c) ||
8195 index_last < index)
8196 expect("invalid index");
8197 } else {
8198 index_last = index;
8200 skip(']');
8201 if (!notfirst)
8202 *cur_index = index_last;
8203 type = pointed_type(type);
8204 elem_size = type_size(type, &align);
8205 c += index * elem_size;
8206 /* NOTE: we only support ranges for last designator */
8207 nb_elems = index_last - index + 1;
8208 if (nb_elems != 1) {
8209 notfirst = 1;
8210 break;
8212 } else {
8213 next();
8214 l = tok;
8215 next();
8216 struct_field:
8217 if ((type->t & VT_BTYPE) != VT_STRUCT)
8218 expect("struct/union type");
8219 s = type->ref;
8220 l |= SYM_FIELD;
8221 f = s->next;
8222 while (f) {
8223 if (f->v == l)
8224 break;
8225 f = f->next;
8227 if (!f)
8228 expect("field");
8229 if (!notfirst)
8230 *cur_field = f;
8231 /* XXX: fix this mess by using explicit storage field */
8232 type1 = f->type;
8233 type1.t |= (type->t & ~VT_TYPE);
8234 type = &type1;
8235 c += f->c;
8237 notfirst = 1;
8239 if (notfirst) {
8240 if (tok == '=') {
8241 next();
8242 } else {
8243 if (!gnu_ext)
8244 expect("=");
8246 } else {
8247 if (type->t & VT_ARRAY) {
8248 index = *cur_index;
8249 type = pointed_type(type);
8250 c += index * type_size(type, &align);
8251 } else {
8252 f = *cur_field;
8253 if (!f)
8254 error("too many field init");
8255 /* XXX: fix this mess by using explicit storage field */
8256 type1 = f->type;
8257 type1.t |= (type->t & ~VT_TYPE);
8258 type = &type1;
8259 c += f->c;
8262 decl_initializer(type, sec, c, 0, size_only);
8264 /* XXX: make it more general */
8265 if (!size_only && nb_elems > 1) {
8266 unsigned long c_end;
8267 uint8_t *src, *dst;
8268 int i;
8270 if (!sec)
8271 error("range init not supported yet for dynamic storage");
8272 c_end = c + nb_elems * elem_size;
8273 if (c_end > sec->data_allocated)
8274 section_realloc(sec, c_end);
8275 src = sec->data + c;
8276 dst = src;
8277 for(i = 1; i < nb_elems; i++) {
8278 dst += elem_size;
8279 memcpy(dst, src, elem_size);
8284 #define EXPR_VAL 0
8285 #define EXPR_CONST 1
8286 #define EXPR_ANY 2
8288 /* store a value or an expression directly in global data or in local array */
8289 static void init_putv(CType *type, Section *sec, unsigned long c,
8290 int v, int expr_type)
8292 int saved_global_expr, bt, bit_pos, bit_size;
8293 void *ptr;
8294 unsigned long long bit_mask;
8295 CType dtype;
8297 switch(expr_type) {
8298 case EXPR_VAL:
8299 vpushi(v);
8300 break;
8301 case EXPR_CONST:
8302 /* compound literals must be allocated globally in this case */
8303 saved_global_expr = global_expr;
8304 global_expr = 1;
8305 expr_const1();
8306 global_expr = saved_global_expr;
8307 /* NOTE: symbols are accepted */
8308 if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST)
8309 error("initializer element is not constant");
8310 break;
8311 case EXPR_ANY:
8312 expr_eq();
8313 break;
8316 dtype = *type;
8317 dtype.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
8319 if (sec) {
8320 /* XXX: not portable */
8321 /* XXX: generate error if incorrect relocation */
8322 gen_assign_cast(&dtype);
8323 bt = type->t & VT_BTYPE;
8324 ptr = sec->data + c;
8325 /* XXX: make code faster ? */
8326 if (!(type->t & VT_BITFIELD)) {
8327 bit_pos = 0;
8328 bit_size = 32;
8329 bit_mask = -1LL;
8330 } else {
8331 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
8332 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
8333 bit_mask = (1LL << bit_size) - 1;
8335 if ((vtop->r & VT_SYM) &&
8336 (bt == VT_BYTE ||
8337 bt == VT_SHORT ||
8338 bt == VT_DOUBLE ||
8339 bt == VT_LDOUBLE ||
8340 bt == VT_LLONG ||
8341 (bt == VT_INT && bit_size != 32)))
8342 error("initializer element is not computable at load time");
8343 switch(bt) {
8344 case VT_BYTE:
8345 *(char *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8346 break;
8347 case VT_SHORT:
8348 *(short *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8349 break;
8350 case VT_DOUBLE:
8351 *(double *)ptr = vtop->c.d;
8352 break;
8353 case VT_LDOUBLE:
8354 *(long double *)ptr = vtop->c.ld;
8355 break;
8356 case VT_LLONG:
8357 *(long long *)ptr |= (vtop->c.ll & bit_mask) << bit_pos;
8358 break;
8359 default:
8360 if (vtop->r & VT_SYM) {
8361 greloc(sec, vtop->sym, c, R_DATA_32);
8363 *(int *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8364 break;
8366 vtop--;
8367 } else {
8368 vset(&dtype, VT_LOCAL, c);
8369 vswap();
8370 vstore();
8371 vpop();
8375 /* put zeros for variable based init */
8376 static void init_putz(CType *t, Section *sec, unsigned long c, int size)
8378 if (sec) {
8379 /* nothing to do because globals are already set to zero */
8380 } else {
8381 vpush_global_sym(&func_old_type, TOK_memset);
8382 vseti(VT_LOCAL, c);
8383 vpushi(0);
8384 vpushi(size);
8385 gfunc_call(3);
8389 /* 't' contains the type and storage info. 'c' is the offset of the
8390 object in section 'sec'. If 'sec' is NULL, it means stack based
8391 allocation. 'first' is true if array '{' must be read (multi
8392 dimension implicit array init handling). 'size_only' is true if
8393 size only evaluation is wanted (only for arrays). */
8394 static void decl_initializer(CType *type, Section *sec, unsigned long c,
8395 int first, int size_only)
8397 int index, array_length, n, no_oblock, nb, parlevel, i;
8398 int size1, align1, expr_type;
8399 Sym *s, *f;
8400 CType *t1;
8402 if (type->t & VT_ARRAY) {
8403 s = type->ref;
8404 n = s->c;
8405 array_length = 0;
8406 t1 = pointed_type(type);
8407 size1 = type_size(t1, &align1);
8409 no_oblock = 1;
8410 if ((first && tok != TOK_LSTR && tok != TOK_STR) ||
8411 tok == '{') {
8412 skip('{');
8413 no_oblock = 0;
8416 /* only parse strings here if correct type (otherwise: handle
8417 them as ((w)char *) expressions */
8418 if ((tok == TOK_LSTR &&
8419 (t1->t & VT_BTYPE) == VT_INT) ||
8420 (tok == TOK_STR &&
8421 (t1->t & VT_BTYPE) == VT_BYTE)) {
8422 while (tok == TOK_STR || tok == TOK_LSTR) {
8423 int cstr_len, ch;
8424 CString *cstr;
8426 cstr = tokc.cstr;
8427 /* compute maximum number of chars wanted */
8428 if (tok == TOK_STR)
8429 cstr_len = cstr->size;
8430 else
8431 cstr_len = cstr->size / sizeof(int);
8432 cstr_len--;
8433 nb = cstr_len;
8434 if (n >= 0 && nb > (n - array_length))
8435 nb = n - array_length;
8436 if (!size_only) {
8437 if (cstr_len > nb)
8438 warning("initializer-string for array is too long");
8439 /* in order to go faster for common case (char
8440 string in global variable, we handle it
8441 specifically */
8442 if (sec && tok == TOK_STR && size1 == 1) {
8443 memcpy(sec->data + c + array_length, cstr->data, nb);
8444 } else {
8445 for(i=0;i<nb;i++) {
8446 if (tok == TOK_STR)
8447 ch = ((unsigned char *)cstr->data)[i];
8448 else
8449 ch = ((int *)cstr->data)[i];
8450 init_putv(t1, sec, c + (array_length + i) * size1,
8451 ch, EXPR_VAL);
8455 array_length += nb;
8456 next();
8458 /* only add trailing zero if enough storage (no
8459 warning in this case since it is standard) */
8460 if (n < 0 || array_length < n) {
8461 if (!size_only) {
8462 init_putv(t1, sec, c + (array_length * size1), 0, EXPR_VAL);
8464 array_length++;
8466 } else {
8467 index = 0;
8468 while (tok != '}') {
8469 decl_designator(type, sec, c, &index, NULL, size_only);
8470 if (n >= 0 && index >= n)
8471 error("index too large");
8472 /* must put zero in holes (note that doing it that way
8473 ensures that it even works with designators) */
8474 if (!size_only && array_length < index) {
8475 init_putz(t1, sec, c + array_length * size1,
8476 (index - array_length) * size1);
8478 index++;
8479 if (index > array_length)
8480 array_length = index;
8481 /* special test for multi dimensional arrays (may not
8482 be strictly correct if designators are used at the
8483 same time) */
8484 if (index >= n && no_oblock)
8485 break;
8486 if (tok == '}')
8487 break;
8488 skip(',');
8491 if (!no_oblock)
8492 skip('}');
8493 /* put zeros at the end */
8494 if (!size_only && n >= 0 && array_length < n) {
8495 init_putz(t1, sec, c + array_length * size1,
8496 (n - array_length) * size1);
8498 /* patch type size if needed */
8499 if (n < 0)
8500 s->c = array_length;
8501 } else if ((type->t & VT_BTYPE) == VT_STRUCT &&
8502 (sec || !first || tok == '{')) {
8503 int par_count;
8505 /* NOTE: the previous test is a specific case for automatic
8506 struct/union init */
8507 /* XXX: union needs only one init */
8509 /* XXX: this test is incorrect for local initializers
8510 beginning with ( without {. It would be much more difficult
8511 to do it correctly (ideally, the expression parser should
8512 be used in all cases) */
8513 par_count = 0;
8514 if (tok == '(') {
8515 AttributeDef ad1;
8516 CType type1;
8517 next();
8518 while (tok == '(') {
8519 par_count++;
8520 next();
8522 if (!parse_btype(&type1, &ad1))
8523 expect("cast");
8524 type_decl(&type1, &ad1, &n, TYPE_ABSTRACT);
8525 #if 0
8526 if (!is_assignable_types(type, &type1))
8527 error("invalid type for cast");
8528 #endif
8529 skip(')');
8531 no_oblock = 1;
8532 if (first || tok == '{') {
8533 skip('{');
8534 no_oblock = 0;
8536 s = type->ref;
8537 f = s->next;
8538 array_length = 0;
8539 index = 0;
8540 n = s->c;
8541 while (tok != '}') {
8542 decl_designator(type, sec, c, NULL, &f, size_only);
8543 index = f->c;
8544 if (!size_only && array_length < index) {
8545 init_putz(type, sec, c + array_length,
8546 index - array_length);
8548 index = index + type_size(&f->type, &align1);
8549 if (index > array_length)
8550 array_length = index;
8551 f = f->next;
8552 if (no_oblock && f == NULL)
8553 break;
8554 if (tok == '}')
8555 break;
8556 skip(',');
8558 /* put zeros at the end */
8559 if (!size_only && array_length < n) {
8560 init_putz(type, sec, c + array_length,
8561 n - array_length);
8563 if (!no_oblock)
8564 skip('}');
8565 while (par_count) {
8566 skip(')');
8567 par_count--;
8569 } else if (tok == '{') {
8570 next();
8571 decl_initializer(type, sec, c, first, size_only);
8572 skip('}');
8573 } else if (size_only) {
8574 /* just skip expression */
8575 parlevel = 0;
8576 while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
8577 tok != -1) {
8578 if (tok == '(')
8579 parlevel++;
8580 else if (tok == ')')
8581 parlevel--;
8582 next();
8584 } else {
8585 /* currently, we always use constant expression for globals
8586 (may change for scripting case) */
8587 expr_type = EXPR_CONST;
8588 if (!sec)
8589 expr_type = EXPR_ANY;
8590 init_putv(type, sec, c, 0, expr_type);
8594 /* parse an initializer for type 't' if 'has_init' is non zero, and
8595 allocate space in local or global data space ('r' is either
8596 VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
8597 variable 'v' of scope 'scope' is declared before initializers are
8598 parsed. If 'v' is zero, then a reference to the new object is put
8599 in the value stack. If 'has_init' is 2, a special parsing is done
8600 to handle string constants. */
8601 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
8602 int has_init, int v, int scope)
8604 int size, align, addr, data_offset;
8605 int level;
8606 ParseState saved_parse_state;
8607 TokenString init_str;
8608 Section *sec;
8610 size = type_size(type, &align);
8611 /* If unknown size, we must evaluate it before
8612 evaluating initializers because
8613 initializers can generate global data too
8614 (e.g. string pointers or ISOC99 compound
8615 literals). It also simplifies local
8616 initializers handling */
8617 tok_str_new(&init_str);
8618 if (size < 0) {
8619 if (!has_init)
8620 error("unknown type size");
8621 /* get all init string */
8622 if (has_init == 2) {
8623 /* only get strings */
8624 while (tok == TOK_STR || tok == TOK_LSTR) {
8625 tok_str_add_tok(&init_str);
8626 next();
8628 } else {
8629 level = 0;
8630 while (level > 0 || (tok != ',' && tok != ';')) {
8631 if (tok < 0)
8632 error("unexpected end of file in initializer");
8633 tok_str_add_tok(&init_str);
8634 if (tok == '{')
8635 level++;
8636 else if (tok == '}') {
8637 if (level == 0)
8638 break;
8639 level--;
8641 next();
8644 tok_str_add(&init_str, -1);
8645 tok_str_add(&init_str, 0);
8647 /* compute size */
8648 save_parse_state(&saved_parse_state);
8650 macro_ptr = init_str.str;
8651 next();
8652 decl_initializer(type, NULL, 0, 1, 1);
8653 /* prepare second initializer parsing */
8654 macro_ptr = init_str.str;
8655 next();
8657 /* if still unknown size, error */
8658 size = type_size(type, &align);
8659 if (size < 0)
8660 error("unknown type size");
8662 /* take into account specified alignment if bigger */
8663 if (ad->aligned) {
8664 if (ad->aligned > align)
8665 align = ad->aligned;
8666 } else if (ad->packed) {
8667 align = 1;
8669 if ((r & VT_VALMASK) == VT_LOCAL) {
8670 sec = NULL;
8671 if (do_bounds_check && (type->t & VT_ARRAY))
8672 loc--;
8673 loc = (loc - size) & -align;
8674 addr = loc;
8675 /* handles bounds */
8676 /* XXX: currently, since we do only one pass, we cannot track
8677 '&' operators, so we add only arrays */
8678 if (do_bounds_check && (type->t & VT_ARRAY)) {
8679 unsigned long *bounds_ptr;
8680 /* add padding between regions */
8681 loc--;
8682 /* then add local bound info */
8683 bounds_ptr = section_ptr_add(lbounds_section, 2 * sizeof(unsigned long));
8684 bounds_ptr[0] = addr;
8685 bounds_ptr[1] = size;
8687 if (v) {
8688 /* local variable */
8689 sym_push(v, type, r, addr);
8690 } else {
8691 /* push local reference */
8692 vset(type, r, addr);
8694 } else {
8695 Sym *sym;
8697 sym = NULL;
8698 if (v && scope == VT_CONST) {
8699 /* see if the symbol was already defined */
8700 sym = sym_find(v);
8701 if (sym) {
8702 if (!is_compatible_types(&sym->type, type))
8703 error("incompatible types for redefinition of '%s'",
8704 get_tok_str(v, NULL));
8705 if (sym->type.t & VT_EXTERN) {
8706 /* if the variable is extern, it was not allocated */
8707 sym->type.t &= ~VT_EXTERN;
8708 /* set array size if it was ommited in extern
8709 declaration */
8710 if ((sym->type.t & VT_ARRAY) &&
8711 sym->type.ref->c < 0 &&
8712 type->ref->c >= 0)
8713 sym->type.ref->c = type->ref->c;
8714 } else {
8715 /* we accept several definitions of the same
8716 global variable. this is tricky, because we
8717 must play with the SHN_COMMON type of the symbol */
8718 /* XXX: should check if the variable was already
8719 initialized. It is incorrect to initialized it
8720 twice */
8721 /* no init data, we won't add more to the symbol */
8722 if (!has_init)
8723 goto no_alloc;
8728 /* allocate symbol in corresponding section */
8729 sec = ad->section;
8730 if (!sec) {
8731 if (has_init)
8732 sec = data_section;
8733 else if (tcc_state->nocommon)
8734 sec = bss_section;
8736 if (sec) {
8737 data_offset = sec->data_offset;
8738 data_offset = (data_offset + align - 1) & -align;
8739 addr = data_offset;
8740 /* very important to increment global pointer at this time
8741 because initializers themselves can create new initializers */
8742 data_offset += size;
8743 /* add padding if bound check */
8744 if (do_bounds_check)
8745 data_offset++;
8746 sec->data_offset = data_offset;
8747 /* allocate section space to put the data */
8748 if (sec->sh_type != SHT_NOBITS &&
8749 data_offset > sec->data_allocated)
8750 section_realloc(sec, data_offset);
8751 /* align section if needed */
8752 if (align > sec->sh_addralign)
8753 sec->sh_addralign = align;
8754 } else {
8755 addr = 0; /* avoid warning */
8758 if (v) {
8759 if (scope == VT_CONST) {
8760 if (!sym)
8761 goto do_def;
8762 } else {
8763 do_def:
8764 sym = sym_push(v, type, r | VT_SYM, 0);
8766 /* update symbol definition */
8767 if (sec) {
8768 put_extern_sym(sym, sec, addr, size);
8769 } else {
8770 Elf32_Sym *esym;
8771 /* put a common area */
8772 put_extern_sym(sym, NULL, align, size);
8773 /* XXX: find a nicer way */
8774 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
8775 esym->st_shndx = SHN_COMMON;
8777 } else {
8778 CValue cval;
8780 /* push global reference */
8781 sym = get_sym_ref(type, sec, addr, size);
8782 cval.ul = 0;
8783 vsetc(type, VT_CONST | VT_SYM, &cval);
8784 vtop->sym = sym;
8787 /* handles bounds now because the symbol must be defined
8788 before for the relocation */
8789 if (do_bounds_check) {
8790 unsigned long *bounds_ptr;
8792 greloc(bounds_section, sym, bounds_section->data_offset, R_DATA_32);
8793 /* then add global bound info */
8794 bounds_ptr = section_ptr_add(bounds_section, 2 * sizeof(long));
8795 bounds_ptr[0] = 0; /* relocated */
8796 bounds_ptr[1] = size;
8799 if (has_init) {
8800 decl_initializer(type, sec, addr, 1, 0);
8801 /* restore parse state if needed */
8802 if (init_str.str) {
8803 tok_str_free(init_str.str);
8804 restore_parse_state(&saved_parse_state);
8807 no_alloc: ;
8810 void put_func_debug(Sym *sym)
8812 char buf[512];
8814 /* stabs info */
8815 /* XXX: we put here a dummy type */
8816 snprintf(buf, sizeof(buf), "%s:%c1",
8817 funcname, sym->type.t & VT_STATIC ? 'f' : 'F');
8818 put_stabs_r(buf, N_FUN, 0, file->line_num, 0,
8819 cur_text_section, sym->c);
8820 last_ind = 0;
8821 last_line_num = 0;
8824 /* parse an old style function declaration list */
8825 /* XXX: check multiple parameter */
8826 static void func_decl_list(Sym *func_sym)
8828 AttributeDef ad;
8829 int v;
8830 Sym *s;
8831 CType btype, type;
8833 /* parse each declaration */
8834 while (tok != '{' && tok != ';' && tok != ',' && tok != TOK_EOF) {
8835 if (!parse_btype(&btype, &ad))
8836 expect("declaration list");
8837 if (((btype.t & VT_BTYPE) == VT_ENUM ||
8838 (btype.t & VT_BTYPE) == VT_STRUCT) &&
8839 tok == ';') {
8840 /* we accept no variable after */
8841 } else {
8842 for(;;) {
8843 type = btype;
8844 type_decl(&type, &ad, &v, TYPE_DIRECT);
8845 /* find parameter in function parameter list */
8846 s = func_sym->next;
8847 while (s != NULL) {
8848 if ((s->v & ~SYM_FIELD) == v)
8849 goto found;
8850 s = s->next;
8852 error("declaration for parameter '%s' but no such parameter",
8853 get_tok_str(v, NULL));
8854 found:
8855 /* check that no storage specifier except 'register' was given */
8856 if (type.t & VT_STORAGE)
8857 error("storage class specified for '%s'", get_tok_str(v, NULL));
8858 convert_parameter_type(&type);
8859 /* we can add the type (NOTE: it could be local to the function) */
8860 s->type = type;
8861 /* accept other parameters */
8862 if (tok == ',')
8863 next();
8864 else
8865 break;
8868 skip(';');
8872 /* parse a function defined by symbol 'sym' and generate its code in
8873 'cur_text_section' */
8874 static void gen_function(Sym *sym)
8876 ind = cur_text_section->data_offset;
8877 /* NOTE: we patch the symbol size later */
8878 put_extern_sym(sym, cur_text_section, ind, 0);
8879 funcname = get_tok_str(sym->v, NULL);
8880 func_ind = ind;
8881 /* put debug symbol */
8882 if (do_debug)
8883 put_func_debug(sym);
8884 /* push a dummy symbol to enable local sym storage */
8885 sym_push2(&local_stack, SYM_FIELD, 0, 0);
8886 gfunc_prolog(&sym->type);
8887 rsym = 0;
8888 block(NULL, NULL, NULL, NULL, 0, 0);
8889 gsym(rsym);
8890 gfunc_epilog();
8891 cur_text_section->data_offset = ind;
8892 label_pop(&global_label_stack, NULL);
8893 sym_pop(&local_stack, NULL); /* reset local stack */
8894 /* end of function */
8895 /* patch symbol size */
8896 ((Elf32_Sym *)symtab_section->data)[sym->c].st_size =
8897 ind - func_ind;
8898 if (do_debug) {
8899 put_stabn(N_FUN, 0, 0, ind - func_ind);
8901 funcname = ""; /* for safety */
8902 func_vt.t = VT_VOID; /* for safety */
8903 ind = 0; /* for safety */
8906 static void gen_inline_functions(void)
8908 Sym *sym;
8909 CType *type;
8910 int *str, inline_generated;
8912 /* iterate while inline function are referenced */
8913 for(;;) {
8914 inline_generated = 0;
8915 for(sym = global_stack; sym != NULL; sym = sym->prev) {
8916 type = &sym->type;
8917 if (((type->t & VT_BTYPE) == VT_FUNC) &&
8918 (type->t & (VT_STATIC | VT_INLINE)) ==
8919 (VT_STATIC | VT_INLINE) &&
8920 sym->c != 0) {
8921 /* the function was used: generate its code and
8922 convert it to a normal function */
8923 str = (int *)sym->r;
8924 sym->r = VT_SYM | VT_CONST;
8925 type->t &= ~VT_INLINE;
8927 macro_ptr = str;
8928 next();
8929 cur_text_section = text_section;
8930 gen_function(sym);
8931 macro_ptr = NULL; /* fail safe */
8933 tok_str_free(str);
8934 inline_generated = 1;
8937 if (!inline_generated)
8938 break;
8941 /* free all remaining inline function tokens */
8942 for(sym = global_stack; sym != NULL; sym = sym->prev) {
8943 type = &sym->type;
8944 if (((type->t & VT_BTYPE) == VT_FUNC) &&
8945 (type->t & (VT_STATIC | VT_INLINE)) ==
8946 (VT_STATIC | VT_INLINE)) {
8947 str = (int *)sym->r;
8948 tok_str_free(str);
8949 sym->r = 0; /* fail safe */
8954 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
8955 static void decl(int l)
8957 int v, has_init, r;
8958 CType type, btype;
8959 Sym *sym;
8960 AttributeDef ad;
8962 while (1) {
8963 if (!parse_btype(&btype, &ad)) {
8964 /* skip redundant ';' */
8965 /* XXX: find more elegant solution */
8966 if (tok == ';') {
8967 next();
8968 continue;
8970 if (l == VT_CONST &&
8971 (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3)) {
8972 /* global asm block */
8973 asm_global_instr();
8974 continue;
8976 /* special test for old K&R protos without explicit int
8977 type. Only accepted when defining global data */
8978 if (l == VT_LOCAL || tok < TOK_DEFINE)
8979 break;
8980 btype.t = VT_INT;
8982 if (((btype.t & VT_BTYPE) == VT_ENUM ||
8983 (btype.t & VT_BTYPE) == VT_STRUCT) &&
8984 tok == ';') {
8985 /* we accept no variable after */
8986 next();
8987 continue;
8989 while (1) { /* iterate thru each declaration */
8990 type = btype;
8991 type_decl(&type, &ad, &v, TYPE_DIRECT);
8992 #if 0
8994 char buf[500];
8995 type_to_str(buf, sizeof(buf), t, get_tok_str(v, NULL));
8996 printf("type = '%s'\n", buf);
8998 #endif
8999 if ((type.t & VT_BTYPE) == VT_FUNC) {
9000 /* if old style function prototype, we accept a
9001 declaration list */
9002 sym = type.ref;
9003 if (sym->c == FUNC_OLD)
9004 func_decl_list(sym);
9007 if (tok == '{') {
9008 if (l == VT_LOCAL)
9009 error("cannot use local functions");
9010 if (!(type.t & VT_FUNC))
9011 expect("function definition");
9013 /* reject abstract declarators in function definition */
9014 sym = type.ref;
9015 while ((sym = sym->next) != NULL)
9016 if (!(sym->v & ~SYM_FIELD))
9017 expect("identifier");
9019 /* XXX: cannot do better now: convert extern line to static inline */
9020 if ((type.t & (VT_EXTERN | VT_INLINE)) == (VT_EXTERN | VT_INLINE))
9021 type.t = (type.t & ~VT_EXTERN) | VT_STATIC;
9023 sym = sym_find(v);
9024 if (sym) {
9025 if ((sym->type.t & VT_BTYPE) != VT_FUNC)
9026 goto func_error1;
9027 /* specific case: if not func_call defined, we put
9028 the one of the prototype */
9029 /* XXX: should have default value */
9030 if (sym->type.ref->r != FUNC_CDECL &&
9031 type.ref->r == FUNC_CDECL)
9032 type.ref->r = sym->type.ref->r;
9033 if (!is_compatible_types(&sym->type, &type)) {
9034 func_error1:
9035 error("incompatible types for redefinition of '%s'",
9036 get_tok_str(v, NULL));
9038 /* if symbol is already defined, then put complete type */
9039 sym->type = type;
9040 } else {
9041 /* put function symbol */
9042 sym = global_identifier_push(v, type.t, 0);
9043 sym->type.ref = type.ref;
9046 /* static inline functions are just recorded as a kind
9047 of macro. Their code will be emitted at the end of
9048 the compilation unit only if they are used */
9049 if ((type.t & (VT_INLINE | VT_STATIC)) ==
9050 (VT_INLINE | VT_STATIC)) {
9051 TokenString func_str;
9052 int block_level;
9054 tok_str_new(&func_str);
9056 block_level = 0;
9057 for(;;) {
9058 int t;
9059 if (tok == TOK_EOF)
9060 error("unexpected end of file");
9061 tok_str_add_tok(&func_str);
9062 t = tok;
9063 next();
9064 if (t == '{') {
9065 block_level++;
9066 } else if (t == '}') {
9067 block_level--;
9068 if (block_level == 0)
9069 break;
9072 tok_str_add(&func_str, -1);
9073 tok_str_add(&func_str, 0);
9074 sym->r = (int)func_str.str;
9075 } else {
9076 /* compute text section */
9077 cur_text_section = ad.section;
9078 if (!cur_text_section)
9079 cur_text_section = text_section;
9080 sym->r = VT_SYM | VT_CONST;
9081 gen_function(sym);
9082 #ifdef TCC_TARGET_PE
9083 if (ad.dllexport) {
9084 ((Elf32_Sym *)symtab_section->data)[sym->c].st_other |= 1;
9086 #endif
9088 break;
9089 } else {
9090 if (btype.t & VT_TYPEDEF) {
9091 /* save typedefed type */
9092 /* XXX: test storage specifiers ? */
9093 sym = sym_push(v, &type, 0, 0);
9094 sym->type.t |= VT_TYPEDEF;
9095 } else if ((type.t & VT_BTYPE) == VT_FUNC) {
9096 /* external function definition */
9097 /* specific case for func_call attribute */
9098 if (ad.func_call)
9099 type.ref->r = ad.func_call;
9100 external_sym(v, &type, 0);
9101 } else {
9102 /* not lvalue if array */
9103 r = 0;
9104 if (!(type.t & VT_ARRAY))
9105 r |= lvalue_type(type.t);
9106 has_init = (tok == '=');
9107 if ((btype.t & VT_EXTERN) ||
9108 ((type.t & VT_ARRAY) && (type.t & VT_STATIC) &&
9109 !has_init && l == VT_CONST && type.ref->c < 0)) {
9110 /* external variable */
9111 /* NOTE: as GCC, uninitialized global static
9112 arrays of null size are considered as
9113 extern */
9114 external_sym(v, &type, r);
9115 } else {
9116 if (type.t & VT_STATIC)
9117 r |= VT_CONST;
9118 else
9119 r |= l;
9120 if (has_init)
9121 next();
9122 decl_initializer_alloc(&type, &ad, r,
9123 has_init, v, l);
9126 if (tok != ',') {
9127 skip(';');
9128 break;
9130 next();
9136 /* better than nothing, but needs extension to handle '-E' option
9137 correctly too */
9138 static void preprocess_init(TCCState *s1)
9140 s1->include_stack_ptr = s1->include_stack;
9141 /* XXX: move that before to avoid having to initialize
9142 file->ifdef_stack_ptr ? */
9143 s1->ifdef_stack_ptr = s1->ifdef_stack;
9144 file->ifdef_stack_ptr = s1->ifdef_stack_ptr;
9146 /* XXX: not ANSI compliant: bound checking says error */
9147 vtop = vstack - 1;
9148 s1->pack_stack[0] = 0;
9149 s1->pack_stack_ptr = s1->pack_stack;
9152 /* compile the C file opened in 'file'. Return non zero if errors. */
9153 static int tcc_compile(TCCState *s1)
9155 Sym *define_start;
9156 char buf[512];
9157 volatile int section_sym;
9159 #ifdef INC_DEBUG
9160 printf("%s: **** new file\n", file->filename);
9161 #endif
9162 preprocess_init(s1);
9164 funcname = "";
9165 anon_sym = SYM_FIRST_ANOM;
9167 /* file info: full path + filename */
9168 section_sym = 0; /* avoid warning */
9169 if (do_debug) {
9170 section_sym = put_elf_sym(symtab_section, 0, 0,
9171 ELF32_ST_INFO(STB_LOCAL, STT_SECTION), 0,
9172 text_section->sh_num, NULL);
9173 getcwd(buf, sizeof(buf));
9174 pstrcat(buf, sizeof(buf), "/");
9175 put_stabs_r(buf, N_SO, 0, 0,
9176 text_section->data_offset, text_section, section_sym);
9177 put_stabs_r(file->filename, N_SO, 0, 0,
9178 text_section->data_offset, text_section, section_sym);
9180 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
9181 symbols can be safely used */
9182 put_elf_sym(symtab_section, 0, 0,
9183 ELF32_ST_INFO(STB_LOCAL, STT_FILE), 0,
9184 SHN_ABS, file->filename);
9186 /* define some often used types */
9187 int_type.t = VT_INT;
9189 char_pointer_type.t = VT_BYTE;
9190 mk_pointer(&char_pointer_type);
9192 func_old_type.t = VT_FUNC;
9193 func_old_type.ref = sym_push(SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD);
9195 #if 0
9196 /* define 'void *alloca(unsigned int)' builtin function */
9198 Sym *s1;
9200 p = anon_sym++;
9201 sym = sym_push(p, mk_pointer(VT_VOID), FUNC_CDECL, FUNC_NEW);
9202 s1 = sym_push(SYM_FIELD, VT_UNSIGNED | VT_INT, 0, 0);
9203 s1->next = NULL;
9204 sym->next = s1;
9205 sym_push(TOK_alloca, VT_FUNC | (p << VT_STRUCT_SHIFT), VT_CONST, 0);
9207 #endif
9209 define_start = define_stack;
9211 if (setjmp(s1->error_jmp_buf) == 0) {
9212 s1->nb_errors = 0;
9213 s1->error_set_jmp_enabled = 1;
9215 ch = file->buf_ptr[0];
9216 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
9217 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM;
9218 next();
9219 decl(VT_CONST);
9220 if (tok != TOK_EOF)
9221 expect("declaration");
9223 /* end of translation unit info */
9224 if (do_debug) {
9225 put_stabs_r(NULL, N_SO, 0, 0,
9226 text_section->data_offset, text_section, section_sym);
9229 s1->error_set_jmp_enabled = 0;
9231 /* reset define stack, but leave -Dsymbols (may be incorrect if
9232 they are undefined) */
9233 free_defines(define_start);
9235 gen_inline_functions();
9237 sym_pop(&global_stack, NULL);
9239 return s1->nb_errors != 0 ? -1 : 0;
9242 #ifdef LIBTCC
9243 int tcc_compile_string(TCCState *s, const char *str)
9245 BufferedFile bf1, *bf = &bf1;
9246 int ret, len;
9247 char *buf;
9249 /* init file structure */
9250 bf->fd = -1;
9251 /* XXX: avoid copying */
9252 len = strlen(str);
9253 buf = tcc_malloc(len + 1);
9254 if (!buf)
9255 return -1;
9256 memcpy(buf, str, len);
9257 buf[len] = CH_EOB;
9258 bf->buf_ptr = buf;
9259 bf->buf_end = buf + len;
9260 pstrcpy(bf->filename, sizeof(bf->filename), "<string>");
9261 bf->line_num = 1;
9262 file = bf;
9264 ret = tcc_compile(s);
9266 tcc_free(buf);
9268 /* currently, no need to close */
9269 return ret;
9271 #endif
9273 /* define a preprocessor symbol. A value can also be provided with the '=' operator */
9274 void tcc_define_symbol(TCCState *s1, const char *sym, const char *value)
9276 BufferedFile bf1, *bf = &bf1;
9278 pstrcpy(bf->buffer, IO_BUF_SIZE, sym);
9279 pstrcat(bf->buffer, IO_BUF_SIZE, " ");
9280 /* default value */
9281 if (!value)
9282 value = "1";
9283 pstrcat(bf->buffer, IO_BUF_SIZE, value);
9285 /* init file structure */
9286 bf->fd = -1;
9287 bf->buf_ptr = bf->buffer;
9288 bf->buf_end = bf->buffer + strlen(bf->buffer);
9289 *bf->buf_end = CH_EOB;
9290 bf->filename[0] = '\0';
9291 bf->line_num = 1;
9292 file = bf;
9294 s1->include_stack_ptr = s1->include_stack;
9296 /* parse with define parser */
9297 ch = file->buf_ptr[0];
9298 next_nomacro();
9299 parse_define();
9300 file = NULL;
9303 /* undefine a preprocessor symbol */
9304 void tcc_undefine_symbol(TCCState *s1, const char *sym)
9306 TokenSym *ts;
9307 Sym *s;
9308 ts = tok_alloc(sym, strlen(sym));
9309 s = define_find(ts->tok);
9310 /* undefine symbol by putting an invalid name */
9311 if (s)
9312 define_undef(s);
9315 #ifdef CONFIG_TCC_ASM
9317 #ifdef TCC_TARGET_I386
9318 #include "i386-asm.c"
9319 #endif
9320 #include "tccasm.c"
9322 #else
9323 static void asm_instr(void)
9325 error("inline asm() not supported");
9327 static void asm_global_instr(void)
9329 error("inline asm() not supported");
9331 #endif
9333 #include "tccelf.c"
9335 #ifdef TCC_TARGET_COFF
9336 #include "tcccoff.c"
9337 #endif
9339 #ifdef TCC_TARGET_PE
9340 #include "tccpe.c"
9341 #endif
9343 /* print the position in the source file of PC value 'pc' by reading
9344 the stabs debug information */
9345 static void rt_printline(unsigned long wanted_pc)
9347 Stab_Sym *sym, *sym_end;
9348 char func_name[128], last_func_name[128];
9349 unsigned long func_addr, last_pc, pc;
9350 const char *incl_files[INCLUDE_STACK_SIZE];
9351 int incl_index, len, last_line_num, i;
9352 const char *str, *p;
9354 fprintf(stderr, "0x%08lx:", wanted_pc);
9356 func_name[0] = '\0';
9357 func_addr = 0;
9358 incl_index = 0;
9359 last_func_name[0] = '\0';
9360 last_pc = 0xffffffff;
9361 last_line_num = 1;
9362 sym = (Stab_Sym *)stab_section->data + 1;
9363 sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset);
9364 while (sym < sym_end) {
9365 switch(sym->n_type) {
9366 /* function start or end */
9367 case N_FUN:
9368 if (sym->n_strx == 0) {
9369 /* we test if between last line and end of function */
9370 pc = sym->n_value + func_addr;
9371 if (wanted_pc >= last_pc && wanted_pc < pc)
9372 goto found;
9373 func_name[0] = '\0';
9374 func_addr = 0;
9375 } else {
9376 str = stabstr_section->data + sym->n_strx;
9377 p = strchr(str, ':');
9378 if (!p) {
9379 pstrcpy(func_name, sizeof(func_name), str);
9380 } else {
9381 len = p - str;
9382 if (len > sizeof(func_name) - 1)
9383 len = sizeof(func_name) - 1;
9384 memcpy(func_name, str, len);
9385 func_name[len] = '\0';
9387 func_addr = sym->n_value;
9389 break;
9390 /* line number info */
9391 case N_SLINE:
9392 pc = sym->n_value + func_addr;
9393 if (wanted_pc >= last_pc && wanted_pc < pc)
9394 goto found;
9395 last_pc = pc;
9396 last_line_num = sym->n_desc;
9397 /* XXX: slow! */
9398 strcpy(last_func_name, func_name);
9399 break;
9400 /* include files */
9401 case N_BINCL:
9402 str = stabstr_section->data + sym->n_strx;
9403 add_incl:
9404 if (incl_index < INCLUDE_STACK_SIZE) {
9405 incl_files[incl_index++] = str;
9407 break;
9408 case N_EINCL:
9409 if (incl_index > 1)
9410 incl_index--;
9411 break;
9412 case N_SO:
9413 if (sym->n_strx == 0) {
9414 incl_index = 0; /* end of translation unit */
9415 } else {
9416 str = stabstr_section->data + sym->n_strx;
9417 /* do not add path */
9418 len = strlen(str);
9419 if (len > 0 && str[len - 1] != '/')
9420 goto add_incl;
9422 break;
9424 sym++;
9427 /* second pass: we try symtab symbols (no line number info) */
9428 incl_index = 0;
9430 Elf32_Sym *sym, *sym_end;
9431 int type;
9433 sym_end = (Elf32_Sym *)(symtab_section->data + symtab_section->data_offset);
9434 for(sym = (Elf32_Sym *)symtab_section->data + 1;
9435 sym < sym_end;
9436 sym++) {
9437 type = ELF32_ST_TYPE(sym->st_info);
9438 if (type == STT_FUNC) {
9439 if (wanted_pc >= sym->st_value &&
9440 wanted_pc < sym->st_value + sym->st_size) {
9441 pstrcpy(last_func_name, sizeof(last_func_name),
9442 strtab_section->data + sym->st_name);
9443 goto found;
9448 /* did not find any info: */
9449 fprintf(stderr, " ???\n");
9450 return;
9451 found:
9452 if (last_func_name[0] != '\0') {
9453 fprintf(stderr, " %s()", last_func_name);
9455 if (incl_index > 0) {
9456 fprintf(stderr, " (%s:%d",
9457 incl_files[incl_index - 1], last_line_num);
9458 for(i = incl_index - 2; i >= 0; i--)
9459 fprintf(stderr, ", included from %s", incl_files[i]);
9460 fprintf(stderr, ")");
9462 fprintf(stderr, "\n");
9465 #if !defined(WIN32) && !defined(CONFIG_TCCBOOT)
9467 #ifdef __i386__
9469 /* fix for glibc 2.1 */
9470 #ifndef REG_EIP
9471 #define REG_EIP EIP
9472 #define REG_EBP EBP
9473 #endif
9475 /* return the PC at frame level 'level'. Return non zero if not found */
9476 static int rt_get_caller_pc(unsigned long *paddr,
9477 ucontext_t *uc, int level)
9479 unsigned long fp;
9480 int i;
9482 if (level == 0) {
9483 #if defined(__FreeBSD__)
9484 *paddr = uc->uc_mcontext.mc_eip;
9485 #elif defined(__dietlibc__)
9486 *paddr = uc->uc_mcontext.eip;
9487 #else
9488 *paddr = uc->uc_mcontext.gregs[REG_EIP];
9489 #endif
9490 return 0;
9491 } else {
9492 #if defined(__FreeBSD__)
9493 fp = uc->uc_mcontext.mc_ebp;
9494 #elif defined(__dietlibc__)
9495 fp = uc->uc_mcontext.ebp;
9496 #else
9497 fp = uc->uc_mcontext.gregs[REG_EBP];
9498 #endif
9499 for(i=1;i<level;i++) {
9500 /* XXX: check address validity with program info */
9501 if (fp <= 0x1000 || fp >= 0xc0000000)
9502 return -1;
9503 fp = ((unsigned long *)fp)[0];
9505 *paddr = ((unsigned long *)fp)[1];
9506 return 0;
9509 #else
9511 #warning add arch specific rt_get_caller_pc()
9513 static int rt_get_caller_pc(unsigned long *paddr,
9514 ucontext_t *uc, int level)
9516 return -1;
9518 #endif
9520 /* emit a run time error at position 'pc' */
9521 void rt_error(ucontext_t *uc, const char *fmt, ...)
9523 va_list ap;
9524 unsigned long pc;
9525 int i;
9527 va_start(ap, fmt);
9528 fprintf(stderr, "Runtime error: ");
9529 vfprintf(stderr, fmt, ap);
9530 fprintf(stderr, "\n");
9531 for(i=0;i<num_callers;i++) {
9532 if (rt_get_caller_pc(&pc, uc, i) < 0)
9533 break;
9534 if (i == 0)
9535 fprintf(stderr, "at ");
9536 else
9537 fprintf(stderr, "by ");
9538 rt_printline(pc);
9540 exit(255);
9541 va_end(ap);
9544 /* signal handler for fatal errors */
9545 static void sig_error(int signum, siginfo_t *siginf, void *puc)
9547 ucontext_t *uc = puc;
9549 switch(signum) {
9550 case SIGFPE:
9551 switch(siginf->si_code) {
9552 case FPE_INTDIV:
9553 case FPE_FLTDIV:
9554 rt_error(uc, "division by zero");
9555 break;
9556 default:
9557 rt_error(uc, "floating point exception");
9558 break;
9560 break;
9561 case SIGBUS:
9562 case SIGSEGV:
9563 if (rt_bound_error_msg && *rt_bound_error_msg)
9564 rt_error(uc, *rt_bound_error_msg);
9565 else
9566 rt_error(uc, "dereferencing invalid pointer");
9567 break;
9568 case SIGILL:
9569 rt_error(uc, "illegal instruction");
9570 break;
9571 case SIGABRT:
9572 rt_error(uc, "abort() called");
9573 break;
9574 default:
9575 rt_error(uc, "caught signal %d", signum);
9576 break;
9578 exit(255);
9580 #endif
9582 /* do all relocations (needed before using tcc_get_symbol()) */
9583 int tcc_relocate(TCCState *s1)
9585 Section *s;
9586 int i;
9588 s1->nb_errors = 0;
9590 #ifdef TCC_TARGET_PE
9591 pe_add_runtime(s1);
9592 #else
9593 tcc_add_runtime(s1);
9594 #endif
9596 relocate_common_syms();
9598 tcc_add_linker_symbols(s1);
9600 build_got_entries(s1);
9602 /* compute relocation address : section are relocated in place. We
9603 also alloc the bss space */
9604 for(i = 1; i < s1->nb_sections; i++) {
9605 s = s1->sections[i];
9606 if (s->sh_flags & SHF_ALLOC) {
9607 if (s->sh_type == SHT_NOBITS)
9608 s->data = tcc_mallocz(s->data_offset);
9609 s->sh_addr = (unsigned long)s->data;
9613 relocate_syms(s1, 1);
9615 if (s1->nb_errors != 0)
9616 return -1;
9618 /* relocate each section */
9619 for(i = 1; i < s1->nb_sections; i++) {
9620 s = s1->sections[i];
9621 if (s->reloc)
9622 relocate_section(s1, s);
9625 /* mark executable sections as executable in memory */
9626 for(i = 1; i < s1->nb_sections; i++) {
9627 s = s1->sections[i];
9628 if ((s->sh_flags & (SHF_ALLOC | SHF_EXECINSTR)) ==
9629 (SHF_ALLOC | SHF_EXECINSTR)) {
9630 #ifdef WIN32
9632 DWORD old_protect;
9633 VirtualProtect(s->data, s->data_offset,
9634 PAGE_EXECUTE_READWRITE, &old_protect);
9636 #else
9638 unsigned long start, end;
9639 start = (unsigned long)(s->data) & ~(PAGESIZE - 1);
9640 end = (unsigned long)(s->data + s->data_offset);
9641 end = (end + PAGESIZE - 1) & ~(PAGESIZE - 1);
9642 mprotect((void *)start, end - start,
9643 PROT_READ | PROT_WRITE | PROT_EXEC);
9645 #endif
9648 return 0;
9651 /* launch the compiled program with the given arguments */
9652 int tcc_run(TCCState *s1, int argc, char **argv)
9654 int (*prog_main)(int, char **);
9656 if (tcc_relocate(s1) < 0)
9657 return -1;
9659 prog_main = tcc_get_symbol_err(s1, "main");
9661 if (do_debug) {
9662 #if defined(WIN32) || defined(CONFIG_TCCBOOT)
9663 error("debug mode currently not available for Windows");
9664 #else
9665 struct sigaction sigact;
9666 /* install TCC signal handlers to print debug info on fatal
9667 runtime errors */
9668 sigact.sa_flags = SA_SIGINFO | SA_RESETHAND;
9669 sigact.sa_sigaction = sig_error;
9670 sigemptyset(&sigact.sa_mask);
9671 sigaction(SIGFPE, &sigact, NULL);
9672 sigaction(SIGILL, &sigact, NULL);
9673 sigaction(SIGSEGV, &sigact, NULL);
9674 sigaction(SIGBUS, &sigact, NULL);
9675 sigaction(SIGABRT, &sigact, NULL);
9676 #endif
9679 #ifdef CONFIG_TCC_BCHECK
9680 if (do_bounds_check) {
9681 void (*bound_init)(void);
9683 /* set error function */
9684 rt_bound_error_msg = (void *)tcc_get_symbol_err(s1,
9685 "__bound_error_msg");
9687 /* XXX: use .init section so that it also work in binary ? */
9688 bound_init = (void *)tcc_get_symbol_err(s1, "__bound_init");
9689 bound_init();
9691 #endif
9692 return (*prog_main)(argc, argv);
9695 TCCState *tcc_new(void)
9697 const char *p, *r;
9698 TCCState *s;
9699 TokenSym *ts;
9700 int i, c;
9702 s = tcc_mallocz(sizeof(TCCState));
9703 if (!s)
9704 return NULL;
9705 tcc_state = s;
9706 s->output_type = TCC_OUTPUT_MEMORY;
9708 /* init isid table */
9709 for(i=0;i<256;i++)
9710 isidnum_table[i] = isid(i) || isnum(i);
9712 /* add all tokens */
9713 table_ident = NULL;
9714 memset(hash_ident, 0, TOK_HASH_SIZE * sizeof(TokenSym *));
9716 tok_ident = TOK_IDENT;
9717 p = tcc_keywords;
9718 while (*p) {
9719 r = p;
9720 for(;;) {
9721 c = *r++;
9722 if (c == '\0')
9723 break;
9725 ts = tok_alloc(p, r - p - 1);
9726 p = r;
9729 /* we add dummy defines for some special macros to speed up tests
9730 and to have working defined() */
9731 define_push(TOK___LINE__, MACRO_OBJ, NULL, NULL);
9732 define_push(TOK___FILE__, MACRO_OBJ, NULL, NULL);
9733 define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL);
9734 define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL);
9736 /* standard defines */
9737 tcc_define_symbol(s, "__STDC__", NULL);
9738 #if defined(TCC_TARGET_I386)
9739 tcc_define_symbol(s, "__i386__", NULL);
9740 #endif
9741 #if defined(TCC_TARGET_ARM)
9742 tcc_define_symbol(s, "__ARM_ARCH_4__", NULL);
9743 tcc_define_symbol(s, "__arm_elf__", NULL);
9744 tcc_define_symbol(s, "__arm_elf", NULL);
9745 tcc_define_symbol(s, "arm_elf", NULL);
9746 tcc_define_symbol(s, "__arm__", NULL);
9747 tcc_define_symbol(s, "__arm", NULL);
9748 tcc_define_symbol(s, "arm", NULL);
9749 tcc_define_symbol(s, "__APCS_32__", NULL);
9750 #endif
9751 #if defined(linux)
9752 tcc_define_symbol(s, "__linux__", NULL);
9753 tcc_define_symbol(s, "linux", NULL);
9754 #endif
9755 /* tiny C specific defines */
9756 tcc_define_symbol(s, "__TINYC__", NULL);
9758 /* tiny C & gcc defines */
9759 tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned int");
9760 tcc_define_symbol(s, "__PTRDIFF_TYPE__", "int");
9761 tcc_define_symbol(s, "__WCHAR_TYPE__", "int");
9763 /* default library paths */
9764 #ifdef TCC_TARGET_PE
9766 char buf[1024];
9767 snprintf(buf, sizeof(buf), "%s/lib", tcc_lib_path);
9768 tcc_add_library_path(s, buf);
9770 #else
9771 tcc_add_library_path(s, "/usr/local/lib");
9772 tcc_add_library_path(s, "/usr/lib");
9773 tcc_add_library_path(s, "/lib");
9774 #endif
9776 /* no section zero */
9777 dynarray_add((void ***)&s->sections, &s->nb_sections, NULL);
9779 /* create standard sections */
9780 text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
9781 data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
9782 bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
9784 /* symbols are always generated for linking stage */
9785 symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0,
9786 ".strtab",
9787 ".hashtab", SHF_PRIVATE);
9788 strtab_section = symtab_section->link;
9790 /* private symbol table for dynamic symbols */
9791 s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE,
9792 ".dynstrtab",
9793 ".dynhashtab", SHF_PRIVATE);
9794 s->alacarte_link = 1;
9796 #ifdef CHAR_IS_UNSIGNED
9797 s->char_is_unsigned = 1;
9798 #endif
9799 #if defined(TCC_TARGET_PE) && 0
9800 /* XXX: currently the PE linker is not ready to support that */
9801 s->leading_underscore = 1;
9802 #endif
9803 return s;
9806 void tcc_delete(TCCState *s1)
9808 int i, n;
9810 /* free -D defines */
9811 free_defines(NULL);
9813 /* free tokens */
9814 n = tok_ident - TOK_IDENT;
9815 for(i = 0; i < n; i++)
9816 tcc_free(table_ident[i]);
9817 tcc_free(table_ident);
9819 /* free all sections */
9821 free_section(symtab_section->hash);
9823 free_section(s1->dynsymtab_section->hash);
9824 free_section(s1->dynsymtab_section->link);
9825 free_section(s1->dynsymtab_section);
9827 for(i = 1; i < s1->nb_sections; i++)
9828 free_section(s1->sections[i]);
9829 tcc_free(s1->sections);
9831 /* free loaded dlls array */
9832 for(i = 0; i < s1->nb_loaded_dlls; i++)
9833 tcc_free(s1->loaded_dlls[i]);
9834 tcc_free(s1->loaded_dlls);
9836 /* library paths */
9837 for(i = 0; i < s1->nb_library_paths; i++)
9838 tcc_free(s1->library_paths[i]);
9839 tcc_free(s1->library_paths);
9841 /* cached includes */
9842 for(i = 0; i < s1->nb_cached_includes; i++)
9843 tcc_free(s1->cached_includes[i]);
9844 tcc_free(s1->cached_includes);
9846 for(i = 0; i < s1->nb_include_paths; i++)
9847 tcc_free(s1->include_paths[i]);
9848 tcc_free(s1->include_paths);
9850 for(i = 0; i < s1->nb_sysinclude_paths; i++)
9851 tcc_free(s1->sysinclude_paths[i]);
9852 tcc_free(s1->sysinclude_paths);
9854 tcc_free(s1);
9857 int tcc_add_include_path(TCCState *s1, const char *pathname)
9859 char *pathname1;
9861 pathname1 = tcc_strdup(pathname);
9862 dynarray_add((void ***)&s1->include_paths, &s1->nb_include_paths, pathname1);
9863 return 0;
9866 int tcc_add_sysinclude_path(TCCState *s1, const char *pathname)
9868 char *pathname1;
9870 pathname1 = tcc_strdup(pathname);
9871 dynarray_add((void ***)&s1->sysinclude_paths, &s1->nb_sysinclude_paths, pathname1);
9872 return 0;
9875 static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
9877 const char *ext, *filename1;
9878 Elf32_Ehdr ehdr;
9879 int fd, ret;
9880 BufferedFile *saved_file;
9882 /* find source file type with extension */
9883 filename1 = strrchr(filename, '/');
9884 if (filename1)
9885 filename1++;
9886 else
9887 filename1 = filename;
9888 ext = strrchr(filename1, '.');
9889 if (ext)
9890 ext++;
9892 /* open the file */
9893 saved_file = file;
9894 file = tcc_open(s1, filename);
9895 if (!file) {
9896 if (flags & AFF_PRINT_ERROR) {
9897 error_noabort("file '%s' not found", filename);
9899 ret = -1;
9900 goto fail1;
9903 if (!ext || !strcmp(ext, "c")) {
9904 /* C file assumed */
9905 ret = tcc_compile(s1);
9906 } else
9907 #ifdef CONFIG_TCC_ASM
9908 if (!strcmp(ext, "S")) {
9909 /* preprocessed assembler */
9910 ret = tcc_assemble(s1, 1);
9911 } else if (!strcmp(ext, "s")) {
9912 /* non preprocessed assembler */
9913 ret = tcc_assemble(s1, 0);
9914 } else
9915 #endif
9916 #ifdef TCC_TARGET_PE
9917 if (!strcmp(ext, "def")) {
9918 ret = pe_load_def_file(s1, fdopen(file->fd, "rb"));
9919 } else
9920 #endif
9922 fd = file->fd;
9923 /* assume executable format: auto guess file type */
9924 ret = read(fd, &ehdr, sizeof(ehdr));
9925 lseek(fd, 0, SEEK_SET);
9926 if (ret <= 0) {
9927 error_noabort("could not read header");
9928 goto fail;
9929 } else if (ret != sizeof(ehdr)) {
9930 goto try_load_script;
9933 if (ehdr.e_ident[0] == ELFMAG0 &&
9934 ehdr.e_ident[1] == ELFMAG1 &&
9935 ehdr.e_ident[2] == ELFMAG2 &&
9936 ehdr.e_ident[3] == ELFMAG3) {
9937 file->line_num = 0; /* do not display line number if error */
9938 if (ehdr.e_type == ET_REL) {
9939 ret = tcc_load_object_file(s1, fd, 0);
9940 } else if (ehdr.e_type == ET_DYN) {
9941 if (s1->output_type == TCC_OUTPUT_MEMORY) {
9942 #ifdef TCC_TARGET_PE
9943 ret = -1;
9944 #else
9945 void *h;
9946 h = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY);
9947 if (h)
9948 ret = 0;
9949 else
9950 ret = -1;
9951 #endif
9952 } else {
9953 ret = tcc_load_dll(s1, fd, filename,
9954 (flags & AFF_REFERENCED_DLL) != 0);
9956 } else {
9957 error_noabort("unrecognized ELF file");
9958 goto fail;
9960 } else if (memcmp((char *)&ehdr, ARMAG, 8) == 0) {
9961 file->line_num = 0; /* do not display line number if error */
9962 ret = tcc_load_archive(s1, fd);
9963 } else
9964 #ifdef TCC_TARGET_COFF
9965 if (*(uint16_t *)(&ehdr) == COFF_C67_MAGIC) {
9966 ret = tcc_load_coff(s1, fd);
9967 } else
9968 #endif
9970 /* as GNU ld, consider it is an ld script if not recognized */
9971 try_load_script:
9972 ret = tcc_load_ldscript(s1);
9973 if (ret < 0) {
9974 error_noabort("unrecognized file type");
9975 goto fail;
9979 the_end:
9980 tcc_close(file);
9981 fail1:
9982 file = saved_file;
9983 return ret;
9984 fail:
9985 ret = -1;
9986 goto the_end;
9989 int tcc_add_file(TCCState *s, const char *filename)
9991 return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR);
9994 int tcc_add_library_path(TCCState *s, const char *pathname)
9996 char *pathname1;
9998 pathname1 = tcc_strdup(pathname);
9999 dynarray_add((void ***)&s->library_paths, &s->nb_library_paths, pathname1);
10000 return 0;
10003 /* find and load a dll. Return non zero if not found */
10004 /* XXX: add '-rpath' option support ? */
10005 static int tcc_add_dll(TCCState *s, const char *filename, int flags)
10007 char buf[1024];
10008 int i;
10010 for(i = 0; i < s->nb_library_paths; i++) {
10011 snprintf(buf, sizeof(buf), "%s/%s",
10012 s->library_paths[i], filename);
10013 if (tcc_add_file_internal(s, buf, flags) == 0)
10014 return 0;
10016 return -1;
10019 /* the library name is the same as the argument of the '-l' option */
10020 int tcc_add_library(TCCState *s, const char *libraryname)
10022 char buf[1024];
10023 int i;
10025 /* first we look for the dynamic library if not static linking */
10026 if (!s->static_link) {
10027 #ifdef TCC_TARGET_PE
10028 snprintf(buf, sizeof(buf), "%s.def", libraryname);
10029 #else
10030 snprintf(buf, sizeof(buf), "lib%s.so", libraryname);
10031 #endif
10032 if (tcc_add_dll(s, buf, 0) == 0)
10033 return 0;
10036 /* then we look for the static library */
10037 for(i = 0; i < s->nb_library_paths; i++) {
10038 snprintf(buf, sizeof(buf), "%s/lib%s.a",
10039 s->library_paths[i], libraryname);
10040 if (tcc_add_file_internal(s, buf, 0) == 0)
10041 return 0;
10043 return -1;
10046 int tcc_add_symbol(TCCState *s, const char *name, unsigned long val)
10048 add_elf_sym(symtab_section, val, 0,
10049 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
10050 SHN_ABS, name);
10051 return 0;
10054 int tcc_set_output_type(TCCState *s, int output_type)
10056 s->output_type = output_type;
10058 if (!s->nostdinc) {
10059 char buf[1024];
10061 /* default include paths */
10062 /* XXX: reverse order needed if -isystem support */
10063 #ifndef TCC_TARGET_PE
10064 tcc_add_sysinclude_path(s, "/usr/local/include");
10065 tcc_add_sysinclude_path(s, "/usr/include");
10066 #endif
10067 snprintf(buf, sizeof(buf), "%s/include", tcc_lib_path);
10068 tcc_add_sysinclude_path(s, buf);
10069 #ifdef TCC_TARGET_PE
10070 snprintf(buf, sizeof(buf), "%s/include/winapi", tcc_lib_path);
10071 tcc_add_sysinclude_path(s, buf);
10072 #endif
10075 /* if bound checking, then add corresponding sections */
10076 #ifdef CONFIG_TCC_BCHECK
10077 if (do_bounds_check) {
10078 /* define symbol */
10079 tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL);
10080 /* create bounds sections */
10081 bounds_section = new_section(s, ".bounds",
10082 SHT_PROGBITS, SHF_ALLOC);
10083 lbounds_section = new_section(s, ".lbounds",
10084 SHT_PROGBITS, SHF_ALLOC);
10086 #endif
10088 if (s->char_is_unsigned) {
10089 tcc_define_symbol(s, "__CHAR_UNSIGNED__", NULL);
10092 /* add debug sections */
10093 if (do_debug) {
10094 /* stab symbols */
10095 stab_section = new_section(s, ".stab", SHT_PROGBITS, 0);
10096 stab_section->sh_entsize = sizeof(Stab_Sym);
10097 stabstr_section = new_section(s, ".stabstr", SHT_STRTAB, 0);
10098 put_elf_str(stabstr_section, "");
10099 stab_section->link = stabstr_section;
10100 /* put first entry */
10101 put_stabs("", 0, 0, 0, 0);
10104 /* add libc crt1/crti objects */
10105 #ifndef TCC_TARGET_PE
10106 if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) &&
10107 !s->nostdlib) {
10108 if (output_type != TCC_OUTPUT_DLL)
10109 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crt1.o");
10110 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crti.o");
10112 #endif
10113 return 0;
10116 #define WD_ALL 0x0001 /* warning is activated when using -Wall */
10117 #define FD_INVERT 0x0002 /* invert value before storing */
10119 typedef struct FlagDef {
10120 uint16_t offset;
10121 uint16_t flags;
10122 const char *name;
10123 } FlagDef;
10125 static const FlagDef warning_defs[] = {
10126 { offsetof(TCCState, warn_unsupported), 0, "unsupported" },
10127 { offsetof(TCCState, warn_write_strings), 0, "write-strings" },
10128 { offsetof(TCCState, warn_error), 0, "error" },
10129 { offsetof(TCCState, warn_implicit_function_declaration), WD_ALL,
10130 "implicit-function-declaration" },
10133 static int set_flag(TCCState *s, const FlagDef *flags, int nb_flags,
10134 const char *name, int value)
10136 int i;
10137 const FlagDef *p;
10138 const char *r;
10140 r = name;
10141 if (r[0] == 'n' && r[1] == 'o' && r[2] == '-') {
10142 r += 3;
10143 value = !value;
10145 for(i = 0, p = flags; i < nb_flags; i++, p++) {
10146 if (!strcmp(r, p->name))
10147 goto found;
10149 return -1;
10150 found:
10151 if (p->flags & FD_INVERT)
10152 value = !value;
10153 *(int *)((uint8_t *)s + p->offset) = value;
10154 return 0;
10158 /* set/reset a warning */
10159 int tcc_set_warning(TCCState *s, const char *warning_name, int value)
10161 int i;
10162 const FlagDef *p;
10164 if (!strcmp(warning_name, "all")) {
10165 for(i = 0, p = warning_defs; i < countof(warning_defs); i++, p++) {
10166 if (p->flags & WD_ALL)
10167 *(int *)((uint8_t *)s + p->offset) = 1;
10169 return 0;
10170 } else {
10171 return set_flag(s, warning_defs, countof(warning_defs),
10172 warning_name, value);
10176 static const FlagDef flag_defs[] = {
10177 { offsetof(TCCState, char_is_unsigned), 0, "unsigned-char" },
10178 { offsetof(TCCState, char_is_unsigned), FD_INVERT, "signed-char" },
10179 { offsetof(TCCState, nocommon), FD_INVERT, "common" },
10180 { offsetof(TCCState, leading_underscore), 0, "leading-underscore" },
10183 /* set/reset a flag */
10184 int tcc_set_flag(TCCState *s, const char *flag_name, int value)
10186 return set_flag(s, flag_defs, countof(flag_defs),
10187 flag_name, value);
10190 #if !defined(LIBTCC)
10192 /* extract the basename of a file */
10193 static const char *tcc_basename(const char *name)
10195 const char *p;
10196 p = strrchr(name, '/');
10197 #ifdef WIN32
10198 if (!p)
10199 p = strrchr(name, '\\');
10200 #endif
10201 if (!p)
10202 p = name;
10203 else
10204 p++;
10205 return p;
10208 static int64_t getclock_us(void)
10210 #ifdef WIN32
10211 struct _timeb tb;
10212 _ftime(&tb);
10213 return (tb.time * 1000LL + tb.millitm) * 1000LL;
10214 #else
10215 struct timeval tv;
10216 gettimeofday(&tv, NULL);
10217 return tv.tv_sec * 1000000LL + tv.tv_usec;
10218 #endif
10221 void help(void)
10223 printf("tcc version " TCC_VERSION " - Tiny C Compiler - Copyright (C) 2001-2005 Fabrice Bellard\n"
10224 "usage: tcc [-v] [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
10225 " [-Wwarn] [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-static]\n"
10226 " [infile1 infile2...] [-run infile args...]\n"
10227 "\n"
10228 "General options:\n"
10229 " -v display current version\n"
10230 " -c compile only - generate an object file\n"
10231 " -o outfile set output filename\n"
10232 " -Bdir set tcc internal library path\n"
10233 " -bench output compilation statistics\n"
10234 " -run run compiled source\n"
10235 " -fflag set or reset (with 'no-' prefix) 'flag' (see man page)\n"
10236 " -Wwarning set or reset (with 'no-' prefix) 'warning' (see man page)\n"
10237 " -w disable all warnings\n"
10238 "Preprocessor options:\n"
10239 " -Idir add include path 'dir'\n"
10240 " -Dsym[=val] define 'sym' with value 'val'\n"
10241 " -Usym undefine 'sym'\n"
10242 "Linker options:\n"
10243 " -Ldir add library path 'dir'\n"
10244 " -llib link with dynamic or static library 'lib'\n"
10245 " -shared generate a shared library\n"
10246 " -static static linking\n"
10247 " -rdynamic export all global symbols to dynamic linker\n"
10248 " -r relocatable output\n"
10249 "Debugger options:\n"
10250 " -g generate runtime debug info\n"
10251 #ifdef CONFIG_TCC_BCHECK
10252 " -b compile with built-in memory and bounds checker (implies -g)\n"
10253 #endif
10254 " -bt N show N callers in stack traces\n"
10258 #define TCC_OPTION_HAS_ARG 0x0001
10259 #define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
10261 typedef struct TCCOption {
10262 const char *name;
10263 uint16_t index;
10264 uint16_t flags;
10265 } TCCOption;
10267 enum {
10268 TCC_OPTION_HELP,
10269 TCC_OPTION_I,
10270 TCC_OPTION_D,
10271 TCC_OPTION_U,
10272 TCC_OPTION_L,
10273 TCC_OPTION_B,
10274 TCC_OPTION_l,
10275 TCC_OPTION_bench,
10276 TCC_OPTION_bt,
10277 TCC_OPTION_b,
10278 TCC_OPTION_g,
10279 TCC_OPTION_c,
10280 TCC_OPTION_static,
10281 TCC_OPTION_shared,
10282 TCC_OPTION_o,
10283 TCC_OPTION_r,
10284 TCC_OPTION_Wl,
10285 TCC_OPTION_W,
10286 TCC_OPTION_O,
10287 TCC_OPTION_m,
10288 TCC_OPTION_f,
10289 TCC_OPTION_nostdinc,
10290 TCC_OPTION_nostdlib,
10291 TCC_OPTION_print_search_dirs,
10292 TCC_OPTION_rdynamic,
10293 TCC_OPTION_run,
10294 TCC_OPTION_v,
10295 TCC_OPTION_w,
10296 TCC_OPTION_pipe,
10299 static const TCCOption tcc_options[] = {
10300 { "h", TCC_OPTION_HELP, 0 },
10301 { "?", TCC_OPTION_HELP, 0 },
10302 { "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG },
10303 { "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG },
10304 { "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG },
10305 { "L", TCC_OPTION_L, TCC_OPTION_HAS_ARG },
10306 { "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG },
10307 { "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10308 { "bench", TCC_OPTION_bench, 0 },
10309 { "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG },
10310 #ifdef CONFIG_TCC_BCHECK
10311 { "b", TCC_OPTION_b, 0 },
10312 #endif
10313 { "g", TCC_OPTION_g, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10314 { "c", TCC_OPTION_c, 0 },
10315 { "static", TCC_OPTION_static, 0 },
10316 { "shared", TCC_OPTION_shared, 0 },
10317 { "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG },
10318 { "run", TCC_OPTION_run, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10319 { "rdynamic", TCC_OPTION_rdynamic, 0 },
10320 { "r", TCC_OPTION_r, 0 },
10321 { "Wl,", TCC_OPTION_Wl, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10322 { "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10323 { "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10324 { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG },
10325 { "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10326 { "nostdinc", TCC_OPTION_nostdinc, 0 },
10327 { "nostdlib", TCC_OPTION_nostdlib, 0 },
10328 { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 },
10329 { "v", TCC_OPTION_v, 0 },
10330 { "w", TCC_OPTION_w, 0 },
10331 { "pipe", TCC_OPTION_pipe, 0},
10332 { NULL },
10335 /* convert 'str' into an array of space separated strings */
10336 static int expand_args(char ***pargv, const char *str)
10338 const char *s1;
10339 char **argv, *arg;
10340 int argc, len;
10342 argc = 0;
10343 argv = NULL;
10344 for(;;) {
10345 while (is_space(*str))
10346 str++;
10347 if (*str == '\0')
10348 break;
10349 s1 = str;
10350 while (*str != '\0' && !is_space(*str))
10351 str++;
10352 len = str - s1;
10353 arg = tcc_malloc(len + 1);
10354 memcpy(arg, s1, len);
10355 arg[len] = '\0';
10356 dynarray_add((void ***)&argv, &argc, arg);
10358 *pargv = argv;
10359 return argc;
10362 static char **files;
10363 static int nb_files, nb_libraries;
10364 static int multiple_files;
10365 static int print_search_dirs;
10366 static int output_type;
10367 static int reloc_output;
10368 static const char *outfile;
10370 int parse_args(TCCState *s, int argc, char **argv)
10372 int optind;
10373 const TCCOption *popt;
10374 const char *optarg, *p1, *r1;
10375 char *r;
10377 optind = 0;
10378 while (1) {
10379 if (optind >= argc) {
10380 if (nb_files == 0 && !print_search_dirs)
10381 goto show_help;
10382 else
10383 break;
10385 r = argv[optind++];
10386 if (r[0] != '-') {
10387 /* add a new file */
10388 dynarray_add((void ***)&files, &nb_files, r);
10389 if (!multiple_files) {
10390 optind--;
10391 /* argv[0] will be this file */
10392 break;
10394 } else {
10395 /* find option in table (match only the first chars */
10396 popt = tcc_options;
10397 for(;;) {
10398 p1 = popt->name;
10399 if (p1 == NULL)
10400 error("invalid option -- '%s'", r);
10401 r1 = r + 1;
10402 for(;;) {
10403 if (*p1 == '\0')
10404 goto option_found;
10405 if (*r1 != *p1)
10406 break;
10407 p1++;
10408 r1++;
10410 popt++;
10412 option_found:
10413 if (popt->flags & TCC_OPTION_HAS_ARG) {
10414 if (*r1 != '\0' || (popt->flags & TCC_OPTION_NOSEP)) {
10415 optarg = r1;
10416 } else {
10417 if (optind >= argc)
10418 error("argument to '%s' is missing", r);
10419 optarg = argv[optind++];
10421 } else {
10422 if (*r1 != '\0')
10423 goto show_help;
10424 optarg = NULL;
10427 switch(popt->index) {
10428 case TCC_OPTION_HELP:
10429 show_help:
10430 help();
10431 exit(1);
10432 case TCC_OPTION_I:
10433 if (tcc_add_include_path(s, optarg) < 0)
10434 error("too many include paths");
10435 break;
10436 case TCC_OPTION_D:
10438 char *sym, *value;
10439 sym = (char *)optarg;
10440 value = strchr(sym, '=');
10441 if (value) {
10442 *value = '\0';
10443 value++;
10445 tcc_define_symbol(s, sym, value);
10447 break;
10448 case TCC_OPTION_U:
10449 tcc_undefine_symbol(s, optarg);
10450 break;
10451 case TCC_OPTION_L:
10452 tcc_add_library_path(s, optarg);
10453 break;
10454 case TCC_OPTION_B:
10455 /* set tcc utilities path (mainly for tcc development) */
10456 tcc_lib_path = optarg;
10457 break;
10458 case TCC_OPTION_l:
10459 dynarray_add((void ***)&files, &nb_files, r);
10460 nb_libraries++;
10461 break;
10462 case TCC_OPTION_bench:
10463 do_bench = 1;
10464 break;
10465 case TCC_OPTION_bt:
10466 num_callers = atoi(optarg);
10467 break;
10468 #ifdef CONFIG_TCC_BCHECK
10469 case TCC_OPTION_b:
10470 do_bounds_check = 1;
10471 do_debug = 1;
10472 break;
10473 #endif
10474 case TCC_OPTION_g:
10475 do_debug = 1;
10476 break;
10477 case TCC_OPTION_c:
10478 multiple_files = 1;
10479 output_type = TCC_OUTPUT_OBJ;
10480 break;
10481 case TCC_OPTION_static:
10482 s->static_link = 1;
10483 break;
10484 case TCC_OPTION_shared:
10485 output_type = TCC_OUTPUT_DLL;
10486 break;
10487 case TCC_OPTION_o:
10488 multiple_files = 1;
10489 outfile = optarg;
10490 break;
10491 case TCC_OPTION_r:
10492 /* generate a .o merging several output files */
10493 reloc_output = 1;
10494 output_type = TCC_OUTPUT_OBJ;
10495 break;
10496 case TCC_OPTION_nostdinc:
10497 s->nostdinc = 1;
10498 break;
10499 case TCC_OPTION_nostdlib:
10500 s->nostdlib = 1;
10501 break;
10502 case TCC_OPTION_print_search_dirs:
10503 print_search_dirs = 1;
10504 break;
10505 case TCC_OPTION_run:
10507 int argc1;
10508 char **argv1;
10509 argc1 = expand_args(&argv1, optarg);
10510 if (argc1 > 0) {
10511 parse_args(s, argc1, argv1);
10513 multiple_files = 0;
10514 output_type = TCC_OUTPUT_MEMORY;
10516 break;
10517 case TCC_OPTION_v:
10518 printf("tcc version %s\n", TCC_VERSION);
10519 exit(0);
10520 case TCC_OPTION_f:
10521 if (tcc_set_flag(s, optarg, 1) < 0 && s->warn_unsupported)
10522 goto unsupported_option;
10523 break;
10524 case TCC_OPTION_W:
10525 if (tcc_set_warning(s, optarg, 1) < 0 &&
10526 s->warn_unsupported)
10527 goto unsupported_option;
10528 break;
10529 case TCC_OPTION_w:
10530 s->warn_none = 1;
10531 break;
10532 case TCC_OPTION_rdynamic:
10533 s->rdynamic = 1;
10534 break;
10535 case TCC_OPTION_Wl:
10537 const char *p;
10538 if (strstart(optarg, "-Ttext,", &p)) {
10539 s->text_addr = strtoul(p, NULL, 16);
10540 s->has_text_addr = 1;
10541 } else if (strstart(optarg, "--oformat,", &p)) {
10542 if (strstart(p, "elf32-", NULL)) {
10543 s->output_format = TCC_OUTPUT_FORMAT_ELF;
10544 } else if (!strcmp(p, "binary")) {
10545 s->output_format = TCC_OUTPUT_FORMAT_BINARY;
10546 } else
10547 #ifdef TCC_TARGET_COFF
10548 if (!strcmp(p, "coff")) {
10549 s->output_format = TCC_OUTPUT_FORMAT_COFF;
10550 } else
10551 #endif
10553 error("target %s not found", p);
10555 } else {
10556 error("unsupported linker option '%s'", optarg);
10559 break;
10560 default:
10561 if (s->warn_unsupported) {
10562 unsupported_option:
10563 warning("unsupported option '%s'", r);
10565 break;
10569 return optind;
10572 int main(int argc, char **argv)
10574 int i;
10575 TCCState *s;
10576 int nb_objfiles, ret, optind;
10577 char objfilename[1024];
10578 int64_t start_time = 0;
10580 #ifdef WIN32
10581 /* on win32, we suppose the lib and includes are at the location
10582 of 'tcc.exe' */
10584 static char path[1024];
10585 char *p, *d;
10587 GetModuleFileNameA(NULL, path, sizeof path);
10588 p = d = strlwr(path);
10589 while (*d)
10591 if (*d == '\\') *d = '/', p = d;
10592 ++d;
10594 *p = '\0';
10595 tcc_lib_path = path;
10597 #endif
10599 s = tcc_new();
10600 output_type = TCC_OUTPUT_EXE;
10601 outfile = NULL;
10602 multiple_files = 1;
10603 files = NULL;
10604 nb_files = 0;
10605 nb_libraries = 0;
10606 reloc_output = 0;
10607 print_search_dirs = 0;
10609 optind = parse_args(s, argc - 1, argv + 1) + 1;
10611 if (print_search_dirs) {
10612 /* enough for Linux kernel */
10613 printf("install: %s/\n", tcc_lib_path);
10614 return 0;
10617 nb_objfiles = nb_files - nb_libraries;
10619 /* if outfile provided without other options, we output an
10620 executable */
10621 if (outfile && output_type == TCC_OUTPUT_MEMORY)
10622 output_type = TCC_OUTPUT_EXE;
10624 /* check -c consistency : only single file handled. XXX: checks file type */
10625 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
10626 /* accepts only a single input file */
10627 if (nb_objfiles != 1)
10628 error("cannot specify multiple files with -c");
10629 if (nb_libraries != 0)
10630 error("cannot specify libraries with -c");
10633 if (output_type != TCC_OUTPUT_MEMORY) {
10634 if (!outfile) {
10635 /* compute default outfile name */
10636 pstrcpy(objfilename, sizeof(objfilename) - 1,
10637 /* strip path */
10638 tcc_basename(files[0]));
10639 #ifdef TCC_TARGET_PE
10640 pe_guess_outfile(objfilename, output_type);
10641 #else
10642 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
10643 char *ext = strrchr(objfilename, '.');
10644 if (!ext)
10645 goto default_outfile;
10646 /* add .o extension */
10647 strcpy(ext + 1, "o");
10648 } else {
10649 default_outfile:
10650 pstrcpy(objfilename, sizeof(objfilename), "a.out");
10652 #endif
10653 outfile = objfilename;
10657 if (do_bench) {
10658 start_time = getclock_us();
10661 tcc_set_output_type(s, output_type);
10663 /* compile or add each files or library */
10664 for(i = 0;i < nb_files; i++) {
10665 const char *filename;
10667 filename = files[i];
10668 if (filename[0] == '-') {
10669 if (tcc_add_library(s, filename + 2) < 0)
10670 error("cannot find %s", filename);
10671 } else {
10672 if (tcc_add_file(s, filename) < 0) {
10673 ret = 1;
10674 goto the_end;
10679 /* free all files */
10680 tcc_free(files);
10682 if (do_bench) {
10683 double total_time;
10684 total_time = (double)(getclock_us() - start_time) / 1000000.0;
10685 if (total_time < 0.001)
10686 total_time = 0.001;
10687 if (total_bytes < 1)
10688 total_bytes = 1;
10689 printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
10690 tok_ident - TOK_IDENT, total_lines, total_bytes,
10691 total_time, (int)(total_lines / total_time),
10692 total_bytes / total_time / 1000000.0);
10695 if (s->output_type == TCC_OUTPUT_MEMORY) {
10696 ret = tcc_run(s, argc - optind, argv + optind);
10697 } else
10698 #ifdef TCC_TARGET_PE
10699 if (s->output_type != TCC_OUTPUT_OBJ) {
10700 ret = tcc_output_pe(s, outfile);
10701 } else
10702 #endif
10704 tcc_output_file(s, outfile);
10705 ret = 0;
10707 the_end:
10708 /* XXX: cannot do it with bound checking because of the malloc hooks */
10709 if (!do_bounds_check)
10710 tcc_delete(s);
10712 #ifdef MEM_DEBUG
10713 if (do_bench) {
10714 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size, mem_max_size);
10716 #endif
10717 return ret;
10720 #endif