trivial jump size optimization
[tinycc.git] / tcc.c
blob750cb391f3190a5609a1f5b524cf39f271b3e80d
1 /*
2 * TCC - Tiny C Compiler
3 *
4 * Copyright (c) 2001, 2002 Fabrice Bellard
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program 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
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <stdarg.h>
23 #include <string.h>
24 #include <errno.h>
25 #include <math.h>
26 #include <unistd.h>
27 #include <signal.h>
28 #include <unistd.h>
29 #include <fcntl.h>
30 #ifndef WIN32
31 #include <sys/ucontext.h>
32 #endif
33 #include "elf.h"
34 #include "stab.h"
35 #ifndef CONFIG_TCC_STATIC
36 #include <dlfcn.h>
37 #endif
39 #include "libtcc.h"
41 //#define DEBUG
42 /* preprocessor debug */
43 //#define PP_DEBUG
44 /* include file debug */
45 //#define INC_DEBUG
47 //#define MEM_DEBUG
49 /* target selection */
50 //#define TCC_TARGET_I386 /* i386 code generator */
51 //#define TCC_TARGET_IL /* .NET CLI generator */
53 /* default target is I386 */
54 #if !defined(TCC_TARGET_I386) && !defined(TCC_TARGET_IL)
55 #define TCC_TARGET_I386
56 #endif
58 #if !defined(WIN32) && !defined(TCC_UCLIBC) && !defined(TCC_TARGET_IL)
59 #define CONFIG_TCC_BCHECK /* enable bound checking code */
60 #endif
62 #ifndef CONFIG_TCC_PREFIX
63 #define CONFIG_TCC_PREFIX "/usr/local"
64 #endif
66 /* path to find crt1.o, crti.o and crtn.o. Only needed when generating
67 executables or dlls */
68 #define CONFIG_TCC_CRT_PREFIX "/usr/lib"
70 #define INCLUDE_STACK_SIZE 32
71 #define IFDEF_STACK_SIZE 64
72 #define VSTACK_SIZE 64
73 #define STRING_MAX_SIZE 1024
75 #define TOK_HASH_SIZE 2048 /* must be a power of two */
76 #define TOK_ALLOC_INCR 512 /* must be a power of two */
77 #define SYM_HASH_SIZE 1031
79 /* token symbol management */
80 typedef struct TokenSym {
81 struct TokenSym *hash_next;
82 int tok; /* token number */
83 int len;
84 char str[1];
85 } TokenSym;
87 typedef struct CString {
88 int size; /* size in bytes */
89 void *data; /* either 'char *' or 'int *' */
90 int size_allocated;
91 void *data_allocated; /* if non NULL, data has been malloced */
92 } CString;
94 /* constant value */
95 typedef union CValue {
96 long double ld;
97 double d;
98 float f;
99 int i;
100 unsigned int ui;
101 unsigned int ul; /* address (should be unsigned long on 64 bit cpu) */
102 long long ll;
103 unsigned long long ull;
104 struct CString *cstr;
105 void *ptr;
106 int tab[1];
107 } CValue;
109 /* value on stack */
110 typedef struct SValue {
111 int t; /* type */
112 unsigned short r; /* register + flags */
113 unsigned short r2; /* second register, used for 'long long'
114 type. If not used, set to VT_CONST */
115 CValue c; /* constant, if VT_CONST */
116 struct Sym *sym; /* symbol, if (VT_SYM | VT_CONST) */
117 } SValue;
119 /* symbol management */
120 typedef struct Sym {
121 int v; /* symbol token */
122 int t; /* associated type */
123 int r; /* associated register */
124 int c; /* associated number */
125 struct Sym *next; /* next related symbol */
126 struct Sym *prev; /* prev symbol in stack */
127 struct Sym *hash_next; /* next symbol in hash table */
128 } Sym;
130 typedef struct SymStack {
131 struct Sym *top;
132 struct Sym *hash[SYM_HASH_SIZE];
133 } SymStack;
135 /* section definition */
136 /* XXX: use directly ELF structure for parameters ? */
137 /* special flag to indicate that the section should not be linked to
138 the other ones */
139 #define SHF_PRIVATE 0x80000000
141 typedef struct Section {
142 unsigned long data_offset; /* current data offset */
143 unsigned char *data; /* section data */
144 unsigned long data_allocated; /* used for realloc() handling */
145 int sh_name; /* elf section name (only used during output) */
146 int sh_num; /* elf section number */
147 int sh_type; /* elf section type */
148 int sh_flags; /* elf section flags */
149 int sh_info; /* elf section info */
150 int sh_addralign; /* elf section alignment */
151 int sh_entsize; /* elf entry size */
152 unsigned long sh_size; /* section size (only used during output) */
153 unsigned long sh_addr; /* address at which the section is relocated */
154 unsigned long sh_offset; /* address at which the section is relocated */
155 int nb_hashed_syms; /* used to resize the hash table */
156 struct Section *link; /* link to another section */
157 struct Section *reloc; /* corresponding section for relocation, if any */
158 struct Section *hash; /* hash table for symbols */
159 struct Section *next;
160 char name[64]; /* section name */
161 } Section;
163 typedef struct DLLReference {
164 int level;
165 char name[1];
166 } DLLReference;
168 /* GNUC attribute definition */
169 typedef struct AttributeDef {
170 int aligned;
171 Section *section;
172 unsigned char func_call; /* FUNC_CDECL or FUNC_STDCALL */
173 } AttributeDef;
175 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
176 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
177 #define SYM_FIRST_ANOM (1 << (31 - VT_STRUCT_SHIFT)) /* first anonymous sym */
179 /* stored in 'Sym.c' field */
180 #define FUNC_NEW 1 /* ansi function prototype */
181 #define FUNC_OLD 2 /* old function prototype */
182 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
184 /* stored in 'Sym.r' field */
185 #define FUNC_CDECL 0 /* standard c call */
186 #define FUNC_STDCALL 1 /* pascal c call */
188 /* field 'Sym.t' for macros */
189 #define MACRO_OBJ 0 /* object like macro */
190 #define MACRO_FUNC 1 /* function like macro */
192 /* field 'Sym.t' for labels */
193 #define LABEL_FORWARD 1 /* label is forward defined */
195 /* type_decl() types */
196 #define TYPE_ABSTRACT 1 /* type without variable */
197 #define TYPE_DIRECT 2 /* type with variable */
199 #define IO_BUF_SIZE 8192
201 typedef struct BufferedFile {
202 unsigned char *buf_ptr;
203 unsigned char *buf_end;
204 int fd;
205 int line_num; /* current line number - here to simply code */
206 int ifndef_macro; /*'#ifndef macro \n #define macro' search */
207 int *ifdef_stack_ptr; /* ifdef_stack value at the start of the file */
208 char inc_type; /* type of include */
209 char inc_filename[512]; /* filename specified by the user */
210 char filename[1024]; /* current filename - here to simplify code */
211 unsigned char buffer[IO_BUF_SIZE + 1]; /* extra size for CH_EOB char */
212 } BufferedFile;
214 #define CH_EOB 0 /* end of buffer or '\0' char in file */
215 #define CH_EOF (-1) /* end of file */
217 /* parsing state (used to save parser state to reparse part of the
218 source several times) */
219 typedef struct ParseState {
220 int *macro_ptr;
221 int line_num;
222 int tok;
223 CValue tokc;
224 } ParseState;
226 /* used to record tokens */
227 typedef struct TokenString {
228 int *str;
229 int len;
230 int last_line_num;
231 } TokenString;
233 /* include file cache, used to find files faster and also to eliminate
234 inclusion if the include file is protected by #ifndef ... #endif */
235 typedef struct CachedInclude {
236 int ifndef_macro;
237 char type; /* '"' or '>' to give include type */
238 char filename[1]; /* path specified in #include */
239 } CachedInclude;
241 /* parser */
242 struct BufferedFile *file;
243 int ch, ch1, tok, tok1;
244 CValue tokc, tok1c;
245 CString tokcstr; /* current parsed string, if any */
246 /* if true, line feed is returned as a token. line feed is also
247 returned at eof */
248 int return_linefeed;
249 /* set to TRUE if eof was reached */
250 int eof_seen;
251 /* sections */
252 Section **sections;
253 int nb_sections; /* number of sections, including first dummy section */
254 Section *text_section, *data_section, *bss_section; /* predefined sections */
255 Section *cur_text_section; /* current section where function code is
256 generated */
257 /* bound check related sections */
258 Section *bounds_section; /* contains global data bound description */
259 Section *lbounds_section; /* contains local data bound description */
260 /* symbol sections */
261 Section *symtab_section, *strtab_section;
262 /* temporary dynamic symbol sections (for dll loading) */
263 Section *dynsymtab_section;
264 /* exported dynamic symbol section */
265 Section *dynsym;
266 /* got handling */
267 Section *got;
268 unsigned long *got_offsets;
269 int nb_got_offsets;
270 int nb_plt_entries;
271 /* give the correspondance from symtab indexes to dynsym indexes */
272 int *symtab_to_dynsym;
274 /* array of all loaded dlls (including those referenced by loaded
275 dlls) */
276 DLLReference **loaded_dlls;
277 int nb_loaded_dlls;
279 /* debug sections */
280 Section *stab_section, *stabstr_section;
282 char **library_paths;
283 int nb_library_paths;
285 CachedInclude **cached_includes;
286 int nb_cached_includes;
288 /* loc : local variable index
289 ind : output code index
290 rsym: return symbol
291 anon_sym: anonymous symbol index
293 int rsym, anon_sym,
294 prog, ind, loc;
295 /* expression generation modifiers */
296 int const_wanted; /* true if constant wanted */
297 int global_expr; /* true if compound literals must be allocated
298 globally (used during initializers parsing */
299 int func_vt, func_vc; /* current function return type (used by
300 return instruction) */
301 int last_line_num, last_ind, func_ind; /* debug last line number and pc */
302 int tok_ident;
303 TokenSym **table_ident;
304 TokenSym *hash_ident[TOK_HASH_SIZE];
305 char token_buf[STRING_MAX_SIZE + 1];
306 char *funcname;
307 SymStack define_stack, global_stack, local_stack, label_stack;
309 SValue vstack[VSTACK_SIZE], *vtop;
310 int *macro_ptr, *macro_ptr_allocated;
311 BufferedFile *include_stack[INCLUDE_STACK_SIZE], **include_stack_ptr;
312 int ifdef_stack[IFDEF_STACK_SIZE], *ifdef_stack_ptr;
313 char **include_paths;
314 int nb_include_paths;
315 char **sysinclude_paths;
316 int nb_sysinclude_paths;
317 int char_pointer_type;
318 int func_old_type;
320 /* compile with debug symbol (and use them if error during execution) */
321 int do_debug = 0;
323 /* compile with built-in memory and bounds checker */
324 int do_bounds_check = 0;
326 /* display benchmark infos */
327 int do_bench = 0;
328 int total_lines;
329 int total_bytes;
331 /* use GNU C extensions */
332 int gnu_ext = 1;
334 /* use Tiny C extensions */
335 int tcc_ext = 1;
337 /* if true, static linking is performed */
338 int static_link = 0;
340 /* give the path of the tcc libraries */
341 static const char *tcc_lib_path = CONFIG_TCC_PREFIX "/lib/tcc";
343 struct TCCState {
344 int output_type;
347 /* The current value can be: */
348 #define VT_VALMASK 0x00ff
349 #define VT_CONST 0x00f0 /* constant in vc
350 (must be first non register value) */
351 #define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */
352 #define VT_LOCAL 0x00f2 /* offset on stack */
353 #define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */
354 #define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */
355 #define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */
356 #define VT_LVAL 0x0100 /* var is an lvalue */
357 #define VT_SYM 0x0200 /* a symbol value is added */
358 #define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for
359 char/short stored in integer registers) */
360 #define VT_MUSTBOUND 0x0800 /* bound checking must be done before
361 dereferencing value */
362 #define VT_BOUNDED 0x8000 /* value is bounded. The address of the
363 bounding function call point is in vc */
364 #define VT_LVAL_BYTE 0x1000 /* lvalue is a byte */
365 #define VT_LVAL_SHORT 0x2000 /* lvalue is a short */
366 #define VT_LVAL_UNSIGNED 0x4000 /* lvalue is unsigned */
367 #define VT_LVAL_TYPE (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)
369 /* types */
370 #define VT_STRUCT_SHIFT 12 /* structure/enum name shift (20 bits left) */
372 #define VT_INT 0 /* integer type */
373 #define VT_BYTE 1 /* signed byte type */
374 #define VT_SHORT 2 /* short type */
375 #define VT_VOID 3 /* void type */
376 #define VT_PTR 4 /* pointer */
377 #define VT_ENUM 5 /* enum definition */
378 #define VT_FUNC 6 /* function type */
379 #define VT_STRUCT 7 /* struct/union definition */
380 #define VT_FLOAT 8 /* IEEE float */
381 #define VT_DOUBLE 9 /* IEEE double */
382 #define VT_LDOUBLE 10 /* IEEE long double */
383 #define VT_BOOL 11 /* ISOC99 boolean type */
384 #define VT_LLONG 12 /* 64 bit integer */
385 #define VT_LONG 13 /* long integer (NEVER USED as type, only
386 during parsing) */
387 #define VT_BTYPE 0x000f /* mask for basic type */
388 #define VT_UNSIGNED 0x0010 /* unsigned type */
389 #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
390 #define VT_BITFIELD 0x0040 /* bitfield modifier */
392 /* storage */
393 #define VT_EXTERN 0x00000080 /* extern definition */
394 #define VT_STATIC 0x00000100 /* static variable */
395 #define VT_TYPEDEF 0x00000200 /* typedef definition */
397 /* type mask (except storage) */
398 #define VT_TYPE (~(VT_EXTERN | VT_STATIC | VT_TYPEDEF))
400 /* token values */
402 /* warning: the following compare tokens depend on i386 asm code */
403 #define TOK_ULT 0x92
404 #define TOK_UGE 0x93
405 #define TOK_EQ 0x94
406 #define TOK_NE 0x95
407 #define TOK_ULE 0x96
408 #define TOK_UGT 0x97
409 #define TOK_LT 0x9c
410 #define TOK_GE 0x9d
411 #define TOK_LE 0x9e
412 #define TOK_GT 0x9f
414 #define TOK_LAND 0xa0
415 #define TOK_LOR 0xa1
417 #define TOK_DEC 0xa2
418 #define TOK_MID 0xa3 /* inc/dec, to void constant */
419 #define TOK_INC 0xa4
420 #define TOK_UDIV 0xb0 /* unsigned division */
421 #define TOK_UMOD 0xb1 /* unsigned modulo */
422 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
423 #define TOK_CINT 0xb3 /* number in tokc */
424 #define TOK_CCHAR 0xb4 /* char constant in tokc */
425 #define TOK_STR 0xb5 /* pointer to string in tokc */
426 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
427 #define TOK_LCHAR 0xb7
428 #define TOK_LSTR 0xb8
429 #define TOK_CFLOAT 0xb9 /* float constant */
430 #define TOK_LINENUM 0xba /* line number info */
431 #define TOK_CDOUBLE 0xc0 /* double constant */
432 #define TOK_CLDOUBLE 0xc1 /* long double constant */
433 #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
434 #define TOK_ADDC1 0xc3 /* add with carry generation */
435 #define TOK_ADDC2 0xc4 /* add with carry use */
436 #define TOK_SUBC1 0xc5 /* add with carry generation */
437 #define TOK_SUBC2 0xc6 /* add with carry use */
438 #define TOK_CUINT 0xc8 /* unsigned int constant */
439 #define TOK_CLLONG 0xc9 /* long long constant */
440 #define TOK_CULLONG 0xca /* unsigned long long constant */
441 #define TOK_ARROW 0xcb
442 #define TOK_DOTS 0xcc /* three dots */
443 #define TOK_SHR 0xcd /* unsigned shift right */
445 #define TOK_SHL 0x01 /* shift left */
446 #define TOK_SAR 0x02 /* signed shift right */
448 /* assignement operators : normal operator or 0x80 */
449 #define TOK_A_MOD 0xa5
450 #define TOK_A_AND 0xa6
451 #define TOK_A_MUL 0xaa
452 #define TOK_A_ADD 0xab
453 #define TOK_A_SUB 0xad
454 #define TOK_A_DIV 0xaf
455 #define TOK_A_XOR 0xde
456 #define TOK_A_OR 0xfc
457 #define TOK_A_SHL 0x81
458 #define TOK_A_SAR 0x82
460 /* WARNING: the content of this string encodes token numbers */
461 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";
463 #define TOK_EOF (-1) /* end of file */
464 #define TOK_LINEFEED 10 /* line feed */
466 /* all identificators and strings have token above that */
467 #define TOK_IDENT 256
469 enum {
470 TOK_INT = TOK_IDENT,
471 TOK_VOID,
472 TOK_CHAR,
473 TOK_IF,
474 TOK_ELSE,
475 TOK_WHILE,
476 TOK_BREAK,
477 TOK_RETURN,
478 TOK_FOR,
479 TOK_EXTERN,
480 TOK_STATIC,
481 TOK_UNSIGNED,
482 TOK_GOTO,
483 TOK_DO,
484 TOK_CONTINUE,
485 TOK_SWITCH,
486 TOK_CASE,
488 /* ignored types Must have contiguous values */
489 TOK_CONST,
490 TOK_VOLATILE,
491 TOK_LONG,
492 TOK_REGISTER,
493 TOK_SIGNED,
494 TOK___SIGNED__, /* gcc keyword */
495 TOK_AUTO,
496 TOK_INLINE,
497 TOK___INLINE__, /* gcc keyword */
498 TOK_RESTRICT,
500 /* unsupported type */
501 TOK_FLOAT,
502 TOK_DOUBLE,
503 TOK_BOOL,
505 TOK_SHORT,
506 TOK_STRUCT,
507 TOK_UNION,
508 TOK_TYPEDEF,
509 TOK_DEFAULT,
510 TOK_ENUM,
511 TOK_SIZEOF,
512 TOK___ATTRIBUTE__,
514 /* preprocessor only */
515 TOK_UIDENT, /* first "user" ident (not keyword) */
516 TOK_DEFINE = TOK_UIDENT,
517 TOK_INCLUDE,
518 TOK_IFDEF,
519 TOK_IFNDEF,
520 TOK_ELIF,
521 TOK_ENDIF,
522 TOK_DEFINED,
523 TOK_UNDEF,
524 TOK_ERROR,
525 TOK_LINE,
527 #define DEF(id, str) id,
528 #include "tcctok.h"
529 #undef DEF
532 char *tcc_keywords =
533 "int\0void\0char\0if\0else\0while\0break\0return\0for\0extern\0static\0"
534 "unsigned\0goto\0do\0continue\0switch\0case\0const\0volatile\0long\0"
535 "register\0signed\0__signed__\0auto\0inline\0__inline__\0restrict\0"
536 "float\0double\0_Bool\0short\0struct\0union\0typedef\0default\0enum\0"
537 "sizeof\0__attribute__\0"
538 /* the following are not keywords. They are included to ease parsing */
539 "define\0include\0ifdef\0ifndef\0elif\0endif\0"
540 "defined\0undef\0error\0line\0"
541 /* builtin functions */
542 #define DEF(id, str) str "\0"
543 #include "tcctok.h"
544 #undef DEF
547 #ifdef WIN32
548 #define snprintf _snprintf
549 #endif
551 #if defined(WIN32) || defined(TCC_UCLIBC)
552 /* currently incorrect */
553 long double strtold(const char *nptr, char **endptr)
555 return (long double)strtod(nptr, endptr);
557 float strtof(const char *nptr, char **endptr)
559 return (float)strtod(nptr, endptr);
561 #else
562 /* XXX: need to define this to use them in non ISOC99 context */
563 extern float strtof (const char *__nptr, char **__endptr);
564 extern long double strtold (const char *__nptr, char **__endptr);
565 #endif
567 static char *pstrcpy(char *buf, int buf_size, const char *s);
568 static char *pstrcat(char *buf, int buf_size, const char *s);
570 void sum(int l);
571 void next(void);
572 void next_nomacro(void);
573 static int expr_const(void);
574 void expr_eq(void);
575 void gexpr(void);
576 void decl(int l);
577 static void decl_initializer(int t, Section *sec, unsigned long c,
578 int first, int size_only);
579 static void decl_initializer_alloc(int t, AttributeDef *ad, int r,
580 int has_init, int v, int scope);
581 int gv(int rc);
582 void gv2(int rc1, int rc2);
583 void move_reg(int r, int s);
584 void save_regs(int n);
585 void save_reg(int r);
586 void vpop(void);
587 void vswap(void);
588 void vdup(void);
589 int get_reg(int rc);
591 static void macro_subst(TokenString *tok_str,
592 Sym **nested_list, int *macro_str);
593 int save_reg_forced(int r);
594 void gen_op(int op);
595 void force_charshort_cast(int t);
596 void gen_cast(int t);
597 void vstore(void);
598 Sym *sym_find(int v);
599 Sym *sym_push(int v, int t, int r, int c);
601 /* type handling */
602 int type_size(int t, int *a);
603 int pointed_type(int t);
604 int pointed_size(int t);
605 static int lvalue_type(int t);
606 int is_compatible_types(int t1, int t2);
607 int parse_btype(int *type_ptr, AttributeDef *ad);
608 int type_decl(AttributeDef *ad, int *v, int t, int td);
610 void error(const char *fmt, ...);
611 void rt_error(unsigned long pc, const char *fmt, ...);
612 void vpushi(int v);
613 void vset(int t, int r, int v);
614 void type_to_str(char *buf, int buf_size,
615 int t, const char *varstr);
616 char *get_tok_str(int v, CValue *cv);
617 static Sym *get_sym_ref(int t, Section *sec,
618 unsigned long offset, unsigned long size);
619 static Sym *external_global_sym(int v, int u, int r);
621 /* section generation */
622 static void section_realloc(Section *sec, unsigned long new_size);
623 static void *section_ptr_add(Section *sec, unsigned long size);
624 static void put_extern_sym(Sym *sym, Section *section,
625 unsigned long value, unsigned long size);
626 static void greloc(Section *s, Sym *sym, unsigned long addr, int type);
627 static int put_elf_str(Section *s, const char *sym);
628 static int put_elf_sym(Section *s,
629 unsigned long value, unsigned long size,
630 int info, int other, int shndx, const char *name);
631 static int add_elf_sym(Section *s, unsigned long value, unsigned long size,
632 int info, int sh_num, const char *name);
633 static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
634 int type, int symbol);
635 static void put_stabs(const char *str, int type, int other, int desc,
636 unsigned long value);
637 static void put_stabs_r(const char *str, int type, int other, int desc,
638 unsigned long value, Section *sec, int sym_index);
639 static void put_stabn(int type, int other, int desc, int value);
640 static void put_stabd(int type, int other, int desc);
641 static int tcc_add_dll(TCCState *s, const char *filename, int flags);
643 #define AFF_PRINT_ERROR 0x0001 /* print error if file not found */
644 #define AFF_REFERENCED_DLL 0x0002 /* load a referenced dll from another dll */
645 static int tcc_add_file_internal(TCCState *s, const char *filename, int flags);
647 /* true if float/double/long double type */
648 static inline int is_float(int t)
650 int bt;
651 bt = t & VT_BTYPE;
652 return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT;
655 #ifdef TCC_TARGET_I386
656 #include "i386-gen.c"
657 #endif
658 #ifdef TCC_TARGET_IL
659 #include "il-gen.c"
660 #endif
662 #ifdef CONFIG_TCC_STATIC
664 #define RTLD_LAZY 0x001
665 #define RTLD_NOW 0x002
666 #define RTLD_GLOBAL 0x100
668 /* dummy function for profiling */
669 void *dlopen(const char *filename, int flag)
671 return NULL;
674 const char *dlerror(void)
676 return "error";
679 typedef struct TCCSyms {
680 char *str;
681 void *ptr;
682 } TCCSyms;
684 #define TCCSYM(a) { #a, &a, },
686 /* add the symbol you want here if no dynamic linking is done */
687 static TCCSyms tcc_syms[] = {
688 TCCSYM(printf)
689 TCCSYM(fprintf)
690 TCCSYM(fopen)
691 TCCSYM(fclose)
692 { NULL, NULL },
695 void *dlsym(void *handle, const char *symbol)
697 TCCSyms *p;
698 p = tcc_syms;
699 while (p->str != NULL) {
700 if (!strcmp(p->str, symbol))
701 return p->ptr;
702 p++;
704 return NULL;
707 #endif
709 /********************************************************/
711 /* we use our own 'finite' function to avoid potential problems with
712 non standard math libs */
713 /* XXX: endianness dependant */
714 int ieee_finite(double d)
716 int *p = (int *)&d;
717 return ((unsigned)((p[1] | 0x800fffff) + 1)) >> 31;
720 /* copy a string and truncate it. */
721 static char *pstrcpy(char *buf, int buf_size, const char *s)
723 char *q, *q_end;
724 int c;
726 if (buf_size > 0) {
727 q = buf;
728 q_end = buf + buf_size - 1;
729 while (q < q_end) {
730 c = *s++;
731 if (c == '\0')
732 break;
733 *q++ = c;
735 *q = '\0';
737 return buf;
740 /* strcat and truncate. */
741 static char *pstrcat(char *buf, int buf_size, const char *s)
743 int len;
744 len = strlen(buf);
745 if (len < buf_size)
746 pstrcpy(buf + len, buf_size - len, s);
747 return buf;
750 /* memory management */
751 #ifdef MEM_DEBUG
752 int mem_cur_size;
753 int mem_max_size;
754 #endif
756 static inline void tcc_free(void *ptr)
758 #ifdef MEM_DEBUG
759 mem_cur_size -= malloc_usable_size(ptr);
760 #endif
761 free(ptr);
764 static void *tcc_malloc(unsigned long size)
766 void *ptr;
767 ptr = malloc(size);
768 if (!ptr)
769 error("memory full");
770 #ifdef MEM_DEBUG
771 mem_cur_size += malloc_usable_size(ptr);
772 if (mem_cur_size > mem_max_size)
773 mem_max_size = mem_cur_size;
774 #endif
775 return ptr;
778 static void *tcc_mallocz(unsigned long size)
780 void *ptr;
781 ptr = tcc_malloc(size);
782 memset(ptr, 0, size);
783 return ptr;
786 static inline void *tcc_realloc(void *ptr, unsigned long size)
788 void *ptr1;
789 #ifdef MEM_DEBUG
790 mem_cur_size -= malloc_usable_size(ptr);
791 #endif
792 ptr1 = realloc(ptr, size);
793 #ifdef MEM_DEBUG
794 /* NOTE: count not correct if alloc error, but not critical */
795 mem_cur_size += malloc_usable_size(ptr1);
796 if (mem_cur_size > mem_max_size)
797 mem_max_size = mem_cur_size;
798 #endif
799 return ptr1;
802 static char *tcc_strdup(const char *str)
804 char *ptr;
805 ptr = tcc_malloc(strlen(str) + 1);
806 strcpy(ptr, str);
807 return ptr;
810 #define free(p) use_tcc_free(p)
811 #define malloc(s) use_tcc_malloc(s)
812 #define realloc(p, s) use_tcc_realloc(p, s)
814 static void dynarray_add(void ***ptab, int *nb_ptr, void *data)
816 int nb, nb_alloc;
817 void **pp;
819 nb = *nb_ptr;
820 pp = *ptab;
821 /* every power of two we double array size */
822 if ((nb & (nb - 1)) == 0) {
823 if (!nb)
824 nb_alloc = 1;
825 else
826 nb_alloc = nb * 2;
827 pp = tcc_realloc(pp, nb_alloc * sizeof(void *));
828 if (!pp)
829 error("memory full");
830 *ptab = pp;
832 pp[nb++] = data;
833 *nb_ptr = nb;
836 Section *new_section(const char *name, int sh_type, int sh_flags)
838 Section *sec;
840 sec = tcc_mallocz(sizeof(Section));
841 pstrcpy(sec->name, sizeof(sec->name), name);
842 sec->sh_type = sh_type;
843 sec->sh_flags = sh_flags;
844 switch(sh_type) {
845 case SHT_HASH:
846 case SHT_REL:
847 case SHT_DYNSYM:
848 case SHT_SYMTAB:
849 case SHT_DYNAMIC:
850 sec->sh_addralign = 4;
851 break;
852 case SHT_STRTAB:
853 sec->sh_addralign = 1;
854 break;
855 default:
856 sec->sh_addralign = 32; /* default conservative alignment */
857 break;
860 /* only add section if not private */
861 if (!(sh_flags & SHF_PRIVATE)) {
862 sec->sh_num = nb_sections;
863 dynarray_add((void ***)&sections, &nb_sections, sec);
865 return sec;
868 /* realloc section and set its content to zero */
869 static void section_realloc(Section *sec, unsigned long new_size)
871 unsigned long size;
872 unsigned char *data;
874 size = sec->data_allocated;
875 if (size == 0)
876 size = 1;
877 while (size < new_size)
878 size = size * 2;
879 data = tcc_realloc(sec->data, size);
880 if (!data)
881 error("memory full");
882 memset(data + sec->data_allocated, 0, size - sec->data_allocated);
883 sec->data = data;
884 sec->data_allocated = size;
887 /* reserve at least 'size' bytes in section 'sec' from
888 sec->data_offset. */
889 static void *section_ptr_add(Section *sec, unsigned long size)
891 unsigned long offset, offset1;
893 offset = sec->data_offset;
894 offset1 = offset + size;
895 if (offset1 > sec->data_allocated)
896 section_realloc(sec, offset1);
897 sec->data_offset = offset1;
898 return sec->data + offset;
901 /* return a reference to a section, and create it if it does not
902 exists */
903 Section *find_section(const char *name)
905 Section *sec;
906 int i;
907 for(i = 1; i < nb_sections; i++) {
908 sec = sections[i];
909 if (!strcmp(name, sec->name))
910 return sec;
912 /* sections are created as PROGBITS */
913 return new_section(name, SHT_PROGBITS, SHF_ALLOC);
916 /* update sym->c so that it points to an external symbol in section
917 'section' with value 'value' */
918 static void put_extern_sym(Sym *sym, Section *section,
919 unsigned long value, unsigned long size)
921 int sym_type, sym_bind, sh_num, info;
922 Elf32_Sym *esym;
923 const char *name;
924 char buf[32];
926 if (section)
927 sh_num = section->sh_num;
928 else
929 sh_num = SHN_UNDEF;
930 if (!sym->c) {
931 if ((sym->t & VT_BTYPE) == VT_FUNC)
932 sym_type = STT_FUNC;
933 else
934 sym_type = STT_OBJECT;
935 if (sym->t & VT_STATIC)
936 sym_bind = STB_LOCAL;
937 else
938 sym_bind = STB_GLOBAL;
940 name = get_tok_str(sym->v, NULL);
941 #ifdef CONFIG_TCC_BCHECK
942 if (do_bounds_check) {
943 /* if bound checking is activated, we change some function
944 names by adding the "__bound" prefix */
945 switch(sym->v) {
946 #if 0
947 /* XXX: we rely only on malloc hooks */
948 case TOK_malloc:
949 case TOK_free:
950 case TOK_realloc:
951 case TOK_memalign:
952 case TOK_calloc:
953 #endif
954 case TOK_memcpy:
955 case TOK_memmove:
956 case TOK_memset:
957 case TOK_strlen:
958 case TOK_strcpy:
959 strcpy(buf, "__bound_");
960 strcat(buf, name);
961 name = buf;
962 break;
965 #endif
966 info = ELF32_ST_INFO(sym_bind, sym_type);
967 sym->c = add_elf_sym(symtab_section, value, size, info, sh_num, name);
968 } else {
969 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
970 esym->st_value = value;
971 esym->st_size = size;
972 esym->st_shndx = sh_num;
976 /* add a new relocation entry to symbol 'sym' in section 's' */
977 static void greloc(Section *s, Sym *sym, unsigned long offset, int type)
979 if (!sym->c)
980 put_extern_sym(sym, NULL, 0, 0);
981 /* now we can add ELF relocation info */
982 put_elf_reloc(symtab_section, s, offset, type, sym->c);
985 static inline int isid(int c)
987 return (c >= 'a' && c <= 'z') ||
988 (c >= 'A' && c <= 'Z') ||
989 c == '_';
992 static inline int isnum(int c)
994 return c >= '0' && c <= '9';
997 static inline int isoct(int c)
999 return c >= '0' && c <= '7';
1002 static inline int toup(int c)
1004 if (ch >= 'a' && ch <= 'z')
1005 return ch - 'a' + 'A';
1006 else
1007 return ch;
1010 void printline(void)
1012 BufferedFile **f;
1014 if (file) {
1015 for(f = include_stack; f < include_stack_ptr; f++)
1016 fprintf(stderr, "In file included from %s:%d:\n",
1017 (*f)->filename, (*f)->line_num);
1018 if (file->line_num > 0) {
1019 fprintf(stderr, "%s:%d: ", file->filename, file->line_num);
1020 } else {
1021 fprintf(stderr, "%s: ", file->filename);
1023 } else {
1024 fprintf(stderr, "tcc: ");
1028 void error(const char *fmt, ...)
1030 va_list ap;
1031 va_start(ap, fmt);
1032 printline();
1033 vfprintf(stderr, fmt, ap);
1034 fprintf(stderr, "\n");
1035 exit(1);
1036 va_end(ap);
1039 void expect(const char *msg)
1041 error("%s expected", msg);
1044 void warning(const char *fmt, ...)
1046 va_list ap;
1048 va_start(ap, fmt);
1049 printline();
1050 fprintf(stderr, "warning: ");
1051 vfprintf(stderr, fmt, ap);
1052 fprintf(stderr, "\n");
1053 va_end(ap);
1056 void skip(int c)
1058 if (tok != c)
1059 error("'%c' expected", c);
1060 next();
1063 void test_lvalue(void)
1065 if (!(vtop->r & VT_LVAL))
1066 expect("lvalue");
1069 TokenSym *tok_alloc(const char *str, int len)
1071 TokenSym *ts, **pts, **ptable;
1072 int h, i;
1074 h = 1;
1075 for(i=0;i<len;i++)
1076 h = (h * 263 + ((unsigned char *)str)[i]) & (TOK_HASH_SIZE - 1);
1078 pts = &hash_ident[h];
1079 while (1) {
1080 ts = *pts;
1081 if (!ts)
1082 break;
1083 if (ts->len == len && !memcmp(ts->str, str, len))
1084 return ts;
1085 pts = &(ts->hash_next);
1088 if (tok_ident >= SYM_FIRST_ANOM)
1089 error("memory full");
1091 /* expand token table if needed */
1092 i = tok_ident - TOK_IDENT;
1093 if ((i % TOK_ALLOC_INCR) == 0) {
1094 ptable = tcc_realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *));
1095 if (!ptable)
1096 error("memory full");
1097 table_ident = ptable;
1100 ts = tcc_malloc(sizeof(TokenSym) + len);
1101 table_ident[i] = ts;
1102 ts->tok = tok_ident++;
1103 ts->len = len;
1104 ts->hash_next = NULL;
1105 memcpy(ts->str, str, len + 1);
1106 *pts = ts;
1107 return ts;
1110 /* CString handling */
1112 static void cstr_realloc(CString *cstr, int new_size)
1114 int size;
1115 void *data;
1117 size = cstr->size_allocated;
1118 if (size == 0)
1119 size = 8; /* no need to allocate a too small first string */
1120 while (size < new_size)
1121 size = size * 2;
1122 data = tcc_realloc(cstr->data_allocated, size);
1123 if (!data)
1124 error("memory full");
1125 cstr->data_allocated = data;
1126 cstr->size_allocated = size;
1127 cstr->data = data;
1130 /* add a byte */
1131 static void cstr_ccat(CString *cstr, int ch)
1133 int size;
1134 size = cstr->size + 1;
1135 if (size > cstr->size_allocated)
1136 cstr_realloc(cstr, size);
1137 ((unsigned char *)cstr->data)[size - 1] = ch;
1138 cstr->size = size;
1141 static void cstr_cat(CString *cstr, const char *str)
1143 int c;
1144 for(;;) {
1145 c = *str;
1146 if (c == '\0')
1147 break;
1148 cstr_ccat(cstr, c);
1149 str++;
1153 /* add a wide char */
1154 static void cstr_wccat(CString *cstr, int ch)
1156 int size;
1157 size = cstr->size + sizeof(int);
1158 if (size > cstr->size_allocated)
1159 cstr_realloc(cstr, size);
1160 *(int *)(((unsigned char *)cstr->data) + size - sizeof(int)) = ch;
1161 cstr->size = size;
1164 static void cstr_new(CString *cstr)
1166 memset(cstr, 0, sizeof(CString));
1169 /* free string and reset it to NULL */
1170 static void cstr_free(CString *cstr)
1172 tcc_free(cstr->data_allocated);
1173 cstr_new(cstr);
1176 #define cstr_reset(cstr) cstr_free(cstr)
1178 /* XXX: unicode ? */
1179 static void add_char(CString *cstr, int c)
1181 if (c == '\'' || c == '\"' || c == '\\') {
1182 /* XXX: could be more precise if char or string */
1183 cstr_ccat(cstr, '\\');
1185 if (c >= 32 && c <= 126) {
1186 cstr_ccat(cstr, c);
1187 } else {
1188 cstr_ccat(cstr, '\\');
1189 if (c == '\n') {
1190 cstr_ccat(cstr, 'n');
1191 } else {
1192 cstr_ccat(cstr, '0' + ((c >> 6) & 7));
1193 cstr_ccat(cstr, '0' + ((c >> 3) & 7));
1194 cstr_ccat(cstr, '0' + (c & 7));
1199 /* XXX: buffer overflow */
1200 /* XXX: float tokens */
1201 char *get_tok_str(int v, CValue *cv)
1203 static char buf[STRING_MAX_SIZE + 1];
1204 static CString cstr_buf;
1205 CString *cstr;
1206 unsigned char *q;
1207 char *p;
1208 int i, len;
1210 /* NOTE: to go faster, we give a fixed buffer for small strings */
1211 cstr_reset(&cstr_buf);
1212 cstr_buf.data = buf;
1213 cstr_buf.size_allocated = sizeof(buf);
1214 p = buf;
1216 switch(v) {
1217 case TOK_CINT:
1218 case TOK_CUINT:
1219 /* XXX: not exact */
1220 sprintf(p, "%u", cv->ui);
1221 break;
1222 case TOK_CCHAR:
1223 case TOK_LCHAR:
1224 cstr_ccat(&cstr_buf, '\'');
1225 add_char(&cstr_buf, cv->i);
1226 cstr_ccat(&cstr_buf, '\'');
1227 cstr_ccat(&cstr_buf, '\0');
1228 break;
1229 case TOK_STR:
1230 case TOK_LSTR:
1231 cstr = cv->cstr;
1232 cstr_ccat(&cstr_buf, '\"');
1233 if (v == TOK_STR) {
1234 len = cstr->size - 1;
1235 for(i=0;i<len;i++)
1236 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1237 } else {
1238 len = (cstr->size / sizeof(int)) - 1;
1239 for(i=0;i<len;i++)
1240 add_char(&cstr_buf, ((int *)cstr->data)[i]);
1242 cstr_ccat(&cstr_buf, '\"');
1243 cstr_ccat(&cstr_buf, '\0');
1244 break;
1245 case TOK_LT:
1246 v = '<';
1247 goto addv;
1248 case TOK_GT:
1249 v = '>';
1250 goto addv;
1251 case TOK_A_SHL:
1252 return strcpy(p, "<<=");
1253 case TOK_A_SAR:
1254 return strcpy(p, ">>=");
1255 default:
1256 if (v < TOK_IDENT) {
1257 /* search in two bytes table */
1258 q = tok_two_chars;
1259 while (*q) {
1260 if (q[2] == v) {
1261 *p++ = q[0];
1262 *p++ = q[1];
1263 *p = '\0';
1264 return buf;
1266 q += 3;
1268 addv:
1269 *p++ = v;
1270 *p = '\0';
1271 } else if (v < tok_ident) {
1272 return table_ident[v - TOK_IDENT]->str;
1273 } else if (v >= SYM_FIRST_ANOM) {
1274 /* special name for anonymous symbol */
1275 sprintf(p, "L.%u", v - SYM_FIRST_ANOM);
1276 } else {
1277 /* should never happen */
1278 return NULL;
1280 break;
1282 return cstr_buf.data;
1285 /* push, without hashing */
1286 Sym *sym_push2(Sym **ps, int v, int t, int c)
1288 Sym *s;
1289 s = tcc_malloc(sizeof(Sym));
1290 s->v = v;
1291 s->t = t;
1292 s->c = c;
1293 s->next = NULL;
1294 /* add in stack */
1295 s->prev = *ps;
1296 *ps = s;
1297 return s;
1300 /* find a symbol and return its associated structure. 's' is the top
1301 of the symbol stack */
1302 Sym *sym_find2(Sym *s, int v)
1304 while (s) {
1305 if (s->v == v)
1306 return s;
1307 s = s->prev;
1309 return NULL;
1312 #define HASH_SYM(v) ((unsigned)(v) % SYM_HASH_SIZE)
1314 /* find a symbol and return its associated structure. 'st' is the
1315 symbol stack */
1316 Sym *sym_find1(SymStack *st, int v)
1318 Sym *s;
1320 s = st->hash[HASH_SYM(v)];
1321 while (s) {
1322 if (s->v == v)
1323 return s;
1324 s = s->hash_next;
1326 return NULL;
1329 Sym *sym_push1(SymStack *st, int v, int t, int c)
1331 Sym *s, **ps;
1332 s = sym_push2(&st->top, v, t, c);
1333 /* add in hash table */
1334 if (v) {
1335 ps = &st->hash[HASH_SYM(v)];
1336 s->hash_next = *ps;
1337 *ps = s;
1339 return s;
1342 /* find a symbol in the right symbol space */
1343 Sym *sym_find(int v)
1345 Sym *s;
1346 s = sym_find1(&local_stack, v);
1347 if (!s)
1348 s = sym_find1(&global_stack, v);
1349 return s;
1352 /* push a given symbol on the symbol stack */
1353 Sym *sym_push(int v, int t, int r, int c)
1355 Sym *s;
1356 if (local_stack.top)
1357 s = sym_push1(&local_stack, v, t, c);
1358 else
1359 s = sym_push1(&global_stack, v, t, c);
1360 s->r = r;
1361 return s;
1364 /* pop symbols until top reaches 'b' */
1365 void sym_pop(SymStack *st, Sym *b)
1367 Sym *s, *ss;
1369 s = st->top;
1370 while(s != b) {
1371 ss = s->prev;
1372 /* free hash table entry, except if symbol was freed (only
1373 used for #undef symbols) */
1374 if (s->v)
1375 st->hash[HASH_SYM(s->v)] = s->hash_next;
1376 tcc_free(s);
1377 s = ss;
1379 st->top = b;
1382 /* undefined a hashed symbol (used for #undef). Its name is set to
1383 zero */
1384 void sym_undef(SymStack *st, Sym *s)
1386 Sym **ss;
1387 ss = &st->hash[HASH_SYM(s->v)];
1388 while (*ss != NULL) {
1389 if (*ss == s)
1390 break;
1391 ss = &(*ss)->hash_next;
1393 *ss = s->hash_next;
1394 s->v = 0;
1397 /* I/O layer */
1399 BufferedFile *tcc_open(const char *filename)
1401 int fd;
1402 BufferedFile *bf;
1404 fd = open(filename, O_RDONLY);
1405 if (fd < 0)
1406 return NULL;
1407 bf = tcc_malloc(sizeof(BufferedFile));
1408 if (!bf) {
1409 close(fd);
1410 return NULL;
1412 bf->fd = fd;
1413 bf->buf_ptr = bf->buffer;
1414 bf->buf_end = bf->buffer;
1415 bf->buffer[0] = CH_EOB; /* put eob symbol */
1416 pstrcpy(bf->filename, sizeof(bf->filename), filename);
1417 bf->line_num = 1;
1418 bf->ifndef_macro = 0;
1419 bf->ifdef_stack_ptr = ifdef_stack_ptr;
1420 // printf("opening '%s'\n", filename);
1421 return bf;
1424 void tcc_close(BufferedFile *bf)
1426 total_lines += bf->line_num;
1427 close(bf->fd);
1428 tcc_free(bf);
1431 /* read one char. MUST call tcc_fillbuf if CH_EOB is read */
1432 #define TCC_GETC(bf) (*(bf)->buf_ptr++)
1434 /* fill input buffer and return next char */
1435 int tcc_getc_slow(BufferedFile *bf)
1437 int len;
1438 /* only tries to read if really end of buffer */
1439 if (bf->buf_ptr >= bf->buf_end) {
1440 if (bf->fd != -1) {
1441 len = read(bf->fd, bf->buffer, IO_BUF_SIZE);
1442 if (len < 0)
1443 len = 0;
1444 } else {
1445 len = 0;
1447 total_bytes += len;
1448 bf->buf_ptr = bf->buffer;
1449 bf->buf_end = bf->buffer + len;
1450 *bf->buf_end = CH_EOB;
1452 if (bf->buf_ptr < bf->buf_end) {
1453 return *bf->buf_ptr++;
1454 } else {
1455 bf->buf_ptr = bf->buf_end;
1456 return CH_EOF;
1460 /* no need to put that inline */
1461 void handle_eob(void)
1463 for(;;) {
1464 ch1 = tcc_getc_slow(file);
1465 if (ch1 != CH_EOF)
1466 return;
1467 eof_seen = 1;
1468 if (return_linefeed) {
1469 ch1 = '\n';
1470 return;
1472 if (include_stack_ptr == include_stack)
1473 return;
1474 /* add end of include file debug info */
1475 if (do_debug) {
1476 put_stabd(N_EINCL, 0, 0);
1478 /* pop include stack */
1479 tcc_close(file);
1480 include_stack_ptr--;
1481 file = *include_stack_ptr;
1485 /* read next char from current input file */
1486 static inline void inp(void)
1488 ch1 = TCC_GETC(file);
1489 /* end of buffer/file handling */
1490 if (ch1 == CH_EOB)
1491 handle_eob();
1492 if (ch1 == '\n')
1493 file->line_num++;
1494 // printf("ch1=%c 0x%x\n", ch1, ch1);
1497 /* handle '\\n' and '\\r\n' */
1498 static void handle_stray(void)
1500 do {
1501 if (ch1 == '\n') {
1502 inp();
1503 } else if (ch1 == '\r') {
1504 inp();
1505 if (ch1 != '\n')
1506 error("invalid character after '\\'");
1507 inp();
1508 } else {
1509 break;
1511 ch = ch1;
1512 inp();
1513 } while (ch == '\\');
1516 /* input with '\\n' handling. Also supports '\\r\n' for horrible MSDOS
1517 case */
1518 static inline void minp(void)
1520 ch = ch1;
1521 inp();
1522 if (ch == '\\')
1523 handle_stray();
1527 /* same as minp, but also skip comments */
1528 static void cinp(void)
1530 int c;
1532 if (ch1 == '/') {
1533 inp();
1534 if (ch1 == '/') {
1535 /* single line C++ comments */
1536 inp();
1537 while (ch1 != '\n' && ch1 != CH_EOF)
1538 inp();
1539 ch = ' '; /* return space */
1540 } else if (ch1 == '*') {
1541 /* C comments */
1542 inp();
1543 while (ch1 != CH_EOF) {
1544 c = ch1;
1545 inp();
1546 if (c == '*' && ch1 == '/') {
1547 inp();
1548 ch = ' '; /* return space */
1549 break;
1552 } else {
1553 ch = '/';
1555 } else {
1556 minp();
1560 /* space exlcuding newline */
1561 static inline int is_space(int ch)
1563 return ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f' || ch == '\r';
1566 static inline void skip_spaces(void)
1568 while (is_space(ch))
1569 cinp();
1572 /* skip block of text until #else, #elif or #endif. skip also pairs of
1573 #if/#endif */
1574 void preprocess_skip(void)
1576 int a;
1577 a = 0;
1578 while (1) {
1579 while (ch != '\n') {
1580 if (ch == CH_EOF)
1581 expect("#endif");
1582 cinp();
1584 cinp();
1585 skip_spaces();
1586 if (ch == '#') {
1587 cinp();
1588 next_nomacro();
1589 if (a == 0 &&
1590 (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
1591 break;
1592 if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
1593 a++;
1594 else if (tok == TOK_ENDIF)
1595 a--;
1600 /* ParseState handling */
1602 /* XXX: currently, no include file info is stored. Thus, we cannot display
1603 accurate messages if the function or data definition spans multiple
1604 files */
1606 /* save current parse state in 's' */
1607 void save_parse_state(ParseState *s)
1609 s->line_num = file->line_num;
1610 s->macro_ptr = macro_ptr;
1611 s->tok = tok;
1612 s->tokc = tokc;
1615 /* restore parse state from 's' */
1616 void restore_parse_state(ParseState *s)
1618 file->line_num = s->line_num;
1619 macro_ptr = s->macro_ptr;
1620 tok = s->tok;
1621 tokc = s->tokc;
1624 /* return the number of additionnal 'ints' necessary to store the
1625 token */
1626 static inline int tok_ext_size(int t)
1628 switch(t) {
1629 /* 4 bytes */
1630 case TOK_CINT:
1631 case TOK_CUINT:
1632 case TOK_CCHAR:
1633 case TOK_LCHAR:
1634 case TOK_STR:
1635 case TOK_LSTR:
1636 case TOK_CFLOAT:
1637 case TOK_LINENUM:
1638 return 1;
1639 case TOK_CDOUBLE:
1640 case TOK_CLLONG:
1641 case TOK_CULLONG:
1642 return 2;
1643 case TOK_CLDOUBLE:
1644 return LDOUBLE_SIZE / 4;
1645 default:
1646 return 0;
1650 /* token string handling */
1652 static inline void tok_str_new(TokenString *s)
1654 s->str = NULL;
1655 s->len = 0;
1656 s->last_line_num = -1;
1659 static void tok_str_free(int *str)
1661 const int *p;
1662 CString *cstr;
1663 int t;
1665 p = str;
1666 for(;;) {
1667 t = *p++;
1668 if (t == 0)
1669 break;
1670 if (t == TOK_STR || t == TOK_LSTR) {
1671 /* XXX: use a macro to be portable on 64 bit ? */
1672 cstr = (CString *)(*p++);
1673 cstr_free(cstr);
1674 tcc_free(cstr);
1675 } else {
1676 p += tok_ext_size(t);
1679 tcc_free(str);
1682 static void tok_str_add(TokenString *s, int t)
1684 int len, *str;
1686 len = s->len;
1687 str = s->str;
1688 if ((len & 63) == 0) {
1689 str = tcc_realloc(str, (len + 64) * sizeof(int));
1690 if (!str)
1691 return;
1692 s->str = str;
1694 str[len++] = t;
1695 s->len = len;
1698 static void tok_str_add2(TokenString *s, int t, CValue *cv)
1700 int n, i, size;
1701 CString *cstr, *cstr1;
1702 CValue cv1;
1704 tok_str_add(s, t);
1705 if (t == TOK_STR || t == TOK_LSTR) {
1706 /* special case: need to duplicate string */
1707 cstr1 = cv->cstr;
1708 cstr = tcc_malloc(sizeof(CString));
1709 size = cstr1->size;
1710 cstr->size = size;
1711 cstr->size_allocated = size;
1712 cstr->data_allocated = tcc_malloc(size);
1713 cstr->data = cstr->data_allocated;
1714 memcpy(cstr->data_allocated, cstr1->data_allocated, size);
1715 cv1.cstr = cstr;
1716 tok_str_add(s, cv1.tab[0]);
1717 } else {
1718 n = tok_ext_size(t);
1719 for(i=0;i<n;i++)
1720 tok_str_add(s, cv->tab[i]);
1724 /* add the current parse token in token string 's' */
1725 static void tok_str_add_tok(TokenString *s)
1727 CValue cval;
1729 /* save line number info */
1730 if (file->line_num != s->last_line_num) {
1731 s->last_line_num = file->line_num;
1732 cval.i = s->last_line_num;
1733 tok_str_add2(s, TOK_LINENUM, &cval);
1735 tok_str_add2(s, tok, &tokc);
1738 /* get a token from an integer array and increment pointer accordingly */
1739 static int tok_get(int **tok_str, CValue *cv)
1741 int *p, t, n, i;
1743 p = *tok_str;
1744 t = *p++;
1745 n = tok_ext_size(t);
1746 for(i=0;i<n;i++)
1747 cv->tab[i] = *p++;
1748 *tok_str = p;
1749 return t;
1752 /* eval an expression for #if/#elif */
1753 int expr_preprocess(void)
1755 int c, t;
1756 TokenString str;
1758 tok_str_new(&str);
1759 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
1760 next(); /* do macro subst */
1761 if (tok == TOK_DEFINED) {
1762 next_nomacro();
1763 t = tok;
1764 if (t == '(')
1765 next_nomacro();
1766 c = sym_find1(&define_stack, tok) != 0;
1767 if (t == '(')
1768 next_nomacro();
1769 tok = TOK_CINT;
1770 tokc.i = c;
1771 } else if (tok >= TOK_IDENT) {
1772 /* if undefined macro */
1773 tok = TOK_CINT;
1774 tokc.i = 0;
1776 tok_str_add_tok(&str);
1778 tok_str_add(&str, -1); /* simulate end of file */
1779 tok_str_add(&str, 0);
1780 /* now evaluate C constant expression */
1781 macro_ptr = str.str;
1782 next();
1783 c = expr_const();
1784 macro_ptr = NULL;
1785 tok_str_free(str.str);
1786 return c != 0;
1789 #if defined(DEBUG) || defined(PP_DEBUG)
1790 void tok_print(int *str)
1792 int t;
1793 CValue cval;
1795 while (1) {
1796 t = tok_get(&str, &cval);
1797 if (!t)
1798 break;
1799 printf(" %s", get_tok_str(t, &cval));
1801 printf("\n");
1803 #endif
1805 /* parse after #define */
1806 void parse_define(void)
1808 Sym *s, *first, **ps;
1809 int v, t, varg, is_vaargs;
1810 TokenString str;
1812 v = tok;
1813 /* XXX: should check if same macro (ANSI) */
1814 first = NULL;
1815 t = MACRO_OBJ;
1816 /* '(' must be just after macro definition for MACRO_FUNC */
1817 if (ch == '(') {
1818 next_nomacro();
1819 next_nomacro();
1820 ps = &first;
1821 while (tok != ')') {
1822 varg = tok;
1823 next_nomacro();
1824 is_vaargs = 0;
1825 if (varg == TOK_DOTS) {
1826 varg = TOK___VA_ARGS__;
1827 is_vaargs = 1;
1828 } else if (tok == TOK_DOTS && gnu_ext) {
1829 is_vaargs = 1;
1830 next_nomacro();
1832 if (varg < TOK_IDENT)
1833 error("badly punctuated parameter list");
1834 s = sym_push1(&define_stack, varg | SYM_FIELD, is_vaargs, 0);
1835 *ps = s;
1836 ps = &s->next;
1837 if (tok != ',')
1838 break;
1839 next_nomacro();
1841 t = MACRO_FUNC;
1843 tok_str_new(&str);
1844 next_nomacro();
1845 /* EOF testing necessary for '-D' handling */
1846 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
1847 tok_str_add2(&str, tok, &tokc);
1848 next_nomacro();
1850 tok_str_add(&str, 0);
1851 #ifdef PP_DEBUG
1852 printf("define %s %d: ", get_tok_str(v, NULL), t);
1853 tok_print(str.str);
1854 #endif
1855 s = sym_push1(&define_stack, v, t, (int)str.str);
1856 s->next = first;
1859 /* XXX: use a token or a hash table to accelerate matching ? */
1860 static CachedInclude *search_cached_include(int type, const char *filename)
1862 CachedInclude *e;
1863 int i;
1865 for(i = 0;i < nb_cached_includes; i++) {
1866 e = cached_includes[i];
1867 if (e->type == type && !strcmp(e->filename, filename))
1868 return e;
1870 return NULL;
1873 static inline void add_cached_include(int type,
1874 const char *filename, int ifndef_macro)
1876 CachedInclude *e;
1878 if (search_cached_include(type, filename))
1879 return;
1880 #ifdef INC_DEBUG
1881 printf("adding cached '%s' %s\n", filename, get_tok_str(ifndef_macro, NULL));
1882 #endif
1883 e = tcc_malloc(sizeof(CachedInclude) + strlen(filename));
1884 if (!e)
1885 return;
1886 e->type = type;
1887 strcpy(e->filename, filename);
1888 e->ifndef_macro = ifndef_macro;
1889 dynarray_add((void ***)&cached_includes, &nb_cached_includes, e);
1893 enum IncludeState {
1894 INCLUDE_STATE_NONE = 0,
1895 INCLUDE_STATE_SEEK_IFNDEF,
1898 void preprocess(void)
1900 int size, i, c, n;
1901 enum IncludeState state;
1902 char buf[1024], *q, *p;
1903 char buf1[1024];
1904 BufferedFile *f;
1905 Sym *s;
1906 CachedInclude *e;
1908 return_linefeed = 1; /* linefeed will be returned as a
1909 token. EOF is also returned as line feed */
1910 state = INCLUDE_STATE_NONE;
1911 eof_seen = 0;
1912 redo1:
1913 cinp();
1914 next_nomacro();
1915 redo:
1916 if (tok == TOK_DEFINE) {
1917 next_nomacro();
1918 parse_define();
1919 } else if (tok == TOK_UNDEF) {
1920 next_nomacro();
1921 s = sym_find1(&define_stack, tok);
1922 /* undefine symbol by putting an invalid name */
1923 if (s)
1924 sym_undef(&define_stack, s);
1925 } else if (tok == TOK_INCLUDE) {
1926 skip_spaces();
1927 if (ch == '<') {
1928 c = '>';
1929 goto read_name;
1930 } else if (ch == '\"') {
1931 c = ch;
1932 read_name:
1933 minp();
1934 q = buf;
1935 while (ch != c && ch != '\n' && ch != CH_EOF) {
1936 if ((q - buf) < sizeof(buf) - 1)
1937 *q++ = ch;
1938 minp();
1940 *q = '\0';
1941 /* eat all spaces and comments after include */
1942 /* XXX: slightly incorrect */
1943 while (ch1 != '\n' && ch1 != CH_EOF)
1944 inp();
1945 } else {
1946 /* computed #include : either we have only strings or
1947 we have anything enclosed in '<>' */
1948 next();
1949 buf[0] = '\0';
1950 if (tok == TOK_STR) {
1951 while (tok != TOK_LINEFEED) {
1952 if (tok != TOK_STR) {
1953 include_syntax:
1954 error("'#include' expects \"FILENAME\" or <FILENAME>");
1956 pstrcat(buf, sizeof(buf), (char *)tokc.cstr->data);
1957 next();
1959 c = '\"';
1960 } else {
1961 int len;
1962 while (tok != TOK_LINEFEED) {
1963 pstrcat(buf, sizeof(buf), get_tok_str(tok, &tokc));
1964 next();
1966 len = strlen(buf);
1967 /* check syntax and remove '<>' */
1968 if (len < 2 || buf[0] != '<' || buf[len - 1] != '>')
1969 goto include_syntax;
1970 memmove(buf, buf + 1, len - 2);
1971 buf[len - 2] = '\0';
1972 c = '>';
1976 ch = '\n';
1977 e = search_cached_include(c, buf);
1978 if (e && sym_find1(&define_stack, e->ifndef_macro)) {
1979 /* no need to parse the include because the 'ifndef macro'
1980 is defined */
1981 #ifdef INC_DEBUG
1982 printf("%s: skipping %s\n", file->filename, buf);
1983 #endif
1984 } else {
1985 if (c == '\"') {
1986 /* first search in current dir if "header.h" */
1987 size = 0;
1988 p = strrchr(file->filename, '/');
1989 if (p)
1990 size = p + 1 - file->filename;
1991 if (size > sizeof(buf1) - 1)
1992 size = sizeof(buf1) - 1;
1993 memcpy(buf1, file->filename, size);
1994 buf1[size] = '\0';
1995 pstrcat(buf1, sizeof(buf1), buf);
1996 f = tcc_open(buf1);
1997 if (f)
1998 goto found;
2000 if (include_stack_ptr >= include_stack + INCLUDE_STACK_SIZE)
2001 error("#include recursion too deep");
2002 /* now search in all the include paths */
2003 n = nb_include_paths + nb_sysinclude_paths;
2004 for(i = 0; i < n; i++) {
2005 const char *path;
2006 if (i < nb_include_paths)
2007 path = include_paths[i];
2008 else
2009 path = sysinclude_paths[i - nb_include_paths];
2010 pstrcpy(buf1, sizeof(buf1), path);
2011 pstrcat(buf1, sizeof(buf1), "/");
2012 pstrcat(buf1, sizeof(buf1), buf);
2013 f = tcc_open(buf1);
2014 if (f)
2015 goto found;
2017 error("include file '%s' not found", buf);
2018 f = NULL;
2019 found:
2020 #ifdef INC_DEBUG
2021 printf("%s: including %s\n", file->filename, buf1);
2022 #endif
2023 f->inc_type = c;
2024 pstrcpy(f->inc_filename, sizeof(f->inc_filename), buf);
2025 /* push current file in stack */
2026 /* XXX: fix current line init */
2027 *include_stack_ptr++ = file;
2028 file = f;
2029 /* add include file debug info */
2030 if (do_debug) {
2031 put_stabs(file->filename, N_BINCL, 0, 0, 0);
2033 /* we check for the construct: #ifndef IDENT \n #define IDENT */
2034 inp();
2035 /* get first non space char */
2036 while (is_space(ch) || ch == '\n')
2037 cinp();
2038 if (ch != '#')
2039 goto the_end;
2040 state = INCLUDE_STATE_SEEK_IFNDEF;
2041 goto redo1;
2043 } else if (tok == TOK_IFNDEF) {
2044 c = 1;
2045 goto do_ifdef;
2046 } else if (tok == TOK_IF) {
2047 c = expr_preprocess();
2048 goto do_if;
2049 } else if (tok == TOK_IFDEF) {
2050 c = 0;
2051 do_ifdef:
2052 next_nomacro();
2053 if (tok < TOK_IDENT)
2054 error("invalid argument for '#if%sdef'", c ? "n" : "");
2055 if (state == INCLUDE_STATE_SEEK_IFNDEF) {
2056 if (c) {
2057 file->ifndef_macro = tok;
2059 state = INCLUDE_STATE_NONE;
2061 c = (sym_find1(&define_stack, tok) != 0) ^ c;
2062 do_if:
2063 if (ifdef_stack_ptr >= ifdef_stack + IFDEF_STACK_SIZE)
2064 error("memory full");
2065 *ifdef_stack_ptr++ = c;
2066 goto test_skip;
2067 } else if (tok == TOK_ELSE) {
2068 if (ifdef_stack_ptr == ifdef_stack)
2069 error("#else without matching #if");
2070 if (ifdef_stack_ptr[-1] & 2)
2071 error("#else after #else");
2072 c = (ifdef_stack_ptr[-1] ^= 3);
2073 goto test_skip;
2074 } else if (tok == TOK_ELIF) {
2075 if (ifdef_stack_ptr == ifdef_stack)
2076 error("#elif without matching #if");
2077 c = ifdef_stack_ptr[-1];
2078 if (c > 1)
2079 error("#elif after #else");
2080 /* last #if/#elif expression was true: we skip */
2081 if (c == 1)
2082 goto skip;
2083 c = expr_preprocess();
2084 ifdef_stack_ptr[-1] = c;
2085 test_skip:
2086 if (!(c & 1)) {
2087 skip:
2088 preprocess_skip();
2089 state = INCLUDE_STATE_NONE;
2090 goto redo;
2092 } else if (tok == TOK_ENDIF) {
2093 if (ifdef_stack_ptr <= file->ifdef_stack_ptr)
2094 error("#endif without matching #if");
2095 if (file->ifndef_macro &&
2096 ifdef_stack_ptr == (file->ifdef_stack_ptr + 1)) {
2097 /* '#ifndef macro \n #define macro' was at the start of
2098 file. Now we check if an '#endif' is exactly at the end
2099 of file */
2100 while (tok != TOK_LINEFEED)
2101 next_nomacro();
2102 /* XXX: should also skip comments, but it is more complicated */
2103 if (eof_seen) {
2104 add_cached_include(file->inc_type, file->inc_filename,
2105 file->ifndef_macro);
2106 } else {
2107 /* if not end of file, we must desactivate the ifndef
2108 macro search */
2109 file->ifndef_macro = 0;
2112 ifdef_stack_ptr--;
2113 } else if (tok == TOK_LINE) {
2114 int line_num;
2115 next();
2116 if (tok != TOK_CINT)
2117 error("#line");
2118 line_num = tokc.i;
2119 next();
2120 if (tok != TOK_LINEFEED) {
2121 if (tok != TOK_STR)
2122 error("#line");
2123 pstrcpy(file->filename, sizeof(file->filename),
2124 (char *)tokc.cstr->data);
2126 /* NOTE: we do it there to avoid problems with linefeed */
2127 file->line_num = line_num;
2128 } else if (tok == TOK_ERROR) {
2129 error("#error");
2131 /* ignore other preprocess commands or #! for C scripts */
2132 while (tok != TOK_LINEFEED && tok != TOK_EOF)
2133 next_nomacro();
2134 the_end:
2135 return_linefeed = 0;
2138 /* read a number in base b */
2139 static int getn(int b)
2141 int n, t;
2142 n = 0;
2143 while (1) {
2144 if (ch >= 'a' && ch <= 'f')
2145 t = ch - 'a' + 10;
2146 else if (ch >= 'A' && ch <= 'F')
2147 t = ch - 'A' + 10;
2148 else if (isnum(ch))
2149 t = ch - '0';
2150 else
2151 break;
2152 if (t < 0 || t >= b)
2153 break;
2154 n = n * b + t;
2155 cinp();
2157 return n;
2160 /* read a character for string or char constant and eval escape codes */
2161 static int getq(void)
2163 int c;
2165 c = ch;
2166 minp();
2167 if (c == '\\') {
2168 if (isoct(ch)) {
2169 /* at most three octal digits */
2170 c = ch - '0';
2171 minp();
2172 if (isoct(ch)) {
2173 c = c * 8 + ch - '0';
2174 minp();
2175 if (isoct(ch)) {
2176 c = c * 8 + ch - '0';
2177 minp();
2180 return c;
2181 } else if (ch == 'x') {
2182 minp();
2183 return getn(16);
2184 } else {
2185 if (ch == 'a')
2186 c = '\a';
2187 else if (ch == 'b')
2188 c = '\b';
2189 else if (ch == 'f')
2190 c = '\f';
2191 else if (ch == 'n')
2192 c = '\n';
2193 else if (ch == 'r')
2194 c = '\r';
2195 else if (ch == 't')
2196 c = '\t';
2197 else if (ch == 'v')
2198 c = '\v';
2199 else if (ch == 'e' && gnu_ext)
2200 c = 27;
2201 else if (ch == '\'' || ch == '\"' || ch == '\\' || ch == '?')
2202 c = ch;
2203 else
2204 error("invalid escaped char");
2205 minp();
2207 } else if (c == '\r' && ch == '\n') {
2208 minp();
2209 c = '\n';
2211 return c;
2214 /* we use 64 bit numbers */
2215 #define BN_SIZE 2
2217 /* bn = (bn << shift) | or_val */
2218 void bn_lshift(unsigned int *bn, int shift, int or_val)
2220 int i;
2221 unsigned int v;
2222 for(i=0;i<BN_SIZE;i++) {
2223 v = bn[i];
2224 bn[i] = (v << shift) | or_val;
2225 or_val = v >> (32 - shift);
2229 void bn_zero(unsigned int *bn)
2231 int i;
2232 for(i=0;i<BN_SIZE;i++) {
2233 bn[i] = 0;
2237 void parse_number(void)
2239 int b, t, shift, frac_bits, s, exp_val;
2240 char *q;
2241 unsigned int bn[BN_SIZE];
2242 double d;
2244 /* number */
2245 q = token_buf;
2246 t = ch;
2247 cinp();
2248 *q++ = t;
2249 b = 10;
2250 if (t == '.') {
2251 /* special dot handling */
2252 if (ch >= '0' && ch <= '9') {
2253 goto float_frac_parse;
2254 } else if (ch == '.') {
2255 cinp();
2256 if (ch != '.')
2257 expect("'.'");
2258 cinp();
2259 tok = TOK_DOTS;
2260 } else {
2261 /* dots */
2262 tok = t;
2264 return;
2265 } else if (t == '0') {
2266 if (ch == 'x' || ch == 'X') {
2267 q--;
2268 cinp();
2269 b = 16;
2270 } else if (tcc_ext && (ch == 'b' || ch == 'B')) {
2271 q--;
2272 cinp();
2273 b = 2;
2276 /* parse all digits. cannot check octal numbers at this stage
2277 because of floating point constants */
2278 while (1) {
2279 if (ch >= 'a' && ch <= 'f')
2280 t = ch - 'a' + 10;
2281 else if (ch >= 'A' && ch <= 'F')
2282 t = ch - 'A' + 10;
2283 else if (isnum(ch))
2284 t = ch - '0';
2285 else
2286 break;
2287 if (t >= b)
2288 break;
2289 if (q >= token_buf + STRING_MAX_SIZE) {
2290 num_too_long:
2291 error("number too long");
2293 *q++ = ch;
2294 cinp();
2296 if (ch == '.' ||
2297 ((ch == 'e' || ch == 'E') && b == 10) ||
2298 ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
2299 if (b != 10) {
2300 /* NOTE: strtox should support that for hexa numbers, but
2301 non ISOC99 libcs do not support it, so we prefer to do
2302 it by hand */
2303 /* hexadecimal or binary floats */
2304 /* XXX: handle overflows */
2305 *q = '\0';
2306 if (b == 16)
2307 shift = 4;
2308 else
2309 shift = 2;
2310 bn_zero(bn);
2311 q = token_buf;
2312 while (1) {
2313 t = *q++;
2314 if (t == '\0') {
2315 break;
2316 } else if (t >= 'a') {
2317 t = t - 'a' + 10;
2318 } else if (t >= 'A') {
2319 t = t - 'A' + 10;
2320 } else {
2321 t = t - '0';
2323 bn_lshift(bn, shift, t);
2325 frac_bits = 0;
2326 if (ch == '.') {
2327 cinp();
2328 while (1) {
2329 t = ch;
2330 if (t >= 'a' && t <= 'f') {
2331 t = t - 'a' + 10;
2332 } else if (t >= 'A' && t <= 'F') {
2333 t = t - 'A' + 10;
2334 } else if (t >= '0' && t <= '9') {
2335 t = t - '0';
2336 } else {
2337 break;
2339 if (t >= b)
2340 error("invalid digit");
2341 bn_lshift(bn, shift, t);
2342 frac_bits += shift;
2343 cinp();
2346 if (ch != 'p' && ch != 'P')
2347 error("exponent expected");
2348 cinp();
2349 s = 1;
2350 exp_val = 0;
2351 if (ch == '+') {
2352 cinp();
2353 } else if (ch == '-') {
2354 s = -1;
2355 cinp();
2357 if (ch < '0' || ch > '9')
2358 error("exponent digits expected");
2359 while (ch >= '0' && ch <= '9') {
2360 exp_val = exp_val * 10 + ch - '0';
2361 cinp();
2363 exp_val = exp_val * s;
2365 /* now we can generate the number */
2366 /* XXX: should patch directly float number */
2367 d = (double)bn[1] * 4294967296.0 + (double)bn[0];
2368 d = ldexp(d, exp_val - frac_bits);
2369 t = toup(ch);
2370 if (t == 'F') {
2371 cinp();
2372 tok = TOK_CFLOAT;
2373 /* float : should handle overflow */
2374 tokc.f = (float)d;
2375 } else if (t == 'L') {
2376 cinp();
2377 tok = TOK_CLDOUBLE;
2378 /* XXX: not large enough */
2379 tokc.ld = (long double)d;
2380 } else {
2381 tok = TOK_CDOUBLE;
2382 tokc.d = d;
2384 } else {
2385 /* decimal floats */
2386 if (ch == '.') {
2387 if (q >= token_buf + STRING_MAX_SIZE)
2388 goto num_too_long;
2389 *q++ = ch;
2390 cinp();
2391 float_frac_parse:
2392 while (ch >= '0' && ch <= '9') {
2393 if (q >= token_buf + STRING_MAX_SIZE)
2394 goto num_too_long;
2395 *q++ = ch;
2396 cinp();
2399 if (ch == 'e' || ch == 'E') {
2400 if (q >= token_buf + STRING_MAX_SIZE)
2401 goto num_too_long;
2402 *q++ = ch;
2403 cinp();
2404 if (ch == '-' || ch == '+') {
2405 if (q >= token_buf + STRING_MAX_SIZE)
2406 goto num_too_long;
2407 *q++ = ch;
2408 cinp();
2410 if (ch < '0' || ch > '9')
2411 error("exponent digits expected");
2412 while (ch >= '0' && ch <= '9') {
2413 if (q >= token_buf + STRING_MAX_SIZE)
2414 goto num_too_long;
2415 *q++ = ch;
2416 cinp();
2419 *q = '\0';
2420 t = toup(ch);
2421 errno = 0;
2422 if (t == 'F') {
2423 cinp();
2424 tok = TOK_CFLOAT;
2425 tokc.f = strtof(token_buf, NULL);
2426 } else if (t == 'L') {
2427 cinp();
2428 tok = TOK_CLDOUBLE;
2429 tokc.ld = strtold(token_buf, NULL);
2430 } else {
2431 tok = TOK_CDOUBLE;
2432 tokc.d = strtod(token_buf, NULL);
2435 } else {
2436 unsigned long long n, n1;
2437 int lcount;
2439 /* integer number */
2440 *q = '\0';
2441 q = token_buf;
2442 if (b == 10 && *q == '0') {
2443 b = 8;
2444 q++;
2446 n = 0;
2447 while(1) {
2448 t = *q++;
2449 /* no need for checks except for base 10 / 8 errors */
2450 if (t == '\0') {
2451 break;
2452 } else if (t >= 'a') {
2453 t = t - 'a' + 10;
2454 } else if (t >= 'A') {
2455 t = t - 'A' + 10;
2456 } else {
2457 t = t - '0';
2458 if (t >= b)
2459 error("invalid digit");
2461 n1 = n;
2462 n = n * b + t;
2463 /* detect overflow */
2464 if (n < n1)
2465 error("integer constant overflow");
2468 /* XXX: not exactly ANSI compliant */
2469 if ((n & 0xffffffff00000000LL) != 0) {
2470 if ((n >> 63) != 0)
2471 tok = TOK_CULLONG;
2472 else
2473 tok = TOK_CLLONG;
2474 } else if (n > 0x7fffffff) {
2475 tok = TOK_CUINT;
2476 } else {
2477 tok = TOK_CINT;
2479 lcount = 0;
2480 for(;;) {
2481 t = toup(ch);
2482 if (t == 'L') {
2483 if (lcount >= 2)
2484 error("three 'l' in integer constant");
2485 lcount++;
2486 if (lcount == 2) {
2487 if (tok == TOK_CINT)
2488 tok = TOK_CLLONG;
2489 else if (tok == TOK_CUINT)
2490 tok = TOK_CULLONG;
2492 cinp();
2493 } else if (t == 'U') {
2494 if (tok == TOK_CINT)
2495 tok = TOK_CUINT;
2496 else if (tok == TOK_CLLONG)
2497 tok = TOK_CULLONG;
2498 cinp();
2499 } else {
2500 break;
2503 if (tok == TOK_CINT || tok == TOK_CUINT)
2504 tokc.ui = n;
2505 else
2506 tokc.ull = n;
2511 /* return next token without macro substitution */
2512 static inline void next_nomacro1(void)
2514 int b;
2515 char *q;
2516 TokenSym *ts;
2518 /* skip spaces */
2519 while(1) {
2520 while (ch == '\n') {
2521 /* during preprocessor parsing, '\n' is a token */
2522 if (return_linefeed) {
2523 tok = TOK_LINEFEED;
2524 return;
2526 cinp();
2527 skip_spaces();
2528 if (ch == '#') {
2529 /* preprocessor command if # at start of line after
2530 spaces */
2531 preprocess();
2534 if (!is_space(ch))
2535 break;
2536 cinp();
2538 if (isid(ch)) {
2539 q = token_buf;
2540 *q++ = ch;
2541 cinp();
2542 if (q[-1] == 'L') {
2543 if (ch == '\'') {
2544 tok = TOK_LCHAR;
2545 goto char_const;
2547 if (ch == '\"') {
2548 tok = TOK_LSTR;
2549 goto str_const;
2552 while (isid(ch) || isnum(ch)) {
2553 if (q >= token_buf + STRING_MAX_SIZE)
2554 error("ident too long");
2555 *q++ = ch;
2556 cinp();
2558 *q = '\0';
2559 ts = tok_alloc(token_buf, q - token_buf);
2560 tok = ts->tok;
2561 } else if (isnum(ch) || ch == '.') {
2562 parse_number();
2563 } else if (ch == '\'') {
2564 tok = TOK_CCHAR;
2565 char_const:
2566 minp();
2567 b = getq();
2568 /* this cast is needed if >= 128 */
2569 if (tok == TOK_CCHAR)
2570 b = (char)b;
2571 tokc.i = b;
2572 if (ch != '\'')
2573 expect("\'");
2574 minp();
2575 } else if (ch == '\"') {
2576 tok = TOK_STR;
2577 str_const:
2578 minp();
2579 cstr_reset(&tokcstr);
2580 while (ch != '\"') {
2581 b = getq();
2582 if (ch == CH_EOF)
2583 error("unterminated string");
2584 if (tok == TOK_STR)
2585 cstr_ccat(&tokcstr, b);
2586 else
2587 cstr_wccat(&tokcstr, b);
2589 if (tok == TOK_STR)
2590 cstr_ccat(&tokcstr, '\0');
2591 else
2592 cstr_wccat(&tokcstr, '\0');
2593 tokc.cstr = &tokcstr;
2594 minp();
2595 } else {
2596 q = tok_two_chars;
2597 /* two chars */
2598 tok = ch;
2599 cinp();
2600 while (*q) {
2601 if (*q == tok && q[1] == ch) {
2602 cinp();
2603 tok = q[2] & 0xff;
2604 /* three chars tests */
2605 if (tok == TOK_SHL || tok == TOK_SAR) {
2606 if (ch == '=') {
2607 tok = tok | 0x80;
2608 cinp();
2610 } else if (tok == TOK_DOTS) {
2611 if (ch != '.')
2612 error("parse error");
2613 cinp();
2615 return;
2617 q = q + 3;
2619 /* single char substitutions */
2620 if (tok == '<')
2621 tok = TOK_LT;
2622 else if (tok == '>')
2623 tok = TOK_GT;
2627 /* return next token without macro substitution. Can read input from
2628 macro_ptr buffer */
2629 void next_nomacro()
2631 if (macro_ptr) {
2632 redo:
2633 tok = *macro_ptr;
2634 if (tok) {
2635 tok = tok_get(&macro_ptr, &tokc);
2636 if (tok == TOK_LINENUM) {
2637 file->line_num = tokc.i;
2638 goto redo;
2641 } else {
2642 next_nomacro1();
2646 /* substitute args in macro_str and return allocated string */
2647 int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
2649 int *st, last_tok, t, notfirst;
2650 Sym *s;
2651 CValue cval;
2652 TokenString str;
2653 CString cstr;
2655 tok_str_new(&str);
2656 last_tok = 0;
2657 while(1) {
2658 t = tok_get(&macro_str, &cval);
2659 if (!t)
2660 break;
2661 if (t == '#') {
2662 /* stringize */
2663 t = tok_get(&macro_str, &cval);
2664 if (!t)
2665 break;
2666 s = sym_find2(args, t);
2667 if (s) {
2668 cstr_new(&cstr);
2669 st = (int *)s->c;
2670 notfirst = 0;
2671 while (*st) {
2672 if (notfirst)
2673 cstr_ccat(&cstr, ' ');
2674 t = tok_get(&st, &cval);
2675 cstr_cat(&cstr, get_tok_str(t, &cval));
2676 notfirst = 1;
2678 cstr_ccat(&cstr, '\0');
2679 #ifdef PP_DEBUG
2680 printf("stringize: %s\n", (char *)cstr.data);
2681 #endif
2682 /* add string */
2683 cval.cstr = &cstr;
2684 tok_str_add2(&str, TOK_STR, &cval);
2685 cstr_free(&cstr);
2686 } else {
2687 tok_str_add2(&str, t, &cval);
2689 } else if (t >= TOK_IDENT) {
2690 s = sym_find2(args, t);
2691 if (s) {
2692 st = (int *)s->c;
2693 /* if '##' is present before or after, no arg substitution */
2694 if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) {
2695 /* special case for var arg macros : ## eats the
2696 ',' if empty VA_ARGS riable. */
2697 /* XXX: test of the ',' is not 100%
2698 reliable. should fix it to avoid security
2699 problems */
2700 if (gnu_ext && s->t && *st == 0 &&
2701 last_tok == TOK_TWOSHARPS &&
2702 str.len >= 2 && str.str[str.len - 2] == ',') {
2703 /* suppress ',' '##' */
2704 str.len -= 2;
2705 } else {
2706 int t1;
2707 for(;;) {
2708 t1 = tok_get(&st, &cval);
2709 if (!t1)
2710 break;
2711 tok_str_add2(&str, t1, &cval);
2714 } else {
2715 macro_subst(&str, nested_list, st);
2717 } else {
2718 tok_str_add(&str, t);
2720 } else {
2721 tok_str_add2(&str, t, &cval);
2723 last_tok = t;
2725 tok_str_add(&str, 0);
2726 return str.str;
2729 /* handle the '##' operator */
2730 static int *macro_twosharps(void)
2732 TokenSym *ts;
2733 int *macro_ptr1;
2734 int t;
2735 char *p;
2736 CValue cval;
2737 TokenString macro_str1;
2739 tok_str_new(&macro_str1);
2740 tok = 0;
2741 while (1) {
2742 next_nomacro();
2743 if (tok == 0)
2744 break;
2745 while (*macro_ptr == TOK_TWOSHARPS) {
2746 macro_ptr++;
2747 macro_ptr1 = macro_ptr;
2748 t = *macro_ptr;
2749 if (t) {
2750 t = tok_get(&macro_ptr, &cval);
2751 /* XXX: we handle only most common cases:
2752 ident + ident or ident + number */
2753 if (tok >= TOK_IDENT &&
2754 (t >= TOK_IDENT || t == TOK_CINT)) {
2755 p = get_tok_str(tok, &tokc);
2756 pstrcpy(token_buf, sizeof(token_buf), p);
2757 p = get_tok_str(t, &cval);
2758 pstrcat(token_buf, sizeof(token_buf), p);
2759 ts = tok_alloc(token_buf, strlen(token_buf));
2760 tok = ts->tok; /* modify current token */
2761 } else {
2762 /* cannot merge tokens: skip '##' */
2763 macro_ptr = macro_ptr1;
2764 break;
2768 tok_str_add2(&macro_str1, tok, &tokc);
2770 tok_str_add(&macro_str1, 0);
2771 return macro_str1.str;
2775 /* do macro substitution of current token with macro 's' and add
2776 result to (tok_str,tok_len). 'nested_list' is the list of all
2777 macros we got inside to avoid recursing. Return non zero if no
2778 substitution needs to be done */
2779 static int macro_subst_tok(TokenString *tok_str,
2780 Sym **nested_list, Sym *s)
2782 Sym *args, *sa, *sa1;
2783 int mstr_allocated, parlevel, *mstr, t;
2784 TokenString str;
2785 char *cstrval;
2786 CValue cval;
2787 CString cstr;
2789 /* if symbol is a macro, prepare substitution */
2790 /* if nested substitution, do nothing */
2791 if (sym_find2(*nested_list, tok))
2792 return -1;
2794 /* special macros */
2795 if (tok == TOK___LINE__) {
2796 cval.i = file->line_num;
2797 tok_str_add2(tok_str, TOK_CINT, &cval);
2798 } else if (tok == TOK___FILE__) {
2799 cstrval = file->filename;
2800 goto add_cstr;
2801 tok_str_add2(tok_str, TOK_STR, &cval);
2802 } else if (tok == TOK___DATE__) {
2803 cstrval = "Jan 1 2002";
2804 goto add_cstr;
2805 } else if (tok == TOK___TIME__) {
2806 cstrval = "00:00:00";
2807 add_cstr:
2808 cstr_new(&cstr);
2809 cstr_cat(&cstr, cstrval);
2810 cstr_ccat(&cstr, '\0');
2811 cval.cstr = &cstr;
2812 tok_str_add2(tok_str, TOK_STR, &cval);
2813 cstr_free(&cstr);
2814 } else {
2815 mstr = (int *)s->c;
2816 mstr_allocated = 0;
2817 if (s->t == MACRO_FUNC) {
2818 /* NOTE: we do not use next_nomacro to avoid eating the
2819 next token. XXX: find better solution */
2820 if (macro_ptr) {
2821 t = *macro_ptr;
2822 } else {
2823 while (is_space(ch) || ch == '\n')
2824 cinp();
2825 t = ch;
2827 if (t != '(') /* no macro subst */
2828 return -1;
2830 /* argument macro */
2831 next_nomacro();
2832 next_nomacro();
2833 args = NULL;
2834 sa = s->next;
2835 /* NOTE: empty args are allowed, except if no args */
2836 for(;;) {
2837 /* handle '()' case */
2838 if (!args && tok == ')')
2839 break;
2840 if (!sa)
2841 error("macro '%s' used with too many args",
2842 get_tok_str(s->v, 0));
2843 tok_str_new(&str);
2844 parlevel = 0;
2845 /* NOTE: non zero sa->t indicates VA_ARGS */
2846 while ((parlevel > 0 ||
2847 (tok != ')' &&
2848 (tok != ',' || sa->t))) &&
2849 tok != -1) {
2850 if (tok == '(')
2851 parlevel++;
2852 else if (tok == ')')
2853 parlevel--;
2854 tok_str_add2(&str, tok, &tokc);
2855 next_nomacro();
2857 tok_str_add(&str, 0);
2858 sym_push2(&args, sa->v & ~SYM_FIELD, sa->t, (int)str.str);
2859 sa = sa->next;
2860 if (tok == ')') {
2861 /* special case for gcc var args: add an empty
2862 var arg argument if it is omitted */
2863 if (sa && sa->t && gnu_ext)
2864 continue;
2865 else
2866 break;
2868 if (tok != ',')
2869 expect(",");
2870 next_nomacro();
2872 if (sa) {
2873 error("macro '%s' used with too few args",
2874 get_tok_str(s->v, 0));
2877 /* now subst each arg */
2878 mstr = macro_arg_subst(nested_list, mstr, args);
2879 /* free memory */
2880 sa = args;
2881 while (sa) {
2882 sa1 = sa->prev;
2883 tok_str_free((int *)sa->c);
2884 tcc_free(sa);
2885 sa = sa1;
2887 mstr_allocated = 1;
2889 sym_push2(nested_list, s->v, 0, 0);
2890 macro_subst(tok_str, nested_list, mstr);
2891 /* pop nested defined symbol */
2892 sa1 = *nested_list;
2893 *nested_list = sa1->prev;
2894 tcc_free(sa1);
2895 if (mstr_allocated)
2896 tok_str_free(mstr);
2898 return 0;
2901 /* do macro substitution of macro_str and add result to
2902 (tok_str,tok_len). 'nested_list' is the list of all macros we got
2903 inside to avoid recursing. */
2904 static void macro_subst(TokenString *tok_str,
2905 Sym **nested_list, int *macro_str)
2907 Sym *s;
2908 int *saved_macro_ptr;
2909 int *macro_str1;
2911 saved_macro_ptr = macro_ptr;
2912 macro_ptr = macro_str;
2913 /* first scan for '##' operator handling */
2914 macro_str1 = macro_twosharps();
2915 macro_ptr = macro_str1;
2917 while (1) {
2918 next_nomacro();
2919 if (tok == 0)
2920 break;
2921 s = sym_find1(&define_stack, tok);
2922 if (s != NULL) {
2923 if (macro_subst_tok(tok_str, nested_list, s) != 0)
2924 goto no_subst;
2925 } else {
2926 no_subst:
2927 tok_str_add2(tok_str, tok, &tokc);
2930 macro_ptr = saved_macro_ptr;
2931 tok_str_free(macro_str1);
2934 /* return next token with macro substitution */
2935 void next(void)
2937 Sym *nested_list, *s;
2938 TokenString str;
2940 /* special 'ungettok' case for label parsing */
2941 if (tok1) {
2942 tok = tok1;
2943 tokc = tok1c;
2944 tok1 = 0;
2945 } else {
2946 redo:
2947 next_nomacro();
2948 if (!macro_ptr) {
2949 /* if not reading from macro substituted string, then try
2950 to substitute macros */
2951 if (tok >= TOK_IDENT) {
2952 s = sym_find1(&define_stack, tok);
2953 if (s) {
2954 /* we have a macro: we try to substitute */
2955 tok_str_new(&str);
2956 nested_list = NULL;
2957 if (macro_subst_tok(&str, &nested_list, s) == 0) {
2958 /* substitution done, NOTE: maybe empty */
2959 tok_str_add(&str, 0);
2960 macro_ptr = str.str;
2961 macro_ptr_allocated = str.str;
2962 goto redo;
2966 } else {
2967 if (tok == 0) {
2968 /* end of macro string: free it */
2969 tok_str_free(macro_ptr_allocated);
2970 macro_ptr = NULL;
2971 goto redo;
2975 #if defined(DEBUG)
2976 printf("token = %s\n", get_tok_str(tok, &tokc));
2977 #endif
2980 void swap(int *p, int *q)
2982 int t;
2983 t = *p;
2984 *p = *q;
2985 *q = t;
2988 void vsetc(int t, int r, CValue *vc)
2990 int v;
2992 if (vtop >= vstack + VSTACK_SIZE)
2993 error("memory full");
2994 /* cannot let cpu flags if other instruction are generated. Also
2995 avoid leaving VT_JMP anywhere except on the top of the stack
2996 because it would complicate the code generator. */
2997 if (vtop >= vstack) {
2998 v = vtop->r & VT_VALMASK;
2999 if (v == VT_CMP || (v & ~1) == VT_JMP)
3000 gv(RC_INT);
3002 vtop++;
3003 vtop->t = t;
3004 vtop->r = r;
3005 vtop->r2 = VT_CONST;
3006 vtop->c = *vc;
3009 /* push integer constant */
3010 void vpushi(int v)
3012 CValue cval;
3013 cval.i = v;
3014 vsetc(VT_INT, VT_CONST, &cval);
3017 /* Return a static symbol pointing to a section */
3018 static Sym *get_sym_ref(int t, Section *sec,
3019 unsigned long offset, unsigned long size)
3021 int v;
3022 Sym *sym;
3024 v = anon_sym++;
3025 sym = sym_push1(&global_stack, v, t | VT_STATIC, 0);
3026 sym->r = VT_CONST | VT_SYM;
3027 put_extern_sym(sym, sec, offset, size);
3028 return sym;
3031 /* push a reference to a section offset by adding a dummy symbol */
3032 static void vpush_ref(int t, Section *sec, unsigned long offset, unsigned long size)
3034 CValue cval;
3036 cval.ul = 0;
3037 vsetc(t, VT_CONST | VT_SYM, &cval);
3038 vtop->sym = get_sym_ref(t, sec, offset, size);
3041 /* define a new external reference to a symbol 'v' of type 'u' */
3042 static Sym *external_global_sym(int v, int u, int r)
3044 Sym *s;
3046 s = sym_find(v);
3047 if (!s) {
3048 /* push forward reference */
3049 s = sym_push1(&global_stack,
3050 v, u | VT_EXTERN, 0);
3051 s->r = r | VT_CONST | VT_SYM;
3053 return s;
3056 /* define a new external reference to a symbol 'v' of type 'u' */
3057 static Sym *external_sym(int v, int u, int r)
3059 Sym *s;
3061 s = sym_find(v);
3062 if (!s) {
3063 /* push forward reference */
3064 s = sym_push(v, u | VT_EXTERN, r | VT_CONST | VT_SYM, 0);
3066 return s;
3069 /* push a reference to global symbol v */
3070 static void vpush_global_sym(int t, int v)
3072 Sym *sym;
3073 CValue cval;
3075 sym = external_global_sym(v, t, 0);
3076 cval.ul = 0;
3077 vsetc(t, VT_CONST | VT_SYM, &cval);
3078 vtop->sym = sym;
3081 void vset(int t, int r, int v)
3083 CValue cval;
3085 cval.i = v;
3086 vsetc(t, r, &cval);
3089 void vswap(void)
3091 SValue tmp;
3093 tmp = vtop[0];
3094 vtop[0] = vtop[-1];
3095 vtop[-1] = tmp;
3098 void vpushv(SValue *v)
3100 if (vtop >= vstack + VSTACK_SIZE)
3101 error("memory full");
3102 vtop++;
3103 *vtop = *v;
3106 void vdup(void)
3108 vpushv(vtop);
3111 /* save r to the memory stack, and mark it as being free */
3112 void save_reg(int r)
3114 int l, saved, t, size, align;
3115 SValue *p, sv;
3117 /* modify all stack values */
3118 saved = 0;
3119 l = 0;
3120 for(p=vstack;p<=vtop;p++) {
3121 if ((p->r & VT_VALMASK) == r ||
3122 (p->r2 & VT_VALMASK) == r) {
3123 /* must save value on stack if not already done */
3124 if (!saved) {
3125 /* store register in the stack */
3126 t = p->t;
3127 if ((p->r & VT_LVAL) ||
3128 (!is_float(t) && (t & VT_BTYPE) != VT_LLONG))
3129 t = VT_INT;
3130 size = type_size(t, &align);
3131 loc = (loc - size) & -align;
3132 sv.t = t;
3133 sv.r = VT_LOCAL | VT_LVAL;
3134 sv.c.ul = loc;
3135 store(r, &sv);
3136 #ifdef TCC_TARGET_I386
3137 /* x86 specific: need to pop fp register ST0 if saved */
3138 if (r == REG_ST0) {
3139 o(0xd9dd); /* fstp %st(1) */
3141 #endif
3142 /* special long long case */
3143 if ((t & VT_BTYPE) == VT_LLONG) {
3144 sv.c.ul += 4;
3145 store(p->r2, &sv);
3147 l = loc;
3148 saved = 1;
3150 /* mark that stack entry as being saved on the stack */
3151 if (p->r & VT_LVAL) {
3152 /* also suppress the bounded flag because the
3153 relocation address of the function was stored in
3154 p->c.ul */
3155 p->r = (p->r & ~(VT_VALMASK | VT_BOUNDED)) | VT_LLOCAL;
3156 } else {
3157 p->r = lvalue_type(p->t) | VT_LOCAL;
3159 p->r2 = VT_CONST;
3160 p->c.ul = l;
3165 /* find a free register of class 'rc'. If none, save one register */
3166 int get_reg(int rc)
3168 int r;
3169 SValue *p;
3171 /* find a free register */
3172 for(r=0;r<NB_REGS;r++) {
3173 if (reg_classes[r] & rc) {
3174 for(p=vstack;p<=vtop;p++) {
3175 if ((p->r & VT_VALMASK) == r ||
3176 (p->r2 & VT_VALMASK) == r)
3177 goto notfound;
3179 return r;
3181 notfound: ;
3184 /* no register left : free the first one on the stack (VERY
3185 IMPORTANT to start from the bottom to ensure that we don't
3186 spill registers used in gen_opi()) */
3187 for(p=vstack;p<=vtop;p++) {
3188 r = p->r & VT_VALMASK;
3189 if (r < VT_CONST && (reg_classes[r] & rc)) {
3190 save_reg(r);
3191 break;
3194 return r;
3197 /* save registers up to (vtop - n) stack entry */
3198 void save_regs(int n)
3200 int r;
3201 SValue *p, *p1;
3202 p1 = vtop - n;
3203 for(p = vstack;p <= p1; p++) {
3204 r = p->r & VT_VALMASK;
3205 if (r < VT_CONST) {
3206 save_reg(r);
3211 /* move register 's' to 'r', and flush previous value of r to memory
3212 if needed */
3213 void move_reg(int r, int s)
3215 SValue sv;
3217 if (r != s) {
3218 save_reg(r);
3219 sv.t = VT_INT;
3220 sv.r = s;
3221 sv.c.ul = 0;
3222 load(r, &sv);
3226 /* get address of vtop (vtop MUST BE an lvalue) */
3227 void gaddrof(void)
3229 vtop->r &= ~VT_LVAL;
3230 /* tricky: if saved lvalue, then we can go back to lvalue */
3231 if ((vtop->r & VT_VALMASK) == VT_LLOCAL)
3232 vtop->r = (vtop->r & ~(VT_VALMASK | VT_LVAL_TYPE)) | VT_LOCAL | VT_LVAL;
3235 #ifdef CONFIG_TCC_BCHECK
3236 /* generate lvalue bound code */
3237 void gbound(void)
3239 int lval_type, t1;
3241 vtop->r &= ~VT_MUSTBOUND;
3242 /* if lvalue, then use checking code before dereferencing */
3243 if (vtop->r & VT_LVAL) {
3244 /* if not VT_BOUNDED value, then make one */
3245 if (!(vtop->r & VT_BOUNDED)) {
3246 lval_type = vtop->r & (VT_LVAL_TYPE | VT_LVAL);
3247 /* must save type because we must set it to int to get pointer */
3248 t1 = vtop->t;
3249 vtop->t = VT_INT;
3250 gaddrof();
3251 vpushi(0);
3252 gen_bounded_ptr_add();
3253 vtop->r |= lval_type;
3254 vtop->t = t1;
3256 /* then check for dereferencing */
3257 gen_bounded_ptr_deref();
3260 #endif
3262 /* store vtop a register belonging to class 'rc'. lvalues are
3263 converted to values. Cannot be used if cannot be converted to
3264 register value (such as structures). */
3265 int gv(int rc)
3267 int r, r2, rc2, bit_pos, bit_size, size, align, i;
3268 unsigned long long ll;
3270 /* NOTE: get_reg can modify vstack[] */
3271 if (vtop->t & VT_BITFIELD) {
3272 bit_pos = (vtop->t >> VT_STRUCT_SHIFT) & 0x3f;
3273 bit_size = (vtop->t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
3274 /* remove bit field info to avoid loops */
3275 vtop->t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
3276 /* generate shifts */
3277 vpushi(32 - (bit_pos + bit_size));
3278 gen_op(TOK_SHL);
3279 vpushi(32 - bit_size);
3280 /* NOTE: transformed to SHR if unsigned */
3281 gen_op(TOK_SAR);
3282 r = gv(rc);
3283 } else {
3284 if (is_float(vtop->t) &&
3285 (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
3286 Sym *sym;
3287 int *ptr;
3288 unsigned long offset;
3290 /* XXX: unify with initializers handling ? */
3291 /* CPUs usually cannot use float constants, so we store them
3292 generically in data segment */
3293 size = type_size(vtop->t, &align);
3294 offset = (data_section->data_offset + align - 1) & -align;
3295 data_section->data_offset = offset;
3296 /* XXX: not portable yet */
3297 ptr = section_ptr_add(data_section, size);
3298 size = size >> 2;
3299 for(i=0;i<size;i++)
3300 ptr[i] = vtop->c.tab[i];
3301 sym = get_sym_ref(vtop->t, data_section, offset, size << 2);
3302 vtop->r |= VT_LVAL | VT_SYM;
3303 vtop->sym = sym;
3304 vtop->c.ul = 0;
3306 #ifdef CONFIG_TCC_BCHECK
3307 if (vtop->r & VT_MUSTBOUND)
3308 gbound();
3309 #endif
3311 r = vtop->r & VT_VALMASK;
3312 /* need to reload if:
3313 - constant
3314 - lvalue (need to dereference pointer)
3315 - already a register, but not in the right class */
3316 if (r >= VT_CONST ||
3317 (vtop->r & VT_LVAL) ||
3318 !(reg_classes[r] & rc) ||
3319 ((vtop->t & VT_BTYPE) == VT_LLONG &&
3320 !(reg_classes[vtop->r2] & rc))) {
3321 r = get_reg(rc);
3322 if ((vtop->t & VT_BTYPE) == VT_LLONG) {
3323 /* two register type load : expand to two words
3324 temporarily */
3325 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
3326 /* load constant */
3327 ll = vtop->c.ull;
3328 vtop->c.ui = ll; /* first word */
3329 load(r, vtop);
3330 vtop->r = r; /* save register value */
3331 vpushi(ll >> 32); /* second word */
3332 } else if (r >= VT_CONST ||
3333 (vtop->r & VT_LVAL)) {
3334 /* load from memory */
3335 load(r, vtop);
3336 vdup();
3337 vtop[-1].r = r; /* save register value */
3338 /* increment pointer to get second word */
3339 vtop->t = VT_INT;
3340 gaddrof();
3341 vpushi(4);
3342 gen_op('+');
3343 vtop->r |= VT_LVAL;
3344 } else {
3345 /* move registers */
3346 load(r, vtop);
3347 vdup();
3348 vtop[-1].r = r; /* save register value */
3349 vtop->r = vtop[-1].r2;
3351 /* allocate second register */
3352 rc2 = RC_INT;
3353 if (rc == RC_IRET)
3354 rc2 = RC_LRET;
3355 r2 = get_reg(rc2);
3356 load(r2, vtop);
3357 vpop();
3358 /* write second register */
3359 vtop->r2 = r2;
3360 } else if ((vtop->r & VT_LVAL) && !is_float(vtop->t)) {
3361 int t1, t;
3362 /* lvalue of scalar type : need to use lvalue type
3363 because of possible cast */
3364 t = vtop->t;
3365 t1 = t;
3366 /* compute memory access type */
3367 if (vtop->r & VT_LVAL_BYTE)
3368 t = VT_BYTE;
3369 else if (vtop->r & VT_LVAL_SHORT)
3370 t = VT_SHORT;
3371 if (vtop->r & VT_LVAL_UNSIGNED)
3372 t |= VT_UNSIGNED;
3373 vtop->t = t;
3374 load(r, vtop);
3375 /* restore wanted type */
3376 vtop->t = t1;
3377 } else {
3378 /* one register type load */
3379 load(r, vtop);
3382 vtop->r = r;
3384 return r;
3387 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
3388 void gv2(int rc1, int rc2)
3390 int v;
3392 /* generate more generic register first. But VT_JMP or VT_CMP
3393 values must be generated first in all cases to avoid possible
3394 reload errors */
3395 v = vtop[0].r & VT_VALMASK;
3396 if (v != VT_CMP && (v & ~1) != VT_JMP && rc1 <= rc2) {
3397 vswap();
3398 gv(rc1);
3399 vswap();
3400 gv(rc2);
3401 /* test if reload is needed for first register */
3402 if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
3403 vswap();
3404 gv(rc1);
3405 vswap();
3407 } else {
3408 gv(rc2);
3409 vswap();
3410 gv(rc1);
3411 vswap();
3412 /* test if reload is needed for first register */
3413 if ((vtop[0].r & VT_VALMASK) >= VT_CONST) {
3414 gv(rc2);
3419 /* expand long long on stack in two int registers */
3420 void lexpand(void)
3422 int u;
3424 u = vtop->t & VT_UNSIGNED;
3425 gv(RC_INT);
3426 vdup();
3427 vtop[0].r = vtop[-1].r2;
3428 vtop[0].r2 = VT_CONST;
3429 vtop[-1].r2 = VT_CONST;
3430 vtop[0].t = VT_INT | u;
3431 vtop[-1].t = VT_INT | u;
3434 /* build a long long from two ints */
3435 void lbuild(int t)
3437 gv2(RC_INT, RC_INT);
3438 vtop[-1].r2 = vtop[0].r;
3439 vtop[-1].t = t;
3440 vpop();
3443 /* rotate n first stack elements to the bottom */
3444 void vrotb(int n)
3446 int i;
3447 SValue tmp;
3449 tmp = vtop[-n + 1];
3450 for(i=-n+1;i!=0;i++)
3451 vtop[i] = vtop[i+1];
3452 vtop[0] = tmp;
3455 /* pop stack value */
3456 void vpop(void)
3458 int v;
3459 v = vtop->r & VT_VALMASK;
3460 #ifdef TCC_TARGET_I386
3461 /* for x86, we need to pop the FP stack */
3462 if (v == REG_ST0) {
3463 o(0xd9dd); /* fstp %st(1) */
3464 } else
3465 #endif
3466 if (v == VT_JMP || v == VT_JMPI) {
3467 /* need to put correct jump if && or || without test */
3468 gsym(vtop->c.ul);
3470 vtop--;
3473 /* convert stack entry to register and duplicate its value in another
3474 register */
3475 void gv_dup(void)
3477 int rc, t, r, r1;
3478 SValue sv;
3480 t = vtop->t;
3481 if ((t & VT_BTYPE) == VT_LLONG) {
3482 lexpand();
3483 gv_dup();
3484 vswap();
3485 vrotb(3);
3486 gv_dup();
3487 vrotb(4);
3488 /* stack: H L L1 H1 */
3489 lbuild(t);
3490 vrotb(3);
3491 vrotb(3);
3492 vswap();
3493 lbuild(t);
3494 vswap();
3495 } else {
3496 /* duplicate value */
3497 rc = RC_INT;
3498 sv.t = VT_INT;
3499 if (is_float(t)) {
3500 rc = RC_FLOAT;
3501 sv.t = t;
3503 r = gv(rc);
3504 r1 = get_reg(rc);
3505 sv.r = r;
3506 sv.c.ul = 0;
3507 load(r1, &sv); /* move r to r1 */
3508 vdup();
3509 /* duplicates value */
3510 vtop->r = r1;
3514 /* generate CPU independent (unsigned) long long operations */
3515 void gen_opl(int op)
3517 int t, a, b, op1, c, i;
3518 int func;
3519 GFuncContext gf;
3520 SValue tmp;
3522 switch(op) {
3523 case '/':
3524 case TOK_PDIV:
3525 func = TOK___divdi3;
3526 goto gen_func;
3527 case TOK_UDIV:
3528 func = TOK___udivdi3;
3529 goto gen_func;
3530 case '%':
3531 func = TOK___moddi3;
3532 goto gen_func;
3533 case TOK_UMOD:
3534 func = TOK___umoddi3;
3535 gen_func:
3536 /* call generic long long function */
3537 gfunc_start(&gf, FUNC_CDECL);
3538 gfunc_param(&gf);
3539 gfunc_param(&gf);
3540 vpush_global_sym(func_old_type, func);
3541 gfunc_call(&gf);
3542 vpushi(0);
3543 vtop->r = REG_IRET;
3544 vtop->r2 = REG_LRET;
3545 break;
3546 case '^':
3547 case '&':
3548 case '|':
3549 case '*':
3550 case '+':
3551 case '-':
3552 t = vtop->t;
3553 vswap();
3554 lexpand();
3555 vrotb(3);
3556 lexpand();
3557 /* stack: L1 H1 L2 H2 */
3558 tmp = vtop[0];
3559 vtop[0] = vtop[-3];
3560 vtop[-3] = tmp;
3561 tmp = vtop[-2];
3562 vtop[-2] = vtop[-3];
3563 vtop[-3] = tmp;
3564 vswap();
3565 /* stack: H1 H2 L1 L2 */
3566 if (op == '*') {
3567 vpushv(vtop - 1);
3568 vpushv(vtop - 1);
3569 gen_op(TOK_UMULL);
3570 lexpand();
3571 /* stack: H1 H2 L1 L2 ML MH */
3572 for(i=0;i<4;i++)
3573 vrotb(6);
3574 /* stack: ML MH H1 H2 L1 L2 */
3575 tmp = vtop[0];
3576 vtop[0] = vtop[-2];
3577 vtop[-2] = tmp;
3578 /* stack: ML MH H1 L2 H2 L1 */
3579 gen_op('*');
3580 vrotb(3);
3581 vrotb(3);
3582 gen_op('*');
3583 /* stack: ML MH M1 M2 */
3584 gen_op('+');
3585 gen_op('+');
3586 } else if (op == '+' || op == '-') {
3587 /* XXX: add non carry method too (for MIPS or alpha) */
3588 if (op == '+')
3589 op1 = TOK_ADDC1;
3590 else
3591 op1 = TOK_SUBC1;
3592 gen_op(op1);
3593 /* stack: H1 H2 (L1 op L2) */
3594 vrotb(3);
3595 vrotb(3);
3596 gen_op(op1 + 1); /* TOK_xxxC2 */
3597 } else {
3598 gen_op(op);
3599 /* stack: H1 H2 (L1 op L2) */
3600 vrotb(3);
3601 vrotb(3);
3602 /* stack: (L1 op L2) H1 H2 */
3603 gen_op(op);
3604 /* stack: (L1 op L2) (H1 op H2) */
3606 /* stack: L H */
3607 lbuild(t);
3608 break;
3609 case TOK_SAR:
3610 case TOK_SHR:
3611 case TOK_SHL:
3612 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
3613 t = vtop[-1].t;
3614 vswap();
3615 lexpand();
3616 vrotb(3);
3617 /* stack: L H shift */
3618 c = (int)vtop->c.i;
3619 /* constant: simpler */
3620 /* NOTE: all comments are for SHL. the other cases are
3621 done by swaping words */
3622 vpop();
3623 if (op != TOK_SHL)
3624 vswap();
3625 if (c >= 32) {
3626 /* stack: L H */
3627 vpop();
3628 if (c > 32) {
3629 vpushi(c - 32);
3630 gen_op(op);
3632 if (op != TOK_SAR) {
3633 vpushi(0);
3634 } else {
3635 gv_dup();
3636 vpushi(31);
3637 gen_op(TOK_SAR);
3639 vswap();
3640 } else {
3641 vswap();
3642 gv_dup();
3643 /* stack: H L L */
3644 vpushi(c);
3645 gen_op(op);
3646 vswap();
3647 vpushi(32 - c);
3648 if (op == TOK_SHL)
3649 gen_op(TOK_SHR);
3650 else
3651 gen_op(TOK_SHL);
3652 vrotb(3);
3653 /* stack: L L H */
3654 vpushi(c);
3655 gen_op(op);
3656 gen_op('|');
3658 if (op != TOK_SHL)
3659 vswap();
3660 lbuild(t);
3661 } else {
3662 /* XXX: should provide a faster fallback on x86 ? */
3663 switch(op) {
3664 case TOK_SAR:
3665 func = TOK___sardi3;
3666 goto gen_func;
3667 case TOK_SHR:
3668 func = TOK___shrdi3;
3669 goto gen_func;
3670 case TOK_SHL:
3671 func = TOK___shldi3;
3672 goto gen_func;
3675 break;
3676 default:
3677 /* compare operations */
3678 t = vtop->t;
3679 vswap();
3680 lexpand();
3681 vrotb(3);
3682 lexpand();
3683 /* stack: L1 H1 L2 H2 */
3684 tmp = vtop[-1];
3685 vtop[-1] = vtop[-2];
3686 vtop[-2] = tmp;
3687 /* stack: L1 L2 H1 H2 */
3688 /* compare high */
3689 op1 = op;
3690 /* when values are equal, we need to compare low words. since
3691 the jump is inverted, we invert the test too. */
3692 if (op1 == TOK_LT)
3693 op1 = TOK_LE;
3694 else if (op1 == TOK_GT)
3695 op1 = TOK_GE;
3696 else if (op1 == TOK_ULT)
3697 op1 = TOK_ULE;
3698 else if (op1 == TOK_UGT)
3699 op1 = TOK_UGE;
3700 a = 0;
3701 b = 0;
3702 gen_op(op1);
3703 if (op1 != TOK_NE) {
3704 a = gtst(1, 0);
3706 if (op != TOK_EQ) {
3707 /* generate non equal test */
3708 /* XXX: NOT PORTABLE yet */
3709 if (a == 0) {
3710 b = gtst(0, 0);
3711 } else {
3712 #ifdef TCC_TARGET_I386
3713 b = psym(0x850f, 0);
3714 #else
3715 error("not implemented");
3716 #endif
3719 /* compare low */
3720 gen_op(op);
3721 a = gtst(1, a);
3722 gsym(b);
3723 vset(VT_INT, VT_JMPI, a);
3724 break;
3728 /* handle integer constant optimizations and various machine
3729 independant opt */
3730 void gen_opic(int op)
3732 int fc, c1, c2, n;
3733 SValue *v1, *v2;
3735 v1 = vtop - 1;
3736 v2 = vtop;
3737 /* currently, we cannot do computations with forward symbols */
3738 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
3739 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
3740 if (c1 && c2) {
3741 fc = v2->c.i;
3742 switch(op) {
3743 case '+': v1->c.i += fc; break;
3744 case '-': v1->c.i -= fc; break;
3745 case '&': v1->c.i &= fc; break;
3746 case '^': v1->c.i ^= fc; break;
3747 case '|': v1->c.i |= fc; break;
3748 case '*': v1->c.i *= fc; break;
3750 case TOK_PDIV:
3751 case '/':
3752 case '%':
3753 case TOK_UDIV:
3754 case TOK_UMOD:
3755 /* if division by zero, generate explicit division */
3756 if (fc == 0) {
3757 if (const_wanted)
3758 error("division by zero in constant");
3759 goto general_case;
3761 switch(op) {
3762 default: v1->c.i /= fc; break;
3763 case '%': v1->c.i %= fc; break;
3764 case TOK_UDIV: v1->c.i = (unsigned)v1->c.i / fc; break;
3765 case TOK_UMOD: v1->c.i = (unsigned)v1->c.i % fc; break;
3767 break;
3768 case TOK_SHL: v1->c.i <<= fc; break;
3769 case TOK_SHR: v1->c.i = (unsigned)v1->c.i >> fc; break;
3770 case TOK_SAR: v1->c.i >>= fc; break;
3771 /* tests */
3772 case TOK_ULT: v1->c.i = (unsigned)v1->c.i < (unsigned)fc; break;
3773 case TOK_UGE: v1->c.i = (unsigned)v1->c.i >= (unsigned)fc; break;
3774 case TOK_EQ: v1->c.i = v1->c.i == fc; break;
3775 case TOK_NE: v1->c.i = v1->c.i != fc; break;
3776 case TOK_ULE: v1->c.i = (unsigned)v1->c.i <= (unsigned)fc; break;
3777 case TOK_UGT: v1->c.i = (unsigned)v1->c.i > (unsigned)fc; break;
3778 case TOK_LT: v1->c.i = v1->c.i < fc; break;
3779 case TOK_GE: v1->c.i = v1->c.i >= fc; break;
3780 case TOK_LE: v1->c.i = v1->c.i <= fc; break;
3781 case TOK_GT: v1->c.i = v1->c.i > fc; break;
3782 /* logical */
3783 case TOK_LAND: v1->c.i = v1->c.i && fc; break;
3784 case TOK_LOR: v1->c.i = v1->c.i || fc; break;
3785 default:
3786 goto general_case;
3788 vtop--;
3789 } else {
3790 /* if commutative ops, put c2 as constant */
3791 if (c1 && (op == '+' || op == '&' || op == '^' ||
3792 op == '|' || op == '*')) {
3793 vswap();
3794 swap(&c1, &c2);
3796 fc = vtop->c.i;
3797 if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
3798 op == TOK_PDIV) &&
3799 fc == 1) ||
3800 ((op == '+' || op == '-' || op == '|' || op == '^' ||
3801 op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
3802 fc == 0) ||
3803 (op == '&' &&
3804 fc == -1))) {
3805 /* nothing to do */
3806 vtop--;
3807 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
3808 /* try to use shifts instead of muls or divs */
3809 if (fc > 0 && (fc & (fc - 1)) == 0) {
3810 n = -1;
3811 while (fc) {
3812 fc >>= 1;
3813 n++;
3815 vtop->c.i = n;
3816 if (op == '*')
3817 op = TOK_SHL;
3818 else if (op == TOK_PDIV)
3819 op = TOK_SAR;
3820 else
3821 op = TOK_SHR;
3823 goto general_case;
3824 } else if (c2 && (op == '+' || op == '-') &&
3825 (vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) ==
3826 (VT_CONST | VT_SYM)) {
3827 /* symbol + constant case */
3828 if (op == '-')
3829 fc = -fc;
3830 vtop--;
3831 vtop->c.i += fc;
3832 } else {
3833 general_case:
3834 /* call low level op generator */
3835 gen_opi(op);
3840 /* generate a floating point operation with constant propagation */
3841 void gen_opif(int op)
3843 int c1, c2;
3844 SValue *v1, *v2;
3845 long double f1, f2;
3847 v1 = vtop - 1;
3848 v2 = vtop;
3849 /* currently, we cannot do computations with forward symbols */
3850 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
3851 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
3852 if (c1 && c2) {
3853 if (v1->t == VT_FLOAT) {
3854 f1 = v1->c.f;
3855 f2 = v2->c.f;
3856 } else if (v1->t == VT_DOUBLE) {
3857 f1 = v1->c.d;
3858 f2 = v2->c.d;
3859 } else {
3860 f1 = v1->c.ld;
3861 f2 = v2->c.ld;
3864 /* NOTE: we only do constant propagation if finite number (not
3865 NaN or infinity) (ANSI spec) */
3866 if (!ieee_finite(f1) || !ieee_finite(f2))
3867 goto general_case;
3869 switch(op) {
3870 case '+': f1 += f2; break;
3871 case '-': f1 -= f2; break;
3872 case '*': f1 *= f2; break;
3873 case '/':
3874 if (f2 == 0.0) {
3875 if (const_wanted)
3876 error("division by zero in constant");
3877 goto general_case;
3879 f1 /= f2;
3880 break;
3881 /* XXX: also handles tests ? */
3882 default:
3883 goto general_case;
3885 /* XXX: overflow test ? */
3886 if (v1->t == VT_FLOAT) {
3887 v1->c.f = f1;
3888 } else if (v1->t == VT_DOUBLE) {
3889 v1->c.d = f1;
3890 } else {
3891 v1->c.ld = f1;
3893 vtop--;
3894 } else {
3895 general_case:
3896 gen_opf(op);
3900 int pointed_size(int t)
3902 return type_size(pointed_type(t), &t);
3905 #if 0
3906 void check_pointer_types(SValue *p1, SValue *p2)
3908 char buf1[256], buf2[256];
3909 int t1, t2;
3910 t1 = p1->t;
3911 t2 = p2->t;
3912 if (!is_compatible_types(t1, t2)) {
3913 type_to_str(buf1, sizeof(buf1), t1, NULL);
3914 type_to_str(buf2, sizeof(buf2), t2, NULL);
3915 error("incompatible pointers '%s' and '%s'", buf1, buf2);
3918 #endif
3920 /* generic gen_op: handles types problems */
3921 void gen_op(int op)
3923 int u, t1, t2, bt1, bt2, t;
3925 t1 = vtop[-1].t;
3926 t2 = vtop[0].t;
3927 bt1 = t1 & VT_BTYPE;
3928 bt2 = t2 & VT_BTYPE;
3930 if (bt1 == VT_PTR || bt2 == VT_PTR) {
3931 /* at least one operand is a pointer */
3932 /* relationnal op: must be both pointers */
3933 if (op >= TOK_ULT && op <= TOK_GT) {
3934 // check_pointer_types(vtop, vtop - 1);
3935 /* pointers are handled are unsigned */
3936 t = VT_INT | VT_UNSIGNED;
3937 goto std_op;
3939 /* if both pointers, then it must be the '-' op */
3940 if ((t1 & VT_BTYPE) == VT_PTR &&
3941 (t2 & VT_BTYPE) == VT_PTR) {
3942 if (op != '-')
3943 error("cannot use pointers here");
3944 // check_pointer_types(vtop - 1, vtop);
3945 /* XXX: check that types are compatible */
3946 u = pointed_size(t1);
3947 gen_opic(op);
3948 /* set to integer type */
3949 vtop->t = VT_INT;
3950 vpushi(u);
3951 gen_op(TOK_PDIV);
3952 } else {
3953 /* exactly one pointer : must be '+' or '-'. */
3954 if (op != '-' && op != '+')
3955 error("cannot use pointers here");
3956 /* Put pointer as first operand */
3957 if ((t2 & VT_BTYPE) == VT_PTR) {
3958 vswap();
3959 swap(&t1, &t2);
3961 /* XXX: cast to int ? (long long case) */
3962 vpushi(pointed_size(vtop[-1].t));
3963 gen_op('*');
3964 #ifdef CONFIG_TCC_BCHECK
3965 /* if evaluating constant expression, no code should be
3966 generated, so no bound check */
3967 if (do_bounds_check && !const_wanted) {
3968 /* if bounded pointers, we generate a special code to
3969 test bounds */
3970 if (op == '-') {
3971 vpushi(0);
3972 vswap();
3973 gen_op('-');
3975 gen_bounded_ptr_add();
3976 } else
3977 #endif
3979 gen_opic(op);
3981 /* put again type if gen_opic() swaped operands */
3982 vtop->t = t1;
3984 } else if (is_float(bt1) || is_float(bt2)) {
3985 /* compute bigger type and do implicit casts */
3986 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
3987 t = VT_LDOUBLE;
3988 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
3989 t = VT_DOUBLE;
3990 } else {
3991 t = VT_FLOAT;
3993 /* floats can only be used for a few operations */
3994 if (op != '+' && op != '-' && op != '*' && op != '/' &&
3995 (op < TOK_ULT || op > TOK_GT))
3996 error("invalid operands for binary operation");
3997 goto std_op;
3998 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
3999 /* cast to biggest op */
4000 t = VT_LLONG;
4001 /* convert to unsigned if it does not fit in a long long */
4002 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
4003 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
4004 t |= VT_UNSIGNED;
4005 goto std_op;
4006 } else {
4007 /* integer operations */
4008 t = VT_INT;
4009 /* convert to unsigned if it does not fit in an integer */
4010 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
4011 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
4012 t |= VT_UNSIGNED;
4013 std_op:
4014 /* XXX: currently, some unsigned operations are explicit, so
4015 we modify them here */
4016 if (t & VT_UNSIGNED) {
4017 if (op == TOK_SAR)
4018 op = TOK_SHR;
4019 else if (op == '/')
4020 op = TOK_UDIV;
4021 else if (op == '%')
4022 op = TOK_UMOD;
4023 else if (op == TOK_LT)
4024 op = TOK_ULT;
4025 else if (op == TOK_GT)
4026 op = TOK_UGT;
4027 else if (op == TOK_LE)
4028 op = TOK_ULE;
4029 else if (op == TOK_GE)
4030 op = TOK_UGE;
4032 vswap();
4033 gen_cast(t);
4034 vswap();
4035 /* special case for shifts and long long: we keep the shift as
4036 an integer */
4037 if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL)
4038 gen_cast(VT_INT);
4039 else
4040 gen_cast(t);
4041 if (is_float(t))
4042 gen_opif(op);
4043 else if ((t & VT_BTYPE) == VT_LLONG)
4044 gen_opl(op);
4045 else
4046 gen_opic(op);
4047 if (op >= TOK_ULT && op <= TOK_GT) {
4048 /* relationnal op: the result is an int */
4049 vtop->t = VT_INT;
4050 } else {
4051 vtop->t = t;
4056 /* generic itof for unsigned long long case */
4057 void gen_cvt_itof1(int t)
4059 GFuncContext gf;
4061 if ((vtop->t & (VT_BTYPE | VT_UNSIGNED)) ==
4062 (VT_LLONG | VT_UNSIGNED)) {
4064 gfunc_start(&gf, FUNC_CDECL);
4065 gfunc_param(&gf);
4066 if (t == VT_FLOAT)
4067 vpush_global_sym(func_old_type, TOK___ulltof);
4068 else if (t == VT_DOUBLE)
4069 vpush_global_sym(func_old_type, TOK___ulltod);
4070 else
4071 vpush_global_sym(func_old_type, TOK___ulltold);
4072 gfunc_call(&gf);
4073 vpushi(0);
4074 vtop->r = REG_FRET;
4075 } else {
4076 gen_cvt_itof(t);
4080 /* generic ftoi for unsigned long long case */
4081 void gen_cvt_ftoi1(int t)
4083 GFuncContext gf;
4084 int st;
4086 if (t == (VT_LLONG | VT_UNSIGNED)) {
4087 /* not handled natively */
4088 gfunc_start(&gf, FUNC_CDECL);
4089 st = vtop->t & VT_BTYPE;
4090 gfunc_param(&gf);
4091 if (st == VT_FLOAT)
4092 vpush_global_sym(func_old_type, TOK___fixunssfdi);
4093 else if (st == VT_DOUBLE)
4094 vpush_global_sym(func_old_type, TOK___fixunsdfdi);
4095 else
4096 vpush_global_sym(func_old_type, TOK___fixunsxfdi);
4097 gfunc_call(&gf);
4098 vpushi(0);
4099 vtop->r = REG_IRET;
4100 vtop->r2 = REG_LRET;
4101 } else {
4102 gen_cvt_ftoi(t);
4106 /* force char or short cast */
4107 void force_charshort_cast(int t)
4109 int bits, dbt;
4110 dbt = t & VT_BTYPE;
4111 /* XXX: add optimization if lvalue : just change type and offset */
4112 if (dbt == VT_BYTE)
4113 bits = 8;
4114 else
4115 bits = 16;
4116 if (t & VT_UNSIGNED) {
4117 vpushi((1 << bits) - 1);
4118 gen_op('&');
4119 } else {
4120 bits = 32 - bits;
4121 vpushi(bits);
4122 gen_op(TOK_SHL);
4123 vpushi(bits);
4124 gen_op(TOK_SAR);
4128 /* cast 'vtop' to 't' type */
4129 void gen_cast(int t)
4131 int sbt, dbt, sf, df, c;
4133 /* special delayed cast for char/short */
4134 /* XXX: in some cases (multiple cascaded casts), it may still
4135 be incorrect */
4136 if (vtop->r & VT_MUSTCAST) {
4137 vtop->r &= ~VT_MUSTCAST;
4138 force_charshort_cast(vtop->t);
4141 dbt = t & (VT_BTYPE | VT_UNSIGNED);
4142 sbt = vtop->t & (VT_BTYPE | VT_UNSIGNED);
4144 if (sbt != dbt) {
4145 sf = is_float(sbt);
4146 df = is_float(dbt);
4147 c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
4148 if (sf && df) {
4149 /* convert from fp to fp */
4150 if (c) {
4151 /* constant case: we can do it now */
4152 /* XXX: in ISOC, cannot do it if error in convert */
4153 if (dbt == VT_FLOAT && sbt == VT_DOUBLE)
4154 vtop->c.f = (float)vtop->c.d;
4155 else if (dbt == VT_FLOAT && sbt == VT_LDOUBLE)
4156 vtop->c.f = (float)vtop->c.ld;
4157 else if (dbt == VT_DOUBLE && sbt == VT_FLOAT)
4158 vtop->c.d = (double)vtop->c.f;
4159 else if (dbt == VT_DOUBLE && sbt == VT_LDOUBLE)
4160 vtop->c.d = (double)vtop->c.ld;
4161 else if (dbt == VT_LDOUBLE && sbt == VT_FLOAT)
4162 vtop->c.ld = (long double)vtop->c.f;
4163 else if (dbt == VT_LDOUBLE && sbt == VT_DOUBLE)
4164 vtop->c.ld = (long double)vtop->c.d;
4165 } else {
4166 /* non constant case: generate code */
4167 gen_cvt_ftof(dbt);
4169 } else if (df) {
4170 /* convert int to fp */
4171 if (c) {
4172 switch(sbt) {
4173 case VT_LLONG | VT_UNSIGNED:
4174 case VT_LLONG:
4175 /* XXX: add const cases for long long */
4176 goto do_itof;
4177 case VT_INT | VT_UNSIGNED:
4178 switch(dbt) {
4179 case VT_FLOAT: vtop->c.f = (float)vtop->c.ui; break;
4180 case VT_DOUBLE: vtop->c.d = (double)vtop->c.ui; break;
4181 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.ui; break;
4183 break;
4184 default:
4185 switch(dbt) {
4186 case VT_FLOAT: vtop->c.f = (float)vtop->c.i; break;
4187 case VT_DOUBLE: vtop->c.d = (double)vtop->c.i; break;
4188 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.i; break;
4190 break;
4192 } else {
4193 do_itof:
4194 gen_cvt_itof1(dbt);
4196 } else if (sf) {
4197 /* convert fp to int */
4198 /* we handle char/short/etc... with generic code */
4199 if (dbt != (VT_INT | VT_UNSIGNED) &&
4200 dbt != (VT_LLONG | VT_UNSIGNED) &&
4201 dbt != VT_LLONG)
4202 dbt = VT_INT;
4203 if (c) {
4204 switch(dbt) {
4205 case VT_LLONG | VT_UNSIGNED:
4206 case VT_LLONG:
4207 /* XXX: add const cases for long long */
4208 goto do_ftoi;
4209 case VT_INT | VT_UNSIGNED:
4210 switch(sbt) {
4211 case VT_FLOAT: vtop->c.ui = (unsigned int)vtop->c.d; break;
4212 case VT_DOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
4213 case VT_LDOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
4215 break;
4216 default:
4217 /* int case */
4218 switch(sbt) {
4219 case VT_FLOAT: vtop->c.i = (int)vtop->c.d; break;
4220 case VT_DOUBLE: vtop->c.i = (int)vtop->c.d; break;
4221 case VT_LDOUBLE: vtop->c.i = (int)vtop->c.d; break;
4223 break;
4225 } else {
4226 do_ftoi:
4227 gen_cvt_ftoi1(dbt);
4229 if (dbt == VT_INT && (t & (VT_BTYPE | VT_UNSIGNED)) != dbt) {
4230 /* additionnal cast for char/short/bool... */
4231 vtop->t = dbt;
4232 gen_cast(t);
4234 } else if ((dbt & VT_BTYPE) == VT_LLONG) {
4235 if ((sbt & VT_BTYPE) != VT_LLONG) {
4236 /* scalar to long long */
4237 if (c) {
4238 if (sbt == (VT_INT | VT_UNSIGNED))
4239 vtop->c.ll = vtop->c.ui;
4240 else
4241 vtop->c.ll = vtop->c.i;
4242 } else {
4243 /* machine independant conversion */
4244 gv(RC_INT);
4245 /* generate high word */
4246 if (sbt == (VT_INT | VT_UNSIGNED)) {
4247 vpushi(0);
4248 gv(RC_INT);
4249 } else {
4250 gv_dup();
4251 vpushi(31);
4252 gen_op(TOK_SAR);
4254 /* patch second register */
4255 vtop[-1].r2 = vtop->r;
4256 vpop();
4259 } else if (dbt == VT_BOOL) {
4260 /* scalar to bool */
4261 vpushi(0);
4262 gen_op(TOK_NE);
4263 } else if ((dbt & VT_BTYPE) == VT_BYTE ||
4264 (dbt & VT_BTYPE) == VT_SHORT) {
4265 force_charshort_cast(t);
4266 } else if ((dbt & VT_BTYPE) == VT_INT) {
4267 /* scalar to int */
4268 if (sbt == VT_LLONG) {
4269 /* from long long: just take low order word */
4270 lexpand();
4271 vpop();
4273 /* if lvalue and single word type, nothing to do because
4274 the lvalue already contains the real type size (see
4275 VT_LVAL_xxx constants) */
4278 vtop->t = t;
4281 /* return type size. Put alignment at 'a' */
4282 int type_size(int t, int *a)
4284 Sym *s;
4285 int bt;
4287 bt = t & VT_BTYPE;
4288 if (bt == VT_STRUCT) {
4289 /* struct/union */
4290 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
4291 *a = 4; /* XXX: cannot store it yet. Doing that is safe */
4292 return s->c;
4293 } else if (bt == VT_PTR) {
4294 if (t & VT_ARRAY) {
4295 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
4296 return type_size(s->t, a) * s->c;
4297 } else {
4298 *a = PTR_SIZE;
4299 return PTR_SIZE;
4301 } else if (bt == VT_LDOUBLE) {
4302 *a = LDOUBLE_ALIGN;
4303 return LDOUBLE_SIZE;
4304 } else if (bt == VT_DOUBLE || bt == VT_LLONG) {
4305 *a = 8;
4306 return 8;
4307 } else if (bt == VT_INT || bt == VT_ENUM || bt == VT_FLOAT) {
4308 *a = 4;
4309 return 4;
4310 } else if (bt == VT_SHORT) {
4311 *a = 2;
4312 return 2;
4313 } else {
4314 /* char, void, function, _Bool */
4315 *a = 1;
4316 return 1;
4320 /* return the pointed type of t */
4321 int pointed_type(int t)
4323 Sym *s;
4324 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
4325 return s->t | (t & ~VT_TYPE);
4328 int mk_pointer(int t)
4330 int p;
4331 p = anon_sym++;
4332 sym_push(p, t, 0, -1);
4333 return VT_PTR | (p << VT_STRUCT_SHIFT) | (t & ~VT_TYPE);
4336 int is_compatible_types(int t1, int t2)
4338 Sym *s1, *s2;
4339 int bt1, bt2;
4341 t1 &= VT_TYPE;
4342 t2 &= VT_TYPE;
4343 bt1 = t1 & VT_BTYPE;
4344 bt2 = t2 & VT_BTYPE;
4345 if (bt1 == VT_PTR) {
4346 t1 = pointed_type(t1);
4347 /* if function, then convert implicitely to function pointer */
4348 if (bt2 != VT_FUNC) {
4349 if (bt2 != VT_PTR)
4350 return 0;
4351 t2 = pointed_type(t2);
4353 /* void matches everything */
4354 t1 &= VT_TYPE;
4355 t2 &= VT_TYPE;
4356 if (t1 == VT_VOID || t2 == VT_VOID)
4357 return 1;
4358 return is_compatible_types(t1, t2);
4359 } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
4360 return (t2 == t1);
4361 } else if (bt1 == VT_FUNC) {
4362 if (bt2 != VT_FUNC)
4363 return 0;
4364 s1 = sym_find(((unsigned)t1 >> VT_STRUCT_SHIFT));
4365 s2 = sym_find(((unsigned)t2 >> VT_STRUCT_SHIFT));
4366 if (!is_compatible_types(s1->t, s2->t))
4367 return 0;
4368 /* XXX: not complete */
4369 if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
4370 return 1;
4371 if (s1->c != s2->c)
4372 return 0;
4373 while (s1 != NULL) {
4374 if (s2 == NULL)
4375 return 0;
4376 if (!is_compatible_types(s1->t, s2->t))
4377 return 0;
4378 s1 = s1->next;
4379 s2 = s2->next;
4381 if (s2)
4382 return 0;
4383 return 1;
4384 } else {
4385 /* XXX: not complete */
4386 return 1;
4390 /* print a type. If 'varstr' is not NULL, then the variable is also
4391 printed in the type */
4392 /* XXX: union */
4393 /* XXX: add array and function pointers */
4394 void type_to_str(char *buf, int buf_size,
4395 int t, const char *varstr)
4397 int bt, v;
4398 Sym *s, *sa;
4399 char buf1[256];
4400 const char *tstr;
4402 t = t & VT_TYPE;
4403 bt = t & VT_BTYPE;
4404 buf[0] = '\0';
4405 if (t & VT_UNSIGNED)
4406 pstrcat(buf, buf_size, "unsigned ");
4407 switch(bt) {
4408 case VT_VOID:
4409 tstr = "void";
4410 goto add_tstr;
4411 case VT_BOOL:
4412 tstr = "_Bool";
4413 goto add_tstr;
4414 case VT_BYTE:
4415 tstr = "char";
4416 goto add_tstr;
4417 case VT_SHORT:
4418 tstr = "short";
4419 goto add_tstr;
4420 case VT_INT:
4421 tstr = "int";
4422 goto add_tstr;
4423 case VT_LONG:
4424 tstr = "long";
4425 goto add_tstr;
4426 case VT_LLONG:
4427 tstr = "long long";
4428 goto add_tstr;
4429 case VT_FLOAT:
4430 tstr = "float";
4431 goto add_tstr;
4432 case VT_DOUBLE:
4433 tstr = "double";
4434 goto add_tstr;
4435 case VT_LDOUBLE:
4436 tstr = "long double";
4437 add_tstr:
4438 pstrcat(buf, buf_size, tstr);
4439 break;
4440 case VT_ENUM:
4441 case VT_STRUCT:
4442 if (bt == VT_STRUCT)
4443 tstr = "struct ";
4444 else
4445 tstr = "enum ";
4446 pstrcat(buf, buf_size, tstr);
4447 v = (unsigned)t >> VT_STRUCT_SHIFT;
4448 if (v >= SYM_FIRST_ANOM)
4449 pstrcat(buf, buf_size, "<anonymous>");
4450 else
4451 pstrcat(buf, buf_size, get_tok_str(v, NULL));
4452 break;
4453 case VT_FUNC:
4454 s = sym_find((unsigned)t >> VT_STRUCT_SHIFT);
4455 type_to_str(buf, buf_size, s->t, varstr);
4456 pstrcat(buf, buf_size, "(");
4457 sa = s->next;
4458 while (sa != NULL) {
4459 type_to_str(buf1, sizeof(buf1), sa->t, NULL);
4460 pstrcat(buf, buf_size, buf1);
4461 sa = sa->next;
4462 if (sa)
4463 pstrcat(buf, buf_size, ", ");
4465 pstrcat(buf, buf_size, ")");
4466 goto no_var;
4467 case VT_PTR:
4468 s = sym_find((unsigned)t >> VT_STRUCT_SHIFT);
4469 pstrcpy(buf1, sizeof(buf1), "*");
4470 if (varstr)
4471 pstrcat(buf1, sizeof(buf1), varstr);
4472 type_to_str(buf, buf_size, s->t, buf1);
4473 goto no_var;
4475 if (varstr) {
4476 pstrcat(buf, buf_size, " ");
4477 pstrcat(buf, buf_size, varstr);
4479 no_var: ;
4482 /* verify type compatibility to store vtop in 'dt' type, and generate
4483 casts if needed. */
4484 void gen_assign_cast(int dt)
4486 int st;
4487 char buf1[256], buf2[256];
4489 st = vtop->t; /* source type */
4490 if ((dt & VT_BTYPE) == VT_PTR) {
4491 /* special cases for pointers */
4492 /* a function is implicitely a function pointer */
4493 if ((st & VT_BTYPE) == VT_FUNC) {
4494 if (!is_compatible_types(pointed_type(dt), st))
4495 goto error;
4496 else
4497 goto type_ok;
4499 /* '0' can also be a pointer */
4500 if ((st & VT_BTYPE) == VT_INT &&
4501 ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) &&
4502 vtop->c.i == 0)
4503 goto type_ok;
4505 if (!is_compatible_types(dt, st)) {
4506 error:
4507 type_to_str(buf1, sizeof(buf1), st, NULL);
4508 type_to_str(buf2, sizeof(buf2), dt, NULL);
4509 error("cannot cast '%s' to '%s'", buf1, buf2);
4511 type_ok:
4512 gen_cast(dt);
4515 /* store vtop in lvalue pushed on stack */
4516 void vstore(void)
4518 int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
4519 GFuncContext gf;
4521 ft = vtop[-1].t;
4522 sbt = vtop->t & VT_BTYPE;
4523 dbt = ft & VT_BTYPE;
4524 if (((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
4525 (sbt == VT_INT && dbt == VT_SHORT)) {
4526 /* optimize char/short casts */
4527 delayed_cast = VT_MUSTCAST;
4528 vtop->t = ft & VT_TYPE;
4529 } else {
4530 delayed_cast = 0;
4531 gen_assign_cast(ft & VT_TYPE);
4534 if (sbt == VT_STRUCT) {
4535 /* if structure, only generate pointer */
4536 /* structure assignment : generate memcpy */
4537 /* XXX: optimize if small size */
4538 vdup();
4539 gfunc_start(&gf, FUNC_CDECL);
4540 /* type size */
4541 size = type_size(vtop->t, &align);
4542 vpushi(size);
4543 gfunc_param(&gf);
4544 /* source */
4545 vtop->t = VT_INT;
4546 gaddrof();
4547 gfunc_param(&gf);
4548 /* destination */
4549 vswap();
4550 vtop->t = VT_INT;
4551 gaddrof();
4552 gfunc_param(&gf);
4554 save_regs(0);
4555 vpush_global_sym(func_old_type, TOK_memcpy);
4556 gfunc_call(&gf);
4557 /* leave source on stack */
4558 } else if (ft & VT_BITFIELD) {
4559 /* bitfield store handling */
4560 bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
4561 bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
4562 /* remove bit field info to avoid loops */
4563 vtop[-1].t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
4565 /* duplicate destination */
4566 vdup();
4567 vtop[-1] = vtop[-2];
4569 /* mask and shift source */
4570 vpushi((1 << bit_size) - 1);
4571 gen_op('&');
4572 vpushi(bit_pos);
4573 gen_op(TOK_SHL);
4574 /* load destination, mask and or with source */
4575 vswap();
4576 vpushi(~(((1 << bit_size) - 1) << bit_pos));
4577 gen_op('&');
4578 gen_op('|');
4579 /* store result */
4580 vstore();
4581 } else {
4582 #ifdef CONFIG_TCC_BCHECK
4583 /* bound check case */
4584 if (vtop[-1].r & VT_MUSTBOUND) {
4585 vswap();
4586 gbound();
4587 vswap();
4589 #endif
4590 rc = RC_INT;
4591 if (is_float(ft))
4592 rc = RC_FLOAT;
4593 r = gv(rc); /* generate value */
4594 /* if lvalue was saved on stack, must read it */
4595 if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
4596 SValue sv;
4597 t = get_reg(RC_INT);
4598 sv.t = VT_INT;
4599 sv.r = VT_LOCAL | VT_LVAL;
4600 sv.c.ul = vtop[-1].c.ul;
4601 load(t, &sv);
4602 vtop[-1].r = t | VT_LVAL;
4604 store(r, vtop - 1);
4605 /* two word case handling : store second register at word + 4 */
4606 if ((ft & VT_BTYPE) == VT_LLONG) {
4607 vswap();
4608 /* convert to int to increment easily */
4609 vtop->t = VT_INT;
4610 gaddrof();
4611 vpushi(4);
4612 gen_op('+');
4613 vtop->r |= VT_LVAL;
4614 vswap();
4615 /* XXX: it works because r2 is spilled last ! */
4616 store(vtop->r2, vtop - 1);
4618 vswap();
4619 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
4620 vtop->r |= delayed_cast;
4624 /* post defines POST/PRE add. c is the token ++ or -- */
4625 void inc(int post, int c)
4627 test_lvalue();
4628 vdup(); /* save lvalue */
4629 if (post) {
4630 gv_dup(); /* duplicate value */
4631 vrotb(3);
4632 vrotb(3);
4634 /* add constant */
4635 vpushi(c - TOK_MID);
4636 gen_op('+');
4637 vstore(); /* store value */
4638 if (post)
4639 vpop(); /* if post op, return saved value */
4642 /* Parse GNUC __attribute__ extension. Currently, the following
4643 extensions are recognized:
4644 - aligned(n) : set data/function alignment.
4645 - section(x) : generate data/code in this section.
4646 - unused : currently ignored, but may be used someday.
4648 void parse_attribute(AttributeDef *ad)
4650 int t, n;
4652 next();
4653 skip('(');
4654 skip('(');
4655 while (tok != ')') {
4656 if (tok < TOK_IDENT)
4657 expect("attribute name");
4658 t = tok;
4659 next();
4660 switch(t) {
4661 case TOK_SECTION:
4662 case TOK___SECTION__:
4663 skip('(');
4664 if (tok != TOK_STR)
4665 expect("section name");
4666 ad->section = find_section((char *)tokc.cstr->data);
4667 next();
4668 skip(')');
4669 break;
4670 case TOK_ALIGNED:
4671 case TOK___ALIGNED__:
4672 skip('(');
4673 n = expr_const();
4674 if (n <= 0 || (n & (n - 1)) != 0)
4675 error("alignment must be a positive power of two");
4676 ad->aligned = n;
4677 skip(')');
4678 break;
4679 case TOK_UNUSED:
4680 case TOK___UNUSED__:
4681 /* currently, no need to handle it because tcc does not
4682 track unused objects */
4683 break;
4684 case TOK_NORETURN:
4685 case TOK___NORETURN__:
4686 /* currently, no need to handle it because tcc does not
4687 track unused objects */
4688 break;
4689 case TOK_CDECL:
4690 case TOK___CDECL:
4691 case TOK___CDECL__:
4692 ad->func_call = FUNC_CDECL;
4693 break;
4694 case TOK_STDCALL:
4695 case TOK___STDCALL:
4696 case TOK___STDCALL__:
4697 ad->func_call = FUNC_STDCALL;
4698 break;
4699 default:
4700 warning("'%s' attribute ignored", get_tok_str(t, NULL));
4701 /* skip parameters */
4702 /* XXX: skip parenthesis too */
4703 if (tok == '(') {
4704 next();
4705 while (tok != ')' && tok != -1)
4706 next();
4707 next();
4709 break;
4711 if (tok != ',')
4712 break;
4713 next();
4715 skip(')');
4716 skip(')');
4719 /* enum/struct/union declaration */
4720 int struct_decl(int u)
4722 int a, t, b, v, size, align, maxalign, c, offset;
4723 int bit_size, bit_pos, bsize, bt, lbit_pos;
4724 Sym *s, *ss, **ps;
4725 AttributeDef ad;
4727 a = tok; /* save decl type */
4728 next();
4729 if (tok != '{') {
4730 v = tok;
4731 next();
4732 /* struct already defined ? return it */
4733 /* XXX: check consistency */
4734 s = sym_find(v | SYM_STRUCT);
4735 if (s) {
4736 if (s->t != a)
4737 error("invalid type");
4738 goto do_decl;
4740 } else {
4741 v = anon_sym++;
4743 s = sym_push(v | SYM_STRUCT, a, 0, 0);
4744 /* put struct/union/enum name in type */
4745 do_decl:
4746 u = u | (v << VT_STRUCT_SHIFT);
4748 if (tok == '{') {
4749 next();
4750 if (s->c)
4751 error("struct/union/enum already defined");
4752 /* cannot be empty */
4753 c = 0;
4754 maxalign = 0;
4755 ps = &s->next;
4756 bit_pos = 0;
4757 offset = 0;
4758 while (1) {
4759 if (a == TOK_ENUM) {
4760 v = tok;
4761 next();
4762 if (tok == '=') {
4763 next();
4764 c = expr_const();
4766 /* enum symbols have static storage */
4767 sym_push(v, VT_STATIC | VT_INT, VT_CONST, c);
4768 if (tok == ',')
4769 next();
4770 c++;
4771 } else {
4772 parse_btype(&b, &ad);
4773 while (1) {
4774 bit_size = -1;
4775 v = 0;
4776 if (tok != ':') {
4777 t = type_decl(&ad, &v, b, TYPE_DIRECT);
4778 if ((t & VT_BTYPE) == VT_FUNC ||
4779 (t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN)))
4780 error("invalid type for '%s'",
4781 get_tok_str(v, NULL));
4782 } else {
4783 t = b;
4785 if (tok == ':') {
4786 next();
4787 bit_size = expr_const();
4788 /* XXX: handle v = 0 case for messages */
4789 if (bit_size < 0)
4790 error("negative width in bit-field '%s'",
4791 get_tok_str(v, NULL));
4792 if (v && bit_size == 0)
4793 error("zero width for bit-field '%s'",
4794 get_tok_str(v, NULL));
4796 size = type_size(t, &align);
4797 lbit_pos = 0;
4798 if (bit_size >= 0) {
4799 bt = t & VT_BTYPE;
4800 if (bt != VT_INT &&
4801 bt != VT_BYTE &&
4802 bt != VT_SHORT)
4803 error("bitfields must have scalar type");
4804 bsize = size * 8;
4805 if (bit_size > bsize) {
4806 error("width of '%s' exceeds its type",
4807 get_tok_str(v, NULL));
4808 } else if (bit_size == bsize) {
4809 /* no need for bit fields */
4810 bit_pos = 0;
4811 } else if (bit_size == 0) {
4812 /* XXX: what to do if only padding in a
4813 structure ? */
4814 /* zero size: means to pad */
4815 if (bit_pos > 0)
4816 bit_pos = bsize;
4817 } else {
4818 /* we do not have enough room ? */
4819 if ((bit_pos + bit_size) > bsize)
4820 bit_pos = 0;
4821 lbit_pos = bit_pos;
4822 /* XXX: handle LSB first */
4823 t |= VT_BITFIELD |
4824 (bit_pos << VT_STRUCT_SHIFT) |
4825 (bit_size << (VT_STRUCT_SHIFT + 6));
4826 bit_pos += bit_size;
4828 } else {
4829 bit_pos = 0;
4831 if (v) {
4832 /* add new memory data only if starting
4833 bit field */
4834 if (lbit_pos == 0) {
4835 if (a == TOK_STRUCT) {
4836 c = (c + align - 1) & -align;
4837 offset = c;
4838 c += size;
4839 } else {
4840 offset = 0;
4841 if (size > c)
4842 c = size;
4844 if (align > maxalign)
4845 maxalign = align;
4847 #if 0
4848 printf("add field %s offset=%d",
4849 get_tok_str(v, NULL), offset);
4850 if (t & VT_BITFIELD) {
4851 printf(" pos=%d size=%d",
4852 (t >> VT_STRUCT_SHIFT) & 0x3f,
4853 (t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
4855 printf("\n");
4856 #endif
4857 ss = sym_push(v | SYM_FIELD, t, 0, offset);
4858 *ps = ss;
4859 ps = &ss->next;
4861 if (tok == ';' || tok == -1)
4862 break;
4863 skip(',');
4865 skip(';');
4867 if (tok == '}')
4868 break;
4870 skip('}');
4871 /* size for struct/union, dummy for enum */
4872 s->c = (c + maxalign - 1) & -maxalign;
4874 return u;
4877 /* return 0 if no type declaration. otherwise, return the basic type
4878 and skip it.
4880 int parse_btype(int *type_ptr, AttributeDef *ad)
4882 int t, u, type_found;
4883 Sym *s;
4885 memset(ad, 0, sizeof(AttributeDef));
4886 type_found = 0;
4887 t = 0;
4888 while(1) {
4889 switch(tok) {
4890 /* basic types */
4891 case TOK_CHAR:
4892 u = VT_BYTE;
4893 basic_type:
4894 next();
4895 basic_type1:
4896 if ((t & VT_BTYPE) != 0)
4897 error("too many basic types");
4898 t |= u;
4899 break;
4900 case TOK_VOID:
4901 u = VT_VOID;
4902 goto basic_type;
4903 case TOK_SHORT:
4904 u = VT_SHORT;
4905 goto basic_type;
4906 case TOK_INT:
4907 next();
4908 break;
4909 case TOK_LONG:
4910 next();
4911 if ((t & VT_BTYPE) == VT_DOUBLE) {
4912 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
4913 } else if ((t & VT_BTYPE) == VT_LONG) {
4914 t = (t & ~VT_BTYPE) | VT_LLONG;
4915 } else {
4916 u = VT_LONG;
4917 goto basic_type1;
4919 break;
4920 case TOK_BOOL:
4921 u = VT_BOOL;
4922 goto basic_type;
4923 case TOK_FLOAT:
4924 u = VT_FLOAT;
4925 goto basic_type;
4926 case TOK_DOUBLE:
4927 next();
4928 if ((t & VT_BTYPE) == VT_LONG) {
4929 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
4930 } else {
4931 u = VT_DOUBLE;
4932 goto basic_type1;
4934 break;
4935 case TOK_ENUM:
4936 u = struct_decl(VT_ENUM);
4937 goto basic_type1;
4938 case TOK_STRUCT:
4939 case TOK_UNION:
4940 u = struct_decl(VT_STRUCT);
4941 goto basic_type1;
4943 /* type modifiers */
4944 case TOK_CONST:
4945 case TOK_VOLATILE:
4946 case TOK_REGISTER:
4947 case TOK_SIGNED:
4948 case TOK___SIGNED__:
4949 case TOK_AUTO:
4950 case TOK_INLINE:
4951 case TOK___INLINE__:
4952 case TOK_RESTRICT:
4953 next();
4954 break;
4955 case TOK_UNSIGNED:
4956 t |= VT_UNSIGNED;
4957 next();
4958 break;
4960 /* storage */
4961 case TOK_EXTERN:
4962 t |= VT_EXTERN;
4963 next();
4964 break;
4965 case TOK_STATIC:
4966 t |= VT_STATIC;
4967 next();
4968 break;
4969 case TOK_TYPEDEF:
4970 t |= VT_TYPEDEF;
4971 next();
4972 break;
4973 /* GNUC attribute */
4974 case TOK___ATTRIBUTE__:
4975 parse_attribute(ad);
4976 break;
4977 default:
4978 s = sym_find(tok);
4979 if (!s || !(s->t & VT_TYPEDEF))
4980 goto the_end;
4981 t |= (s->t & ~VT_TYPEDEF);
4982 next();
4983 break;
4985 type_found = 1;
4987 the_end:
4988 /* long is never used as type */
4989 if ((t & VT_BTYPE) == VT_LONG)
4990 t = (t & ~VT_BTYPE) | VT_INT;
4991 *type_ptr = t;
4992 return type_found;
4995 int post_type(int t, AttributeDef *ad)
4997 int p, n, pt, l, t1;
4998 Sym **plast, *s, *first;
4999 AttributeDef ad1;
5001 if (tok == '(') {
5002 /* function declaration */
5003 next();
5004 l = 0;
5005 first = NULL;
5006 plast = &first;
5007 while (tok != ')') {
5008 /* read param name and compute offset */
5009 if (l != FUNC_OLD) {
5010 if (!parse_btype(&pt, &ad1)) {
5011 if (l) {
5012 error("invalid type");
5013 } else {
5014 l = FUNC_OLD;
5015 goto old_proto;
5018 l = FUNC_NEW;
5019 if ((pt & VT_BTYPE) == VT_VOID && tok == ')')
5020 break;
5021 pt = type_decl(&ad1, &n, pt, TYPE_DIRECT | TYPE_ABSTRACT);
5022 if ((pt & VT_BTYPE) == VT_VOID)
5023 error("parameter declared as void");
5024 } else {
5025 old_proto:
5026 n = tok;
5027 pt = VT_INT;
5028 next();
5030 /* array must be transformed to pointer according to ANSI C */
5031 pt &= ~VT_ARRAY;
5032 s = sym_push(n | SYM_FIELD, pt, 0, 0);
5033 *plast = s;
5034 plast = &s->next;
5035 if (tok == ',') {
5036 next();
5037 if (l == FUNC_NEW && tok == TOK_DOTS) {
5038 l = FUNC_ELLIPSIS;
5039 next();
5040 break;
5044 /* if no parameters, then old type prototype */
5045 if (l == 0)
5046 l = FUNC_OLD;
5047 skip(')');
5048 t1 = t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN);
5049 t = post_type(t & ~(VT_TYPEDEF | VT_STATIC | VT_EXTERN), ad);
5050 /* we push a anonymous symbol which will contain the function prototype */
5051 p = anon_sym++;
5052 s = sym_push(p, t, ad->func_call, l);
5053 s->next = first;
5054 t = t1 | VT_FUNC | (p << VT_STRUCT_SHIFT);
5055 } else if (tok == '[') {
5056 /* array definition */
5057 next();
5058 n = -1;
5059 if (tok != ']') {
5060 n = expr_const();
5061 if (n < 0)
5062 error("invalid array size");
5064 skip(']');
5065 /* parse next post type */
5066 t1 = t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN);
5067 t = post_type(t & ~(VT_TYPEDEF | VT_STATIC | VT_EXTERN), ad);
5069 /* we push a anonymous symbol which will contain the array
5070 element type */
5071 p = anon_sym++;
5072 sym_push(p, t, 0, n);
5073 t = t1 | VT_ARRAY | VT_PTR | (p << VT_STRUCT_SHIFT);
5075 return t;
5078 /* Read a type declaration (except basic type), and return the
5079 type. 'td' is a bitmask indicating which kind of type decl is
5080 expected. 't' should contain the basic type. 'ad' is the attribute
5081 definition of the basic type. It can be modified by type_decl(). */
5082 int type_decl(AttributeDef *ad, int *v, int t, int td)
5084 int u, p;
5085 Sym *s;
5087 while (tok == '*') {
5088 next();
5089 while (tok == TOK_CONST || tok == TOK_VOLATILE || tok == TOK_RESTRICT)
5090 next();
5091 t = mk_pointer(t);
5094 /* recursive type */
5095 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
5096 if (tok == '(') {
5097 next();
5098 /* XXX: this is not correct to modify 'ad' at this point, but
5099 the syntax is not clear */
5100 if (tok == TOK___ATTRIBUTE__)
5101 parse_attribute(ad);
5102 u = type_decl(ad, v, 0, td);
5103 skip(')');
5104 } else {
5105 u = 0;
5106 /* type identifier */
5107 if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
5108 *v = tok;
5109 next();
5110 } else {
5111 if (!(td & TYPE_ABSTRACT))
5112 expect("identifier");
5113 *v = 0;
5116 /* append t at the end of u */
5117 t = post_type(t, ad);
5118 if (tok == TOK___ATTRIBUTE__)
5119 parse_attribute(ad);
5120 if (!u)
5121 return t;
5122 p = u;
5123 while(1) {
5124 s = sym_find((unsigned)p >> VT_STRUCT_SHIFT);
5125 p = s->t;
5126 if (!p) {
5127 s->t = t;
5128 break;
5131 return u;
5134 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
5135 static int lvalue_type(int t)
5137 int bt, r;
5138 r = VT_LVAL;
5139 bt = t & VT_BTYPE;
5140 if (bt == VT_BYTE)
5141 r |= VT_LVAL_BYTE;
5142 else if (bt == VT_SHORT)
5143 r |= VT_LVAL_SHORT;
5144 else
5145 return r;
5146 if (t & VT_UNSIGNED)
5147 r |= VT_LVAL_UNSIGNED;
5148 return r;
5151 /* indirection with full error checking and bound check */
5152 static void indir(void)
5154 if ((vtop->t & VT_BTYPE) != VT_PTR)
5155 expect("pointer");
5156 if (vtop->r & VT_LVAL)
5157 gv(RC_INT);
5158 vtop->t = pointed_type(vtop->t);
5159 /* an array is never an lvalue */
5160 if (!(vtop->t & VT_ARRAY)) {
5161 vtop->r |= lvalue_type(vtop->t);
5162 /* if bound checking, the referenced pointer must be checked */
5163 if (do_bounds_check)
5164 vtop->r |= VT_MUSTBOUND;
5168 /* pass a parameter to a function and do type checking and casting */
5169 void gfunc_param_typed(GFuncContext *gf, Sym *func, Sym *arg)
5171 int func_type;
5172 func_type = func->c;
5173 if (func_type == FUNC_OLD ||
5174 (func_type == FUNC_ELLIPSIS && arg == NULL)) {
5175 /* default casting : only need to convert float to double */
5176 if ((vtop->t & VT_BTYPE) == VT_FLOAT)
5177 gen_cast(VT_DOUBLE);
5178 } else if (arg == NULL) {
5179 error("too many arguments to function");
5180 } else {
5181 gen_assign_cast(arg->t);
5183 gfunc_param(gf);
5186 void unary(void)
5188 int n, t, ft, align, size, r;
5189 Sym *s;
5190 GFuncContext gf;
5191 AttributeDef ad;
5193 if (tok == TOK_CINT || tok == TOK_CCHAR || tok == TOK_LCHAR) {
5194 vpushi(tokc.i);
5195 next();
5196 } else if (tok == TOK_CUINT) {
5197 vsetc(VT_INT | VT_UNSIGNED, VT_CONST, &tokc);
5198 next();
5199 } else if (tok == TOK_CLLONG) {
5200 vsetc(VT_LLONG, VT_CONST, &tokc);
5201 next();
5202 } else if (tok == TOK_CULLONG) {
5203 vsetc(VT_LLONG | VT_UNSIGNED, VT_CONST, &tokc);
5204 next();
5205 } else if (tok == TOK_CFLOAT) {
5206 vsetc(VT_FLOAT, VT_CONST, &tokc);
5207 next();
5208 } else if (tok == TOK_CDOUBLE) {
5209 vsetc(VT_DOUBLE, VT_CONST, &tokc);
5210 next();
5211 } else if (tok == TOK_CLDOUBLE) {
5212 vsetc(VT_LDOUBLE, VT_CONST, &tokc);
5213 next();
5214 } else if (tok == TOK___FUNC__ || (tok == TOK___FUNCTION__ && gnu_ext)) {
5215 void *ptr;
5216 int len;
5217 /* special function name identifier */
5219 len = strlen(funcname) + 1;
5220 /* generate char[len] type */
5221 t = VT_ARRAY | mk_pointer(VT_BYTE);
5222 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
5223 s->c = len;
5224 vpush_ref(t, data_section, data_section->data_offset, len);
5225 ptr = section_ptr_add(data_section, len);
5226 memcpy(ptr, funcname, len);
5227 next();
5228 } else if (tok == TOK_LSTR) {
5229 t = VT_INT;
5230 goto str_init;
5231 } else if (tok == TOK_STR) {
5232 /* string parsing */
5233 t = VT_BYTE;
5234 str_init:
5235 t = VT_ARRAY | mk_pointer(t);
5236 memset(&ad, 0, sizeof(AttributeDef));
5237 decl_initializer_alloc(t, &ad, VT_CONST, 2, 0, 0);
5238 } else {
5239 t = tok;
5240 next();
5241 if (t == '(') {
5242 /* cast ? */
5243 if (parse_btype(&t, &ad)) {
5244 ft = type_decl(&ad, &n, t, TYPE_ABSTRACT);
5245 skip(')');
5246 /* check ISOC99 compound literal */
5247 if (tok == '{') {
5248 /* data is allocated locally by default */
5249 if (global_expr)
5250 r = VT_CONST;
5251 else
5252 r = VT_LOCAL;
5253 /* all except arrays are lvalues */
5254 if (!(ft & VT_ARRAY))
5255 r |= lvalue_type(ft);
5256 memset(&ad, 0, sizeof(AttributeDef));
5257 decl_initializer_alloc(ft, &ad, r, 1, 0, 0);
5258 } else {
5259 unary();
5260 gen_cast(ft);
5262 } else {
5263 gexpr();
5264 skip(')');
5266 } else if (t == '*') {
5267 unary();
5268 indir();
5269 } else if (t == '&') {
5270 unary();
5271 /* functions names must be treated as function pointers,
5272 except for unary '&' and sizeof. Since we consider that
5273 functions are not lvalues, we only have to handle it
5274 there and in function calls. */
5275 /* arrays can also be used although they are not lvalues */
5276 if ((vtop->t & VT_BTYPE) != VT_FUNC &&
5277 !(vtop->t & VT_ARRAY))
5278 test_lvalue();
5279 vtop->t = mk_pointer(vtop->t);
5280 gaddrof();
5281 } else
5282 if (t == '!') {
5283 unary();
5284 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST)
5285 vtop->c.i = !vtop->c.i;
5286 else if ((vtop->r & VT_VALMASK) == VT_CMP)
5287 vtop->c.i = vtop->c.i ^ 1;
5288 else
5289 vset(VT_INT, VT_JMP, gtst(1, 0));
5290 } else
5291 if (t == '~') {
5292 unary();
5293 vpushi(-1);
5294 gen_op('^');
5295 } else
5296 if (t == '+') {
5297 /* in order to force cast, we add zero */
5298 unary();
5299 if ((vtop->t & VT_BTYPE) == VT_PTR)
5300 error("pointer not accepted for unary plus");
5301 vpushi(0);
5302 gen_op('+');
5303 } else
5304 if (t == TOK_SIZEOF) {
5305 if (tok == '(') {
5306 next();
5307 if (parse_btype(&t, &ad)) {
5308 t = type_decl(&ad, &n, t, TYPE_ABSTRACT);
5309 } else {
5310 /* XXX: some code could be generated: add eval
5311 flag */
5312 gexpr();
5313 t = vtop->t;
5314 vpop();
5316 skip(')');
5317 } else {
5318 unary();
5319 t = vtop->t;
5320 vpop();
5322 vpushi(type_size(t, &t));
5323 } else
5324 if (t == TOK_INC || t == TOK_DEC) {
5325 unary();
5326 inc(0, t);
5327 } else if (t == '-') {
5328 vpushi(0);
5329 unary();
5330 gen_op('-');
5331 } else
5333 if (t < TOK_UIDENT)
5334 expect("identifier");
5335 s = sym_find(t);
5336 if (!s) {
5337 if (tok != '(')
5338 error("'%s' undeclared", get_tok_str(t, NULL));
5339 /* for simple function calls, we tolerate undeclared
5340 external reference to int() function */
5341 s = external_global_sym(t, func_old_type, 0);
5343 vset(s->t, s->r, s->c);
5344 /* if forward reference, we must point to s */
5345 if (vtop->r & VT_SYM) {
5346 vtop->sym = s;
5347 vtop->c.ul = 0;
5352 /* post operations */
5353 while (1) {
5354 if (tok == TOK_INC || tok == TOK_DEC) {
5355 inc(1, tok);
5356 next();
5357 } else if (tok == '.' || tok == TOK_ARROW) {
5358 /* field */
5359 if (tok == TOK_ARROW)
5360 indir();
5361 test_lvalue();
5362 gaddrof();
5363 next();
5364 /* expect pointer on structure */
5365 if ((vtop->t & VT_BTYPE) != VT_STRUCT)
5366 expect("struct or union");
5367 s = sym_find(((unsigned)vtop->t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
5368 /* find field */
5369 tok |= SYM_FIELD;
5370 while ((s = s->next) != NULL) {
5371 if (s->v == tok)
5372 break;
5374 if (!s)
5375 error("field not found");
5376 /* add field offset to pointer */
5377 vtop->t = char_pointer_type; /* change type to 'char *' */
5378 vpushi(s->c);
5379 gen_op('+');
5380 /* change type to field type, and set to lvalue */
5381 vtop->t = s->t;
5382 /* an array is never an lvalue */
5383 if (!(vtop->t & VT_ARRAY)) {
5384 vtop->r |= lvalue_type(vtop->t);
5385 /* if bound checking, the referenced pointer must be checked */
5386 if (do_bounds_check)
5387 vtop->r |= VT_MUSTBOUND;
5389 next();
5390 } else if (tok == '[') {
5391 next();
5392 gexpr();
5393 gen_op('+');
5394 indir();
5395 skip(']');
5396 } else if (tok == '(') {
5397 SValue ret;
5398 Sym *sa;
5400 /* function call */
5401 if ((vtop->t & VT_BTYPE) != VT_FUNC) {
5402 /* pointer test (no array accepted) */
5403 if ((vtop->t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
5404 vtop->t = pointed_type(vtop->t);
5405 if ((vtop->t & VT_BTYPE) != VT_FUNC)
5406 goto error_func;
5407 } else {
5408 error_func:
5409 expect("function pointer");
5411 } else {
5412 vtop->r &= ~VT_LVAL; /* no lvalue */
5414 /* get return type */
5415 s = sym_find((unsigned)vtop->t >> VT_STRUCT_SHIFT);
5416 save_regs(0); /* save used temporary registers */
5417 gfunc_start(&gf, s->r);
5418 next();
5419 sa = s->next; /* first parameter */
5420 #ifdef INVERT_FUNC_PARAMS
5422 int parlevel;
5423 Sym *args, *s1;
5424 ParseState saved_parse_state;
5425 TokenString str;
5427 /* read each argument and store it on a stack */
5428 args = NULL;
5429 if (tok != ')') {
5430 for(;;) {
5431 tok_str_new(&str);
5432 parlevel = 0;
5433 while ((parlevel > 0 || (tok != ')' && tok != ',')) &&
5434 tok != TOK_EOF) {
5435 if (tok == '(')
5436 parlevel++;
5437 else if (tok == ')')
5438 parlevel--;
5439 tok_str_add_tok(&str);
5440 next();
5442 tok_str_add(&str, -1); /* end of file added */
5443 tok_str_add(&str, 0);
5444 s1 = sym_push2(&args, 0, 0, (int)str.str);
5445 s1->next = sa; /* add reference to argument */
5446 if (sa)
5447 sa = sa->next;
5448 if (tok == ')')
5449 break;
5450 skip(',');
5454 /* now generate code in reverse order by reading the stack */
5455 save_parse_state(&saved_parse_state);
5456 while (args) {
5457 macro_ptr = (int *)args->c;
5458 next();
5459 expr_eq();
5460 if (tok != -1)
5461 expect("',' or ')'");
5462 gfunc_param_typed(&gf, s, args->next);
5463 s1 = args->prev;
5464 tok_str_free((int *)args->c);
5465 tcc_free(args);
5466 args = s1;
5468 restore_parse_state(&saved_parse_state);
5470 #endif
5471 /* compute first implicit argument if a structure is returned */
5472 if ((s->t & VT_BTYPE) == VT_STRUCT) {
5473 /* get some space for the returned structure */
5474 size = type_size(s->t, &align);
5475 loc = (loc - size) & -align;
5476 ret.t = s->t;
5477 ret.r = VT_LOCAL | VT_LVAL;
5478 /* pass it as 'int' to avoid structure arg passing
5479 problems */
5480 vset(VT_INT, VT_LOCAL, loc);
5481 ret.c = vtop->c;
5482 gfunc_param(&gf);
5483 } else {
5484 ret.t = s->t;
5485 ret.r2 = VT_CONST;
5486 /* return in register */
5487 if (is_float(ret.t)) {
5488 ret.r = REG_FRET;
5489 } else {
5490 if ((ret.t & VT_BTYPE) == VT_LLONG)
5491 ret.r2 = REG_LRET;
5492 ret.r = REG_IRET;
5494 ret.c.i = 0;
5496 #ifndef INVERT_FUNC_PARAMS
5497 if (tok != ')') {
5498 for(;;) {
5499 expr_eq();
5500 gfunc_param_typed(&gf, s, sa);
5501 if (sa)
5502 sa = sa->next;
5503 if (tok == ')')
5504 break;
5505 skip(',');
5508 #endif
5509 if (sa)
5510 error("too few arguments to function");
5511 skip(')');
5512 gfunc_call(&gf);
5513 /* return value */
5514 vsetc(ret.t, ret.r, &ret.c);
5515 vtop->r2 = ret.r2;
5516 } else {
5517 break;
5522 void uneq(void)
5524 int t;
5526 unary();
5527 if (tok == '=' ||
5528 (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
5529 tok == TOK_A_XOR || tok == TOK_A_OR ||
5530 tok == TOK_A_SHL || tok == TOK_A_SAR) {
5531 test_lvalue();
5532 t = tok;
5533 next();
5534 if (t == '=') {
5535 expr_eq();
5536 } else {
5537 vdup();
5538 expr_eq();
5539 gen_op(t & 0x7f);
5541 vstore();
5545 void sum(int l)
5547 int t;
5549 if (l == 0)
5550 uneq();
5551 else {
5552 sum(--l);
5553 while ((l == 0 && (tok == '*' || tok == '/' || tok == '%')) ||
5554 (l == 1 && (tok == '+' || tok == '-')) ||
5555 (l == 2 && (tok == TOK_SHL || tok == TOK_SAR)) ||
5556 (l == 3 && ((tok >= TOK_ULE && tok <= TOK_GT) ||
5557 tok == TOK_ULT || tok == TOK_UGE)) ||
5558 (l == 4 && (tok == TOK_EQ || tok == TOK_NE)) ||
5559 (l == 5 && tok == '&') ||
5560 (l == 6 && tok == '^') ||
5561 (l == 7 && tok == '|') ||
5562 (l == 8 && tok == TOK_LAND) ||
5563 (l == 9 && tok == TOK_LOR)) {
5564 t = tok;
5565 next();
5566 sum(l);
5567 gen_op(t);
5572 /* only used if non constant */
5573 void eand(void)
5575 int t;
5577 sum(8);
5578 t = 0;
5579 while (1) {
5580 if (tok != TOK_LAND) {
5581 if (t) {
5582 t = gtst(1, t);
5583 vset(VT_INT, VT_JMPI, t);
5585 break;
5587 t = gtst(1, t);
5588 next();
5589 sum(8);
5593 void eor(void)
5595 int t;
5597 eand();
5598 t = 0;
5599 while (1) {
5600 if (tok != TOK_LOR) {
5601 if (t) {
5602 t = gtst(0, t);
5603 vset(VT_INT, VT_JMP, t);
5605 break;
5607 t = gtst(0, t);
5608 next();
5609 eand();
5613 /* XXX: better constant handling */
5614 void expr_eq(void)
5616 int tt, u, r1, r2, rc, t1, t2, t, bt1, bt2;
5617 SValue sv;
5619 if (const_wanted) {
5620 int c1, c;
5621 sum(10);
5622 if (tok == '?') {
5623 c = vtop->c.i;
5624 vpop();
5625 next();
5626 gexpr();
5627 c1 = vtop->c.i;
5628 vpop();
5629 skip(':');
5630 expr_eq();
5631 if (c)
5632 vtop->c.i = c1;
5634 } else {
5635 eor();
5636 if (tok == '?') {
5637 next();
5638 save_regs(1); /* we need to save all registers here except
5639 at the top because it is a branch point */
5640 tt = gtst(1, 0);
5641 gexpr();
5642 t1 = vtop->t;
5643 bt1 = t1 & VT_BTYPE;
5644 sv = *vtop; /* save value to handle it later */
5645 vtop--; /* no vpop so that FP stack is not flushed */
5646 skip(':');
5647 u = gjmp(0);
5649 gsym(tt);
5650 expr_eq();
5651 t2 = vtop->t;
5653 bt2 = t2 & VT_BTYPE;
5654 /* cast operands to correct type according to ISOC rules */
5655 if (is_float(bt1) || is_float(bt2)) {
5656 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
5657 t = VT_LDOUBLE;
5658 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
5659 t = VT_DOUBLE;
5660 } else {
5661 t = VT_FLOAT;
5663 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
5664 /* cast to biggest op */
5665 t = VT_LLONG;
5666 /* convert to unsigned if it does not fit in a long long */
5667 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
5668 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
5669 t |= VT_UNSIGNED;
5670 } else if (bt1 == VT_PTR || bt2 == VT_PTR) {
5671 /* XXX: test pointer compatibility */
5672 t = t1;
5673 } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
5674 /* XXX: test structure compatibility */
5675 t = t1;
5676 } else if (bt1 == VT_VOID || bt2 == VT_VOID) {
5677 /* NOTE: as an extension, we accept void on only one side */
5678 t = VT_VOID;
5679 } else {
5680 /* integer operations */
5681 t = VT_INT;
5682 /* convert to unsigned if it does not fit in an integer */
5683 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
5684 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
5685 t |= VT_UNSIGNED;
5688 /* now we convert second operand */
5689 gen_cast(t);
5690 rc = RC_INT;
5691 if (is_float(t)) {
5692 rc = RC_FLOAT;
5693 } else if ((t & VT_BTYPE) == VT_LLONG) {
5694 /* for long longs, we use fixed registers to avoid having
5695 to handle a complicated move */
5696 rc = RC_IRET;
5698 r2 = gv(rc);
5699 /* this is horrible, but we must also convert first
5700 operand */
5701 tt = gjmp(0);
5702 gsym(u);
5703 /* put again first value and cast it */
5704 *vtop = sv;
5705 gen_cast(t);
5706 r1 = gv(rc);
5707 move_reg(r2, r1);
5708 vtop->r = r2;
5709 gsym(tt);
5714 void gexpr(void)
5716 while (1) {
5717 expr_eq();
5718 if (tok != ',')
5719 break;
5720 vpop();
5721 next();
5725 /* parse a constant expression and return value in vtop. */
5726 static void expr_const1(void)
5728 int a;
5729 a = const_wanted;
5730 const_wanted = 1;
5731 expr_eq();
5732 const_wanted = a;
5735 /* parse an integer constant and return its value. */
5736 static int expr_const(void)
5738 int c;
5739 expr_const1();
5740 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
5741 expect("constant expression");
5742 c = vtop->c.i;
5743 vpop();
5744 return c;
5747 /* return the label token if current token is a label, otherwise
5748 return zero */
5749 int is_label(void)
5751 int t;
5752 CValue c;
5754 /* fast test first */
5755 if (tok < TOK_UIDENT)
5756 return 0;
5757 /* no need to save tokc since we expect an identifier */
5758 t = tok;
5759 c = tokc;
5760 next();
5761 if (tok == ':') {
5762 next();
5763 return t;
5764 } else {
5765 /* XXX: may not work in all cases (macros ?) */
5766 tok1 = tok;
5767 tok1c = tokc;
5768 tok = t;
5769 tokc = c;
5770 return 0;
5774 void block(int *bsym, int *csym, int *case_sym, int *def_sym, int case_reg)
5776 int a, b, c, d;
5777 Sym *s;
5779 /* generate line number info */
5780 if (do_debug &&
5781 (last_line_num != file->line_num || last_ind != ind)) {
5782 put_stabn(N_SLINE, 0, file->line_num, ind - func_ind);
5783 last_ind = ind;
5784 last_line_num = file->line_num;
5787 if (tok == TOK_IF) {
5788 /* if test */
5789 next();
5790 skip('(');
5791 gexpr();
5792 skip(')');
5793 a = gtst(1, 0);
5794 block(bsym, csym, case_sym, def_sym, case_reg);
5795 c = tok;
5796 if (c == TOK_ELSE) {
5797 next();
5798 d = gjmp(0);
5799 gsym(a);
5800 block(bsym, csym, case_sym, def_sym, case_reg);
5801 gsym(d); /* patch else jmp */
5802 } else
5803 gsym(a);
5804 } else if (tok == TOK_WHILE) {
5805 next();
5806 d = ind;
5807 skip('(');
5808 gexpr();
5809 skip(')');
5810 a = gtst(1, 0);
5811 b = 0;
5812 block(&a, &b, case_sym, def_sym, case_reg);
5813 gjmp_addr(d);
5814 gsym(a);
5815 gsym_addr(b, d);
5816 } else if (tok == '{') {
5817 next();
5818 /* declarations */
5819 s = local_stack.top;
5820 while (tok != '}') {
5821 decl(VT_LOCAL);
5822 if (tok != '}')
5823 block(bsym, csym, case_sym, def_sym, case_reg);
5825 /* pop locally defined symbols */
5826 sym_pop(&local_stack, s);
5827 next();
5828 } else if (tok == TOK_RETURN) {
5829 next();
5830 if (tok != ';') {
5831 gexpr();
5832 gen_assign_cast(func_vt);
5833 if ((func_vt & VT_BTYPE) == VT_STRUCT) {
5834 /* if returning structure, must copy it to implicit
5835 first pointer arg location */
5836 vset(mk_pointer(func_vt), VT_LOCAL | VT_LVAL, func_vc);
5837 indir();
5838 vswap();
5839 /* copy structure value to pointer */
5840 vstore();
5841 } else if (is_float(func_vt)) {
5842 gv(RC_FRET);
5843 } else {
5844 gv(RC_IRET);
5846 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
5848 skip(';');
5849 rsym = gjmp(rsym); /* jmp */
5850 } else if (tok == TOK_BREAK) {
5851 /* compute jump */
5852 if (!bsym)
5853 error("cannot break");
5854 *bsym = gjmp(*bsym);
5855 next();
5856 skip(';');
5857 } else if (tok == TOK_CONTINUE) {
5858 /* compute jump */
5859 if (!csym)
5860 error("cannot continue");
5861 *csym = gjmp(*csym);
5862 next();
5863 skip(';');
5864 } else if (tok == TOK_FOR) {
5865 int e;
5866 next();
5867 skip('(');
5868 if (tok != ';') {
5869 gexpr();
5870 vpop();
5872 skip(';');
5873 d = ind;
5874 c = ind;
5875 a = 0;
5876 b = 0;
5877 if (tok != ';') {
5878 gexpr();
5879 a = gtst(1, 0);
5881 skip(';');
5882 if (tok != ')') {
5883 e = gjmp(0);
5884 c = ind;
5885 gexpr();
5886 vpop();
5887 gjmp_addr(d);
5888 gsym(e);
5890 skip(')');
5891 block(&a, &b, case_sym, def_sym, case_reg);
5892 gjmp_addr(c);
5893 gsym(a);
5894 gsym_addr(b, c);
5895 } else
5896 if (tok == TOK_DO) {
5897 next();
5898 a = 0;
5899 b = 0;
5900 d = ind;
5901 block(&a, &b, case_sym, def_sym, case_reg);
5902 skip(TOK_WHILE);
5903 skip('(');
5904 gsym(b);
5905 gexpr();
5906 c = gtst(0, 0);
5907 gsym_addr(c, d);
5908 skip(')');
5909 gsym(a);
5910 skip(';');
5911 } else
5912 if (tok == TOK_SWITCH) {
5913 next();
5914 skip('(');
5915 gexpr();
5916 /* XXX: other types than integer */
5917 case_reg = gv(RC_INT);
5918 vpop();
5919 skip(')');
5920 a = 0;
5921 b = gjmp(0); /* jump to first case */
5922 c = 0;
5923 block(&a, csym, &b, &c, case_reg);
5924 /* if no default, jmp after switch */
5925 if (c == 0)
5926 c = ind;
5927 /* default label */
5928 gsym_addr(b, c);
5929 /* break label */
5930 gsym(a);
5931 } else
5932 if (tok == TOK_CASE) {
5933 int v1, v2;
5934 if (!case_sym)
5935 expect("switch");
5936 next();
5937 v1 = expr_const();
5938 v2 = v1;
5939 if (gnu_ext && tok == TOK_DOTS) {
5940 next();
5941 v2 = expr_const();
5942 if (v2 < v1)
5943 warning("empty case range");
5945 /* since a case is like a label, we must skip it with a jmp */
5946 b = gjmp(0);
5947 gsym(*case_sym);
5948 vset(VT_INT, case_reg, 0);
5949 vpushi(v1);
5950 if (v1 == v2) {
5951 gen_op(TOK_EQ);
5952 *case_sym = gtst(1, 0);
5953 } else {
5954 gen_op(TOK_GE);
5955 *case_sym = gtst(1, 0);
5956 vset(VT_INT, case_reg, 0);
5957 vpushi(v2);
5958 gen_op(TOK_LE);
5959 *case_sym = gtst(1, *case_sym);
5961 gsym(b);
5962 skip(':');
5963 block(bsym, csym, case_sym, def_sym, case_reg);
5964 } else
5965 if (tok == TOK_DEFAULT) {
5966 next();
5967 skip(':');
5968 if (!def_sym)
5969 expect("switch");
5970 if (*def_sym)
5971 error("too many 'default'");
5972 *def_sym = ind;
5973 block(bsym, csym, case_sym, def_sym, case_reg);
5974 } else
5975 if (tok == TOK_GOTO) {
5976 next();
5977 s = sym_find1(&label_stack, tok);
5978 /* put forward definition if needed */
5979 if (!s)
5980 s = sym_push1(&label_stack, tok, LABEL_FORWARD, 0);
5981 /* label already defined */
5982 if (s->t & LABEL_FORWARD)
5983 s->c = gjmp(s->c);
5984 else
5985 gjmp_addr(s->c);
5986 next();
5987 skip(';');
5988 } else {
5989 b = is_label();
5990 if (b) {
5991 /* label case */
5992 s = sym_find1(&label_stack, b);
5993 if (s) {
5994 if (!(s->t & LABEL_FORWARD))
5995 error("multiple defined label");
5996 gsym(s->c);
5997 s->c = ind;
5998 s->t = 0;
5999 } else {
6000 sym_push1(&label_stack, b, 0, ind);
6002 /* we accept this, but it is a mistake */
6003 if (tok == '}')
6004 warning("deprecated use of label at end of compound statement");
6005 else
6006 block(bsym, csym, case_sym, def_sym, case_reg);
6007 } else {
6008 /* expression case */
6009 if (tok != ';') {
6010 gexpr();
6011 vpop();
6013 skip(';');
6018 /* t is the array or struct type. c is the array or struct
6019 address. cur_index/cur_field is the pointer to the current
6020 value. 'size_only' is true if only size info is needed (only used
6021 in arrays) */
6022 static void decl_designator(int t, Section *sec, unsigned long c,
6023 int *cur_index, Sym **cur_field,
6024 int size_only)
6026 Sym *s, *f;
6027 int notfirst, index, align, l;
6029 notfirst = 0;
6030 if (gnu_ext && (l = is_label()) != 0)
6031 goto struct_field;
6033 while (tok == '[' || tok == '.') {
6034 if (tok == '[') {
6035 if (!(t & VT_ARRAY))
6036 expect("array type");
6037 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
6038 next();
6039 index = expr_const();
6040 if (index < 0 || (s->c >= 0 && index >= s->c))
6041 expect("invalid index");
6042 skip(']');
6043 if (!notfirst)
6044 *cur_index = index;
6045 t = pointed_type(t);
6046 c += index * type_size(t, &align);
6047 } else {
6048 next();
6049 l = tok;
6050 next();
6051 struct_field:
6052 if ((t & VT_BTYPE) != VT_STRUCT)
6053 expect("struct/union type");
6054 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
6055 l |= SYM_FIELD;
6056 f = s->next;
6057 while (f) {
6058 if (f->v == l)
6059 break;
6060 f = f->next;
6062 if (!f)
6063 expect("field");
6064 if (!notfirst)
6065 *cur_field = f;
6066 t = f->t | (t & ~VT_TYPE);
6067 c += f->c;
6069 notfirst = 1;
6071 if (notfirst) {
6072 if (tok == '=') {
6073 next();
6074 } else {
6075 if (!gnu_ext)
6076 expect("=");
6078 } else {
6079 if (t & VT_ARRAY) {
6080 index = *cur_index;
6081 t = pointed_type(t);
6082 c += index * type_size(t, &align);
6083 } else {
6084 f = *cur_field;
6085 if (!f)
6086 error("too many field init");
6087 t = f->t | (t & ~VT_TYPE);
6088 c += f->c;
6091 decl_initializer(t, sec, c, 0, size_only);
6094 #define EXPR_VAL 0
6095 #define EXPR_CONST 1
6096 #define EXPR_ANY 2
6098 /* store a value or an expression directly in global data or in local array */
6099 static void init_putv(int t, Section *sec, unsigned long c,
6100 int v, int expr_type)
6102 int saved_global_expr, bt;
6103 void *ptr;
6105 switch(expr_type) {
6106 case EXPR_VAL:
6107 vpushi(v);
6108 break;
6109 case EXPR_CONST:
6110 /* compound literals must be allocated globally in this case */
6111 saved_global_expr = global_expr;
6112 global_expr = 1;
6113 expr_const1();
6114 global_expr = saved_global_expr;
6115 /* NOTE: symbols are accepted */
6116 if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST)
6117 error("initializer element is not constant");
6118 break;
6119 case EXPR_ANY:
6120 expr_eq();
6121 break;
6124 if (sec) {
6125 /* XXX: not portable */
6126 /* XXX: generate error if incorrect relocation */
6127 gen_assign_cast(t);
6128 bt = t & VT_BTYPE;
6129 ptr = sec->data + c;
6130 if ((vtop->r & VT_SYM) &&
6131 (bt == VT_BYTE ||
6132 bt == VT_SHORT ||
6133 bt == VT_DOUBLE ||
6134 bt == VT_LDOUBLE ||
6135 bt == VT_LLONG))
6136 error("initializer element is not computable at load time");
6137 switch(bt) {
6138 case VT_BYTE:
6139 *(char *)ptr = vtop->c.i;
6140 break;
6141 case VT_SHORT:
6142 *(short *)ptr = vtop->c.i;
6143 break;
6144 case VT_DOUBLE:
6145 *(double *)ptr = vtop->c.d;
6146 break;
6147 case VT_LDOUBLE:
6148 *(long double *)ptr = vtop->c.ld;
6149 break;
6150 case VT_LLONG:
6151 *(long long *)ptr = vtop->c.ll;
6152 break;
6153 default:
6154 if (vtop->r & VT_SYM) {
6155 greloc(sec, vtop->sym, c, R_DATA_32);
6157 *(int *)ptr = vtop->c.i;
6158 break;
6160 vtop--;
6161 } else {
6162 vset(t, VT_LOCAL, c);
6163 vswap();
6164 vstore();
6165 vpop();
6169 /* put zeros for variable based init */
6170 static void init_putz(int t, Section *sec, unsigned long c, int size)
6172 GFuncContext gf;
6174 if (sec) {
6175 /* nothing to do because globals are already set to zero */
6176 } else {
6177 gfunc_start(&gf, FUNC_CDECL);
6178 vpushi(size);
6179 gfunc_param(&gf);
6180 vpushi(0);
6181 gfunc_param(&gf);
6182 vset(VT_INT, VT_LOCAL, c);
6183 gfunc_param(&gf);
6184 vpush_global_sym(func_old_type, TOK_memset);
6185 gfunc_call(&gf);
6189 /* 't' contains the type and storage info. 'c' is the offset of the
6190 object in section 'sec'. If 'sec' is NULL, it means stack based
6191 allocation. 'first' is true if array '{' must be read (multi
6192 dimension implicit array init handling). 'size_only' is true if
6193 size only evaluation is wanted (only for arrays). */
6194 static void decl_initializer(int t, Section *sec, unsigned long c,
6195 int first, int size_only)
6197 int index, array_length, n, no_oblock, nb, parlevel, i;
6198 int t1, size1, align1, expr_type;
6199 Sym *s, *f;
6201 if (t & VT_ARRAY) {
6202 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
6203 n = s->c;
6204 array_length = 0;
6205 t1 = pointed_type(t);
6206 size1 = type_size(t1, &align1);
6208 no_oblock = 1;
6209 if ((first && tok != TOK_LSTR && tok != TOK_STR) ||
6210 tok == '{') {
6211 skip('{');
6212 no_oblock = 0;
6215 /* only parse strings here if correct type (otherwise: handle
6216 them as ((w)char *) expressions */
6217 if ((tok == TOK_LSTR &&
6218 (t1 & VT_BTYPE) == VT_INT) ||
6219 (tok == TOK_STR &&
6220 (t1 & VT_BTYPE) == VT_BYTE)) {
6221 while (tok == TOK_STR || tok == TOK_LSTR) {
6222 int cstr_len, ch;
6223 CString *cstr;
6225 cstr = tokc.cstr;
6226 /* compute maximum number of chars wanted */
6227 if (tok == TOK_STR)
6228 cstr_len = cstr->size;
6229 else
6230 cstr_len = cstr->size / sizeof(int);
6231 cstr_len--;
6232 nb = cstr_len;
6233 if (n >= 0 && nb > (n - array_length))
6234 nb = n - array_length;
6235 if (!size_only) {
6236 if (cstr_len > nb)
6237 warning("initializer-string for array is too long");
6238 /* in order to go faster for common case (char
6239 string in global variable, we handle it
6240 specifically */
6241 if (sec && tok == TOK_STR && size1 == 1) {
6242 memcpy(sec->data + c + array_length, cstr->data, nb);
6243 } else {
6244 for(i=0;i<nb;i++) {
6245 if (tok == TOK_STR)
6246 ch = ((unsigned char *)cstr->data)[i];
6247 else
6248 ch = ((int *)cstr->data)[i];
6249 init_putv(t1, sec, c + (array_length + i) * size1,
6250 ch, EXPR_VAL);
6254 array_length += nb;
6255 next();
6257 /* only add trailing zero if enough storage (no
6258 warning in this case since it is standard) */
6259 if (n < 0 || array_length < n) {
6260 if (!size_only) {
6261 init_putv(t1, sec, c + (array_length * size1), 0, EXPR_VAL);
6263 array_length++;
6265 } else {
6266 index = 0;
6267 while (tok != '}') {
6268 decl_designator(t, sec, c, &index, NULL, size_only);
6269 if (n >= 0 && index >= n)
6270 error("index too large");
6271 /* must put zero in holes (note that doing it that way
6272 ensures that it even works with designators) */
6273 if (!size_only && array_length < index) {
6274 init_putz(t1, sec, c + array_length * size1,
6275 (index - array_length) * size1);
6277 index++;
6278 if (index > array_length)
6279 array_length = index;
6280 /* special test for multi dimensional arrays (may not
6281 be strictly correct if designators are used at the
6282 same time) */
6283 if (index >= n && no_oblock)
6284 break;
6285 if (tok == '}')
6286 break;
6287 skip(',');
6290 if (!no_oblock)
6291 skip('}');
6292 /* put zeros at the end */
6293 if (!size_only && n >= 0 && array_length < n) {
6294 init_putz(t1, sec, c + array_length * size1,
6295 (n - array_length) * size1);
6297 /* patch type size if needed */
6298 if (n < 0)
6299 s->c = array_length;
6300 } else if ((t & VT_BTYPE) == VT_STRUCT && tok == '{') {
6301 /* XXX: union needs only one init */
6302 next();
6303 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
6304 f = s->next;
6305 array_length = 0;
6306 index = 0;
6307 n = s->c;
6308 while (tok != '}') {
6309 decl_designator(t, sec, c, NULL, &f, size_only);
6310 /* fill with zero between fields */
6311 index = f->c;
6312 if (!size_only && array_length < index) {
6313 init_putz(t, sec, c + array_length,
6314 index - array_length);
6316 index = index + type_size(f->t, &align1);
6317 if (index > array_length)
6318 array_length = index;
6319 if (tok == '}')
6320 break;
6321 skip(',');
6322 f = f->next;
6324 /* put zeros at the end */
6325 if (!size_only && array_length < n) {
6326 init_putz(t, sec, c + array_length,
6327 n - array_length);
6329 skip('}');
6330 } else if (tok == '{') {
6331 next();
6332 decl_initializer(t, sec, c, first, size_only);
6333 skip('}');
6334 } else if (size_only) {
6335 /* just skip expression */
6336 parlevel = 0;
6337 while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
6338 tok != -1) {
6339 if (tok == '(')
6340 parlevel++;
6341 else if (tok == ')')
6342 parlevel--;
6343 next();
6345 } else {
6346 /* currently, we always use constant expression for globals
6347 (may change for scripting case) */
6348 expr_type = EXPR_CONST;
6349 if (!sec)
6350 expr_type = EXPR_ANY;
6351 init_putv(t, sec, c, 0, expr_type);
6355 /* parse an initializer for type 't' if 'has_init' is non zero, and
6356 allocate space in local or global data space ('r' is either
6357 VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
6358 variable 'v' of scope 'scope' is declared before initializers are
6359 parsed. If 'v' is zero, then a reference to the new object is put
6360 in the value stack. If 'has_init' is 2, a special parsing is done
6361 to handle string constants. */
6362 static void decl_initializer_alloc(int t, AttributeDef *ad, int r,
6363 int has_init, int v, int scope)
6365 int size, align, addr, data_offset;
6366 int level;
6367 ParseState saved_parse_state;
6368 TokenString init_str;
6369 Section *sec;
6371 size = type_size(t, &align);
6372 /* If unknown size, we must evaluate it before
6373 evaluating initializers because
6374 initializers can generate global data too
6375 (e.g. string pointers or ISOC99 compound
6376 literals). It also simplifies local
6377 initializers handling */
6378 tok_str_new(&init_str);
6379 if (size < 0) {
6380 if (!has_init)
6381 error("unknown type size");
6382 /* get all init string */
6383 if (has_init == 2) {
6384 /* only get strings */
6385 while (tok == TOK_STR || tok == TOK_LSTR) {
6386 tok_str_add_tok(&init_str);
6387 next();
6389 } else {
6390 level = 0;
6391 while (level > 0 || (tok != ',' && tok != ';')) {
6392 if (tok < 0)
6393 error("unexpected end of file in initializer");
6394 tok_str_add_tok(&init_str);
6395 if (tok == '{')
6396 level++;
6397 else if (tok == '}') {
6398 if (level == 0)
6399 break;
6400 level--;
6402 next();
6405 tok_str_add(&init_str, -1);
6406 tok_str_add(&init_str, 0);
6408 /* compute size */
6409 save_parse_state(&saved_parse_state);
6411 macro_ptr = init_str.str;
6412 next();
6413 decl_initializer(t, NULL, 0, 1, 1);
6414 /* prepare second initializer parsing */
6415 macro_ptr = init_str.str;
6416 next();
6418 /* if still unknown size, error */
6419 size = type_size(t, &align);
6420 if (size < 0)
6421 error("unknown type size");
6423 /* take into account specified alignment if bigger */
6424 if (ad->aligned > align)
6425 align = ad->aligned;
6426 if ((r & VT_VALMASK) == VT_LOCAL) {
6427 sec = NULL;
6428 if (do_bounds_check && (t & VT_ARRAY))
6429 loc--;
6430 #ifdef TCC_TARGET_IL
6431 /* XXX: ugly patch to allocate local variables for IL, just
6432 for testing */
6433 addr = loc;
6434 loc++;
6435 #else
6436 loc = (loc - size) & -align;
6437 addr = loc;
6438 #endif
6439 /* handles bounds */
6440 /* XXX: currently, since we do only one pass, we cannot track
6441 '&' operators, so we add only arrays */
6442 if (do_bounds_check && (t & VT_ARRAY)) {
6443 unsigned long *bounds_ptr;
6444 /* add padding between regions */
6445 loc--;
6446 /* then add local bound info */
6447 bounds_ptr = section_ptr_add(lbounds_section, 2 * sizeof(unsigned long));
6448 bounds_ptr[0] = addr;
6449 bounds_ptr[1] = size;
6451 } else {
6452 /* compute section */
6453 sec = ad->section;
6454 if (!sec) {
6455 if (has_init)
6456 sec = data_section;
6457 else
6458 sec = bss_section;
6460 data_offset = sec->data_offset;
6461 data_offset = (data_offset + align - 1) & -align;
6462 addr = data_offset;
6463 /* very important to increment global pointer at this time
6464 because initializers themselves can create new initializers */
6465 data_offset += size;
6466 /* add padding if bound check */
6467 if (do_bounds_check)
6468 data_offset++;
6469 sec->data_offset = data_offset;
6470 /* allocate section space to put the data */
6471 if (sec->sh_type != SHT_NOBITS &&
6472 data_offset > sec->data_allocated)
6473 section_realloc(sec, data_offset);
6475 if (!sec) {
6476 if (v) {
6477 /* local variable */
6478 sym_push(v, t, r, addr);
6479 } else {
6480 /* push local reference */
6481 vset(t, r, addr);
6483 } else {
6484 Sym *sym;
6486 if (v) {
6487 if (scope == VT_CONST) {
6488 /* global scope: see if already defined */
6489 sym = sym_find(v);
6490 if (!sym)
6491 goto do_def;
6492 if (!is_compatible_types(sym->t, t))
6493 error("incompatible types for redefinition of '%s'",
6494 get_tok_str(v, NULL));
6495 if (!(sym->t & VT_EXTERN))
6496 error("redefinition of '%s'", get_tok_str(v, NULL));
6497 sym->t &= ~VT_EXTERN;
6498 } else {
6499 do_def:
6500 sym = sym_push(v, t, r | VT_SYM, 0);
6502 put_extern_sym(sym, sec, addr, size);
6503 } else {
6504 CValue cval;
6506 /* push global reference */
6507 sym = get_sym_ref(t, sec, addr, size);
6508 cval.ul = 0;
6509 vsetc(t, VT_CONST | VT_SYM, &cval);
6510 vtop->sym = sym;
6513 /* handles bounds now because the symbol must be defined
6514 before for the relocation */
6515 if (do_bounds_check) {
6516 unsigned long *bounds_ptr;
6518 greloc(bounds_section, sym, bounds_section->data_offset, R_DATA_32);
6519 /* then add global bound info */
6520 bounds_ptr = section_ptr_add(bounds_section, 2 * sizeof(long));
6521 bounds_ptr[0] = 0; /* relocated */
6522 bounds_ptr[1] = size;
6525 if (has_init) {
6526 decl_initializer(t, sec, addr, 1, 0);
6527 /* restore parse state if needed */
6528 if (init_str.str) {
6529 tok_str_free(init_str.str);
6530 restore_parse_state(&saved_parse_state);
6535 void put_func_debug(Sym *sym)
6537 char buf[512];
6539 /* stabs info */
6540 /* XXX: we put here a dummy type */
6541 snprintf(buf, sizeof(buf), "%s:%c1",
6542 funcname, sym->t & VT_STATIC ? 'f' : 'F');
6543 put_stabs_r(buf, N_FUN, 0, file->line_num, 0,
6544 cur_text_section, sym->c);
6545 last_ind = 0;
6546 last_line_num = 0;
6549 /* not finished : try to put some local vars in registers */
6550 //#define CONFIG_REG_VARS
6552 #ifdef CONFIG_REG_VARS
6553 void add_var_ref(int t)
6555 printf("%s:%d: &%s\n",
6556 file->filename, file->line_num,
6557 get_tok_str(t, NULL));
6560 /* first pass on a function with heuristic to extract variable usage
6561 and pointer references to local variables for register allocation */
6562 void analyse_function(void)
6564 int level, t;
6566 for(;;) {
6567 if (tok == -1)
6568 break;
6569 /* any symbol coming after '&' is considered as being a
6570 variable whose reference is taken. It is highly unaccurate
6571 but it is difficult to do better without a complete parse */
6572 if (tok == '&') {
6573 next();
6574 /* if '& number', then no need to examine next tokens */
6575 if (tok == TOK_CINT ||
6576 tok == TOK_CUINT ||
6577 tok == TOK_CLLONG ||
6578 tok == TOK_CULLONG) {
6579 continue;
6580 } else if (tok >= TOK_UIDENT) {
6581 /* if '& ident [' or '& ident ->', then ident address
6582 is not needed */
6583 t = tok;
6584 next();
6585 if (tok != '[' && tok != TOK_ARROW)
6586 add_var_ref(t);
6587 } else {
6588 level = 0;
6589 while (tok != '}' && tok != ';' &&
6590 !((tok == ',' || tok == ')') && level == 0)) {
6591 if (tok >= TOK_UIDENT) {
6592 add_var_ref(tok);
6593 } else if (tok == '(') {
6594 level++;
6595 } else if (tok == ')') {
6596 level--;
6598 next();
6601 } else {
6602 next();
6606 #endif
6608 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
6609 void decl(int l)
6611 int t, b, v, has_init, r;
6612 Sym *sym;
6613 AttributeDef ad;
6615 while (1) {
6616 if (!parse_btype(&b, &ad)) {
6617 /* skip redundant ';' */
6618 /* XXX: find more elegant solution */
6619 if (tok == ';') {
6620 next();
6621 continue;
6623 /* special test for old K&R protos without explicit int
6624 type. Only accepted when defining global data */
6625 if (l == VT_LOCAL || tok < TOK_DEFINE)
6626 break;
6627 b = VT_INT;
6629 if (((b & VT_BTYPE) == VT_ENUM ||
6630 (b & VT_BTYPE) == VT_STRUCT) &&
6631 tok == ';') {
6632 /* we accept no variable after */
6633 next();
6634 continue;
6636 while (1) { /* iterate thru each declaration */
6637 t = type_decl(&ad, &v, b, TYPE_DIRECT);
6638 #if 0
6640 char buf[500];
6641 type_to_str(buf, sizeof(buf), t, get_tok_str(v, NULL));
6642 printf("type = '%s'\n", buf);
6644 #endif
6645 if (tok == '{') {
6646 #ifdef CONFIG_REG_VARS
6647 TokenString func_str;
6648 ParseState saved_parse_state;
6649 int block_level;
6650 #endif
6652 if (l == VT_LOCAL)
6653 error("cannot use local functions");
6654 if (!(t & VT_FUNC))
6655 expect("function definition");
6657 #ifdef CONFIG_REG_VARS
6658 /* parse all function code and record it */
6660 tok_str_new(&func_str);
6662 block_level = 0;
6663 for(;;) {
6664 int t;
6665 if (tok == -1)
6666 error("unexpected end of file");
6667 tok_str_add_tok(&func_str);
6668 t = tok;
6669 next();
6670 if (t == '{') {
6671 block_level++;
6672 } else if (t == '}') {
6673 block_level--;
6674 if (block_level == 0)
6675 break;
6678 tok_str_add(&func_str, -1);
6679 tok_str_add(&func_str, 0);
6681 save_parse_state(&saved_parse_state);
6683 macro_ptr = func_str.str;
6684 next();
6685 analyse_function();
6686 #endif
6688 /* compute text section */
6689 cur_text_section = ad.section;
6690 if (!cur_text_section)
6691 cur_text_section = text_section;
6692 ind = cur_text_section->data_offset;
6693 funcname = get_tok_str(v, NULL);
6694 sym = sym_find(v);
6695 if (sym) {
6696 /* if symbol is already defined, then put complete type */
6697 sym->t = t;
6698 } else {
6699 /* put function symbol */
6700 sym = sym_push1(&global_stack, v, t, 0);
6702 /* NOTE: we patch the symbol size later */
6703 put_extern_sym(sym, cur_text_section, ind, 0);
6704 func_ind = ind;
6705 sym->r = VT_SYM | VT_CONST;
6706 /* put debug symbol */
6707 if (do_debug)
6708 put_func_debug(sym);
6709 /* push a dummy symbol to enable local sym storage */
6710 sym_push1(&local_stack, 0, 0, 0);
6711 gfunc_prolog(t);
6712 loc = 0;
6713 rsym = 0;
6714 #ifdef CONFIG_REG_VARS
6715 macro_ptr = func_str.str;
6716 next();
6717 #endif
6718 block(NULL, NULL, NULL, NULL, 0);
6719 gsym(rsym);
6720 gfunc_epilog();
6721 cur_text_section->data_offset = ind;
6722 sym_pop(&label_stack, NULL); /* reset label stack */
6723 sym_pop(&local_stack, NULL); /* reset local stack */
6724 /* end of function */
6725 /* patch symbol size */
6726 ((Elf32_Sym *)symtab_section->data)[sym->c].st_size =
6727 ind - func_ind;
6728 if (do_debug) {
6729 put_stabn(N_FUN, 0, 0, ind - func_ind);
6731 funcname = ""; /* for safety */
6732 func_vt = VT_VOID; /* for safety */
6733 ind = 0; /* for safety */
6735 #ifdef CONFIG_REG_VARS
6736 tok_str_free(func_str.str);
6737 restore_parse_state(&saved_parse_state);
6738 #endif
6739 break;
6740 } else {
6741 if (b & VT_TYPEDEF) {
6742 /* save typedefed type */
6743 /* XXX: test storage specifiers ? */
6744 sym_push(v, t | VT_TYPEDEF, 0, 0);
6745 } else if ((t & VT_BTYPE) == VT_FUNC) {
6746 /* external function definition */
6747 external_sym(v, t, 0);
6748 } else {
6749 /* not lvalue if array */
6750 r = 0;
6751 if (!(t & VT_ARRAY))
6752 r |= lvalue_type(t);
6753 if (b & VT_EXTERN) {
6754 /* external variable */
6755 external_sym(v, t, r);
6756 } else {
6757 if (t & VT_STATIC)
6758 r |= VT_CONST;
6759 else
6760 r |= l;
6761 has_init = (tok == '=');
6762 if (has_init)
6763 next();
6764 decl_initializer_alloc(t, &ad, r,
6765 has_init, v, l);
6768 if (tok != ',') {
6769 skip(';');
6770 break;
6772 next();
6778 /* compile the C file opened in 'file'. Return non zero if errors. */
6779 static int tcc_compile(TCCState *s)
6781 Sym *define_start, *sym;
6782 char buf[512];
6783 int p, section_sym;
6785 #ifdef INC_DEBUG
6786 printf("%s: **** new file\n", file->filename);
6787 #endif
6788 funcname = "";
6789 include_stack_ptr = include_stack;
6790 /* XXX: move that before to avoid having to initialize
6791 file->ifdef_stack_ptr ? */
6792 ifdef_stack_ptr = ifdef_stack;
6793 file->ifdef_stack_ptr = ifdef_stack_ptr;
6795 /* XXX: not ANSI compliant: bound checking says error */
6796 vtop = vstack - 1;
6797 anon_sym = SYM_FIRST_ANOM;
6799 /* file info: full path + filename */
6800 section_sym = 0; /* avoid warning */
6801 if (do_debug) {
6802 section_sym = put_elf_sym(symtab_section, 0, 0,
6803 ELF32_ST_INFO(STB_LOCAL, STT_SECTION), 0,
6804 text_section->sh_num, NULL);
6805 getcwd(buf, sizeof(buf));
6806 pstrcat(buf, sizeof(buf), "/");
6807 put_stabs_r(buf, N_SO, 0, 0,
6808 text_section->data_offset, text_section, section_sym);
6809 put_stabs_r(file->filename, N_SO, 0, 0,
6810 text_section->data_offset, text_section, section_sym);
6812 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
6813 symbols can be safely used */
6814 put_elf_sym(symtab_section, 0, 0,
6815 ELF32_ST_INFO(STB_LOCAL, STT_FILE), 0,
6816 SHN_ABS, file->filename);
6818 /* define common 'char *' type because it is often used internally
6819 for arrays and struct dereference */
6820 char_pointer_type = mk_pointer(VT_BYTE);
6821 /* define an old type function 'int func()' */
6822 p = anon_sym++;
6823 sym = sym_push(p, 0, FUNC_CDECL, FUNC_OLD);
6824 func_old_type = VT_FUNC | (p << VT_STRUCT_SHIFT);
6825 #if 0
6826 /* define 'void *alloca(unsigned int)' builtin function */
6828 Sym *s1;
6830 p = anon_sym++;
6831 sym = sym_push(p, mk_pointer(VT_VOID), FUNC_CDECL, FUNC_NEW);
6832 s1 = sym_push(0, VT_UNSIGNED | VT_INT, 0, 0);
6833 s1->next = NULL;
6834 sym->next = s1;
6835 sym_push(TOK_alloca, VT_FUNC | (p << VT_STRUCT_SHIFT), VT_CONST, 0);
6837 #endif
6839 define_start = define_stack.top;
6840 inp();
6841 ch = '\n'; /* needed to parse correctly first preprocessor command */
6842 next();
6843 decl(VT_CONST);
6844 if (tok != -1)
6845 expect("declaration");
6847 /* end of translation unit info */
6848 if (do_debug) {
6849 put_stabs_r(NULL, N_SO, 0, 0,
6850 text_section->data_offset, text_section, section_sym);
6853 /* reset define stack, but leave -Dsymbols (may be incorrect if
6854 they are undefined) */
6855 sym_pop(&define_stack, define_start);
6857 sym_pop(&global_stack, NULL);
6859 return 0;
6862 int tcc_compile_string(TCCState *s, const char *str)
6864 BufferedFile bf1, *bf = &bf1;
6865 int ret;
6867 /* init file structure */
6868 bf->fd = -1;
6869 bf->buf_ptr = (char *)str;
6870 bf->buf_end = (char *)str + strlen(bf->buffer);
6871 pstrcpy(bf->filename, sizeof(bf->filename), "<string>");
6872 bf->line_num = 1;
6873 file = bf;
6875 ret = tcc_compile(s);
6877 /* currently, no need to close */
6878 return ret;
6881 /* define a symbol. A value can also be provided with the '=' operator */
6882 void tcc_define_symbol(TCCState *s, const char *sym, const char *value)
6884 BufferedFile bf1, *bf = &bf1;
6886 pstrcpy(bf->buffer, IO_BUF_SIZE, sym);
6887 pstrcat(bf->buffer, IO_BUF_SIZE, " ");
6888 /* default value */
6889 if (!value)
6890 value = "1";
6891 pstrcat(bf->buffer, IO_BUF_SIZE, value);
6893 /* init file structure */
6894 bf->fd = -1;
6895 bf->buf_ptr = bf->buffer;
6896 bf->buf_end = bf->buffer + strlen(bf->buffer);
6897 bf->filename[0] = '\0';
6898 bf->line_num = 1;
6899 file = bf;
6901 include_stack_ptr = include_stack;
6903 /* parse with define parser */
6904 inp();
6905 ch = '\n'; /* needed to parse correctly first preprocessor command */
6906 next_nomacro();
6907 parse_define();
6908 file = NULL;
6911 void tcc_undefine_symbol(TCCState *s1, const char *sym)
6913 TokenSym *ts;
6914 Sym *s;
6915 ts = tok_alloc(sym, strlen(sym));
6916 s = sym_find1(&define_stack, tok);
6917 /* undefine symbol by putting an invalid name */
6918 if (s)
6919 sym_undef(&define_stack, s);
6922 #include "tccelf.c"
6924 /* print the position in the source file of PC value 'pc' by reading
6925 the stabs debug information */
6926 static void rt_printline(unsigned long wanted_pc)
6928 Stab_Sym *sym, *sym_end;
6929 char func_name[128], last_func_name[128];
6930 unsigned long func_addr, last_pc, pc;
6931 const char *incl_files[INCLUDE_STACK_SIZE];
6932 int incl_index, len, last_line_num, i;
6933 const char *str, *p;
6935 func_name[0] = '\0';
6936 func_addr = 0;
6937 incl_index = 0;
6938 last_func_name[0] = '\0';
6939 last_pc = 0xffffffff;
6940 last_line_num = 1;
6941 sym = (Stab_Sym *)stab_section->data + 1;
6942 sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset);
6943 while (sym < sym_end) {
6944 switch(sym->n_type) {
6945 /* function start or end */
6946 case N_FUN:
6947 if (sym->n_strx == 0) {
6948 func_name[0] = '\0';
6949 func_addr = 0;
6950 } else {
6951 str = stabstr_section->data + sym->n_strx;
6952 p = strchr(str, ':');
6953 if (!p) {
6954 pstrcpy(func_name, sizeof(func_name), str);
6955 } else {
6956 len = p - str;
6957 if (len > sizeof(func_name) - 1)
6958 len = sizeof(func_name) - 1;
6959 memcpy(func_name, str, len);
6960 func_name[len] = '\0';
6962 func_addr = sym->n_value;
6964 break;
6965 /* line number info */
6966 case N_SLINE:
6967 pc = sym->n_value + func_addr;
6968 if (wanted_pc >= last_pc && wanted_pc < pc)
6969 goto found;
6970 last_pc = pc;
6971 last_line_num = sym->n_desc;
6972 /* XXX: slow! */
6973 strcpy(last_func_name, func_name);
6974 break;
6975 /* include files */
6976 case N_BINCL:
6977 str = stabstr_section->data + sym->n_strx;
6978 add_incl:
6979 if (incl_index < INCLUDE_STACK_SIZE) {
6980 incl_files[incl_index++] = str;
6982 break;
6983 case N_EINCL:
6984 if (incl_index > 1)
6985 incl_index--;
6986 break;
6987 case N_SO:
6988 if (sym->n_strx == 0) {
6989 incl_index = 0; /* end of translation unit */
6990 } else {
6991 str = stabstr_section->data + sym->n_strx;
6992 /* do not add path */
6993 len = strlen(str);
6994 if (len > 0 && str[len - 1] != '/')
6995 goto add_incl;
6997 break;
6999 sym++;
7001 /* did not find line number info: */
7002 fprintf(stderr, "(no debug info, pc=0x%08lx): ", wanted_pc);
7003 return;
7004 found:
7005 for(i = 0; i < incl_index - 1; i++)
7006 fprintf(stderr, "In file included from %s\n",
7007 incl_files[i]);
7008 if (incl_index > 0) {
7009 fprintf(stderr, "%s:%d: ",
7010 incl_files[incl_index - 1], last_line_num);
7012 if (last_func_name[0] != '\0') {
7013 fprintf(stderr, "in function '%s()': ", last_func_name);
7017 /* emit a run time error at position 'pc' */
7018 void rt_error(unsigned long pc, const char *fmt, ...)
7020 va_list ap;
7021 va_start(ap, fmt);
7023 rt_printline(pc);
7024 vfprintf(stderr, fmt, ap);
7025 fprintf(stderr, "\n");
7026 exit(255);
7027 va_end(ap);
7030 #ifndef WIN32
7031 /* signal handler for fatal errors */
7032 static void sig_error(int signum, siginfo_t *siginf, void *puc)
7034 struct ucontext *uc = puc;
7035 unsigned long pc;
7037 #ifdef __i386__
7038 pc = uc->uc_mcontext.gregs[14];
7039 #else
7040 #error please put the right sigcontext field
7041 #endif
7043 switch(signum) {
7044 case SIGFPE:
7045 switch(siginf->si_code) {
7046 case FPE_INTDIV:
7047 case FPE_FLTDIV:
7048 rt_error(pc, "division by zero");
7049 break;
7050 default:
7051 rt_error(pc, "floating point exception");
7052 break;
7054 break;
7055 case SIGBUS:
7056 case SIGSEGV:
7057 rt_error(pc, "dereferencing invalid pointer");
7058 break;
7059 case SIGILL:
7060 rt_error(pc, "illegal instruction");
7061 break;
7062 case SIGABRT:
7063 rt_error(pc, "abort() called");
7064 break;
7065 default:
7066 rt_error(pc, "caught signal %d", signum);
7067 break;
7069 exit(255);
7071 #endif
7073 /* launch the compiled program with the given arguments */
7074 int tcc_run(TCCState *s1, int argc, char **argv)
7076 Section *s;
7077 int (*prog_main)(int, char **);
7078 int i;
7080 tcc_add_runtime(s1);
7082 relocate_common_syms();
7084 /* compute relocation address : section are relocated in place. We
7085 also alloc the bss space */
7086 for(i = 1; i < nb_sections; i++) {
7087 s = sections[i];
7088 if (s->sh_flags & SHF_ALLOC) {
7089 void *data;
7090 if (s->sh_type == SHT_NOBITS) {
7091 data = tcc_mallocz(s->data_offset);
7092 } else {
7093 data = s->data;
7095 s->sh_addr = (unsigned long)data;
7099 relocate_syms(1);
7101 /* relocate each section */
7102 for(i = 1; i < nb_sections; i++) {
7103 s = sections[i];
7104 if (s->reloc)
7105 relocate_section(s1, s);
7108 prog_main = (void *)get_elf_sym_val("main");
7110 if (do_debug) {
7111 #ifdef WIN32
7112 error("debug mode currently not available for Windows");
7113 #else
7114 struct sigaction sigact;
7115 /* install TCC signal handlers to print debug info on fatal
7116 runtime errors */
7117 sigact.sa_flags = SA_SIGINFO | SA_ONESHOT;
7118 sigact.sa_sigaction = sig_error;
7119 sigemptyset(&sigact.sa_mask);
7120 sigaction(SIGFPE, &sigact, NULL);
7121 sigaction(SIGILL, &sigact, NULL);
7122 sigaction(SIGSEGV, &sigact, NULL);
7123 sigaction(SIGBUS, &sigact, NULL);
7124 sigaction(SIGABRT, &sigact, NULL);
7125 #endif
7128 #ifdef CONFIG_TCC_BCHECK
7129 if (do_bounds_check) {
7130 void (*bound_init)(void);
7131 void **bound_error_func;
7133 /* set error function */
7134 bound_error_func = (void **)get_elf_sym_val("__bound_error_func");
7135 *bound_error_func = rt_error;
7137 /* XXX: use .init section so that it also work in binary ? */
7138 bound_init = (void *)get_elf_sym_val("__bound_init");
7139 bound_init();
7141 #endif
7142 return (*prog_main)(argc, argv);
7145 TCCState *tcc_new(void)
7147 char *p, *r;
7148 TCCState *s;
7150 s = tcc_malloc(sizeof(TCCState));
7151 if (!s)
7152 return NULL;
7153 s->output_type = TCC_OUTPUT_MEMORY;
7155 /* default include paths */
7156 tcc_add_sysinclude_path(s, "/usr/local/include");
7157 tcc_add_sysinclude_path(s, "/usr/include");
7158 tcc_add_sysinclude_path(s, CONFIG_TCC_PREFIX "/lib/tcc/include");
7160 /* add all tokens */
7161 tok_ident = TOK_IDENT;
7162 p = tcc_keywords;
7163 while (*p) {
7164 r = p;
7165 while (*r++);
7166 tok_alloc(p, r - p - 1);
7167 p = r;
7170 /* we add dummy defines for some special macros to speed up tests
7171 and to have working defined() */
7172 sym_push1(&define_stack, TOK___LINE__, MACRO_OBJ, 0);
7173 sym_push1(&define_stack, TOK___FILE__, MACRO_OBJ, 0);
7174 sym_push1(&define_stack, TOK___DATE__, MACRO_OBJ, 0);
7175 sym_push1(&define_stack, TOK___TIME__, MACRO_OBJ, 0);
7177 /* standard defines */
7178 tcc_define_symbol(s, "__STDC__", NULL);
7179 #if defined(TCC_TARGET_I386)
7180 tcc_define_symbol(s, "__i386__", NULL);
7181 #endif
7182 #if defined(linux)
7183 tcc_define_symbol(s, "linux", NULL);
7184 #endif
7185 /* tiny C specific defines */
7186 tcc_define_symbol(s, "__TINYC__", NULL);
7188 /* default library paths */
7189 tcc_add_library_path(s, "/usr/local/lib");
7190 tcc_add_library_path(s, "/usr/lib");
7191 tcc_add_library_path(s, "/lib");
7193 /* no section zero */
7194 dynarray_add((void ***)&sections, &nb_sections, NULL);
7196 /* create standard sections */
7197 text_section = new_section(".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
7198 data_section = new_section(".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
7199 bss_section = new_section(".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
7201 /* symbols are always generated for linking stage */
7202 symtab_section = new_symtab(".symtab", SHT_SYMTAB, 0,
7203 ".strtab",
7204 ".hashtab", SHF_PRIVATE);
7205 strtab_section = symtab_section->link;
7207 /* private symbol table for dynamic symbols */
7208 dynsymtab_section = new_symtab(".dynsymtab", SHT_SYMTAB, SHF_PRIVATE,
7209 ".dynstrtab",
7210 ".dynhashtab", SHF_PRIVATE);
7211 return s;
7214 void tcc_delete(TCCState *s)
7216 tcc_free(s);
7219 int tcc_add_include_path(TCCState *s, const char *pathname)
7221 char *pathname1;
7223 pathname1 = tcc_strdup(pathname);
7224 dynarray_add((void ***)&include_paths, &nb_include_paths, pathname1);
7225 return 0;
7228 int tcc_add_sysinclude_path(TCCState *s, const char *pathname)
7230 char *pathname1;
7232 pathname1 = tcc_strdup(pathname);
7233 dynarray_add((void ***)&sysinclude_paths, &nb_sysinclude_paths, pathname1);
7234 return 0;
7237 static int tcc_add_file_internal(TCCState *s, const char *filename, int flags)
7239 const char *ext;
7240 Elf32_Ehdr ehdr;
7241 int fd;
7242 BufferedFile *saved_file;
7244 /* find source file type with extension */
7245 ext = strrchr(filename, '.');
7246 if (ext)
7247 ext++;
7249 /* open the file */
7250 saved_file = file;
7251 file = tcc_open(filename);
7252 if (!file) {
7253 if (flags & AFF_PRINT_ERROR) {
7254 error("file '%s' not found", filename);
7255 } else {
7256 file = saved_file;
7257 return -1;
7261 if (!ext || !strcmp(ext, "c")) {
7262 /* C file assumed */
7263 tcc_compile(s);
7264 } else {
7265 fd = file->fd;
7266 /* assume executable format: auto guess file type */
7267 if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
7268 error("could not read header");
7269 lseek(fd, 0, SEEK_SET);
7271 if (ehdr.e_ident[0] == ELFMAG0 &&
7272 ehdr.e_ident[1] == ELFMAG1 &&
7273 ehdr.e_ident[2] == ELFMAG2 &&
7274 ehdr.e_ident[3] == ELFMAG3) {
7275 file->line_num = 0; /* do not display line number if error */
7276 if (ehdr.e_type == ET_REL) {
7277 tcc_load_object_file(s, fd, 0);
7278 } else if (ehdr.e_type == ET_DYN) {
7279 tcc_load_dll(s, fd, filename, (flags & AFF_REFERENCED_DLL) != 0);
7280 } else {
7281 error("unrecognized ELF file");
7283 } else if (memcmp((char *)&ehdr, ARMAG, 8) == 0) {
7284 file->line_num = 0; /* do not display line number if error */
7285 tcc_load_archive(s, fd);
7286 } else {
7287 /* as GNU ld, consider it is an ld script if not recognized */
7288 if (tcc_load_ldscript(s) < 0)
7289 error("unrecognized file type");
7292 tcc_close(file);
7293 file = saved_file;
7294 return 0;
7297 void tcc_add_file(TCCState *s, const char *filename)
7299 tcc_add_file_internal(s, filename, AFF_PRINT_ERROR);
7302 int tcc_add_library_path(TCCState *s, const char *pathname)
7304 char *pathname1;
7306 pathname1 = tcc_strdup(pathname);
7307 dynarray_add((void ***)&library_paths, &nb_library_paths, pathname1);
7308 return 0;
7311 /* find and load a dll. Return non zero if not found */
7312 /* XXX: add '-rpath' option support ? */
7313 static int tcc_add_dll(TCCState *s, const char *filename, int flags)
7315 char buf[1024];
7316 int i;
7318 for(i = 0; i < nb_library_paths; i++) {
7319 snprintf(buf, sizeof(buf), "%s/%s",
7320 library_paths[i], filename);
7321 if (tcc_add_file_internal(s, buf, flags) == 0)
7322 return 0;
7324 return -1;
7327 /* the library name is the same as the argument of the '-l' option */
7328 int tcc_add_library(TCCState *s, const char *libraryname)
7330 char buf[1024];
7331 int i;
7332 void *h;
7334 /* first we look for the dynamic library if not static linking */
7335 if (!static_link) {
7336 snprintf(buf, sizeof(buf), "lib%s.so", libraryname);
7337 /* if we output to memory, then we simply we dlopen(). */
7338 if (s->output_type == TCC_OUTPUT_MEMORY) {
7339 /* Since the libc is already loaded, we don't need to load it again */
7340 if (!strcmp(libraryname, "c"))
7341 return 0;
7342 h = dlopen(buf, RTLD_GLOBAL | RTLD_LAZY);
7343 if (h)
7344 return 0;
7345 } else {
7346 if (tcc_add_dll(s, buf, 0) == 0)
7347 return 0;
7351 /* then we look for the static library */
7352 for(i = 0; i < nb_library_paths; i++) {
7353 snprintf(buf, sizeof(buf), "%s/lib%s.a",
7354 library_paths[i], libraryname);
7355 if (tcc_add_file_internal(s, buf, 0) == 0)
7356 return 0;
7358 return -1;
7361 int tcc_add_symbol(TCCState *s, const char *name, unsigned long val)
7363 add_elf_sym(symtab_section, val, 0,
7364 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE),
7365 SHN_ABS, name);
7366 return 0;
7369 int tcc_set_output_type(TCCState *s, int output_type)
7371 s->output_type = output_type;
7373 /* if bound checking, then add corresponding sections */
7374 #ifdef CONFIG_TCC_BCHECK
7375 if (do_bounds_check) {
7376 /* define symbol */
7377 tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL);
7378 /* create bounds sections */
7379 bounds_section = new_section(".bounds",
7380 SHT_PROGBITS, SHF_ALLOC);
7381 lbounds_section = new_section(".lbounds",
7382 SHT_PROGBITS, SHF_ALLOC);
7384 #endif
7386 /* add debug sections */
7387 if (do_debug) {
7388 /* stab symbols */
7389 stab_section = new_section(".stab", SHT_PROGBITS, 0);
7390 stab_section->sh_entsize = sizeof(Stab_Sym);
7391 stabstr_section = new_section(".stabstr", SHT_STRTAB, 0);
7392 put_elf_str(stabstr_section, "");
7393 stab_section->link = stabstr_section;
7394 /* put first entry */
7395 put_stabs("", 0, 0, 0, 0);
7398 /* add libc crt1/crti objects */
7399 if (output_type == TCC_OUTPUT_EXE ||
7400 output_type == TCC_OUTPUT_DLL) {
7401 if (output_type != TCC_OUTPUT_DLL)
7402 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crt1.o");
7403 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crti.o");
7405 return 0;
7408 #if !defined(LIBTCC)
7410 void help(void)
7412 printf("tcc version 0.9.12 - Tiny C Compiler - Copyright (C) 2001, 2002 Fabrice Bellard\n"
7413 "usage: tcc [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
7414 " [-g] [-b] [-Ldir] [-llib] [-shared] [-static]\n"
7415 " [--] infile1 [infile2... --] [infile_args...]\n"
7416 "\n"
7417 "General options:\n"
7418 " -c compile only - generate an object file\n"
7419 " -o outfile set output filename\n"
7420 " -- allows multiples input files if no -o option given. Also\n"
7421 " separate input files from runtime arguments\n"
7422 " -Bdir set tcc internal library path\n"
7423 " -bench output compilation statistics\n"
7424 "Preprocessor options:\n"
7425 " -Idir add include path 'dir'\n"
7426 " -Dsym[=val] define 'sym' with value 'val'\n"
7427 " -Usym undefine 'sym'\n"
7428 "C compiler options:\n"
7429 " -g generate runtime debug info\n"
7430 #ifdef CONFIG_TCC_BCHECK
7431 " -b compile with built-in memory and bounds checker (implies -g)\n"
7432 #endif
7433 "Linker options:\n"
7434 " -Ldir add library path 'dir'\n"
7435 " -llib link with dynamic or static library 'lib'\n"
7436 " -shared generate a shared library\n"
7437 " -static static linking\n"
7438 " -r relocatable output\n"
7442 int main(int argc, char **argv)
7444 char *r, *outfile;
7445 int optind, output_type, multiple_files, i, reloc_output;
7446 TCCState *s;
7447 char **files;
7448 int nb_files, nb_libraries, nb_objfiles, dminus;
7449 char objfilename[1024];
7451 s = tcc_new();
7452 output_type = TCC_OUTPUT_MEMORY;
7454 optind = 1;
7455 outfile = NULL;
7456 multiple_files = 0;
7457 dminus = 0;
7458 files = NULL;
7459 nb_files = 0;
7460 nb_libraries = 0;
7461 reloc_output = 0;
7462 while (1) {
7463 if (optind >= argc) {
7464 if (nb_files == 0)
7465 goto show_help;
7466 else
7467 break;
7469 r = argv[optind++];
7470 if (r[0] != '-') {
7471 /* add a new file */
7472 dynarray_add((void ***)&files, &nb_files, r);
7473 if (!multiple_files) {
7474 optind--;
7475 /* argv[0] will be this file */
7476 break;
7478 } else if (r[1] == '-') {
7479 /* '--' enables multiple files input and also ends several file input */
7480 if (dminus && multiple_files) {
7481 optind--; /* argv[0] will be '--' */
7482 break;
7484 dminus = 1;
7485 multiple_files = 1;
7486 } else if (r[1] == 'h' || r[1] == '?') {
7487 show_help:
7488 help();
7489 return 1;
7490 } else if (r[1] == 'I') {
7491 if (tcc_add_include_path(s, r + 2) < 0)
7492 error("too many include paths");
7493 } else if (r[1] == 'D') {
7494 char *sym, *value;
7495 sym = r + 2;
7496 value = strchr(sym, '=');
7497 if (value) {
7498 *value = '\0';
7499 value++;
7501 tcc_define_symbol(s, sym, value);
7502 } else if (r[1] == 'U') {
7503 tcc_undefine_symbol(s, r + 2);
7504 } else if (r[1] == 'L') {
7505 tcc_add_library_path(s, r + 2);
7506 } else if (r[1] == 'B') {
7507 /* set tcc utilities path (mainly for tcc development) */
7508 tcc_lib_path = r + 2;
7509 } else if (r[1] == 'l') {
7510 dynarray_add((void ***)&files, &nb_files, r);
7511 nb_libraries++;
7512 } else if (!strcmp(r + 1, "bench")) {
7513 do_bench = 1;
7514 } else
7515 #ifdef CONFIG_TCC_BCHECK
7516 if (r[1] == 'b') {
7517 do_bounds_check = 1;
7518 do_debug = 1;
7519 } else
7520 #endif
7521 if (r[1] == 'g') {
7522 do_debug = 1;
7523 } else if (r[1] == 'c') {
7524 multiple_files = 1;
7525 output_type = TCC_OUTPUT_OBJ;
7526 } else if (!strcmp(r + 1, "static")) {
7527 static_link = 1;
7528 } else if (!strcmp(r + 1, "shared")) {
7529 output_type = TCC_OUTPUT_DLL;
7530 } else if (r[1] == 'o') {
7531 if (optind >= argc)
7532 goto show_help;
7533 multiple_files = 1;
7534 outfile = argv[optind++];
7535 } else if (r[1] == 'r') {
7536 /* generate a .o merging several output files */
7537 reloc_output = 1;
7538 output_type = TCC_OUTPUT_OBJ;
7539 } else {
7540 error("invalid option -- '%s'", r);
7544 nb_objfiles = nb_files - nb_libraries;
7546 /* if outfile provided without other options, we output an
7547 executable */
7548 if (outfile && output_type == TCC_OUTPUT_MEMORY)
7549 output_type = TCC_OUTPUT_EXE;
7551 /* check -c consistency : only single file handled. XXX: checks file type */
7552 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
7553 /* accepts only a single input file */
7554 if (nb_objfiles != 1)
7555 error("cannot specify multiple files with -c");
7556 if (nb_libraries != 0)
7557 error("cannot specify libraries with -c");
7560 /* compute default outfile name */
7561 if (output_type != TCC_OUTPUT_MEMORY && !outfile) {
7562 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
7563 char *ext;
7564 /* add .o extension */
7565 pstrcpy(objfilename, sizeof(objfilename) - 1, files[0]);
7566 ext = strrchr(objfilename, '.');
7567 if (!ext)
7568 goto default_outfile;
7569 strcpy(ext + 1, "o");
7570 } else {
7571 default_outfile:
7572 pstrcpy(objfilename, sizeof(objfilename), "a.out");
7574 outfile = objfilename;
7577 tcc_set_output_type(s, output_type);
7579 /* compile or add each files or library */
7580 for(i = 0;i < nb_files; i++) {
7581 const char *filename;
7583 filename = files[i];
7584 if (filename[0] == '-') {
7585 if (tcc_add_library(s, filename + 2) < 0)
7586 error("cannot find %s", filename);
7587 } else {
7588 tcc_add_file(s, filename);
7592 if (do_bench) {
7593 printf("total: %d idents, %d lines, %d bytes\n",
7594 tok_ident - TOK_IDENT, total_lines, total_bytes);
7595 #ifdef MEM_DEBUG
7596 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size, mem_max_size);
7597 #endif
7600 if (s->output_type != TCC_OUTPUT_MEMORY) {
7601 tcc_output_file(s, outfile);
7602 return 0;
7603 } else {
7604 return tcc_run(s, argc - optind, argv + optind);
7608 #endif