fixed bound checking for structures - fixed ?: type handling - fixed '--' parsing
[tinycc/miki.git] / tcc.c
blob35b6297b9d133d4369cd9cfe9a4613155dad3d3a
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
45 //#define MEM_DEBUG
47 /* target selection */
48 //#define TCC_TARGET_I386 /* i386 code generator */
49 //#define TCC_TARGET_IL /* .NET CLI generator */
51 /* default target is I386 */
52 #if !defined(TCC_TARGET_I386) && !defined(TCC_TARGET_IL)
53 #define TCC_TARGET_I386
54 #endif
56 #if !defined(WIN32) && !defined(TCC_UCLIBC) && !defined(TCC_TARGET_IL)
57 #define CONFIG_TCC_BCHECK /* enable bound checking code */
58 #endif
60 #ifndef CONFIG_TCC_PREFIX
61 #define CONFIG_TCC_PREFIX "/usr/local"
62 #endif
64 /* path to find crt1.o, crti.o and crtn.o. Only needed when generating
65 executables or dlls */
66 #define CONFIG_TCC_CRT_PREFIX "/usr/lib"
68 #define INCLUDE_STACK_SIZE 32
69 #define IFDEF_STACK_SIZE 64
70 #define VSTACK_SIZE 64
71 #define STRING_MAX_SIZE 1024
73 #define TOK_HASH_SIZE 2048 /* must be a power of two */
74 #define TOK_ALLOC_INCR 512 /* must be a power of two */
75 #define SYM_HASH_SIZE 1031
77 /* token symbol management */
78 typedef struct TokenSym {
79 struct TokenSym *hash_next;
80 int tok; /* token number */
81 int len;
82 char str[1];
83 } TokenSym;
85 typedef struct CString {
86 int size; /* size in bytes */
87 void *data; /* either 'char *' or 'int *' */
88 int size_allocated;
89 void *data_allocated; /* if non NULL, data has been malloced */
90 } CString;
92 /* constant value */
93 typedef union CValue {
94 long double ld;
95 double d;
96 float f;
97 int i;
98 unsigned int ui;
99 unsigned int ul; /* address (should be unsigned long on 64 bit cpu) */
100 long long ll;
101 unsigned long long ull;
102 struct CString *cstr;
103 void *ptr;
104 int tab[1];
105 } CValue;
107 /* value on stack */
108 typedef struct SValue {
109 int t; /* type */
110 unsigned short r; /* register + flags */
111 unsigned short r2; /* second register, used for 'long long'
112 type. If not used, set to VT_CONST */
113 CValue c; /* constant, if VT_CONST */
114 struct Sym *sym; /* symbol, if (VT_SYM | VT_CONST) */
115 } SValue;
117 /* symbol management */
118 typedef struct Sym {
119 int v; /* symbol token */
120 int t; /* associated type */
121 int r; /* associated register */
122 int c; /* associated number */
123 struct Sym *next; /* next related symbol */
124 struct Sym *prev; /* prev symbol in stack */
125 struct Sym *hash_next; /* next symbol in hash table */
126 } Sym;
128 typedef struct SymStack {
129 struct Sym *top;
130 struct Sym *hash[SYM_HASH_SIZE];
131 } SymStack;
133 /* section definition */
134 /* XXX: use directly ELF structure for parameters ? */
135 /* special flag to indicate that the section should not be linked to
136 the other ones */
137 #define SHF_PRIVATE 0x80000000
139 typedef struct Section {
140 unsigned long data_offset; /* current data offset */
141 unsigned char *data; /* section data */
142 unsigned long data_allocated; /* used for realloc() handling */
143 int sh_name; /* elf section name (only used during output) */
144 int sh_num; /* elf section number */
145 int sh_type; /* elf section type */
146 int sh_flags; /* elf section flags */
147 int sh_info; /* elf section info */
148 int sh_addralign; /* elf section alignment */
149 int sh_entsize; /* elf entry size */
150 unsigned long sh_size; /* section size (only used during output) */
151 unsigned long sh_addr; /* address at which the section is relocated */
152 unsigned long sh_offset; /* address at which the section is relocated */
153 int nb_hashed_syms; /* used to resize the hash table */
154 struct Section *link; /* link to another section */
155 struct Section *reloc; /* corresponding section for relocation, if any */
156 struct Section *hash; /* hash table for symbols */
157 struct Section *next;
158 char name[64]; /* section name */
159 } Section;
161 typedef struct DLLReference {
162 int level;
163 char name[1];
164 } DLLReference;
166 /* GNUC attribute definition */
167 typedef struct AttributeDef {
168 int aligned;
169 Section *section;
170 unsigned char func_call; /* FUNC_CDECL or FUNC_STDCALL */
171 } AttributeDef;
173 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
174 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
175 #define SYM_FIRST_ANOM (1 << (31 - VT_STRUCT_SHIFT)) /* first anonymous sym */
177 /* stored in 'Sym.c' field */
178 #define FUNC_NEW 1 /* ansi function prototype */
179 #define FUNC_OLD 2 /* old function prototype */
180 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
182 /* stored in 'Sym.r' field */
183 #define FUNC_CDECL 0 /* standard c call */
184 #define FUNC_STDCALL 1 /* pascal c call */
186 /* field 'Sym.t' for macros */
187 #define MACRO_OBJ 0 /* object like macro */
188 #define MACRO_FUNC 1 /* function like macro */
190 /* field 'Sym.t' for labels */
191 #define LABEL_FORWARD 1 /* label is forward defined */
193 /* type_decl() types */
194 #define TYPE_ABSTRACT 1 /* type without variable */
195 #define TYPE_DIRECT 2 /* type with variable */
197 #define IO_BUF_SIZE 8192
199 typedef struct BufferedFile {
200 unsigned char *buf_ptr;
201 unsigned char *buf_end;
202 int fd;
203 int line_num; /* current line number - here to simply code */
204 char filename[1024]; /* current filename - here to simplify code */
205 unsigned char buffer[IO_BUF_SIZE + 1]; /* extra size for CH_EOB char */
206 } BufferedFile;
208 #define CH_EOB 0 /* end of buffer or '\0' char in file */
209 #define CH_EOF (-1) /* end of file */
211 /* parsing state (used to save parser state to reparse part of the
212 source several times) */
213 typedef struct ParseState {
214 int *macro_ptr;
215 int line_num;
216 int tok;
217 CValue tokc;
218 } ParseState;
220 /* used to record tokens */
221 typedef struct TokenString {
222 int *str;
223 int len;
224 int last_line_num;
225 } TokenString;
227 /* parser */
228 struct BufferedFile *file;
229 int ch, ch1, tok, tok1;
230 CValue tokc, tok1c;
231 CString tokcstr; /* current parsed string, if any */
232 int return_linefeed; /* if true, line feed is returned as a token */
234 /* sections */
235 Section **sections;
236 int nb_sections; /* number of sections, including first dummy section */
237 Section *text_section, *data_section, *bss_section; /* predefined sections */
238 Section *cur_text_section; /* current section where function code is
239 generated */
240 /* bound check related sections */
241 Section *bounds_section; /* contains global data bound description */
242 Section *lbounds_section; /* contains local data bound description */
243 /* symbol sections */
244 Section *symtab_section, *strtab_section;
245 /* temporary dynamic symbol sections (for dll loading) */
246 Section *dynsymtab_section;
247 /* exported dynamic symbol section */
248 Section *dynsym;
249 /* got handling */
250 Section *got;
251 unsigned long *got_offsets;
252 int nb_got_offsets;
253 int nb_plt_entries;
254 /* give the correspondance from symtab indexes to dynsym indexes */
255 int *symtab_to_dynsym;
257 /* array of all loaded dlls (including those referenced by loaded
258 dlls) */
259 DLLReference **loaded_dlls;
260 int nb_loaded_dlls;
262 /* debug sections */
263 Section *stab_section, *stabstr_section;
265 char **library_paths;
266 int nb_library_paths;
268 /* loc : local variable index
269 ind : output code index
270 rsym: return symbol
271 anon_sym: anonymous symbol index
273 int rsym, anon_sym,
274 prog, ind, loc;
275 /* expression generation modifiers */
276 int const_wanted; /* true if constant wanted */
277 int global_expr; /* true if compound literals must be allocated
278 globally (used during initializers parsing */
279 int func_vt, func_vc; /* current function return type (used by
280 return instruction) */
281 int last_line_num, last_ind, func_ind; /* debug last line number and pc */
282 int tok_ident;
283 TokenSym **table_ident;
284 TokenSym *hash_ident[TOK_HASH_SIZE];
285 char token_buf[STRING_MAX_SIZE + 1];
286 char *funcname;
287 SymStack define_stack, global_stack, local_stack, label_stack;
289 SValue vstack[VSTACK_SIZE], *vtop;
290 int *macro_ptr, *macro_ptr_allocated;
291 BufferedFile *include_stack[INCLUDE_STACK_SIZE], **include_stack_ptr;
292 int ifdef_stack[IFDEF_STACK_SIZE], *ifdef_stack_ptr;
293 char **include_paths;
294 int nb_include_paths;
295 char **sysinclude_paths;
296 int nb_sysinclude_paths;
297 int char_pointer_type;
298 int func_old_type;
300 /* compile with debug symbol (and use them if error during execution) */
301 int do_debug = 0;
303 /* compile with built-in memory and bounds checker */
304 int do_bounds_check = 0;
306 /* display benchmark infos */
307 int do_bench = 0;
308 int total_lines;
309 int total_bytes;
311 /* use GNU C extensions */
312 int gnu_ext = 1;
314 /* use Tiny C extensions */
315 int tcc_ext = 1;
317 /* if true, static linking is performed */
318 int static_link = 0;
320 /* give the path of the tcc libraries */
321 static const char *tcc_lib_path = CONFIG_TCC_PREFIX "/lib/tcc";
323 struct TCCState {
324 int output_type;
327 /* The current value can be: */
328 #define VT_VALMASK 0x00ff
329 #define VT_CONST 0x00f0 /* constant in vc
330 (must be first non register value) */
331 #define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */
332 #define VT_LOCAL 0x00f2 /* offset on stack */
333 #define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */
334 #define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */
335 #define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */
336 #define VT_LVAL 0x0100 /* var is an lvalue */
337 #define VT_SYM 0x0200 /* a symbol value is added */
338 #define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for
339 char/short stored in integer registers) */
340 #define VT_MUSTBOUND 0x0800 /* bound checking must be done before
341 dereferencing value */
342 #define VT_BOUNDED 0x8000 /* value is bounded. The address of the
343 bounding function call point is in vc */
344 #define VT_LVAL_BYTE 0x1000 /* lvalue is a byte */
345 #define VT_LVAL_SHORT 0x2000 /* lvalue is a short */
346 #define VT_LVAL_UNSIGNED 0x4000 /* lvalue is unsigned */
347 #define VT_LVAL_TYPE (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)
349 /* types */
350 #define VT_STRUCT_SHIFT 12 /* structure/enum name shift (20 bits left) */
352 #define VT_INT 0 /* integer type */
353 #define VT_BYTE 1 /* signed byte type */
354 #define VT_SHORT 2 /* short type */
355 #define VT_VOID 3 /* void type */
356 #define VT_PTR 4 /* pointer */
357 #define VT_ENUM 5 /* enum definition */
358 #define VT_FUNC 6 /* function type */
359 #define VT_STRUCT 7 /* struct/union definition */
360 #define VT_FLOAT 8 /* IEEE float */
361 #define VT_DOUBLE 9 /* IEEE double */
362 #define VT_LDOUBLE 10 /* IEEE long double */
363 #define VT_BOOL 11 /* ISOC99 boolean type */
364 #define VT_LLONG 12 /* 64 bit integer */
365 #define VT_LONG 13 /* long integer (NEVER USED as type, only
366 during parsing) */
367 #define VT_BTYPE 0x000f /* mask for basic type */
368 #define VT_UNSIGNED 0x0010 /* unsigned type */
369 #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
370 #define VT_BITFIELD 0x0040 /* bitfield modifier */
372 /* storage */
373 #define VT_EXTERN 0x00000080 /* extern definition */
374 #define VT_STATIC 0x00000100 /* static variable */
375 #define VT_TYPEDEF 0x00000200 /* typedef definition */
377 /* type mask (except storage) */
378 #define VT_TYPE (~(VT_EXTERN | VT_STATIC | VT_TYPEDEF))
380 /* token values */
382 /* warning: the following compare tokens depend on i386 asm code */
383 #define TOK_ULT 0x92
384 #define TOK_UGE 0x93
385 #define TOK_EQ 0x94
386 #define TOK_NE 0x95
387 #define TOK_ULE 0x96
388 #define TOK_UGT 0x97
389 #define TOK_LT 0x9c
390 #define TOK_GE 0x9d
391 #define TOK_LE 0x9e
392 #define TOK_GT 0x9f
394 #define TOK_LAND 0xa0
395 #define TOK_LOR 0xa1
397 #define TOK_DEC 0xa2
398 #define TOK_MID 0xa3 /* inc/dec, to void constant */
399 #define TOK_INC 0xa4
400 #define TOK_UDIV 0xb0 /* unsigned division */
401 #define TOK_UMOD 0xb1 /* unsigned modulo */
402 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
403 #define TOK_CINT 0xb3 /* number in tokc */
404 #define TOK_CCHAR 0xb4 /* char constant in tokc */
405 #define TOK_STR 0xb5 /* pointer to string in tokc */
406 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
407 #define TOK_LCHAR 0xb7
408 #define TOK_LSTR 0xb8
409 #define TOK_CFLOAT 0xb9 /* float constant */
410 #define TOK_LINENUM 0xba /* line number info */
411 #define TOK_CDOUBLE 0xc0 /* double constant */
412 #define TOK_CLDOUBLE 0xc1 /* long double constant */
413 #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
414 #define TOK_ADDC1 0xc3 /* add with carry generation */
415 #define TOK_ADDC2 0xc4 /* add with carry use */
416 #define TOK_SUBC1 0xc5 /* add with carry generation */
417 #define TOK_SUBC2 0xc6 /* add with carry use */
418 #define TOK_CUINT 0xc8 /* unsigned int constant */
419 #define TOK_CLLONG 0xc9 /* long long constant */
420 #define TOK_CULLONG 0xca /* unsigned long long constant */
421 #define TOK_ARROW 0xcb
422 #define TOK_DOTS 0xcc /* three dots */
423 #define TOK_SHR 0xcd /* unsigned shift right */
425 #define TOK_SHL 0x01 /* shift left */
426 #define TOK_SAR 0x02 /* signed shift right */
428 /* assignement operators : normal operator or 0x80 */
429 #define TOK_A_MOD 0xa5
430 #define TOK_A_AND 0xa6
431 #define TOK_A_MUL 0xaa
432 #define TOK_A_ADD 0xab
433 #define TOK_A_SUB 0xad
434 #define TOK_A_DIV 0xaf
435 #define TOK_A_XOR 0xde
436 #define TOK_A_OR 0xfc
437 #define TOK_A_SHL 0x81
438 #define TOK_A_SAR 0x82
440 /* WARNING: the content of this string encodes token numbers */
441 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";
443 #define TOK_EOF (-1) /* end of file */
444 #define TOK_LINEFEED 10 /* line feed */
446 /* all identificators and strings have token above that */
447 #define TOK_IDENT 256
449 enum {
450 TOK_INT = TOK_IDENT,
451 TOK_VOID,
452 TOK_CHAR,
453 TOK_IF,
454 TOK_ELSE,
455 TOK_WHILE,
456 TOK_BREAK,
457 TOK_RETURN,
458 TOK_FOR,
459 TOK_EXTERN,
460 TOK_STATIC,
461 TOK_UNSIGNED,
462 TOK_GOTO,
463 TOK_DO,
464 TOK_CONTINUE,
465 TOK_SWITCH,
466 TOK_CASE,
468 /* ignored types Must have contiguous values */
469 TOK_CONST,
470 TOK_VOLATILE,
471 TOK_LONG,
472 TOK_REGISTER,
473 TOK_SIGNED,
474 TOK___SIGNED__, /* gcc keyword */
475 TOK_AUTO,
476 TOK_INLINE,
477 TOK___INLINE__, /* gcc keyword */
478 TOK_RESTRICT,
480 /* unsupported type */
481 TOK_FLOAT,
482 TOK_DOUBLE,
483 TOK_BOOL,
485 TOK_SHORT,
486 TOK_STRUCT,
487 TOK_UNION,
488 TOK_TYPEDEF,
489 TOK_DEFAULT,
490 TOK_ENUM,
491 TOK_SIZEOF,
492 TOK___ATTRIBUTE__,
494 /* preprocessor only */
495 TOK_UIDENT, /* first "user" ident (not keyword) */
496 TOK_DEFINE = TOK_UIDENT,
497 TOK_INCLUDE,
498 TOK_IFDEF,
499 TOK_IFNDEF,
500 TOK_ELIF,
501 TOK_ENDIF,
502 TOK_DEFINED,
503 TOK_UNDEF,
504 TOK_ERROR,
505 TOK_LINE,
507 #define DEF(id, str) id,
508 #include "tcctok.h"
509 #undef DEF
512 char *tcc_keywords =
513 "int\0void\0char\0if\0else\0while\0break\0return\0for\0extern\0static\0"
514 "unsigned\0goto\0do\0continue\0switch\0case\0const\0volatile\0long\0"
515 "register\0signed\0__signed__\0auto\0inline\0__inline__\0restrict\0"
516 "float\0double\0_Bool\0short\0struct\0union\0typedef\0default\0enum\0"
517 "sizeof\0__attribute__\0"
518 /* the following are not keywords. They are included to ease parsing */
519 "define\0include\0ifdef\0ifndef\0elif\0endif\0"
520 "defined\0undef\0error\0line\0"
521 /* builtin functions */
522 #define DEF(id, str) str "\0"
523 #include "tcctok.h"
524 #undef DEF
527 #ifdef WIN32
528 #define snprintf _snprintf
529 #endif
531 #if defined(WIN32) || defined(TCC_UCLIBC)
532 /* currently incorrect */
533 long double strtold(const char *nptr, char **endptr)
535 return (long double)strtod(nptr, endptr);
537 float strtof(const char *nptr, char **endptr)
539 return (float)strtod(nptr, endptr);
541 #else
542 /* XXX: need to define this to use them in non ISOC99 context */
543 extern float strtof (const char *__nptr, char **__endptr);
544 extern long double strtold (const char *__nptr, char **__endptr);
545 #endif
547 static char *pstrcpy(char *buf, int buf_size, const char *s);
548 static char *pstrcat(char *buf, int buf_size, const char *s);
550 void sum(int l);
551 void next(void);
552 void next_nomacro(void);
553 static int expr_const(void);
554 void expr_eq(void);
555 void gexpr(void);
556 void decl(int l);
557 static void decl_initializer(int t, Section *sec, unsigned long c,
558 int first, int size_only);
559 static void decl_initializer_alloc(int t, AttributeDef *ad, int r,
560 int has_init, int v, int scope);
561 int gv(int rc);
562 void gv2(int rc1, int rc2);
563 void move_reg(int r, int s);
564 void save_regs(int n);
565 void save_reg(int r);
566 void vpop(void);
567 void vswap(void);
568 void vdup(void);
569 int get_reg(int rc);
571 void macro_subst(TokenString *tok_str,
572 Sym **nested_list, int *macro_str);
573 int save_reg_forced(int r);
574 void gen_op(int op);
575 void force_charshort_cast(int t);
576 void gen_cast(int t);
577 void vstore(void);
578 Sym *sym_find(int v);
579 Sym *sym_push(int v, int t, int r, int c);
581 /* type handling */
582 int type_size(int t, int *a);
583 int pointed_type(int t);
584 int pointed_size(int t);
585 static int lvalue_type(int t);
586 int is_compatible_types(int t1, int t2);
587 int parse_btype(int *type_ptr, AttributeDef *ad);
588 int type_decl(AttributeDef *ad, int *v, int t, int td);
590 void error(const char *fmt, ...);
591 void rt_error(unsigned long pc, const char *fmt, ...);
592 void vpushi(int v);
593 void vset(int t, int r, int v);
594 void type_to_str(char *buf, int buf_size,
595 int t, const char *varstr);
596 char *get_tok_str(int v, CValue *cv);
597 static Sym *get_sym_ref(int t, Section *sec,
598 unsigned long offset, unsigned long size);
599 static Sym *external_global_sym(int v, int u, int r);
601 /* section generation */
602 static void section_realloc(Section *sec, unsigned long new_size);
603 static void *section_ptr_add(Section *sec, unsigned long size);
604 static void put_extern_sym(Sym *sym, Section *section,
605 unsigned long value, unsigned long size);
606 static void greloc(Section *s, Sym *sym, unsigned long addr, int type);
607 static int put_elf_str(Section *s, const char *sym);
608 static int put_elf_sym(Section *s,
609 unsigned long value, unsigned long size,
610 int info, int other, int shndx, const char *name);
611 static int add_elf_sym(Section *s, unsigned long value, unsigned long size,
612 int info, int sh_num, const char *name);
613 static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
614 int type, int symbol);
615 static void put_stabs(const char *str, int type, int other, int desc,
616 unsigned long value);
617 static void put_stabs_r(const char *str, int type, int other, int desc,
618 unsigned long value, Section *sec, int sym_index);
619 static void put_stabn(int type, int other, int desc, int value);
620 static void put_stabd(int type, int other, int desc);
621 static int tcc_add_dll(TCCState *s, const char *filename, int flags);
623 #define AFF_PRINT_ERROR 0x0001 /* print error if file not found */
624 #define AFF_REFERENCED_DLL 0x0002 /* load a referenced dll from another dll */
625 static int tcc_add_file_internal(TCCState *s, const char *filename, int flags);
627 /* true if float/double/long double type */
628 static inline int is_float(int t)
630 int bt;
631 bt = t & VT_BTYPE;
632 return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT;
635 #ifdef TCC_TARGET_I386
636 #include "i386-gen.c"
637 #endif
638 #ifdef TCC_TARGET_IL
639 #include "il-gen.c"
640 #endif
642 #ifdef CONFIG_TCC_STATIC
644 #define RTLD_LAZY 0x001
645 #define RTLD_NOW 0x002
646 #define RTLD_GLOBAL 0x100
648 /* dummy function for profiling */
649 void *dlopen(const char *filename, int flag)
651 return NULL;
654 const char *dlerror(void)
656 return "error";
659 typedef struct TCCSyms {
660 char *str;
661 void *ptr;
662 } TCCSyms;
664 #define TCCSYM(a) { #a, &a, },
666 /* add the symbol you want here if no dynamic linking is done */
667 static TCCSyms tcc_syms[] = {
668 TCCSYM(printf)
669 TCCSYM(fprintf)
670 TCCSYM(fopen)
671 TCCSYM(fclose)
672 { NULL, NULL },
675 void *dlsym(void *handle, const char *symbol)
677 TCCSyms *p;
678 p = tcc_syms;
679 while (p->str != NULL) {
680 if (!strcmp(p->str, symbol))
681 return p->ptr;
682 p++;
684 return NULL;
687 #endif
689 /********************************************************/
691 /* we use our own 'finite' function to avoid potential problems with
692 non standard math libs */
693 /* XXX: endianness dependant */
694 int ieee_finite(double d)
696 int *p = (int *)&d;
697 return ((unsigned)((p[1] | 0x800fffff) + 1)) >> 31;
700 /* copy a string and truncate it. */
701 static char *pstrcpy(char *buf, int buf_size, const char *s)
703 char *q, *q_end;
704 int c;
706 if (buf_size > 0) {
707 q = buf;
708 q_end = buf + buf_size - 1;
709 while (q < q_end) {
710 c = *s++;
711 if (c == '\0')
712 break;
713 *q++ = c;
715 *q = '\0';
717 return buf;
720 /* strcat and truncate. */
721 static char *pstrcat(char *buf, int buf_size, const char *s)
723 int len;
724 len = strlen(buf);
725 if (len < buf_size)
726 pstrcpy(buf + len, buf_size - len, s);
727 return buf;
730 /* memory management */
731 #ifdef MEM_DEBUG
732 int mem_cur_size;
733 int mem_max_size;
734 #endif
736 static inline void tcc_free(void *ptr)
738 #ifdef MEM_DEBUG
739 mem_cur_size -= malloc_usable_size(ptr);
740 #endif
741 free(ptr);
744 static void *tcc_malloc(unsigned long size)
746 void *ptr;
747 ptr = malloc(size);
748 if (!ptr)
749 error("memory full");
750 #ifdef MEM_DEBUG
751 mem_cur_size += malloc_usable_size(ptr);
752 if (mem_cur_size > mem_max_size)
753 mem_max_size = mem_cur_size;
754 #endif
755 return ptr;
758 static void *tcc_mallocz(unsigned long size)
760 void *ptr;
761 ptr = tcc_malloc(size);
762 memset(ptr, 0, size);
763 return ptr;
766 static inline void *tcc_realloc(void *ptr, unsigned long size)
768 void *ptr1;
769 #ifdef MEM_DEBUG
770 mem_cur_size -= malloc_usable_size(ptr);
771 #endif
772 ptr1 = realloc(ptr, size);
773 #ifdef MEM_DEBUG
774 /* NOTE: count not correct if alloc error, but not critical */
775 mem_cur_size += malloc_usable_size(ptr1);
776 if (mem_cur_size > mem_max_size)
777 mem_max_size = mem_cur_size;
778 #endif
779 return ptr1;
782 static char *tcc_strdup(const char *str)
784 char *ptr;
785 ptr = tcc_malloc(strlen(str) + 1);
786 strcpy(ptr, str);
787 return ptr;
790 #define free(p) use_tcc_free(p)
791 #define malloc(s) use_tcc_malloc(s)
792 #define realloc(p, s) use_tcc_realloc(p, s)
794 static void dynarray_add(void ***ptab, int *nb_ptr, void *data)
796 int nb, nb_alloc;
797 void **pp;
799 nb = *nb_ptr;
800 pp = *ptab;
801 /* every power of two we double array size */
802 if ((nb & (nb - 1)) == 0) {
803 if (!nb)
804 nb_alloc = 1;
805 else
806 nb_alloc = nb * 2;
807 pp = tcc_realloc(pp, nb_alloc * sizeof(void *));
808 if (!pp)
809 error("memory full");
810 *ptab = pp;
812 pp[nb++] = data;
813 *nb_ptr = nb;
816 Section *new_section(const char *name, int sh_type, int sh_flags)
818 Section *sec;
820 sec = tcc_mallocz(sizeof(Section));
821 pstrcpy(sec->name, sizeof(sec->name), name);
822 sec->sh_type = sh_type;
823 sec->sh_flags = sh_flags;
824 switch(sh_type) {
825 case SHT_HASH:
826 case SHT_REL:
827 case SHT_DYNSYM:
828 case SHT_SYMTAB:
829 case SHT_DYNAMIC:
830 sec->sh_addralign = 4;
831 break;
832 case SHT_STRTAB:
833 sec->sh_addralign = 1;
834 break;
835 default:
836 sec->sh_addralign = 32; /* default conservative alignment */
837 break;
840 /* only add section if not private */
841 if (!(sh_flags & SHF_PRIVATE)) {
842 sec->sh_num = nb_sections;
843 dynarray_add((void ***)&sections, &nb_sections, sec);
845 return sec;
848 /* realloc section and set its content to zero */
849 static void section_realloc(Section *sec, unsigned long new_size)
851 unsigned long size;
852 unsigned char *data;
854 size = sec->data_allocated;
855 if (size == 0)
856 size = 1;
857 while (size < new_size)
858 size = size * 2;
859 data = tcc_realloc(sec->data, size);
860 if (!data)
861 error("memory full");
862 memset(data + sec->data_allocated, 0, size - sec->data_allocated);
863 sec->data = data;
864 sec->data_allocated = size;
867 /* reserve at least 'size' bytes in section 'sec' from
868 sec->data_offset. */
869 static void *section_ptr_add(Section *sec, unsigned long size)
871 unsigned long offset, offset1;
873 offset = sec->data_offset;
874 offset1 = offset + size;
875 if (offset1 > sec->data_allocated)
876 section_realloc(sec, offset1);
877 sec->data_offset = offset1;
878 return sec->data + offset;
881 /* return a reference to a section, and create it if it does not
882 exists */
883 Section *find_section(const char *name)
885 Section *sec;
886 int i;
887 for(i = 1; i < nb_sections; i++) {
888 sec = sections[i];
889 if (!strcmp(name, sec->name))
890 return sec;
892 /* sections are created as PROGBITS */
893 return new_section(name, SHT_PROGBITS, SHF_ALLOC);
896 /* update sym->c so that it points to an external symbol in section
897 'section' with value 'value' */
898 static void put_extern_sym(Sym *sym, Section *section,
899 unsigned long value, unsigned long size)
901 int sym_type, sym_bind, sh_num, info;
902 Elf32_Sym *esym;
903 const char *name;
904 char buf[32];
906 if (section)
907 sh_num = section->sh_num;
908 else
909 sh_num = SHN_UNDEF;
910 if (!sym->c) {
911 if ((sym->t & VT_BTYPE) == VT_FUNC)
912 sym_type = STT_FUNC;
913 else
914 sym_type = STT_OBJECT;
915 if (sym->t & VT_STATIC)
916 sym_bind = STB_LOCAL;
917 else
918 sym_bind = STB_GLOBAL;
920 name = get_tok_str(sym->v, NULL);
921 #ifdef CONFIG_TCC_BCHECK
922 if (do_bounds_check) {
923 /* if bound checking is activated, we change some function
924 names by adding the "__bound" prefix */
925 switch(sym->v) {
926 #if 0
927 /* XXX: we rely only on malloc hooks */
928 case TOK_malloc:
929 case TOK_free:
930 case TOK_realloc:
931 case TOK_memalign:
932 case TOK_calloc:
933 #endif
934 case TOK_memcpy:
935 case TOK_memmove:
936 case TOK_memset:
937 case TOK_strlen:
938 case TOK_strcpy:
939 strcpy(buf, "__bound_");
940 strcat(buf, name);
941 name = buf;
942 break;
945 #endif
946 info = ELF32_ST_INFO(sym_bind, sym_type);
947 sym->c = add_elf_sym(symtab_section, value, size, info, sh_num, name);
948 } else {
949 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
950 esym->st_value = value;
951 esym->st_size = size;
952 esym->st_shndx = sh_num;
956 /* add a new relocation entry to symbol 'sym' in section 's' */
957 static void greloc(Section *s, Sym *sym, unsigned long offset, int type)
959 if (!sym->c)
960 put_extern_sym(sym, NULL, 0, 0);
961 /* now we can add ELF relocation info */
962 put_elf_reloc(symtab_section, s, offset, type, sym->c);
965 static inline int isid(int c)
967 return (c >= 'a' && c <= 'z') ||
968 (c >= 'A' && c <= 'Z') ||
969 c == '_';
972 static inline int isnum(int c)
974 return c >= '0' && c <= '9';
977 static inline int isoct(int c)
979 return c >= '0' && c <= '7';
982 static inline int toup(int c)
984 if (ch >= 'a' && ch <= 'z')
985 return ch - 'a' + 'A';
986 else
987 return ch;
990 void printline(void)
992 BufferedFile **f;
994 if (file) {
995 for(f = include_stack; f < include_stack_ptr; f++)
996 fprintf(stderr, "In file included from %s:%d:\n",
997 (*f)->filename, (*f)->line_num);
998 if (file->line_num > 0) {
999 fprintf(stderr, "%s:%d: ", file->filename, file->line_num);
1000 } else {
1001 fprintf(stderr, "%s: ", file->filename);
1003 } else {
1004 fprintf(stderr, "tcc: ");
1008 void error(const char *fmt, ...)
1010 va_list ap;
1011 va_start(ap, fmt);
1012 printline();
1013 vfprintf(stderr, fmt, ap);
1014 fprintf(stderr, "\n");
1015 exit(1);
1016 va_end(ap);
1019 void expect(const char *msg)
1021 error("%s expected", msg);
1024 void warning(const char *fmt, ...)
1026 va_list ap;
1028 va_start(ap, fmt);
1029 printline();
1030 fprintf(stderr, "warning: ");
1031 vfprintf(stderr, fmt, ap);
1032 fprintf(stderr, "\n");
1033 va_end(ap);
1036 void skip(int c)
1038 if (tok != c)
1039 error("'%c' expected", c);
1040 next();
1043 void test_lvalue(void)
1045 if (!(vtop->r & VT_LVAL))
1046 expect("lvalue");
1049 TokenSym *tok_alloc(const char *str, int len)
1051 TokenSym *ts, **pts, **ptable;
1052 int h, i;
1054 if (len <= 0)
1055 len = strlen(str);
1056 h = 1;
1057 for(i=0;i<len;i++)
1058 h = (h * 263 + ((unsigned char *)str)[i]) & (TOK_HASH_SIZE - 1);
1060 pts = &hash_ident[h];
1061 while (1) {
1062 ts = *pts;
1063 if (!ts)
1064 break;
1065 if (ts->len == len && !memcmp(ts->str, str, len))
1066 return ts;
1067 pts = &(ts->hash_next);
1070 if (tok_ident >= SYM_FIRST_ANOM)
1071 error("memory full");
1073 /* expand token table if needed */
1074 i = tok_ident - TOK_IDENT;
1075 if ((i % TOK_ALLOC_INCR) == 0) {
1076 ptable = tcc_realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *));
1077 if (!ptable)
1078 error("memory full");
1079 table_ident = ptable;
1082 ts = tcc_malloc(sizeof(TokenSym) + len);
1083 table_ident[i] = ts;
1084 ts->tok = tok_ident++;
1085 ts->len = len;
1086 ts->hash_next = NULL;
1087 memcpy(ts->str, str, len + 1);
1088 *pts = ts;
1089 return ts;
1092 /* CString handling */
1094 static void cstr_realloc(CString *cstr, int new_size)
1096 int size;
1097 void *data;
1099 size = cstr->size_allocated;
1100 if (size == 0)
1101 size = 8; /* no need to allocate a too small first string */
1102 while (size < new_size)
1103 size = size * 2;
1104 data = tcc_realloc(cstr->data_allocated, size);
1105 if (!data)
1106 error("memory full");
1107 cstr->data_allocated = data;
1108 cstr->size_allocated = size;
1109 cstr->data = data;
1112 /* add a byte */
1113 static void cstr_ccat(CString *cstr, int ch)
1115 int size;
1116 size = cstr->size + 1;
1117 if (size > cstr->size_allocated)
1118 cstr_realloc(cstr, size);
1119 ((unsigned char *)cstr->data)[size - 1] = ch;
1120 cstr->size = size;
1123 static void cstr_cat(CString *cstr, const char *str)
1125 int c;
1126 for(;;) {
1127 c = *str;
1128 if (c == '\0')
1129 break;
1130 cstr_ccat(cstr, c);
1131 str++;
1135 /* add a wide char */
1136 static void cstr_wccat(CString *cstr, int ch)
1138 int size;
1139 size = cstr->size + sizeof(int);
1140 if (size > cstr->size_allocated)
1141 cstr_realloc(cstr, size);
1142 *(int *)(((unsigned char *)cstr->data) + size - sizeof(int)) = ch;
1143 cstr->size = size;
1146 static void cstr_new(CString *cstr)
1148 memset(cstr, 0, sizeof(CString));
1151 /* free string and reset it to NULL */
1152 static void cstr_free(CString *cstr)
1154 tcc_free(cstr->data_allocated);
1155 cstr_new(cstr);
1158 #define cstr_reset(cstr) cstr_free(cstr)
1160 /* XXX: unicode ? */
1161 static void add_char(CString *cstr, int c)
1163 if (c == '\'' || c == '\"' || c == '\\') {
1164 /* XXX: could be more precise if char or string */
1165 cstr_ccat(cstr, '\\');
1167 if (c >= 32 && c <= 126) {
1168 cstr_ccat(cstr, c);
1169 } else {
1170 cstr_ccat(cstr, '\\');
1171 if (c == '\n') {
1172 cstr_ccat(cstr, 'n');
1173 } else {
1174 cstr_ccat(cstr, '0' + ((c >> 6) & 7));
1175 cstr_ccat(cstr, '0' + ((c >> 3) & 7));
1176 cstr_ccat(cstr, '0' + (c & 7));
1181 /* XXX: buffer overflow */
1182 /* XXX: float tokens */
1183 char *get_tok_str(int v, CValue *cv)
1185 static char buf[STRING_MAX_SIZE + 1];
1186 static CString cstr_buf;
1187 CString *cstr;
1188 unsigned char *q;
1189 char *p;
1190 int i, len;
1192 /* NOTE: to go faster, we give a fixed buffer for small strings */
1193 cstr_reset(&cstr_buf);
1194 cstr_buf.data = buf;
1195 cstr_buf.size_allocated = sizeof(buf);
1196 p = buf;
1198 switch(v) {
1199 case TOK_CINT:
1200 case TOK_CUINT:
1201 /* XXX: not exact */
1202 sprintf(p, "%u", cv->ui);
1203 break;
1204 case TOK_CCHAR:
1205 case TOK_LCHAR:
1206 cstr_ccat(&cstr_buf, '\'');
1207 add_char(&cstr_buf, cv->i);
1208 cstr_ccat(&cstr_buf, '\'');
1209 cstr_ccat(&cstr_buf, '\0');
1210 break;
1211 case TOK_STR:
1212 case TOK_LSTR:
1213 cstr = cv->cstr;
1214 cstr_ccat(&cstr_buf, '\"');
1215 if (v == TOK_STR) {
1216 len = cstr->size - 1;
1217 for(i=0;i<len;i++)
1218 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1219 } else {
1220 len = (cstr->size / sizeof(int)) - 1;
1221 for(i=0;i<len;i++)
1222 add_char(&cstr_buf, ((int *)cstr->data)[i]);
1224 cstr_ccat(&cstr_buf, '\"');
1225 cstr_ccat(&cstr_buf, '\0');
1226 break;
1227 case TOK_LT:
1228 v = '<';
1229 goto addv;
1230 case TOK_GT:
1231 v = '>';
1232 goto addv;
1233 case TOK_A_SHL:
1234 return strcpy(p, "<<=");
1235 case TOK_A_SAR:
1236 return strcpy(p, ">>=");
1237 default:
1238 if (v < TOK_IDENT) {
1239 /* search in two bytes table */
1240 q = tok_two_chars;
1241 while (*q) {
1242 if (q[2] == v) {
1243 *p++ = q[0];
1244 *p++ = q[1];
1245 *p = '\0';
1246 return buf;
1248 q += 3;
1250 addv:
1251 *p++ = v;
1252 *p = '\0';
1253 } else if (v < tok_ident) {
1254 return table_ident[v - TOK_IDENT]->str;
1255 } else if (v >= SYM_FIRST_ANOM) {
1256 /* special name for anonymous symbol */
1257 sprintf(p, "L.%u", v - SYM_FIRST_ANOM);
1258 } else {
1259 /* should never happen */
1260 return NULL;
1262 break;
1264 return cstr_buf.data;
1267 /* push, without hashing */
1268 Sym *sym_push2(Sym **ps, int v, int t, int c)
1270 Sym *s;
1271 s = tcc_malloc(sizeof(Sym));
1272 s->v = v;
1273 s->t = t;
1274 s->c = c;
1275 s->next = NULL;
1276 /* add in stack */
1277 s->prev = *ps;
1278 *ps = s;
1279 return s;
1282 /* find a symbol and return its associated structure. 's' is the top
1283 of the symbol stack */
1284 Sym *sym_find2(Sym *s, int v)
1286 while (s) {
1287 if (s->v == v)
1288 return s;
1289 s = s->prev;
1291 return NULL;
1294 #define HASH_SYM(v) ((unsigned)(v) % SYM_HASH_SIZE)
1296 /* find a symbol and return its associated structure. 'st' is the
1297 symbol stack */
1298 Sym *sym_find1(SymStack *st, int v)
1300 Sym *s;
1302 s = st->hash[HASH_SYM(v)];
1303 while (s) {
1304 if (s->v == v)
1305 return s;
1306 s = s->hash_next;
1308 return NULL;
1311 Sym *sym_push1(SymStack *st, int v, int t, int c)
1313 Sym *s, **ps;
1314 s = sym_push2(&st->top, v, t, c);
1315 /* add in hash table */
1316 if (v) {
1317 ps = &st->hash[HASH_SYM(v)];
1318 s->hash_next = *ps;
1319 *ps = s;
1321 return s;
1324 /* find a symbol in the right symbol space */
1325 Sym *sym_find(int v)
1327 Sym *s;
1328 s = sym_find1(&local_stack, v);
1329 if (!s)
1330 s = sym_find1(&global_stack, v);
1331 return s;
1334 /* push a given symbol on the symbol stack */
1335 Sym *sym_push(int v, int t, int r, int c)
1337 Sym *s;
1338 if (local_stack.top)
1339 s = sym_push1(&local_stack, v, t, c);
1340 else
1341 s = sym_push1(&global_stack, v, t, c);
1342 s->r = r;
1343 return s;
1346 /* pop symbols until top reaches 'b' */
1347 void sym_pop(SymStack *st, Sym *b)
1349 Sym *s, *ss;
1351 s = st->top;
1352 while(s != b) {
1353 ss = s->prev;
1354 /* free hash table entry, except if symbol was freed (only
1355 used for #undef symbols) */
1356 if (s->v)
1357 st->hash[HASH_SYM(s->v)] = s->hash_next;
1358 tcc_free(s);
1359 s = ss;
1361 st->top = b;
1364 /* undefined a hashed symbol (used for #undef). Its name is set to
1365 zero */
1366 void sym_undef(SymStack *st, Sym *s)
1368 Sym **ss;
1369 ss = &st->hash[HASH_SYM(s->v)];
1370 while (*ss != NULL) {
1371 if (*ss == s)
1372 break;
1373 ss = &(*ss)->hash_next;
1375 *ss = s->hash_next;
1376 s->v = 0;
1379 /* I/O layer */
1381 BufferedFile *tcc_open(const char *filename)
1383 int fd;
1384 BufferedFile *bf;
1386 fd = open(filename, O_RDONLY);
1387 if (fd < 0)
1388 return NULL;
1389 bf = tcc_malloc(sizeof(BufferedFile));
1390 if (!bf) {
1391 close(fd);
1392 return NULL;
1394 bf->fd = fd;
1395 bf->buf_ptr = bf->buffer;
1396 bf->buf_end = bf->buffer;
1397 bf->buffer[0] = CH_EOB; /* put eob symbol */
1398 pstrcpy(bf->filename, sizeof(bf->filename), filename);
1399 bf->line_num = 1;
1400 // printf("opening '%s'\n", filename);
1401 return bf;
1404 void tcc_close(BufferedFile *bf)
1406 total_lines += bf->line_num;
1407 close(bf->fd);
1408 tcc_free(bf);
1411 /* read one char. MUST call tcc_fillbuf if CH_EOB is read */
1412 #define TCC_GETC(bf) (*(bf)->buf_ptr++)
1414 /* fill input buffer and return next char */
1415 int tcc_getc_slow(BufferedFile *bf)
1417 int len;
1418 /* only tries to read if really end of buffer */
1419 if (bf->buf_ptr >= bf->buf_end) {
1420 if (bf->fd != -1) {
1421 len = read(bf->fd, bf->buffer, IO_BUF_SIZE);
1422 if (len < 0)
1423 len = 0;
1424 } else {
1425 len = 0;
1427 total_bytes += len;
1428 bf->buf_ptr = bf->buffer;
1429 bf->buf_end = bf->buffer + len;
1430 *bf->buf_end = CH_EOB;
1432 if (bf->buf_ptr < bf->buf_end) {
1433 return *bf->buf_ptr++;
1434 } else {
1435 bf->buf_ptr = bf->buf_end;
1436 return CH_EOF;
1440 /* no need to put that inline */
1441 void handle_eob(void)
1443 for(;;) {
1444 ch1 = tcc_getc_slow(file);
1445 if (ch1 != CH_EOF)
1446 return;
1448 if (include_stack_ptr == include_stack)
1449 return;
1450 /* add end of include file debug info */
1451 if (do_debug) {
1452 put_stabd(N_EINCL, 0, 0);
1454 /* pop include stack */
1455 tcc_close(file);
1456 include_stack_ptr--;
1457 file = *include_stack_ptr;
1461 /* read next char from current input file */
1462 static inline void inp(void)
1464 ch1 = TCC_GETC(file);
1465 /* end of buffer/file handling */
1466 if (ch1 == CH_EOB)
1467 handle_eob();
1468 if (ch1 == '\n')
1469 file->line_num++;
1470 // printf("ch1=%c 0x%x\n", ch1, ch1);
1473 /* handle '\\n' and '\\r\n' */
1474 static void handle_stray(void)
1476 do {
1477 if (ch1 == '\n') {
1478 inp();
1479 } else if (ch1 == '\r') {
1480 inp();
1481 if (ch1 != '\n')
1482 error("invalid character after '\\'");
1483 inp();
1484 } else {
1485 break;
1487 ch = ch1;
1488 inp();
1489 } while (ch == '\\');
1492 /* input with '\\n' handling. Also supports '\\r\n' for horrible MSDOS
1493 case */
1494 static inline void minp(void)
1496 ch = ch1;
1497 inp();
1498 if (ch == '\\')
1499 handle_stray();
1503 /* same as minp, but also skip comments */
1504 static void cinp(void)
1506 int c;
1508 if (ch1 == '/') {
1509 inp();
1510 if (ch1 == '/') {
1511 /* single line C++ comments */
1512 inp();
1513 while (ch1 != '\n' && ch1 != CH_EOF)
1514 inp();
1515 ch = ' '; /* return space */
1516 } else if (ch1 == '*') {
1517 /* C comments */
1518 inp();
1519 while (ch1 != CH_EOF) {
1520 c = ch1;
1521 inp();
1522 if (c == '*' && ch1 == '/') {
1523 inp();
1524 ch = ' '; /* return space */
1525 break;
1528 } else {
1529 ch = '/';
1531 } else {
1532 minp();
1536 /* space exlcuding newline */
1537 static inline int is_space(int ch)
1539 return ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f' || ch == '\r';
1542 static inline void skip_spaces(void)
1544 while (is_space(ch))
1545 cinp();
1548 /* skip block of text until #else, #elif or #endif. skip also pairs of
1549 #if/#endif */
1550 void preprocess_skip(void)
1552 int a;
1553 a = 0;
1554 while (1) {
1555 while (ch != '\n') {
1556 if (ch == CH_EOF)
1557 expect("#endif");
1558 cinp();
1560 cinp();
1561 skip_spaces();
1562 if (ch == '#') {
1563 cinp();
1564 next_nomacro();
1565 if (a == 0 &&
1566 (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
1567 break;
1568 if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
1569 a++;
1570 else if (tok == TOK_ENDIF)
1571 a--;
1576 /* ParseState handling */
1578 /* XXX: currently, no include file info is stored. Thus, we cannot display
1579 accurate messages if the function or data definition spans multiple
1580 files */
1582 /* save current parse state in 's' */
1583 void save_parse_state(ParseState *s)
1585 s->line_num = file->line_num;
1586 s->macro_ptr = macro_ptr;
1587 s->tok = tok;
1588 s->tokc = tokc;
1591 /* restore parse state from 's' */
1592 void restore_parse_state(ParseState *s)
1594 file->line_num = s->line_num;
1595 macro_ptr = s->macro_ptr;
1596 tok = s->tok;
1597 tokc = s->tokc;
1600 /* return the number of additionnal 'ints' necessary to store the
1601 token */
1602 static inline int tok_ext_size(int t)
1604 switch(t) {
1605 /* 4 bytes */
1606 case TOK_CINT:
1607 case TOK_CUINT:
1608 case TOK_CCHAR:
1609 case TOK_LCHAR:
1610 case TOK_STR:
1611 case TOK_LSTR:
1612 case TOK_CFLOAT:
1613 case TOK_LINENUM:
1614 return 1;
1615 case TOK_CDOUBLE:
1616 case TOK_CLLONG:
1617 case TOK_CULLONG:
1618 return 2;
1619 case TOK_CLDOUBLE:
1620 return LDOUBLE_SIZE / 4;
1621 default:
1622 return 0;
1626 /* token string handling */
1628 static inline void tok_str_new(TokenString *s)
1630 s->str = NULL;
1631 s->len = 0;
1632 s->last_line_num = -1;
1635 static void tok_str_free(int *str)
1637 const int *p;
1638 CString *cstr;
1639 int t;
1641 p = str;
1642 for(;;) {
1643 t = *p++;
1644 if (t == 0)
1645 break;
1646 if (t == TOK_STR || t == TOK_LSTR) {
1647 /* XXX: use a macro to be portable on 64 bit ? */
1648 cstr = (CString *)(*p++);
1649 cstr_free(cstr);
1650 tcc_free(cstr);
1651 } else {
1652 p += tok_ext_size(t);
1655 tcc_free(str);
1658 static void tok_str_add(TokenString *s, int t)
1660 int len, *str;
1662 len = s->len;
1663 str = s->str;
1664 if ((len & 63) == 0) {
1665 str = tcc_realloc(str, (len + 64) * sizeof(int));
1666 if (!str)
1667 return;
1668 s->str = str;
1670 str[len++] = t;
1671 s->len = len;
1674 static void tok_str_add2(TokenString *s, int t, CValue *cv)
1676 int n, i, size;
1677 CString *cstr, *cstr1;
1678 CValue cv1;
1680 tok_str_add(s, t);
1681 if (t == TOK_STR || t == TOK_LSTR) {
1682 /* special case: need to duplicate string */
1683 cstr1 = cv->cstr;
1684 cstr = tcc_malloc(sizeof(CString));
1685 size = cstr1->size;
1686 cstr->size = size;
1687 cstr->size_allocated = size;
1688 cstr->data_allocated = tcc_malloc(size);
1689 cstr->data = cstr->data_allocated;
1690 memcpy(cstr->data_allocated, cstr1->data_allocated, size);
1691 cv1.cstr = cstr;
1692 tok_str_add(s, cv1.tab[0]);
1693 } else {
1694 n = tok_ext_size(t);
1695 for(i=0;i<n;i++)
1696 tok_str_add(s, cv->tab[i]);
1700 /* add the current parse token in token string 's' */
1701 static void tok_str_add_tok(TokenString *s)
1703 CValue cval;
1705 /* save line number info */
1706 if (file->line_num != s->last_line_num) {
1707 s->last_line_num = file->line_num;
1708 cval.i = s->last_line_num;
1709 tok_str_add2(s, TOK_LINENUM, &cval);
1711 tok_str_add2(s, tok, &tokc);
1714 /* get a token from an integer array and increment pointer accordingly */
1715 static int tok_get(int **tok_str, CValue *cv)
1717 int *p, t, n, i;
1719 p = *tok_str;
1720 t = *p++;
1721 n = tok_ext_size(t);
1722 for(i=0;i<n;i++)
1723 cv->tab[i] = *p++;
1724 *tok_str = p;
1725 return t;
1728 /* eval an expression for #if/#elif */
1729 int expr_preprocess(void)
1731 int c, t;
1732 TokenString str;
1734 tok_str_new(&str);
1735 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
1736 next(); /* do macro subst */
1737 if (tok == TOK_DEFINED) {
1738 next_nomacro();
1739 t = tok;
1740 if (t == '(')
1741 next_nomacro();
1742 c = sym_find1(&define_stack, tok) != 0;
1743 if (t == '(')
1744 next_nomacro();
1745 tok = TOK_CINT;
1746 tokc.i = c;
1747 } else if (tok >= TOK_IDENT) {
1748 /* if undefined macro */
1749 tok = TOK_CINT;
1750 tokc.i = 0;
1752 tok_str_add_tok(&str);
1754 tok_str_add(&str, -1); /* simulate end of file */
1755 tok_str_add(&str, 0);
1756 /* now evaluate C constant expression */
1757 macro_ptr = str.str;
1758 next();
1759 c = expr_const();
1760 macro_ptr = NULL;
1761 tok_str_free(str.str);
1762 return c != 0;
1765 #if defined(DEBUG) || defined(PP_DEBUG)
1766 void tok_print(int *str)
1768 int t;
1769 CValue cval;
1771 while (1) {
1772 t = tok_get(&str, &cval);
1773 if (!t)
1774 break;
1775 printf(" %s", get_tok_str(t, &cval));
1777 printf("\n");
1779 #endif
1781 /* parse after #define */
1782 void parse_define(void)
1784 Sym *s, *first, **ps;
1785 int v, t, varg, is_vaargs;
1786 TokenString str;
1788 v = tok;
1789 /* XXX: should check if same macro (ANSI) */
1790 first = NULL;
1791 t = MACRO_OBJ;
1792 /* '(' must be just after macro definition for MACRO_FUNC */
1793 if (ch == '(') {
1794 next_nomacro();
1795 next_nomacro();
1796 ps = &first;
1797 while (tok != ')') {
1798 varg = tok;
1799 next_nomacro();
1800 is_vaargs = 0;
1801 if (varg == TOK_DOTS) {
1802 varg = TOK___VA_ARGS__;
1803 is_vaargs = 1;
1804 } else if (tok == TOK_DOTS && gnu_ext) {
1805 is_vaargs = 1;
1806 next_nomacro();
1808 if (varg < TOK_IDENT)
1809 error("badly punctuated parameter list");
1810 s = sym_push1(&define_stack, varg | SYM_FIELD, is_vaargs, 0);
1811 *ps = s;
1812 ps = &s->next;
1813 if (tok != ',')
1814 break;
1815 next_nomacro();
1817 t = MACRO_FUNC;
1819 tok_str_new(&str);
1820 while (1) {
1821 skip_spaces();
1822 if (ch == '\n' || ch == CH_EOF)
1823 break;
1824 next_nomacro();
1825 tok_str_add2(&str, tok, &tokc);
1827 tok_str_add(&str, 0);
1828 #ifdef PP_DEBUG
1829 printf("define %s %d: ", get_tok_str(v, NULL), t);
1830 tok_print(str.str);
1831 #endif
1832 s = sym_push1(&define_stack, v, t, (int)str.str);
1833 s->next = first;
1836 void preprocess(void)
1838 int size, i, c, n;
1839 char buf[1024], *q, *p;
1840 char buf1[1024];
1841 BufferedFile *f;
1842 Sym *s;
1844 return_linefeed = 1; /* linefeed will be returned as a token */
1845 cinp();
1846 next_nomacro();
1847 redo:
1848 if (tok == TOK_DEFINE) {
1849 next_nomacro();
1850 parse_define();
1851 } else if (tok == TOK_UNDEF) {
1852 next_nomacro();
1853 s = sym_find1(&define_stack, tok);
1854 /* undefine symbol by putting an invalid name */
1855 if (s)
1856 sym_undef(&define_stack, s);
1857 } else if (tok == TOK_INCLUDE) {
1858 skip_spaces();
1859 if (ch == '<') {
1860 c = '>';
1861 goto read_name;
1862 } else if (ch == '\"') {
1863 c = ch;
1864 read_name:
1865 minp();
1866 q = buf;
1867 while (ch != c && ch != '\n' && ch != CH_EOF) {
1868 if ((q - buf) < sizeof(buf) - 1)
1869 *q++ = ch;
1870 minp();
1872 *q = '\0';
1873 /* eat all spaces and comments after include */
1874 /* XXX: slightly incorrect */
1875 while (ch1 != '\n' && ch1 != CH_EOF)
1876 inp();
1877 } else {
1878 /* computed #include : either we have only strings or
1879 we have anything enclosed in '<>' */
1880 next();
1881 buf[0] = '\0';
1882 if (tok == TOK_STR) {
1883 while (tok != TOK_LINEFEED) {
1884 if (tok != TOK_STR) {
1885 include_syntax:
1886 error("'#include' expects \"FILENAME\" or <FILENAME>");
1888 pstrcat(buf, sizeof(buf), (char *)tokc.cstr->data);
1889 next();
1891 c = '\"';
1892 } else {
1893 int len;
1894 while (tok != TOK_LINEFEED) {
1895 pstrcat(buf, sizeof(buf), get_tok_str(tok, &tokc));
1896 next();
1898 len = strlen(buf);
1899 /* check syntax and remove '<>' */
1900 if (len < 2 || buf[0] != '<' || buf[len - 1] != '>')
1901 goto include_syntax;
1902 memmove(buf, buf + 1, len - 2);
1903 buf[len - 2] = '\0';
1904 c = '>';
1908 if (include_stack_ptr >= include_stack + INCLUDE_STACK_SIZE)
1909 error("#include recursion too deep");
1910 if (c == '\"') {
1911 /* first search in current dir if "header.h" */
1912 size = 0;
1913 p = strrchr(file->filename, '/');
1914 if (p)
1915 size = p + 1 - file->filename;
1916 if (size > sizeof(buf1) - 1)
1917 size = sizeof(buf1) - 1;
1918 memcpy(buf1, file->filename, size);
1919 buf1[size] = '\0';
1920 pstrcat(buf1, sizeof(buf1), buf);
1921 f = tcc_open(buf1);
1922 if (f)
1923 goto found;
1925 /* now search in all the include paths */
1926 n = nb_include_paths + nb_sysinclude_paths;
1927 for(i = 0; i < n; i++) {
1928 const char *path;
1929 if (i < nb_include_paths)
1930 path = include_paths[i];
1931 else
1932 path = sysinclude_paths[i - nb_include_paths];
1933 pstrcpy(buf1, sizeof(buf1), path);
1934 pstrcat(buf1, sizeof(buf1), "/");
1935 pstrcat(buf1, sizeof(buf1), buf);
1936 f = tcc_open(buf1);
1937 if (f)
1938 goto found;
1940 error("include file '%s' not found", buf);
1941 f = NULL;
1942 found:
1943 /* push current file in stack */
1944 /* XXX: fix current line init */
1945 *include_stack_ptr++ = file;
1946 file = f;
1947 /* add include file debug info */
1948 if (do_debug) {
1949 put_stabs(file->filename, N_BINCL, 0, 0, 0);
1951 ch = '\n';
1952 goto the_end;
1953 } else if (tok == TOK_IFNDEF) {
1954 c = 1;
1955 goto do_ifdef;
1956 } else if (tok == TOK_IF) {
1957 c = expr_preprocess();
1958 goto do_if;
1959 } else if (tok == TOK_IFDEF) {
1960 c = 0;
1961 do_ifdef:
1962 next_nomacro();
1963 c = (sym_find1(&define_stack, tok) != 0) ^ c;
1964 do_if:
1965 if (ifdef_stack_ptr >= ifdef_stack + IFDEF_STACK_SIZE)
1966 error("memory full");
1967 *ifdef_stack_ptr++ = c;
1968 goto test_skip;
1969 } else if (tok == TOK_ELSE) {
1970 if (ifdef_stack_ptr == ifdef_stack)
1971 error("#else without matching #if");
1972 if (ifdef_stack_ptr[-1] & 2)
1973 error("#else after #else");
1974 c = (ifdef_stack_ptr[-1] ^= 3);
1975 goto test_skip;
1976 } else if (tok == TOK_ELIF) {
1977 if (ifdef_stack_ptr == ifdef_stack)
1978 error("#elif without matching #if");
1979 c = ifdef_stack_ptr[-1];
1980 if (c > 1)
1981 error("#elif after #else");
1982 /* last #if/#elif expression was true: we skip */
1983 if (c == 1)
1984 goto skip;
1985 c = expr_preprocess();
1986 ifdef_stack_ptr[-1] = c;
1987 test_skip:
1988 if (!(c & 1)) {
1989 skip:
1990 preprocess_skip();
1991 goto redo;
1993 } else if (tok == TOK_ENDIF) {
1994 if (ifdef_stack_ptr == ifdef_stack)
1995 error("#endif without matching #if");
1996 ifdef_stack_ptr--;
1997 } else if (tok == TOK_LINE) {
1998 int line_num;
1999 next();
2000 if (tok != TOK_CINT)
2001 error("#line");
2002 line_num = tokc.i;
2003 next();
2004 if (tok != TOK_LINEFEED) {
2005 if (tok != TOK_STR)
2006 error("#line");
2007 pstrcpy(file->filename, sizeof(file->filename),
2008 (char *)tokc.cstr->data);
2010 /* NOTE: we do it there to avoid problems with linefeed */
2011 file->line_num = line_num;
2012 } else if (tok == TOK_ERROR) {
2013 error("#error");
2015 /* ignore other preprocess commands or #! for C scripts */
2016 while (tok != TOK_LINEFEED && tok != TOK_EOF)
2017 next_nomacro();
2018 the_end:
2019 return_linefeed = 0;
2022 /* read a number in base b */
2023 static int getn(int b)
2025 int n, t;
2026 n = 0;
2027 while (1) {
2028 if (ch >= 'a' && ch <= 'f')
2029 t = ch - 'a' + 10;
2030 else if (ch >= 'A' && ch <= 'F')
2031 t = ch - 'A' + 10;
2032 else if (isnum(ch))
2033 t = ch - '0';
2034 else
2035 break;
2036 if (t < 0 || t >= b)
2037 break;
2038 n = n * b + t;
2039 cinp();
2041 return n;
2044 /* read a character for string or char constant and eval escape codes */
2045 static int getq(void)
2047 int c;
2049 c = ch;
2050 minp();
2051 if (c == '\\') {
2052 if (isoct(ch)) {
2053 /* at most three octal digits */
2054 c = ch - '0';
2055 minp();
2056 if (isoct(ch)) {
2057 c = c * 8 + ch - '0';
2058 minp();
2059 if (isoct(ch)) {
2060 c = c * 8 + ch - '0';
2061 minp();
2064 return c;
2065 } else if (ch == 'x') {
2066 minp();
2067 return getn(16);
2068 } else {
2069 if (ch == 'a')
2070 c = '\a';
2071 else if (ch == 'b')
2072 c = '\b';
2073 else if (ch == 'f')
2074 c = '\f';
2075 else if (ch == 'n')
2076 c = '\n';
2077 else if (ch == 'r')
2078 c = '\r';
2079 else if (ch == 't')
2080 c = '\t';
2081 else if (ch == 'v')
2082 c = '\v';
2083 else if (ch == 'e' && gnu_ext)
2084 c = 27;
2085 else if (ch == '\'' || ch == '\"' || ch == '\\' || ch == '?')
2086 c = ch;
2087 else
2088 error("invalid escaped char");
2089 minp();
2091 } else if (c == '\r' && ch == '\n') {
2092 minp();
2093 c = '\n';
2095 return c;
2098 /* we use 64 bit numbers */
2099 #define BN_SIZE 2
2101 /* bn = (bn << shift) | or_val */
2102 void bn_lshift(unsigned int *bn, int shift, int or_val)
2104 int i;
2105 unsigned int v;
2106 for(i=0;i<BN_SIZE;i++) {
2107 v = bn[i];
2108 bn[i] = (v << shift) | or_val;
2109 or_val = v >> (32 - shift);
2113 void bn_zero(unsigned int *bn)
2115 int i;
2116 for(i=0;i<BN_SIZE;i++) {
2117 bn[i] = 0;
2121 void parse_number(void)
2123 int b, t, shift, frac_bits, s, exp_val;
2124 char *q;
2125 unsigned int bn[BN_SIZE];
2126 double d;
2128 /* number */
2129 q = token_buf;
2130 t = ch;
2131 cinp();
2132 *q++ = t;
2133 b = 10;
2134 if (t == '.') {
2135 /* special dot handling */
2136 if (ch >= '0' && ch <= '9') {
2137 goto float_frac_parse;
2138 } else if (ch == '.') {
2139 cinp();
2140 if (ch != '.')
2141 expect("'.'");
2142 cinp();
2143 tok = TOK_DOTS;
2144 } else {
2145 /* dots */
2146 tok = t;
2148 return;
2149 } else if (t == '0') {
2150 if (ch == 'x' || ch == 'X') {
2151 q--;
2152 cinp();
2153 b = 16;
2154 } else if (tcc_ext && (ch == 'b' || ch == 'B')) {
2155 q--;
2156 cinp();
2157 b = 2;
2160 /* parse all digits. cannot check octal numbers at this stage
2161 because of floating point constants */
2162 while (1) {
2163 if (ch >= 'a' && ch <= 'f')
2164 t = ch - 'a' + 10;
2165 else if (ch >= 'A' && ch <= 'F')
2166 t = ch - 'A' + 10;
2167 else if (isnum(ch))
2168 t = ch - '0';
2169 else
2170 break;
2171 if (t >= b)
2172 break;
2173 if (q >= token_buf + STRING_MAX_SIZE) {
2174 num_too_long:
2175 error("number too long");
2177 *q++ = ch;
2178 cinp();
2180 if (ch == '.' ||
2181 ((ch == 'e' || ch == 'E') && b == 10) ||
2182 ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
2183 if (b != 10) {
2184 /* NOTE: strtox should support that for hexa numbers, but
2185 non ISOC99 libcs do not support it, so we prefer to do
2186 it by hand */
2187 /* hexadecimal or binary floats */
2188 /* XXX: handle overflows */
2189 *q = '\0';
2190 if (b == 16)
2191 shift = 4;
2192 else
2193 shift = 2;
2194 bn_zero(bn);
2195 q = token_buf;
2196 while (1) {
2197 t = *q++;
2198 if (t == '\0') {
2199 break;
2200 } else if (t >= 'a') {
2201 t = t - 'a' + 10;
2202 } else if (t >= 'A') {
2203 t = t - 'A' + 10;
2204 } else {
2205 t = t - '0';
2207 bn_lshift(bn, shift, t);
2209 frac_bits = 0;
2210 if (ch == '.') {
2211 cinp();
2212 while (1) {
2213 t = ch;
2214 if (t >= 'a' && t <= 'f') {
2215 t = t - 'a' + 10;
2216 } else if (t >= 'A' && t <= 'F') {
2217 t = t - 'A' + 10;
2218 } else if (t >= '0' && t <= '9') {
2219 t = t - '0';
2220 } else {
2221 break;
2223 if (t >= b)
2224 error("invalid digit");
2225 bn_lshift(bn, shift, t);
2226 frac_bits += shift;
2227 cinp();
2230 if (ch != 'p' && ch != 'P')
2231 error("exponent expected");
2232 cinp();
2233 s = 1;
2234 exp_val = 0;
2235 if (ch == '+') {
2236 cinp();
2237 } else if (ch == '-') {
2238 s = -1;
2239 cinp();
2241 if (ch < '0' || ch > '9')
2242 error("exponent digits expected");
2243 while (ch >= '0' && ch <= '9') {
2244 exp_val = exp_val * 10 + ch - '0';
2245 cinp();
2247 exp_val = exp_val * s;
2249 /* now we can generate the number */
2250 /* XXX: should patch directly float number */
2251 d = (double)bn[1] * 4294967296.0 + (double)bn[0];
2252 d = ldexp(d, exp_val - frac_bits);
2253 t = toup(ch);
2254 if (t == 'F') {
2255 cinp();
2256 tok = TOK_CFLOAT;
2257 /* float : should handle overflow */
2258 tokc.f = (float)d;
2259 } else if (t == 'L') {
2260 cinp();
2261 tok = TOK_CLDOUBLE;
2262 /* XXX: not large enough */
2263 tokc.ld = (long double)d;
2264 } else {
2265 tok = TOK_CDOUBLE;
2266 tokc.d = d;
2268 } else {
2269 /* decimal floats */
2270 if (ch == '.') {
2271 if (q >= token_buf + STRING_MAX_SIZE)
2272 goto num_too_long;
2273 *q++ = ch;
2274 cinp();
2275 float_frac_parse:
2276 while (ch >= '0' && ch <= '9') {
2277 if (q >= token_buf + STRING_MAX_SIZE)
2278 goto num_too_long;
2279 *q++ = ch;
2280 cinp();
2283 if (ch == 'e' || ch == 'E') {
2284 if (q >= token_buf + STRING_MAX_SIZE)
2285 goto num_too_long;
2286 *q++ = ch;
2287 cinp();
2288 if (ch == '-' || ch == '+') {
2289 if (q >= token_buf + STRING_MAX_SIZE)
2290 goto num_too_long;
2291 *q++ = ch;
2292 cinp();
2294 if (ch < '0' || ch > '9')
2295 error("exponent digits expected");
2296 while (ch >= '0' && ch <= '9') {
2297 if (q >= token_buf + STRING_MAX_SIZE)
2298 goto num_too_long;
2299 *q++ = ch;
2300 cinp();
2303 *q = '\0';
2304 t = toup(ch);
2305 errno = 0;
2306 if (t == 'F') {
2307 cinp();
2308 tok = TOK_CFLOAT;
2309 tokc.f = strtof(token_buf, NULL);
2310 } else if (t == 'L') {
2311 cinp();
2312 tok = TOK_CLDOUBLE;
2313 tokc.ld = strtold(token_buf, NULL);
2314 } else {
2315 tok = TOK_CDOUBLE;
2316 tokc.d = strtod(token_buf, NULL);
2319 } else {
2320 unsigned long long n, n1;
2321 int lcount;
2323 /* integer number */
2324 *q = '\0';
2325 q = token_buf;
2326 if (b == 10 && *q == '0') {
2327 b = 8;
2328 q++;
2330 n = 0;
2331 while(1) {
2332 t = *q++;
2333 /* no need for checks except for base 10 / 8 errors */
2334 if (t == '\0') {
2335 break;
2336 } else if (t >= 'a') {
2337 t = t - 'a' + 10;
2338 } else if (t >= 'A') {
2339 t = t - 'A' + 10;
2340 } else {
2341 t = t - '0';
2342 if (t >= b)
2343 error("invalid digit");
2345 n1 = n;
2346 n = n * b + t;
2347 /* detect overflow */
2348 if (n < n1)
2349 error("integer constant overflow");
2352 /* XXX: not exactly ANSI compliant */
2353 if ((n & 0xffffffff00000000LL) != 0) {
2354 if ((n >> 63) != 0)
2355 tok = TOK_CULLONG;
2356 else
2357 tok = TOK_CLLONG;
2358 } else if (n > 0x7fffffff) {
2359 tok = TOK_CUINT;
2360 } else {
2361 tok = TOK_CINT;
2363 lcount = 0;
2364 for(;;) {
2365 t = toup(ch);
2366 if (t == 'L') {
2367 if (lcount >= 2)
2368 error("three 'l' in integer constant");
2369 lcount++;
2370 if (lcount == 2) {
2371 if (tok == TOK_CINT)
2372 tok = TOK_CLLONG;
2373 else if (tok == TOK_CUINT)
2374 tok = TOK_CULLONG;
2376 cinp();
2377 } else if (t == 'U') {
2378 if (tok == TOK_CINT)
2379 tok = TOK_CUINT;
2380 else if (tok == TOK_CLLONG)
2381 tok = TOK_CULLONG;
2382 cinp();
2383 } else {
2384 break;
2387 if (tok == TOK_CINT || tok == TOK_CUINT)
2388 tokc.ui = n;
2389 else
2390 tokc.ull = n;
2395 /* return next token without macro substitution */
2396 void next_nomacro1(void)
2398 int b;
2399 char *q;
2400 TokenSym *ts;
2402 /* skip spaces */
2403 while(1) {
2404 while (ch == '\n') {
2405 /* during preprocessor parsing, '\n' is a token */
2406 if (return_linefeed) {
2407 tok = TOK_LINEFEED;
2408 return;
2410 cinp();
2411 skip_spaces();
2412 if (ch == '#') {
2413 /* preprocessor command if # at start of line after
2414 spaces */
2415 preprocess();
2418 if (!is_space(ch))
2419 break;
2420 cinp();
2422 if (isid(ch)) {
2423 q = token_buf;
2424 *q++ = ch;
2425 cinp();
2426 if (q[-1] == 'L') {
2427 if (ch == '\'') {
2428 tok = TOK_LCHAR;
2429 goto char_const;
2431 if (ch == '\"') {
2432 tok = TOK_LSTR;
2433 goto str_const;
2436 while (isid(ch) || isnum(ch)) {
2437 if (q >= token_buf + STRING_MAX_SIZE)
2438 error("ident too long");
2439 *q++ = ch;
2440 cinp();
2442 *q = '\0';
2443 ts = tok_alloc(token_buf, q - token_buf);
2444 tok = ts->tok;
2445 } else if (isnum(ch) || ch == '.') {
2446 parse_number();
2447 } else if (ch == '\'') {
2448 tok = TOK_CCHAR;
2449 char_const:
2450 minp();
2451 b = getq();
2452 /* this cast is needed if >= 128 */
2453 if (tok == TOK_CCHAR)
2454 b = (char)b;
2455 tokc.i = b;
2456 if (ch != '\'')
2457 expect("\'");
2458 minp();
2459 } else if (ch == '\"') {
2460 tok = TOK_STR;
2461 str_const:
2462 minp();
2463 cstr_reset(&tokcstr);
2464 while (ch != '\"') {
2465 b = getq();
2466 if (ch == CH_EOF)
2467 error("unterminated string");
2468 if (tok == TOK_STR)
2469 cstr_ccat(&tokcstr, b);
2470 else
2471 cstr_wccat(&tokcstr, b);
2473 if (tok == TOK_STR)
2474 cstr_ccat(&tokcstr, '\0');
2475 else
2476 cstr_wccat(&tokcstr, '\0');
2477 tokc.cstr = &tokcstr;
2478 minp();
2479 } else {
2480 q = tok_two_chars;
2481 /* two chars */
2482 tok = ch;
2483 cinp();
2484 while (*q) {
2485 if (*q == tok && q[1] == ch) {
2486 cinp();
2487 tok = q[2] & 0xff;
2488 /* three chars tests */
2489 if (tok == TOK_SHL || tok == TOK_SAR) {
2490 if (ch == '=') {
2491 tok = tok | 0x80;
2492 cinp();
2494 } else if (tok == TOK_DOTS) {
2495 if (ch != '.')
2496 error("parse error");
2497 cinp();
2499 return;
2501 q = q + 3;
2503 /* single char substitutions */
2504 if (tok == '<')
2505 tok = TOK_LT;
2506 else if (tok == '>')
2507 tok = TOK_GT;
2511 /* return next token without macro substitution. Can read input from
2512 macro_ptr buffer */
2513 void next_nomacro()
2515 if (macro_ptr) {
2516 redo:
2517 tok = *macro_ptr;
2518 if (tok) {
2519 tok = tok_get(&macro_ptr, &tokc);
2520 if (tok == TOK_LINENUM) {
2521 file->line_num = tokc.i;
2522 goto redo;
2525 } else {
2526 next_nomacro1();
2530 /* substitute args in macro_str and return allocated string */
2531 int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
2533 int *st, last_tok, t, notfirst;
2534 Sym *s;
2535 CValue cval;
2536 TokenString str;
2537 CString cstr;
2539 tok_str_new(&str);
2540 last_tok = 0;
2541 while(1) {
2542 t = tok_get(&macro_str, &cval);
2543 if (!t)
2544 break;
2545 if (t == '#') {
2546 /* stringize */
2547 t = tok_get(&macro_str, &cval);
2548 if (!t)
2549 break;
2550 s = sym_find2(args, t);
2551 if (s) {
2552 cstr_new(&cstr);
2553 st = (int *)s->c;
2554 notfirst = 0;
2555 while (*st) {
2556 if (notfirst)
2557 cstr_ccat(&cstr, ' ');
2558 t = tok_get(&st, &cval);
2559 cstr_cat(&cstr, get_tok_str(t, &cval));
2560 notfirst = 1;
2562 cstr_ccat(&cstr, '\0');
2563 #ifdef PP_DEBUG
2564 printf("stringize: %s\n", (char *)cstr.data);
2565 #endif
2566 /* add string */
2567 cval.cstr = &cstr;
2568 tok_str_add2(&str, TOK_STR, &cval);
2569 cstr_free(&cstr);
2570 } else {
2571 tok_str_add2(&str, t, &cval);
2573 } else if (t >= TOK_IDENT) {
2574 s = sym_find2(args, t);
2575 if (s) {
2576 st = (int *)s->c;
2577 /* if '##' is present before or after, no arg substitution */
2578 if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) {
2579 /* special case for var arg macros : ## eats the
2580 ',' if empty VA_ARGS riable. */
2581 /* XXX: test of the ',' is not 100%
2582 reliable. should fix it to avoid security
2583 problems */
2584 if (gnu_ext && s->t && *st == 0 &&
2585 last_tok == TOK_TWOSHARPS &&
2586 str.len >= 2 && str.str[str.len - 2] == ',') {
2587 /* suppress ',' '##' */
2588 str.len -= 2;
2589 } else {
2590 int t1;
2591 for(;;) {
2592 t1 = tok_get(&st, &cval);
2593 if (!t1)
2594 break;
2595 tok_str_add2(&str, t1, &cval);
2598 } else {
2599 macro_subst(&str, nested_list, st);
2601 } else {
2602 tok_str_add(&str, t);
2604 } else {
2605 tok_str_add2(&str, t, &cval);
2607 last_tok = t;
2609 tok_str_add(&str, 0);
2610 return str.str;
2613 /* handle the '##' operator */
2614 int *macro_twosharps(int *macro_str)
2616 TokenSym *ts;
2617 int *macro_ptr1;
2618 int t;
2619 char *p;
2620 CValue cval;
2621 TokenString macro_str1;
2623 tok_str_new(&macro_str1);
2624 tok = 0;
2625 while (1) {
2626 next_nomacro();
2627 if (tok == 0)
2628 break;
2629 while (*macro_ptr == TOK_TWOSHARPS) {
2630 macro_ptr++;
2631 macro_ptr1 = macro_ptr;
2632 t = *macro_ptr;
2633 if (t) {
2634 t = tok_get(&macro_ptr, &cval);
2635 /* XXX: we handle only most common cases:
2636 ident + ident or ident + number */
2637 if (tok >= TOK_IDENT &&
2638 (t >= TOK_IDENT || t == TOK_CINT)) {
2639 p = get_tok_str(tok, &tokc);
2640 pstrcpy(token_buf, sizeof(token_buf), p);
2641 p = get_tok_str(t, &cval);
2642 pstrcat(token_buf, sizeof(token_buf), p);
2643 ts = tok_alloc(token_buf, 0);
2644 tok = ts->tok; /* modify current token */
2645 } else {
2646 /* cannot merge tokens: skip '##' */
2647 macro_ptr = macro_ptr1;
2648 break;
2652 tok_str_add2(&macro_str1, tok, &tokc);
2654 tok_str_add(&macro_str1, 0);
2655 return macro_str1.str;
2658 /* do macro substitution of macro_str and add result to
2659 (tok_str,tok_len). If macro_str is NULL, then input stream token is
2660 substituted. 'nested_list' is the list of all macros we got inside
2661 to avoid recursing. */
2662 void macro_subst(TokenString *tok_str,
2663 Sym **nested_list, int *macro_str)
2665 Sym *s, *args, *sa, *sa1;
2666 int parlevel, *mstr, t, *saved_macro_ptr;
2667 int mstr_allocated, *macro_str1;
2668 CString cstr;
2669 CValue cval;
2670 TokenString str;
2671 char *cstrval;
2673 saved_macro_ptr = macro_ptr;
2674 macro_ptr = macro_str;
2675 macro_str1 = NULL;
2676 if (macro_str) {
2677 /* first scan for '##' operator handling */
2678 macro_str1 = macro_twosharps(macro_str);
2679 macro_ptr = macro_str1;
2682 while (1) {
2683 next_nomacro();
2684 if (tok == 0)
2685 break;
2686 if ((s = sym_find1(&define_stack, tok)) != NULL) {
2687 /* if symbol is a macro, prepare substitution */
2688 /* if nested substitution, do nothing */
2689 if (sym_find2(*nested_list, tok))
2690 goto no_subst;
2692 /* special macros */
2693 if (tok == TOK___LINE__) {
2694 cval.i = file->line_num;
2695 tok_str_add2(tok_str, TOK_CINT, &cval);
2696 } else if (tok == TOK___FILE__) {
2697 cstrval = file->filename;
2698 goto add_cstr;
2699 tok_str_add2(tok_str, TOK_STR, &cval);
2700 } else if (tok == TOK___DATE__) {
2701 cstrval = "Jan 1 2002";
2702 goto add_cstr;
2703 } else if (tok == TOK___TIME__) {
2704 cstrval = "00:00:00";
2705 add_cstr:
2706 cstr_new(&cstr);
2707 cstr_cat(&cstr, cstrval);
2708 cstr_ccat(&cstr, '\0');
2709 cval.cstr = &cstr;
2710 tok_str_add2(tok_str, TOK_STR, &cval);
2711 cstr_free(&cstr);
2712 } else {
2713 mstr = (int *)s->c;
2714 mstr_allocated = 0;
2715 if (s->t == MACRO_FUNC) {
2716 /* NOTE: we do not use next_nomacro to avoid eating the
2717 next token. XXX: find better solution */
2718 if (macro_ptr) {
2719 t = *macro_ptr;
2720 } else {
2721 while (is_space(ch) || ch == '\n')
2722 cinp();
2723 t = ch;
2725 if (t != '(') /* no macro subst */
2726 goto no_subst;
2728 /* argument macro */
2729 next_nomacro();
2730 next_nomacro();
2731 args = NULL;
2732 sa = s->next;
2733 /* NOTE: empty args are allowed, except if no args */
2734 for(;;) {
2735 /* handle '()' case */
2736 if (!args && tok == ')')
2737 break;
2738 if (!sa)
2739 error("macro '%s' used with too many args",
2740 get_tok_str(s->v, 0));
2741 tok_str_new(&str);
2742 parlevel = 0;
2743 /* NOTE: non zero sa->t indicates VA_ARGS */
2744 while ((parlevel > 0 ||
2745 (tok != ')' &&
2746 (tok != ',' || sa->t))) &&
2747 tok != -1) {
2748 if (tok == '(')
2749 parlevel++;
2750 else if (tok == ')')
2751 parlevel--;
2752 tok_str_add2(&str, tok, &tokc);
2753 next_nomacro();
2755 tok_str_add(&str, 0);
2756 sym_push2(&args, sa->v & ~SYM_FIELD, sa->t, (int)str.str);
2757 sa = sa->next;
2758 if (tok == ')') {
2759 /* special case for gcc var args: add an empty
2760 var arg argument if it is omitted */
2761 if (sa && sa->t && gnu_ext)
2762 continue;
2763 else
2764 break;
2766 if (tok != ',')
2767 expect(",");
2768 next_nomacro();
2770 if (sa) {
2771 error("macro '%s' used with too few args",
2772 get_tok_str(s->v, 0));
2775 /* now subst each arg */
2776 mstr = macro_arg_subst(nested_list, mstr, args);
2777 /* free memory */
2778 sa = args;
2779 while (sa) {
2780 sa1 = sa->prev;
2781 tok_str_free((int *)sa->c);
2782 tcc_free(sa);
2783 sa = sa1;
2785 mstr_allocated = 1;
2787 sym_push2(nested_list, s->v, 0, 0);
2788 macro_subst(tok_str, nested_list, mstr);
2789 /* pop nested defined symbol */
2790 sa1 = *nested_list;
2791 *nested_list = sa1->prev;
2792 tcc_free(sa1);
2793 if (mstr_allocated)
2794 tok_str_free(mstr);
2796 } else {
2797 no_subst:
2798 /* no need to add if reading input stream */
2799 if (!macro_str)
2800 return;
2801 tok_str_add2(tok_str, tok, &tokc);
2803 /* only replace one macro while parsing input stream */
2804 if (!macro_str)
2805 return;
2807 macro_ptr = saved_macro_ptr;
2808 if (macro_str1)
2809 tok_str_free(macro_str1);
2812 /* return next token with macro substitution */
2813 void next(void)
2815 Sym *nested_list;
2816 TokenString str;
2818 /* special 'ungettok' case for label parsing */
2819 if (tok1) {
2820 tok = tok1;
2821 tokc = tok1c;
2822 tok1 = 0;
2823 } else {
2824 redo:
2825 if (!macro_ptr) {
2826 /* if not reading from macro substituted string, then try
2827 to substitute */
2828 /* XXX: optimize non macro case */
2829 tok_str_new(&str);
2830 nested_list = NULL;
2831 macro_subst(&str, &nested_list, NULL);
2832 if (str.str) {
2833 tok_str_add(&str, 0);
2834 macro_ptr = str.str;
2835 macro_ptr_allocated = str.str;
2836 goto redo;
2838 if (tok == 0)
2839 goto redo;
2840 } else {
2841 next_nomacro();
2842 if (tok == 0) {
2843 /* end of macro string: free it */
2844 tok_str_free(macro_ptr_allocated);
2845 macro_ptr = NULL;
2846 goto redo;
2850 #if defined(DEBUG)
2851 printf("token = %s\n", get_tok_str(tok, &tokc));
2852 #endif
2855 void swap(int *p, int *q)
2857 int t;
2858 t = *p;
2859 *p = *q;
2860 *q = t;
2863 void vsetc(int t, int r, CValue *vc)
2865 int v;
2867 if (vtop >= vstack + VSTACK_SIZE)
2868 error("memory full");
2869 /* cannot let cpu flags if other instruction are generated. Also
2870 avoid leaving VT_JMP anywhere except on the top of the stack
2871 because it would complicate the code generator. */
2872 if (vtop >= vstack) {
2873 v = vtop->r & VT_VALMASK;
2874 if (v == VT_CMP || (v & ~1) == VT_JMP)
2875 gv(RC_INT);
2877 vtop++;
2878 vtop->t = t;
2879 vtop->r = r;
2880 vtop->r2 = VT_CONST;
2881 vtop->c = *vc;
2884 /* push integer constant */
2885 void vpushi(int v)
2887 CValue cval;
2888 cval.i = v;
2889 vsetc(VT_INT, VT_CONST, &cval);
2892 /* Return a static symbol pointing to a section */
2893 static Sym *get_sym_ref(int t, Section *sec,
2894 unsigned long offset, unsigned long size)
2896 int v;
2897 Sym *sym;
2899 v = anon_sym++;
2900 sym = sym_push1(&global_stack, v, t | VT_STATIC, 0);
2901 sym->r = VT_CONST | VT_SYM;
2902 put_extern_sym(sym, sec, offset, size);
2903 return sym;
2906 /* push a reference to a section offset by adding a dummy symbol */
2907 static void vpush_ref(int t, Section *sec, unsigned long offset, unsigned long size)
2909 CValue cval;
2911 cval.ul = 0;
2912 vsetc(t, VT_CONST | VT_SYM, &cval);
2913 vtop->sym = get_sym_ref(t, sec, offset, size);
2916 /* define a new external reference to a symbol 'v' of type 'u' */
2917 static Sym *external_global_sym(int v, int u, int r)
2919 Sym *s;
2921 s = sym_find(v);
2922 if (!s) {
2923 /* push forward reference */
2924 s = sym_push1(&global_stack,
2925 v, u | VT_EXTERN, 0);
2926 s->r = r | VT_CONST | VT_SYM;
2928 return s;
2931 /* define a new external reference to a symbol 'v' of type 'u' */
2932 static Sym *external_sym(int v, int u, int r)
2934 Sym *s;
2936 s = sym_find(v);
2937 if (!s) {
2938 /* push forward reference */
2939 s = sym_push(v, u | VT_EXTERN, r | VT_CONST | VT_SYM, 0);
2941 return s;
2944 /* push a reference to global symbol v */
2945 static void vpush_global_sym(int t, int v)
2947 Sym *sym;
2948 CValue cval;
2950 sym = external_global_sym(v, t, 0);
2951 cval.ul = 0;
2952 vsetc(t, VT_CONST | VT_SYM, &cval);
2953 vtop->sym = sym;
2956 void vset(int t, int r, int v)
2958 CValue cval;
2960 cval.i = v;
2961 vsetc(t, r, &cval);
2964 void vswap(void)
2966 SValue tmp;
2968 tmp = vtop[0];
2969 vtop[0] = vtop[-1];
2970 vtop[-1] = tmp;
2973 void vpushv(SValue *v)
2975 if (vtop >= vstack + VSTACK_SIZE)
2976 error("memory full");
2977 vtop++;
2978 *vtop = *v;
2981 void vdup(void)
2983 vpushv(vtop);
2986 /* save r to the memory stack, and mark it as being free */
2987 void save_reg(int r)
2989 int l, saved, t, size, align;
2990 SValue *p, sv;
2992 /* modify all stack values */
2993 saved = 0;
2994 l = 0;
2995 for(p=vstack;p<=vtop;p++) {
2996 if ((p->r & VT_VALMASK) == r ||
2997 (p->r2 & VT_VALMASK) == r) {
2998 /* must save value on stack if not already done */
2999 if (!saved) {
3000 /* store register in the stack */
3001 t = p->t;
3002 if ((p->r & VT_LVAL) ||
3003 (!is_float(t) && (t & VT_BTYPE) != VT_LLONG))
3004 t = VT_INT;
3005 size = type_size(t, &align);
3006 loc = (loc - size) & -align;
3007 sv.t = t;
3008 sv.r = VT_LOCAL | VT_LVAL;
3009 sv.c.ul = loc;
3010 store(r, &sv);
3011 #ifdef TCC_TARGET_I386
3012 /* x86 specific: need to pop fp register ST0 if saved */
3013 if (r == REG_ST0) {
3014 o(0xd9dd); /* fstp %st(1) */
3016 #endif
3017 /* special long long case */
3018 if ((t & VT_BTYPE) == VT_LLONG) {
3019 sv.c.ul += 4;
3020 store(p->r2, &sv);
3022 l = loc;
3023 saved = 1;
3025 /* mark that stack entry as being saved on the stack */
3026 if (p->r & VT_LVAL) {
3027 /* also suppress the bounded flag because the
3028 relocation address of the function was stored in
3029 p->c.ul */
3030 p->r = (p->r & ~(VT_VALMASK | VT_BOUNDED)) | VT_LLOCAL;
3031 } else {
3032 p->r = lvalue_type(p->t) | VT_LOCAL;
3034 p->r2 = VT_CONST;
3035 p->c.ul = l;
3040 /* find a free register of class 'rc'. If none, save one register */
3041 int get_reg(int rc)
3043 int r;
3044 SValue *p;
3046 /* find a free register */
3047 for(r=0;r<NB_REGS;r++) {
3048 if (reg_classes[r] & rc) {
3049 for(p=vstack;p<=vtop;p++) {
3050 if ((p->r & VT_VALMASK) == r ||
3051 (p->r2 & VT_VALMASK) == r)
3052 goto notfound;
3054 return r;
3056 notfound: ;
3059 /* no register left : free the first one on the stack (VERY
3060 IMPORTANT to start from the bottom to ensure that we don't
3061 spill registers used in gen_opi()) */
3062 for(p=vstack;p<=vtop;p++) {
3063 r = p->r & VT_VALMASK;
3064 if (r < VT_CONST && (reg_classes[r] & rc)) {
3065 save_reg(r);
3066 break;
3069 return r;
3072 /* save registers up to (vtop - n) stack entry */
3073 void save_regs(int n)
3075 int r;
3076 SValue *p, *p1;
3077 p1 = vtop - n;
3078 for(p = vstack;p <= p1; p++) {
3079 r = p->r & VT_VALMASK;
3080 if (r < VT_CONST) {
3081 save_reg(r);
3086 /* move register 's' to 'r', and flush previous value of r to memory
3087 if needed */
3088 void move_reg(int r, int s)
3090 SValue sv;
3092 if (r != s) {
3093 save_reg(r);
3094 sv.t = VT_INT;
3095 sv.r = s;
3096 sv.c.ul = 0;
3097 load(r, &sv);
3101 /* get address of vtop (vtop MUST BE an lvalue) */
3102 void gaddrof(void)
3104 vtop->r &= ~VT_LVAL;
3105 /* tricky: if saved lvalue, then we can go back to lvalue */
3106 if ((vtop->r & VT_VALMASK) == VT_LLOCAL)
3107 vtop->r = (vtop->r & ~(VT_VALMASK | VT_LVAL_TYPE)) | VT_LOCAL | VT_LVAL;
3110 #ifdef CONFIG_TCC_BCHECK
3111 /* generate lvalue bound code */
3112 void gbound(void)
3114 int lval_type, t1;
3116 vtop->r &= ~VT_MUSTBOUND;
3117 /* if lvalue, then use checking code before dereferencing */
3118 if (vtop->r & VT_LVAL) {
3119 /* if not VT_BOUNDED value, then make one */
3120 if (!(vtop->r & VT_BOUNDED)) {
3121 lval_type = vtop->r & (VT_LVAL_TYPE | VT_LVAL);
3122 /* must save type because we must set it to int to get pointer */
3123 t1 = vtop->t;
3124 vtop->t = VT_INT;
3125 gaddrof();
3126 vpushi(0);
3127 gen_bounded_ptr_add();
3128 vtop->r |= lval_type;
3129 vtop->t = t1;
3131 /* then check for dereferencing */
3132 gen_bounded_ptr_deref();
3135 #endif
3137 /* store vtop a register belonging to class 'rc'. lvalues are
3138 converted to values. Cannot be used if cannot be converted to
3139 register value (such as structures). */
3140 int gv(int rc)
3142 int r, r2, rc2, bit_pos, bit_size, size, align, i;
3143 unsigned long long ll;
3145 /* NOTE: get_reg can modify vstack[] */
3146 if (vtop->t & VT_BITFIELD) {
3147 bit_pos = (vtop->t >> VT_STRUCT_SHIFT) & 0x3f;
3148 bit_size = (vtop->t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
3149 /* remove bit field info to avoid loops */
3150 vtop->t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
3151 /* generate shifts */
3152 vpushi(32 - (bit_pos + bit_size));
3153 gen_op(TOK_SHL);
3154 vpushi(32 - bit_size);
3155 /* NOTE: transformed to SHR if unsigned */
3156 gen_op(TOK_SAR);
3157 r = gv(rc);
3158 } else {
3159 if (is_float(vtop->t) &&
3160 (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
3161 Sym *sym;
3162 int *ptr;
3163 unsigned long offset;
3165 /* XXX: unify with initializers handling ? */
3166 /* CPUs usually cannot use float constants, so we store them
3167 generically in data segment */
3168 size = type_size(vtop->t, &align);
3169 offset = (data_section->data_offset + align - 1) & -align;
3170 data_section->data_offset = offset;
3171 /* XXX: not portable yet */
3172 ptr = section_ptr_add(data_section, size);
3173 size = size >> 2;
3174 for(i=0;i<size;i++)
3175 ptr[i] = vtop->c.tab[i];
3176 sym = get_sym_ref(vtop->t, data_section, offset, size << 2);
3177 vtop->r |= VT_LVAL | VT_SYM;
3178 vtop->sym = sym;
3179 vtop->c.ul = 0;
3181 #ifdef CONFIG_TCC_BCHECK
3182 if (vtop->r & VT_MUSTBOUND)
3183 gbound();
3184 #endif
3186 r = vtop->r & VT_VALMASK;
3187 /* need to reload if:
3188 - constant
3189 - lvalue (need to dereference pointer)
3190 - already a register, but not in the right class */
3191 if (r >= VT_CONST ||
3192 (vtop->r & VT_LVAL) ||
3193 !(reg_classes[r] & rc) ||
3194 ((vtop->t & VT_BTYPE) == VT_LLONG &&
3195 !(reg_classes[vtop->r2] & rc))) {
3196 r = get_reg(rc);
3197 if ((vtop->t & VT_BTYPE) == VT_LLONG) {
3198 /* two register type load : expand to two words
3199 temporarily */
3200 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
3201 /* load constant */
3202 ll = vtop->c.ull;
3203 vtop->c.ui = ll; /* first word */
3204 load(r, vtop);
3205 vtop->r = r; /* save register value */
3206 vpushi(ll >> 32); /* second word */
3207 } else if (r >= VT_CONST ||
3208 (vtop->r & VT_LVAL)) {
3209 /* load from memory */
3210 load(r, vtop);
3211 vdup();
3212 vtop[-1].r = r; /* save register value */
3213 /* increment pointer to get second word */
3214 vtop->t = VT_INT;
3215 gaddrof();
3216 vpushi(4);
3217 gen_op('+');
3218 vtop->r |= VT_LVAL;
3219 } else {
3220 /* move registers */
3221 load(r, vtop);
3222 vdup();
3223 vtop[-1].r = r; /* save register value */
3224 vtop->r = vtop[-1].r2;
3226 /* allocate second register */
3227 rc2 = RC_INT;
3228 if (rc == RC_IRET)
3229 rc2 = RC_LRET;
3230 r2 = get_reg(rc2);
3231 load(r2, vtop);
3232 vpop();
3233 /* write second register */
3234 vtop->r2 = r2;
3235 } else if ((vtop->r & VT_LVAL) && !is_float(vtop->t)) {
3236 int t1, t;
3237 /* lvalue of scalar type : need to use lvalue type
3238 because of possible cast */
3239 t = vtop->t;
3240 t1 = t;
3241 /* compute memory access type */
3242 if (vtop->r & VT_LVAL_BYTE)
3243 t = VT_BYTE;
3244 else if (vtop->r & VT_LVAL_SHORT)
3245 t = VT_SHORT;
3246 if (vtop->r & VT_LVAL_UNSIGNED)
3247 t |= VT_UNSIGNED;
3248 vtop->t = t;
3249 load(r, vtop);
3250 /* restore wanted type */
3251 vtop->t = t1;
3252 } else {
3253 /* one register type load */
3254 load(r, vtop);
3257 vtop->r = r;
3259 return r;
3262 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
3263 void gv2(int rc1, int rc2)
3265 int v;
3267 /* generate more generic register first. But VT_JMP or VT_CMP
3268 values must be generated first in all cases to avoid possible
3269 reload errors */
3270 v = vtop[0].r & VT_VALMASK;
3271 if (v != VT_CMP && (v & ~1) != VT_JMP && rc1 <= rc2) {
3272 vswap();
3273 gv(rc1);
3274 vswap();
3275 gv(rc2);
3276 /* test if reload is needed for first register */
3277 if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
3278 vswap();
3279 gv(rc1);
3280 vswap();
3282 } else {
3283 gv(rc2);
3284 vswap();
3285 gv(rc1);
3286 vswap();
3287 /* test if reload is needed for first register */
3288 if ((vtop[0].r & VT_VALMASK) >= VT_CONST) {
3289 gv(rc2);
3294 /* expand long long on stack in two int registers */
3295 void lexpand(void)
3297 int u;
3299 u = vtop->t & VT_UNSIGNED;
3300 gv(RC_INT);
3301 vdup();
3302 vtop[0].r = vtop[-1].r2;
3303 vtop[0].r2 = VT_CONST;
3304 vtop[-1].r2 = VT_CONST;
3305 vtop[0].t = VT_INT | u;
3306 vtop[-1].t = VT_INT | u;
3309 /* build a long long from two ints */
3310 void lbuild(int t)
3312 gv2(RC_INT, RC_INT);
3313 vtop[-1].r2 = vtop[0].r;
3314 vtop[-1].t = t;
3315 vpop();
3318 /* rotate n first stack elements to the bottom */
3319 void vrotb(int n)
3321 int i;
3322 SValue tmp;
3324 tmp = vtop[-n + 1];
3325 for(i=-n+1;i!=0;i++)
3326 vtop[i] = vtop[i+1];
3327 vtop[0] = tmp;
3330 /* pop stack value */
3331 void vpop(void)
3333 int v;
3334 v = vtop->r & VT_VALMASK;
3335 #ifdef TCC_TARGET_I386
3336 /* for x86, we need to pop the FP stack */
3337 if (v == REG_ST0) {
3338 o(0xd9dd); /* fstp %st(1) */
3339 } else
3340 #endif
3341 if (v == VT_JMP || v == VT_JMPI) {
3342 /* need to put correct jump if && or || without test */
3343 gsym(vtop->c.ul);
3345 vtop--;
3348 /* convert stack entry to register and duplicate its value in another
3349 register */
3350 void gv_dup(void)
3352 int rc, t, r, r1;
3353 SValue sv;
3355 t = vtop->t;
3356 if ((t & VT_BTYPE) == VT_LLONG) {
3357 lexpand();
3358 gv_dup();
3359 vswap();
3360 vrotb(3);
3361 gv_dup();
3362 vrotb(4);
3363 /* stack: H L L1 H1 */
3364 lbuild(t);
3365 vrotb(3);
3366 vrotb(3);
3367 vswap();
3368 lbuild(t);
3369 vswap();
3370 } else {
3371 /* duplicate value */
3372 rc = RC_INT;
3373 sv.t = VT_INT;
3374 if (is_float(t)) {
3375 rc = RC_FLOAT;
3376 sv.t = t;
3378 r = gv(rc);
3379 r1 = get_reg(rc);
3380 sv.r = r;
3381 sv.c.ul = 0;
3382 load(r1, &sv); /* move r to r1 */
3383 vdup();
3384 /* duplicates value */
3385 vtop->r = r1;
3389 /* generate CPU independent (unsigned) long long operations */
3390 void gen_opl(int op)
3392 int t, a, b, op1, c, i;
3393 int func;
3394 GFuncContext gf;
3395 SValue tmp;
3397 switch(op) {
3398 case '/':
3399 case TOK_PDIV:
3400 func = TOK___divdi3;
3401 goto gen_func;
3402 case TOK_UDIV:
3403 func = TOK___udivdi3;
3404 goto gen_func;
3405 case '%':
3406 func = TOK___moddi3;
3407 goto gen_func;
3408 case TOK_UMOD:
3409 func = TOK___umoddi3;
3410 gen_func:
3411 /* call generic long long function */
3412 gfunc_start(&gf, FUNC_CDECL);
3413 gfunc_param(&gf);
3414 gfunc_param(&gf);
3415 vpush_global_sym(func_old_type, func);
3416 gfunc_call(&gf);
3417 vpushi(0);
3418 vtop->r = REG_IRET;
3419 vtop->r2 = REG_LRET;
3420 break;
3421 case '^':
3422 case '&':
3423 case '|':
3424 case '*':
3425 case '+':
3426 case '-':
3427 t = vtop->t;
3428 vswap();
3429 lexpand();
3430 vrotb(3);
3431 lexpand();
3432 /* stack: L1 H1 L2 H2 */
3433 tmp = vtop[0];
3434 vtop[0] = vtop[-3];
3435 vtop[-3] = tmp;
3436 tmp = vtop[-2];
3437 vtop[-2] = vtop[-3];
3438 vtop[-3] = tmp;
3439 vswap();
3440 /* stack: H1 H2 L1 L2 */
3441 if (op == '*') {
3442 vpushv(vtop - 1);
3443 vpushv(vtop - 1);
3444 gen_op(TOK_UMULL);
3445 lexpand();
3446 /* stack: H1 H2 L1 L2 ML MH */
3447 for(i=0;i<4;i++)
3448 vrotb(6);
3449 /* stack: ML MH H1 H2 L1 L2 */
3450 tmp = vtop[0];
3451 vtop[0] = vtop[-2];
3452 vtop[-2] = tmp;
3453 /* stack: ML MH H1 L2 H2 L1 */
3454 gen_op('*');
3455 vrotb(3);
3456 vrotb(3);
3457 gen_op('*');
3458 /* stack: ML MH M1 M2 */
3459 gen_op('+');
3460 gen_op('+');
3461 } else if (op == '+' || op == '-') {
3462 /* XXX: add non carry method too (for MIPS or alpha) */
3463 if (op == '+')
3464 op1 = TOK_ADDC1;
3465 else
3466 op1 = TOK_SUBC1;
3467 gen_op(op1);
3468 /* stack: H1 H2 (L1 op L2) */
3469 vrotb(3);
3470 vrotb(3);
3471 gen_op(op1 + 1); /* TOK_xxxC2 */
3472 } else {
3473 gen_op(op);
3474 /* stack: H1 H2 (L1 op L2) */
3475 vrotb(3);
3476 vrotb(3);
3477 /* stack: (L1 op L2) H1 H2 */
3478 gen_op(op);
3479 /* stack: (L1 op L2) (H1 op H2) */
3481 /* stack: L H */
3482 lbuild(t);
3483 break;
3484 case TOK_SAR:
3485 case TOK_SHR:
3486 case TOK_SHL:
3487 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
3488 t = vtop[-1].t;
3489 vswap();
3490 lexpand();
3491 vrotb(3);
3492 /* stack: L H shift */
3493 c = (int)vtop->c.i;
3494 /* constant: simpler */
3495 /* NOTE: all comments are for SHL. the other cases are
3496 done by swaping words */
3497 vpop();
3498 if (op != TOK_SHL)
3499 vswap();
3500 if (c >= 32) {
3501 /* stack: L H */
3502 vpop();
3503 if (c > 32) {
3504 vpushi(c - 32);
3505 gen_op(op);
3507 if (op != TOK_SAR) {
3508 vpushi(0);
3509 } else {
3510 gv_dup();
3511 vpushi(31);
3512 gen_op(TOK_SAR);
3514 vswap();
3515 } else {
3516 vswap();
3517 gv_dup();
3518 /* stack: H L L */
3519 vpushi(c);
3520 gen_op(op);
3521 vswap();
3522 vpushi(32 - c);
3523 if (op == TOK_SHL)
3524 gen_op(TOK_SHR);
3525 else
3526 gen_op(TOK_SHL);
3527 vrotb(3);
3528 /* stack: L L H */
3529 vpushi(c);
3530 gen_op(op);
3531 gen_op('|');
3533 if (op != TOK_SHL)
3534 vswap();
3535 lbuild(t);
3536 } else {
3537 /* XXX: should provide a faster fallback on x86 ? */
3538 switch(op) {
3539 case TOK_SAR:
3540 func = TOK___sardi3;
3541 goto gen_func;
3542 case TOK_SHR:
3543 func = TOK___shrdi3;
3544 goto gen_func;
3545 case TOK_SHL:
3546 func = TOK___shldi3;
3547 goto gen_func;
3550 break;
3551 default:
3552 /* compare operations */
3553 t = vtop->t;
3554 vswap();
3555 lexpand();
3556 vrotb(3);
3557 lexpand();
3558 /* stack: L1 H1 L2 H2 */
3559 tmp = vtop[-1];
3560 vtop[-1] = vtop[-2];
3561 vtop[-2] = tmp;
3562 /* stack: L1 L2 H1 H2 */
3563 /* compare high */
3564 op1 = op;
3565 /* when values are equal, we need to compare low words. since
3566 the jump is inverted, we invert the test too. */
3567 if (op1 == TOK_LT)
3568 op1 = TOK_LE;
3569 else if (op1 == TOK_GT)
3570 op1 = TOK_GE;
3571 else if (op1 == TOK_ULT)
3572 op1 = TOK_ULE;
3573 else if (op1 == TOK_UGT)
3574 op1 = TOK_UGE;
3575 a = 0;
3576 b = 0;
3577 gen_op(op1);
3578 if (op1 != TOK_NE) {
3579 a = gtst(1, 0);
3581 if (op != TOK_EQ) {
3582 /* generate non equal test */
3583 /* XXX: NOT PORTABLE yet */
3584 if (a == 0) {
3585 b = gtst(0, 0);
3586 } else {
3587 #ifdef TCC_TARGET_I386
3588 b = psym(0x850f, 0);
3589 #else
3590 error("not implemented");
3591 #endif
3594 /* compare low */
3595 gen_op(op);
3596 a = gtst(1, a);
3597 gsym(b);
3598 vset(VT_INT, VT_JMPI, a);
3599 break;
3603 /* handle integer constant optimizations and various machine
3604 independant opt */
3605 void gen_opic(int op)
3607 int fc, c1, c2, n;
3608 SValue *v1, *v2;
3610 v1 = vtop - 1;
3611 v2 = vtop;
3612 /* currently, we cannot do computations with forward symbols */
3613 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
3614 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
3615 if (c1 && c2) {
3616 fc = v2->c.i;
3617 switch(op) {
3618 case '+': v1->c.i += fc; break;
3619 case '-': v1->c.i -= fc; break;
3620 case '&': v1->c.i &= fc; break;
3621 case '^': v1->c.i ^= fc; break;
3622 case '|': v1->c.i |= fc; break;
3623 case '*': v1->c.i *= fc; break;
3625 case TOK_PDIV:
3626 case '/':
3627 case '%':
3628 case TOK_UDIV:
3629 case TOK_UMOD:
3630 /* if division by zero, generate explicit division */
3631 if (fc == 0) {
3632 if (const_wanted)
3633 error("division by zero in constant");
3634 goto general_case;
3636 switch(op) {
3637 default: v1->c.i /= fc; break;
3638 case '%': v1->c.i %= fc; break;
3639 case TOK_UDIV: v1->c.i = (unsigned)v1->c.i / fc; break;
3640 case TOK_UMOD: v1->c.i = (unsigned)v1->c.i % fc; break;
3642 break;
3643 case TOK_SHL: v1->c.i <<= fc; break;
3644 case TOK_SHR: v1->c.i = (unsigned)v1->c.i >> fc; break;
3645 case TOK_SAR: v1->c.i >>= fc; break;
3646 /* tests */
3647 case TOK_ULT: v1->c.i = (unsigned)v1->c.i < (unsigned)fc; break;
3648 case TOK_UGE: v1->c.i = (unsigned)v1->c.i >= (unsigned)fc; break;
3649 case TOK_EQ: v1->c.i = v1->c.i == fc; break;
3650 case TOK_NE: v1->c.i = v1->c.i != fc; break;
3651 case TOK_ULE: v1->c.i = (unsigned)v1->c.i <= (unsigned)fc; break;
3652 case TOK_UGT: v1->c.i = (unsigned)v1->c.i > (unsigned)fc; break;
3653 case TOK_LT: v1->c.i = v1->c.i < fc; break;
3654 case TOK_GE: v1->c.i = v1->c.i >= fc; break;
3655 case TOK_LE: v1->c.i = v1->c.i <= fc; break;
3656 case TOK_GT: v1->c.i = v1->c.i > fc; break;
3657 /* logical */
3658 case TOK_LAND: v1->c.i = v1->c.i && fc; break;
3659 case TOK_LOR: v1->c.i = v1->c.i || fc; break;
3660 default:
3661 goto general_case;
3663 vtop--;
3664 } else {
3665 /* if commutative ops, put c2 as constant */
3666 if (c1 && (op == '+' || op == '&' || op == '^' ||
3667 op == '|' || op == '*')) {
3668 vswap();
3669 swap(&c1, &c2);
3671 fc = vtop->c.i;
3672 if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
3673 op == TOK_PDIV) &&
3674 fc == 1) ||
3675 ((op == '+' || op == '-' || op == '|' || op == '^' ||
3676 op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
3677 fc == 0) ||
3678 (op == '&' &&
3679 fc == -1))) {
3680 /* nothing to do */
3681 vtop--;
3682 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
3683 /* try to use shifts instead of muls or divs */
3684 if (fc > 0 && (fc & (fc - 1)) == 0) {
3685 n = -1;
3686 while (fc) {
3687 fc >>= 1;
3688 n++;
3690 vtop->c.i = n;
3691 if (op == '*')
3692 op = TOK_SHL;
3693 else if (op == TOK_PDIV)
3694 op = TOK_SAR;
3695 else
3696 op = TOK_SHR;
3698 goto general_case;
3699 } else if (c2 && (op == '+' || op == '-') &&
3700 (vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) ==
3701 (VT_CONST | VT_SYM)) {
3702 /* symbol + constant case */
3703 if (op == '-')
3704 fc = -fc;
3705 vtop--;
3706 vtop->c.i += fc;
3707 } else {
3708 general_case:
3709 /* call low level op generator */
3710 gen_opi(op);
3715 /* generate a floating point operation with constant propagation */
3716 void gen_opif(int op)
3718 int c1, c2;
3719 SValue *v1, *v2;
3720 long double f1, f2;
3722 v1 = vtop - 1;
3723 v2 = vtop;
3724 /* currently, we cannot do computations with forward symbols */
3725 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
3726 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
3727 if (c1 && c2) {
3728 if (v1->t == VT_FLOAT) {
3729 f1 = v1->c.f;
3730 f2 = v2->c.f;
3731 } else if (v1->t == VT_DOUBLE) {
3732 f1 = v1->c.d;
3733 f2 = v2->c.d;
3734 } else {
3735 f1 = v1->c.ld;
3736 f2 = v2->c.ld;
3739 /* NOTE: we only do constant propagation if finite number (not
3740 NaN or infinity) (ANSI spec) */
3741 if (!ieee_finite(f1) || !ieee_finite(f2))
3742 goto general_case;
3744 switch(op) {
3745 case '+': f1 += f2; break;
3746 case '-': f1 -= f2; break;
3747 case '*': f1 *= f2; break;
3748 case '/':
3749 if (f2 == 0.0) {
3750 if (const_wanted)
3751 error("division by zero in constant");
3752 goto general_case;
3754 f1 /= f2;
3755 break;
3756 /* XXX: also handles tests ? */
3757 default:
3758 goto general_case;
3760 /* XXX: overflow test ? */
3761 if (v1->t == VT_FLOAT) {
3762 v1->c.f = f1;
3763 } else if (v1->t == VT_DOUBLE) {
3764 v1->c.d = f1;
3765 } else {
3766 v1->c.ld = f1;
3768 vtop--;
3769 } else {
3770 general_case:
3771 gen_opf(op);
3775 int pointed_size(int t)
3777 return type_size(pointed_type(t), &t);
3780 #if 0
3781 void check_pointer_types(SValue *p1, SValue *p2)
3783 char buf1[256], buf2[256];
3784 int t1, t2;
3785 t1 = p1->t;
3786 t2 = p2->t;
3787 if (!is_compatible_types(t1, t2)) {
3788 type_to_str(buf1, sizeof(buf1), t1, NULL);
3789 type_to_str(buf2, sizeof(buf2), t2, NULL);
3790 error("incompatible pointers '%s' and '%s'", buf1, buf2);
3793 #endif
3795 /* generic gen_op: handles types problems */
3796 void gen_op(int op)
3798 int u, t1, t2, bt1, bt2, t;
3800 t1 = vtop[-1].t;
3801 t2 = vtop[0].t;
3802 bt1 = t1 & VT_BTYPE;
3803 bt2 = t2 & VT_BTYPE;
3805 if (bt1 == VT_PTR || bt2 == VT_PTR) {
3806 /* at least one operand is a pointer */
3807 /* relationnal op: must be both pointers */
3808 if (op >= TOK_ULT && op <= TOK_GT) {
3809 // check_pointer_types(vtop, vtop - 1);
3810 /* pointers are handled are unsigned */
3811 t = VT_INT | VT_UNSIGNED;
3812 goto std_op;
3814 /* if both pointers, then it must be the '-' op */
3815 if ((t1 & VT_BTYPE) == VT_PTR &&
3816 (t2 & VT_BTYPE) == VT_PTR) {
3817 if (op != '-')
3818 error("cannot use pointers here");
3819 // check_pointer_types(vtop - 1, vtop);
3820 /* XXX: check that types are compatible */
3821 u = pointed_size(t1);
3822 gen_opic(op);
3823 /* set to integer type */
3824 vtop->t = VT_INT;
3825 vpushi(u);
3826 gen_op(TOK_PDIV);
3827 } else {
3828 /* exactly one pointer : must be '+' or '-'. */
3829 if (op != '-' && op != '+')
3830 error("cannot use pointers here");
3831 /* Put pointer as first operand */
3832 if ((t2 & VT_BTYPE) == VT_PTR) {
3833 vswap();
3834 swap(&t1, &t2);
3836 /* XXX: cast to int ? (long long case) */
3837 vpushi(pointed_size(vtop[-1].t));
3838 gen_op('*');
3839 #ifdef CONFIG_TCC_BCHECK
3840 /* if evaluating constant expression, no code should be
3841 generated, so no bound check */
3842 if (do_bounds_check && !const_wanted) {
3843 /* if bounded pointers, we generate a special code to
3844 test bounds */
3845 if (op == '-') {
3846 vpushi(0);
3847 vswap();
3848 gen_op('-');
3850 gen_bounded_ptr_add();
3851 } else
3852 #endif
3854 gen_opic(op);
3856 /* put again type if gen_opic() swaped operands */
3857 vtop->t = t1;
3859 } else if (is_float(bt1) || is_float(bt2)) {
3860 /* compute bigger type and do implicit casts */
3861 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
3862 t = VT_LDOUBLE;
3863 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
3864 t = VT_DOUBLE;
3865 } else {
3866 t = VT_FLOAT;
3868 /* floats can only be used for a few operations */
3869 if (op != '+' && op != '-' && op != '*' && op != '/' &&
3870 (op < TOK_ULT || op > TOK_GT))
3871 error("invalid operands for binary operation");
3872 goto std_op;
3873 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
3874 /* cast to biggest op */
3875 t = VT_LLONG;
3876 /* convert to unsigned if it does not fit in a long long */
3877 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
3878 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
3879 t |= VT_UNSIGNED;
3880 goto std_op;
3881 } else {
3882 /* integer operations */
3883 t = VT_INT;
3884 /* convert to unsigned if it does not fit in an integer */
3885 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
3886 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
3887 t |= VT_UNSIGNED;
3888 std_op:
3889 /* XXX: currently, some unsigned operations are explicit, so
3890 we modify them here */
3891 if (t & VT_UNSIGNED) {
3892 if (op == TOK_SAR)
3893 op = TOK_SHR;
3894 else if (op == '/')
3895 op = TOK_UDIV;
3896 else if (op == '%')
3897 op = TOK_UMOD;
3898 else if (op == TOK_LT)
3899 op = TOK_ULT;
3900 else if (op == TOK_GT)
3901 op = TOK_UGT;
3902 else if (op == TOK_LE)
3903 op = TOK_ULE;
3904 else if (op == TOK_GE)
3905 op = TOK_UGE;
3907 vswap();
3908 gen_cast(t);
3909 vswap();
3910 /* special case for shifts and long long: we keep the shift as
3911 an integer */
3912 if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL)
3913 gen_cast(VT_INT);
3914 else
3915 gen_cast(t);
3916 if (is_float(t))
3917 gen_opif(op);
3918 else if ((t & VT_BTYPE) == VT_LLONG)
3919 gen_opl(op);
3920 else
3921 gen_opic(op);
3922 if (op >= TOK_ULT && op <= TOK_GT) {
3923 /* relationnal op: the result is an int */
3924 vtop->t = VT_INT;
3925 } else {
3926 vtop->t = t;
3931 /* generic itof for unsigned long long case */
3932 void gen_cvt_itof1(int t)
3934 GFuncContext gf;
3936 if ((vtop->t & (VT_BTYPE | VT_UNSIGNED)) ==
3937 (VT_LLONG | VT_UNSIGNED)) {
3939 gfunc_start(&gf, FUNC_CDECL);
3940 gfunc_param(&gf);
3941 if (t == VT_FLOAT)
3942 vpush_global_sym(func_old_type, TOK___ulltof);
3943 else if (t == VT_DOUBLE)
3944 vpush_global_sym(func_old_type, TOK___ulltod);
3945 else
3946 vpush_global_sym(func_old_type, TOK___ulltold);
3947 gfunc_call(&gf);
3948 vpushi(0);
3949 vtop->r = REG_FRET;
3950 } else {
3951 gen_cvt_itof(t);
3955 /* generic ftoi for unsigned long long case */
3956 void gen_cvt_ftoi1(int t)
3958 GFuncContext gf;
3959 int st;
3961 if (t == (VT_LLONG | VT_UNSIGNED)) {
3962 /* not handled natively */
3963 gfunc_start(&gf, FUNC_CDECL);
3964 st = vtop->t & VT_BTYPE;
3965 gfunc_param(&gf);
3966 if (st == VT_FLOAT)
3967 vpush_global_sym(func_old_type, TOK___fixunssfdi);
3968 else if (st == VT_DOUBLE)
3969 vpush_global_sym(func_old_type, TOK___fixunsdfdi);
3970 else
3971 vpush_global_sym(func_old_type, TOK___fixunsxfdi);
3972 gfunc_call(&gf);
3973 vpushi(0);
3974 vtop->r = REG_IRET;
3975 vtop->r2 = REG_LRET;
3976 } else {
3977 gen_cvt_ftoi(t);
3981 /* force char or short cast */
3982 void force_charshort_cast(int t)
3984 int bits, dbt;
3985 dbt = t & VT_BTYPE;
3986 /* XXX: add optimization if lvalue : just change type and offset */
3987 if (dbt == VT_BYTE)
3988 bits = 8;
3989 else
3990 bits = 16;
3991 if (t & VT_UNSIGNED) {
3992 vpushi((1 << bits) - 1);
3993 gen_op('&');
3994 } else {
3995 bits = 32 - bits;
3996 vpushi(bits);
3997 gen_op(TOK_SHL);
3998 vpushi(bits);
3999 gen_op(TOK_SAR);
4003 /* cast 'vtop' to 't' type */
4004 void gen_cast(int t)
4006 int sbt, dbt, sf, df, c;
4008 /* special delayed cast for char/short */
4009 /* XXX: in some cases (multiple cascaded casts), it may still
4010 be incorrect */
4011 if (vtop->r & VT_MUSTCAST) {
4012 vtop->r &= ~VT_MUSTCAST;
4013 force_charshort_cast(vtop->t);
4016 dbt = t & (VT_BTYPE | VT_UNSIGNED);
4017 sbt = vtop->t & (VT_BTYPE | VT_UNSIGNED);
4019 if (sbt != dbt) {
4020 sf = is_float(sbt);
4021 df = is_float(dbt);
4022 c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
4023 if (sf && df) {
4024 /* convert from fp to fp */
4025 if (c) {
4026 /* constant case: we can do it now */
4027 /* XXX: in ISOC, cannot do it if error in convert */
4028 if (dbt == VT_FLOAT && sbt == VT_DOUBLE)
4029 vtop->c.f = (float)vtop->c.d;
4030 else if (dbt == VT_FLOAT && sbt == VT_LDOUBLE)
4031 vtop->c.f = (float)vtop->c.ld;
4032 else if (dbt == VT_DOUBLE && sbt == VT_FLOAT)
4033 vtop->c.d = (double)vtop->c.f;
4034 else if (dbt == VT_DOUBLE && sbt == VT_LDOUBLE)
4035 vtop->c.d = (double)vtop->c.ld;
4036 else if (dbt == VT_LDOUBLE && sbt == VT_FLOAT)
4037 vtop->c.ld = (long double)vtop->c.f;
4038 else if (dbt == VT_LDOUBLE && sbt == VT_DOUBLE)
4039 vtop->c.ld = (long double)vtop->c.d;
4040 } else {
4041 /* non constant case: generate code */
4042 gen_cvt_ftof(dbt);
4044 } else if (df) {
4045 /* convert int to fp */
4046 if (c) {
4047 switch(sbt) {
4048 case VT_LLONG | VT_UNSIGNED:
4049 case VT_LLONG:
4050 /* XXX: add const cases for long long */
4051 goto do_itof;
4052 case VT_INT | VT_UNSIGNED:
4053 switch(dbt) {
4054 case VT_FLOAT: vtop->c.f = (float)vtop->c.ui; break;
4055 case VT_DOUBLE: vtop->c.d = (double)vtop->c.ui; break;
4056 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.ui; break;
4058 break;
4059 default:
4060 switch(dbt) {
4061 case VT_FLOAT: vtop->c.f = (float)vtop->c.i; break;
4062 case VT_DOUBLE: vtop->c.d = (double)vtop->c.i; break;
4063 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.i; break;
4065 break;
4067 } else {
4068 do_itof:
4069 gen_cvt_itof1(dbt);
4071 } else if (sf) {
4072 /* convert fp to int */
4073 /* we handle char/short/etc... with generic code */
4074 if (dbt != (VT_INT | VT_UNSIGNED) &&
4075 dbt != (VT_LLONG | VT_UNSIGNED) &&
4076 dbt != VT_LLONG)
4077 dbt = VT_INT;
4078 if (c) {
4079 switch(dbt) {
4080 case VT_LLONG | VT_UNSIGNED:
4081 case VT_LLONG:
4082 /* XXX: add const cases for long long */
4083 goto do_ftoi;
4084 case VT_INT | VT_UNSIGNED:
4085 switch(sbt) {
4086 case VT_FLOAT: vtop->c.ui = (unsigned int)vtop->c.d; break;
4087 case VT_DOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
4088 case VT_LDOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
4090 break;
4091 default:
4092 /* int case */
4093 switch(sbt) {
4094 case VT_FLOAT: vtop->c.i = (int)vtop->c.d; break;
4095 case VT_DOUBLE: vtop->c.i = (int)vtop->c.d; break;
4096 case VT_LDOUBLE: vtop->c.i = (int)vtop->c.d; break;
4098 break;
4100 } else {
4101 do_ftoi:
4102 gen_cvt_ftoi1(dbt);
4104 if (dbt == VT_INT && (t & (VT_BTYPE | VT_UNSIGNED)) != dbt) {
4105 /* additionnal cast for char/short/bool... */
4106 vtop->t = dbt;
4107 gen_cast(t);
4109 } else if ((dbt & VT_BTYPE) == VT_LLONG) {
4110 if ((sbt & VT_BTYPE) != VT_LLONG) {
4111 /* scalar to long long */
4112 if (c) {
4113 if (sbt == (VT_INT | VT_UNSIGNED))
4114 vtop->c.ll = vtop->c.ui;
4115 else
4116 vtop->c.ll = vtop->c.i;
4117 } else {
4118 /* machine independant conversion */
4119 gv(RC_INT);
4120 /* generate high word */
4121 if (sbt == (VT_INT | VT_UNSIGNED)) {
4122 vpushi(0);
4123 gv(RC_INT);
4124 } else {
4125 gv_dup();
4126 vpushi(31);
4127 gen_op(TOK_SAR);
4129 /* patch second register */
4130 vtop[-1].r2 = vtop->r;
4131 vpop();
4134 } else if (dbt == VT_BOOL) {
4135 /* scalar to bool */
4136 vpushi(0);
4137 gen_op(TOK_NE);
4138 } else if ((dbt & VT_BTYPE) == VT_BYTE ||
4139 (dbt & VT_BTYPE) == VT_SHORT) {
4140 force_charshort_cast(t);
4141 } else if ((dbt & VT_BTYPE) == VT_INT) {
4142 /* scalar to int */
4143 if (sbt == VT_LLONG) {
4144 /* from long long: just take low order word */
4145 lexpand();
4146 vpop();
4148 /* if lvalue and single word type, nothing to do because
4149 the lvalue already contains the real type size (see
4150 VT_LVAL_xxx constants) */
4153 vtop->t = t;
4156 /* return type size. Put alignment at 'a' */
4157 int type_size(int t, int *a)
4159 Sym *s;
4160 int bt;
4162 bt = t & VT_BTYPE;
4163 if (bt == VT_STRUCT) {
4164 /* struct/union */
4165 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
4166 *a = 4; /* XXX: cannot store it yet. Doing that is safe */
4167 return s->c;
4168 } else if (bt == VT_PTR) {
4169 if (t & VT_ARRAY) {
4170 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
4171 return type_size(s->t, a) * s->c;
4172 } else {
4173 *a = PTR_SIZE;
4174 return PTR_SIZE;
4176 } else if (bt == VT_LDOUBLE) {
4177 *a = LDOUBLE_ALIGN;
4178 return LDOUBLE_SIZE;
4179 } else if (bt == VT_DOUBLE || bt == VT_LLONG) {
4180 *a = 8;
4181 return 8;
4182 } else if (bt == VT_INT || bt == VT_ENUM || bt == VT_FLOAT) {
4183 *a = 4;
4184 return 4;
4185 } else if (bt == VT_SHORT) {
4186 *a = 2;
4187 return 2;
4188 } else {
4189 /* char, void, function, _Bool */
4190 *a = 1;
4191 return 1;
4195 /* return the pointed type of t */
4196 int pointed_type(int t)
4198 Sym *s;
4199 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
4200 return s->t | (t & ~VT_TYPE);
4203 int mk_pointer(int t)
4205 int p;
4206 p = anon_sym++;
4207 sym_push(p, t, 0, -1);
4208 return VT_PTR | (p << VT_STRUCT_SHIFT) | (t & ~VT_TYPE);
4211 int is_compatible_types(int t1, int t2)
4213 Sym *s1, *s2;
4214 int bt1, bt2;
4216 t1 &= VT_TYPE;
4217 t2 &= VT_TYPE;
4218 bt1 = t1 & VT_BTYPE;
4219 bt2 = t2 & VT_BTYPE;
4220 if (bt1 == VT_PTR) {
4221 t1 = pointed_type(t1);
4222 /* if function, then convert implicitely to function pointer */
4223 if (bt2 != VT_FUNC) {
4224 if (bt2 != VT_PTR)
4225 return 0;
4226 t2 = pointed_type(t2);
4228 /* void matches everything */
4229 t1 &= VT_TYPE;
4230 t2 &= VT_TYPE;
4231 if (t1 == VT_VOID || t2 == VT_VOID)
4232 return 1;
4233 return is_compatible_types(t1, t2);
4234 } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
4235 return (t2 == t1);
4236 } else if (bt1 == VT_FUNC) {
4237 if (bt2 != VT_FUNC)
4238 return 0;
4239 s1 = sym_find(((unsigned)t1 >> VT_STRUCT_SHIFT));
4240 s2 = sym_find(((unsigned)t2 >> VT_STRUCT_SHIFT));
4241 if (!is_compatible_types(s1->t, s2->t))
4242 return 0;
4243 /* XXX: not complete */
4244 if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
4245 return 1;
4246 if (s1->c != s2->c)
4247 return 0;
4248 while (s1 != NULL) {
4249 if (s2 == NULL)
4250 return 0;
4251 if (!is_compatible_types(s1->t, s2->t))
4252 return 0;
4253 s1 = s1->next;
4254 s2 = s2->next;
4256 if (s2)
4257 return 0;
4258 return 1;
4259 } else {
4260 /* XXX: not complete */
4261 return 1;
4265 /* print a type. If 'varstr' is not NULL, then the variable is also
4266 printed in the type */
4267 /* XXX: union */
4268 /* XXX: add array and function pointers */
4269 void type_to_str(char *buf, int buf_size,
4270 int t, const char *varstr)
4272 int bt, v;
4273 Sym *s, *sa;
4274 char buf1[256];
4275 const char *tstr;
4277 t = t & VT_TYPE;
4278 bt = t & VT_BTYPE;
4279 buf[0] = '\0';
4280 if (t & VT_UNSIGNED)
4281 pstrcat(buf, buf_size, "unsigned ");
4282 switch(bt) {
4283 case VT_VOID:
4284 tstr = "void";
4285 goto add_tstr;
4286 case VT_BOOL:
4287 tstr = "_Bool";
4288 goto add_tstr;
4289 case VT_BYTE:
4290 tstr = "char";
4291 goto add_tstr;
4292 case VT_SHORT:
4293 tstr = "short";
4294 goto add_tstr;
4295 case VT_INT:
4296 tstr = "int";
4297 goto add_tstr;
4298 case VT_LONG:
4299 tstr = "long";
4300 goto add_tstr;
4301 case VT_LLONG:
4302 tstr = "long long";
4303 goto add_tstr;
4304 case VT_FLOAT:
4305 tstr = "float";
4306 goto add_tstr;
4307 case VT_DOUBLE:
4308 tstr = "double";
4309 goto add_tstr;
4310 case VT_LDOUBLE:
4311 tstr = "long double";
4312 add_tstr:
4313 pstrcat(buf, buf_size, tstr);
4314 break;
4315 case VT_ENUM:
4316 case VT_STRUCT:
4317 if (bt == VT_STRUCT)
4318 tstr = "struct ";
4319 else
4320 tstr = "enum ";
4321 pstrcat(buf, buf_size, tstr);
4322 v = (unsigned)t >> VT_STRUCT_SHIFT;
4323 if (v >= SYM_FIRST_ANOM)
4324 pstrcat(buf, buf_size, "<anonymous>");
4325 else
4326 pstrcat(buf, buf_size, get_tok_str(v, NULL));
4327 break;
4328 case VT_FUNC:
4329 s = sym_find((unsigned)t >> VT_STRUCT_SHIFT);
4330 type_to_str(buf, buf_size, s->t, varstr);
4331 pstrcat(buf, buf_size, "(");
4332 sa = s->next;
4333 while (sa != NULL) {
4334 type_to_str(buf1, sizeof(buf1), sa->t, NULL);
4335 pstrcat(buf, buf_size, buf1);
4336 sa = sa->next;
4337 if (sa)
4338 pstrcat(buf, buf_size, ", ");
4340 pstrcat(buf, buf_size, ")");
4341 goto no_var;
4342 case VT_PTR:
4343 s = sym_find((unsigned)t >> VT_STRUCT_SHIFT);
4344 pstrcpy(buf1, sizeof(buf1), "*");
4345 if (varstr)
4346 pstrcat(buf1, sizeof(buf1), varstr);
4347 type_to_str(buf, buf_size, s->t, buf1);
4348 goto no_var;
4350 if (varstr) {
4351 pstrcat(buf, buf_size, " ");
4352 pstrcat(buf, buf_size, varstr);
4354 no_var: ;
4357 /* verify type compatibility to store vtop in 'dt' type, and generate
4358 casts if needed. */
4359 void gen_assign_cast(int dt)
4361 int st;
4362 char buf1[256], buf2[256];
4364 st = vtop->t; /* source type */
4365 if ((dt & VT_BTYPE) == VT_PTR) {
4366 /* special cases for pointers */
4367 /* a function is implicitely a function pointer */
4368 if ((st & VT_BTYPE) == VT_FUNC) {
4369 if (!is_compatible_types(pointed_type(dt), st))
4370 goto error;
4371 else
4372 goto type_ok;
4374 /* '0' can also be a pointer */
4375 if ((st & VT_BTYPE) == VT_INT &&
4376 ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) &&
4377 vtop->c.i == 0)
4378 goto type_ok;
4380 if (!is_compatible_types(dt, st)) {
4381 error:
4382 type_to_str(buf1, sizeof(buf1), st, NULL);
4383 type_to_str(buf2, sizeof(buf2), dt, NULL);
4384 error("cannot cast '%s' to '%s'", buf1, buf2);
4386 type_ok:
4387 gen_cast(dt);
4390 /* store vtop in lvalue pushed on stack */
4391 void vstore(void)
4393 int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
4394 GFuncContext gf;
4396 ft = vtop[-1].t;
4397 sbt = vtop->t & VT_BTYPE;
4398 dbt = ft & VT_BTYPE;
4399 if (((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
4400 (sbt == VT_INT && dbt == VT_SHORT)) {
4401 /* optimize char/short casts */
4402 delayed_cast = VT_MUSTCAST;
4403 vtop->t = ft & VT_TYPE;
4404 } else {
4405 delayed_cast = 0;
4406 gen_assign_cast(ft & VT_TYPE);
4409 if (sbt == VT_STRUCT) {
4410 /* if structure, only generate pointer */
4411 /* structure assignment : generate memcpy */
4412 /* XXX: optimize if small size */
4413 vdup();
4414 gfunc_start(&gf, FUNC_CDECL);
4415 /* type size */
4416 size = type_size(vtop->t, &align);
4417 vpushi(size);
4418 gfunc_param(&gf);
4419 /* source */
4420 vtop->t = VT_INT;
4421 gaddrof();
4422 gfunc_param(&gf);
4423 /* destination */
4424 vswap();
4425 vtop->t = VT_INT;
4426 gaddrof();
4427 gfunc_param(&gf);
4429 save_regs(0);
4430 vpush_global_sym(func_old_type, TOK_memcpy);
4431 gfunc_call(&gf);
4432 /* leave source on stack */
4433 } else if (ft & VT_BITFIELD) {
4434 /* bitfield store handling */
4435 bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
4436 bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
4437 /* remove bit field info to avoid loops */
4438 vtop[-1].t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
4440 /* duplicate destination */
4441 vdup();
4442 vtop[-1] = vtop[-2];
4444 /* mask and shift source */
4445 vpushi((1 << bit_size) - 1);
4446 gen_op('&');
4447 vpushi(bit_pos);
4448 gen_op(TOK_SHL);
4449 /* load destination, mask and or with source */
4450 vswap();
4451 vpushi(~(((1 << bit_size) - 1) << bit_pos));
4452 gen_op('&');
4453 gen_op('|');
4454 /* store result */
4455 vstore();
4456 } else {
4457 #ifdef CONFIG_TCC_BCHECK
4458 /* bound check case */
4459 if (vtop[-1].r & VT_MUSTBOUND) {
4460 vswap();
4461 gbound();
4462 vswap();
4464 #endif
4465 rc = RC_INT;
4466 if (is_float(ft))
4467 rc = RC_FLOAT;
4468 r = gv(rc); /* generate value */
4469 /* if lvalue was saved on stack, must read it */
4470 if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
4471 SValue sv;
4472 t = get_reg(RC_INT);
4473 sv.t = VT_INT;
4474 sv.r = VT_LOCAL | VT_LVAL;
4475 sv.c.ul = vtop[-1].c.ul;
4476 load(t, &sv);
4477 vtop[-1].r = t | VT_LVAL;
4479 store(r, vtop - 1);
4480 /* two word case handling : store second register at word + 4 */
4481 if ((ft & VT_BTYPE) == VT_LLONG) {
4482 vswap();
4483 /* convert to int to increment easily */
4484 vtop->t = VT_INT;
4485 gaddrof();
4486 vpushi(4);
4487 gen_op('+');
4488 vtop->r |= VT_LVAL;
4489 vswap();
4490 /* XXX: it works because r2 is spilled last ! */
4491 store(vtop->r2, vtop - 1);
4493 vswap();
4494 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
4495 vtop->r |= delayed_cast;
4499 /* post defines POST/PRE add. c is the token ++ or -- */
4500 void inc(int post, int c)
4502 test_lvalue();
4503 vdup(); /* save lvalue */
4504 if (post) {
4505 gv_dup(); /* duplicate value */
4506 vrotb(3);
4507 vrotb(3);
4509 /* add constant */
4510 vpushi(c - TOK_MID);
4511 gen_op('+');
4512 vstore(); /* store value */
4513 if (post)
4514 vpop(); /* if post op, return saved value */
4517 /* Parse GNUC __attribute__ extension. Currently, the following
4518 extensions are recognized:
4519 - aligned(n) : set data/function alignment.
4520 - section(x) : generate data/code in this section.
4521 - unused : currently ignored, but may be used someday.
4523 void parse_attribute(AttributeDef *ad)
4525 int t, n;
4527 next();
4528 skip('(');
4529 skip('(');
4530 while (tok != ')') {
4531 if (tok < TOK_IDENT)
4532 expect("attribute name");
4533 t = tok;
4534 next();
4535 switch(t) {
4536 case TOK_SECTION:
4537 case TOK___SECTION__:
4538 skip('(');
4539 if (tok != TOK_STR)
4540 expect("section name");
4541 ad->section = find_section((char *)tokc.cstr->data);
4542 next();
4543 skip(')');
4544 break;
4545 case TOK_ALIGNED:
4546 case TOK___ALIGNED__:
4547 skip('(');
4548 n = expr_const();
4549 if (n <= 0 || (n & (n - 1)) != 0)
4550 error("alignment must be a positive power of two");
4551 ad->aligned = n;
4552 skip(')');
4553 break;
4554 case TOK_UNUSED:
4555 case TOK___UNUSED__:
4556 /* currently, no need to handle it because tcc does not
4557 track unused objects */
4558 break;
4559 case TOK_NORETURN:
4560 case TOK___NORETURN__:
4561 /* currently, no need to handle it because tcc does not
4562 track unused objects */
4563 break;
4564 case TOK_CDECL:
4565 case TOK___CDECL:
4566 case TOK___CDECL__:
4567 ad->func_call = FUNC_CDECL;
4568 break;
4569 case TOK_STDCALL:
4570 case TOK___STDCALL:
4571 case TOK___STDCALL__:
4572 ad->func_call = FUNC_STDCALL;
4573 break;
4574 default:
4575 warning("'%s' attribute ignored", get_tok_str(t, NULL));
4576 /* skip parameters */
4577 /* XXX: skip parenthesis too */
4578 if (tok == '(') {
4579 next();
4580 while (tok != ')' && tok != -1)
4581 next();
4582 next();
4584 break;
4586 if (tok != ',')
4587 break;
4588 next();
4590 skip(')');
4591 skip(')');
4594 /* enum/struct/union declaration */
4595 int struct_decl(int u)
4597 int a, t, b, v, size, align, maxalign, c, offset;
4598 int bit_size, bit_pos, bsize, bt, lbit_pos;
4599 Sym *s, *ss, **ps;
4600 AttributeDef ad;
4602 a = tok; /* save decl type */
4603 next();
4604 if (tok != '{') {
4605 v = tok;
4606 next();
4607 /* struct already defined ? return it */
4608 /* XXX: check consistency */
4609 s = sym_find(v | SYM_STRUCT);
4610 if (s) {
4611 if (s->t != a)
4612 error("invalid type");
4613 goto do_decl;
4615 } else {
4616 v = anon_sym++;
4618 s = sym_push(v | SYM_STRUCT, a, 0, 0);
4619 /* put struct/union/enum name in type */
4620 do_decl:
4621 u = u | (v << VT_STRUCT_SHIFT);
4623 if (tok == '{') {
4624 next();
4625 if (s->c)
4626 error("struct/union/enum already defined");
4627 /* cannot be empty */
4628 c = 0;
4629 maxalign = 0;
4630 ps = &s->next;
4631 bit_pos = 0;
4632 offset = 0;
4633 while (1) {
4634 if (a == TOK_ENUM) {
4635 v = tok;
4636 next();
4637 if (tok == '=') {
4638 next();
4639 c = expr_const();
4641 /* enum symbols have static storage */
4642 sym_push(v, VT_STATIC | VT_INT, VT_CONST, c);
4643 if (tok == ',')
4644 next();
4645 c++;
4646 } else {
4647 parse_btype(&b, &ad);
4648 while (1) {
4649 bit_size = -1;
4650 v = 0;
4651 if (tok != ':') {
4652 t = type_decl(&ad, &v, b, TYPE_DIRECT);
4653 if ((t & VT_BTYPE) == VT_FUNC ||
4654 (t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN)))
4655 error("invalid type for '%s'",
4656 get_tok_str(v, NULL));
4657 } else {
4658 t = b;
4660 if (tok == ':') {
4661 next();
4662 bit_size = expr_const();
4663 /* XXX: handle v = 0 case for messages */
4664 if (bit_size < 0)
4665 error("negative width in bit-field '%s'",
4666 get_tok_str(v, NULL));
4667 if (v && bit_size == 0)
4668 error("zero width for bit-field '%s'",
4669 get_tok_str(v, NULL));
4671 size = type_size(t, &align);
4672 lbit_pos = 0;
4673 if (bit_size >= 0) {
4674 bt = t & VT_BTYPE;
4675 if (bt != VT_INT &&
4676 bt != VT_BYTE &&
4677 bt != VT_SHORT)
4678 error("bitfields must have scalar type");
4679 bsize = size * 8;
4680 if (bit_size > bsize) {
4681 error("width of '%s' exceeds its type",
4682 get_tok_str(v, NULL));
4683 } else if (bit_size == bsize) {
4684 /* no need for bit fields */
4685 bit_pos = 0;
4686 } else if (bit_size == 0) {
4687 /* XXX: what to do if only padding in a
4688 structure ? */
4689 /* zero size: means to pad */
4690 if (bit_pos > 0)
4691 bit_pos = bsize;
4692 } else {
4693 /* we do not have enough room ? */
4694 if ((bit_pos + bit_size) > bsize)
4695 bit_pos = 0;
4696 lbit_pos = bit_pos;
4697 /* XXX: handle LSB first */
4698 t |= VT_BITFIELD |
4699 (bit_pos << VT_STRUCT_SHIFT) |
4700 (bit_size << (VT_STRUCT_SHIFT + 6));
4701 bit_pos += bit_size;
4703 } else {
4704 bit_pos = 0;
4706 if (v) {
4707 /* add new memory data only if starting
4708 bit field */
4709 if (lbit_pos == 0) {
4710 if (a == TOK_STRUCT) {
4711 c = (c + align - 1) & -align;
4712 offset = c;
4713 c += size;
4714 } else {
4715 offset = 0;
4716 if (size > c)
4717 c = size;
4719 if (align > maxalign)
4720 maxalign = align;
4722 #if 0
4723 printf("add field %s offset=%d",
4724 get_tok_str(v, NULL), offset);
4725 if (t & VT_BITFIELD) {
4726 printf(" pos=%d size=%d",
4727 (t >> VT_STRUCT_SHIFT) & 0x3f,
4728 (t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
4730 printf("\n");
4731 #endif
4732 ss = sym_push(v | SYM_FIELD, t, 0, offset);
4733 *ps = ss;
4734 ps = &ss->next;
4736 if (tok == ';' || tok == -1)
4737 break;
4738 skip(',');
4740 skip(';');
4742 if (tok == '}')
4743 break;
4745 skip('}');
4746 /* size for struct/union, dummy for enum */
4747 s->c = (c + maxalign - 1) & -maxalign;
4749 return u;
4752 /* return 0 if no type declaration. otherwise, return the basic type
4753 and skip it.
4755 int parse_btype(int *type_ptr, AttributeDef *ad)
4757 int t, u, type_found;
4758 Sym *s;
4760 memset(ad, 0, sizeof(AttributeDef));
4761 type_found = 0;
4762 t = 0;
4763 while(1) {
4764 switch(tok) {
4765 /* basic types */
4766 case TOK_CHAR:
4767 u = VT_BYTE;
4768 basic_type:
4769 next();
4770 basic_type1:
4771 if ((t & VT_BTYPE) != 0)
4772 error("too many basic types");
4773 t |= u;
4774 break;
4775 case TOK_VOID:
4776 u = VT_VOID;
4777 goto basic_type;
4778 case TOK_SHORT:
4779 u = VT_SHORT;
4780 goto basic_type;
4781 case TOK_INT:
4782 next();
4783 break;
4784 case TOK_LONG:
4785 next();
4786 if ((t & VT_BTYPE) == VT_DOUBLE) {
4787 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
4788 } else if ((t & VT_BTYPE) == VT_LONG) {
4789 t = (t & ~VT_BTYPE) | VT_LLONG;
4790 } else {
4791 u = VT_LONG;
4792 goto basic_type1;
4794 break;
4795 case TOK_BOOL:
4796 u = VT_BOOL;
4797 goto basic_type;
4798 case TOK_FLOAT:
4799 u = VT_FLOAT;
4800 goto basic_type;
4801 case TOK_DOUBLE:
4802 next();
4803 if ((t & VT_BTYPE) == VT_LONG) {
4804 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
4805 } else {
4806 u = VT_DOUBLE;
4807 goto basic_type1;
4809 break;
4810 case TOK_ENUM:
4811 u = struct_decl(VT_ENUM);
4812 goto basic_type1;
4813 case TOK_STRUCT:
4814 case TOK_UNION:
4815 u = struct_decl(VT_STRUCT);
4816 goto basic_type1;
4818 /* type modifiers */
4819 case TOK_CONST:
4820 case TOK_VOLATILE:
4821 case TOK_REGISTER:
4822 case TOK_SIGNED:
4823 case TOK___SIGNED__:
4824 case TOK_AUTO:
4825 case TOK_INLINE:
4826 case TOK___INLINE__:
4827 case TOK_RESTRICT:
4828 next();
4829 break;
4830 case TOK_UNSIGNED:
4831 t |= VT_UNSIGNED;
4832 next();
4833 break;
4835 /* storage */
4836 case TOK_EXTERN:
4837 t |= VT_EXTERN;
4838 next();
4839 break;
4840 case TOK_STATIC:
4841 t |= VT_STATIC;
4842 next();
4843 break;
4844 case TOK_TYPEDEF:
4845 t |= VT_TYPEDEF;
4846 next();
4847 break;
4848 /* GNUC attribute */
4849 case TOK___ATTRIBUTE__:
4850 parse_attribute(ad);
4851 break;
4852 default:
4853 s = sym_find(tok);
4854 if (!s || !(s->t & VT_TYPEDEF))
4855 goto the_end;
4856 t |= (s->t & ~VT_TYPEDEF);
4857 next();
4858 break;
4860 type_found = 1;
4862 the_end:
4863 /* long is never used as type */
4864 if ((t & VT_BTYPE) == VT_LONG)
4865 t = (t & ~VT_BTYPE) | VT_INT;
4866 *type_ptr = t;
4867 return type_found;
4870 int post_type(int t, AttributeDef *ad)
4872 int p, n, pt, l, t1;
4873 Sym **plast, *s, *first;
4874 AttributeDef ad1;
4876 if (tok == '(') {
4877 /* function declaration */
4878 next();
4879 l = 0;
4880 first = NULL;
4881 plast = &first;
4882 while (tok != ')') {
4883 /* read param name and compute offset */
4884 if (l != FUNC_OLD) {
4885 if (!parse_btype(&pt, &ad1)) {
4886 if (l) {
4887 error("invalid type");
4888 } else {
4889 l = FUNC_OLD;
4890 goto old_proto;
4893 l = FUNC_NEW;
4894 if ((pt & VT_BTYPE) == VT_VOID && tok == ')')
4895 break;
4896 pt = type_decl(&ad1, &n, pt, TYPE_DIRECT | TYPE_ABSTRACT);
4897 if ((pt & VT_BTYPE) == VT_VOID)
4898 error("parameter declared as void");
4899 } else {
4900 old_proto:
4901 n = tok;
4902 pt = VT_INT;
4903 next();
4905 /* array must be transformed to pointer according to ANSI C */
4906 pt &= ~VT_ARRAY;
4907 s = sym_push(n | SYM_FIELD, pt, 0, 0);
4908 *plast = s;
4909 plast = &s->next;
4910 if (tok == ',') {
4911 next();
4912 if (l == FUNC_NEW && tok == TOK_DOTS) {
4913 l = FUNC_ELLIPSIS;
4914 next();
4915 break;
4919 /* if no parameters, then old type prototype */
4920 if (l == 0)
4921 l = FUNC_OLD;
4922 skip(')');
4923 t1 = t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN);
4924 t = post_type(t & ~(VT_TYPEDEF | VT_STATIC | VT_EXTERN), ad);
4925 /* we push a anonymous symbol which will contain the function prototype */
4926 p = anon_sym++;
4927 s = sym_push(p, t, ad->func_call, l);
4928 s->next = first;
4929 t = t1 | VT_FUNC | (p << VT_STRUCT_SHIFT);
4930 } else if (tok == '[') {
4931 /* array definition */
4932 next();
4933 n = -1;
4934 if (tok != ']') {
4935 n = expr_const();
4936 if (n < 0)
4937 error("invalid array size");
4939 skip(']');
4940 /* parse next post type */
4941 t1 = t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN);
4942 t = post_type(t & ~(VT_TYPEDEF | VT_STATIC | VT_EXTERN), ad);
4944 /* we push a anonymous symbol which will contain the array
4945 element type */
4946 p = anon_sym++;
4947 sym_push(p, t, 0, n);
4948 t = t1 | VT_ARRAY | VT_PTR | (p << VT_STRUCT_SHIFT);
4950 return t;
4953 /* Read a type declaration (except basic type), and return the
4954 type. 'td' is a bitmask indicating which kind of type decl is
4955 expected. 't' should contain the basic type. 'ad' is the attribute
4956 definition of the basic type. It can be modified by type_decl(). */
4957 int type_decl(AttributeDef *ad, int *v, int t, int td)
4959 int u, p;
4960 Sym *s;
4962 while (tok == '*') {
4963 next();
4964 while (tok == TOK_CONST || tok == TOK_VOLATILE || tok == TOK_RESTRICT)
4965 next();
4966 t = mk_pointer(t);
4969 /* recursive type */
4970 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
4971 if (tok == '(') {
4972 next();
4973 /* XXX: this is not correct to modify 'ad' at this point, but
4974 the syntax is not clear */
4975 if (tok == TOK___ATTRIBUTE__)
4976 parse_attribute(ad);
4977 u = type_decl(ad, v, 0, td);
4978 skip(')');
4979 } else {
4980 u = 0;
4981 /* type identifier */
4982 if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
4983 *v = tok;
4984 next();
4985 } else {
4986 if (!(td & TYPE_ABSTRACT))
4987 expect("identifier");
4988 *v = 0;
4991 /* append t at the end of u */
4992 t = post_type(t, ad);
4993 if (tok == TOK___ATTRIBUTE__)
4994 parse_attribute(ad);
4995 if (!u)
4996 return t;
4997 p = u;
4998 while(1) {
4999 s = sym_find((unsigned)p >> VT_STRUCT_SHIFT);
5000 p = s->t;
5001 if (!p) {
5002 s->t = t;
5003 break;
5006 return u;
5009 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
5010 static int lvalue_type(int t)
5012 int bt, r;
5013 r = VT_LVAL;
5014 bt = t & VT_BTYPE;
5015 if (bt == VT_BYTE)
5016 r |= VT_LVAL_BYTE;
5017 else if (bt == VT_SHORT)
5018 r |= VT_LVAL_SHORT;
5019 else
5020 return r;
5021 if (t & VT_UNSIGNED)
5022 r |= VT_LVAL_UNSIGNED;
5023 return r;
5026 /* indirection with full error checking and bound check */
5027 static void indir(void)
5029 if ((vtop->t & VT_BTYPE) != VT_PTR)
5030 expect("pointer");
5031 if (vtop->r & VT_LVAL)
5032 gv(RC_INT);
5033 vtop->t = pointed_type(vtop->t);
5034 /* an array is never an lvalue */
5035 if (!(vtop->t & VT_ARRAY)) {
5036 vtop->r |= lvalue_type(vtop->t);
5037 /* if bound checking, the referenced pointer must be checked */
5038 if (do_bounds_check)
5039 vtop->r |= VT_MUSTBOUND;
5043 /* pass a parameter to a function and do type checking and casting */
5044 void gfunc_param_typed(GFuncContext *gf, Sym *func, Sym *arg)
5046 int func_type;
5047 func_type = func->c;
5048 if (func_type == FUNC_OLD ||
5049 (func_type == FUNC_ELLIPSIS && arg == NULL)) {
5050 /* default casting : only need to convert float to double */
5051 if ((vtop->t & VT_BTYPE) == VT_FLOAT)
5052 gen_cast(VT_DOUBLE);
5053 } else if (arg == NULL) {
5054 error("too many arguments to function");
5055 } else {
5056 gen_assign_cast(arg->t);
5058 gfunc_param(gf);
5061 void unary(void)
5063 int n, t, ft, align, size, r;
5064 Sym *s;
5065 GFuncContext gf;
5066 AttributeDef ad;
5068 if (tok == TOK_CINT || tok == TOK_CCHAR || tok == TOK_LCHAR) {
5069 vpushi(tokc.i);
5070 next();
5071 } else if (tok == TOK_CUINT) {
5072 vsetc(VT_INT | VT_UNSIGNED, VT_CONST, &tokc);
5073 next();
5074 } else if (tok == TOK_CLLONG) {
5075 vsetc(VT_LLONG, VT_CONST, &tokc);
5076 next();
5077 } else if (tok == TOK_CULLONG) {
5078 vsetc(VT_LLONG | VT_UNSIGNED, VT_CONST, &tokc);
5079 next();
5080 } else if (tok == TOK_CFLOAT) {
5081 vsetc(VT_FLOAT, VT_CONST, &tokc);
5082 next();
5083 } else if (tok == TOK_CDOUBLE) {
5084 vsetc(VT_DOUBLE, VT_CONST, &tokc);
5085 next();
5086 } else if (tok == TOK_CLDOUBLE) {
5087 vsetc(VT_LDOUBLE, VT_CONST, &tokc);
5088 next();
5089 } else if (tok == TOK___FUNC__ || (tok == TOK___FUNCTION__ && gnu_ext)) {
5090 void *ptr;
5091 int len;
5092 /* special function name identifier */
5094 len = strlen(funcname) + 1;
5095 /* generate char[len] type */
5096 t = VT_ARRAY | mk_pointer(VT_BYTE);
5097 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
5098 s->c = len;
5099 vpush_ref(t, data_section, data_section->data_offset, len);
5100 ptr = section_ptr_add(data_section, len);
5101 memcpy(ptr, funcname, len);
5102 next();
5103 } else if (tok == TOK_LSTR) {
5104 t = VT_INT;
5105 goto str_init;
5106 } else if (tok == TOK_STR) {
5107 /* string parsing */
5108 t = VT_BYTE;
5109 str_init:
5110 t = VT_ARRAY | mk_pointer(t);
5111 memset(&ad, 0, sizeof(AttributeDef));
5112 decl_initializer_alloc(t, &ad, VT_CONST, 2, 0, 0);
5113 } else {
5114 t = tok;
5115 next();
5116 if (t == '(') {
5117 /* cast ? */
5118 if (parse_btype(&t, &ad)) {
5119 ft = type_decl(&ad, &n, t, TYPE_ABSTRACT);
5120 skip(')');
5121 /* check ISOC99 compound literal */
5122 if (tok == '{') {
5123 /* data is allocated locally by default */
5124 if (global_expr)
5125 r = VT_CONST;
5126 else
5127 r = VT_LOCAL;
5128 /* all except arrays are lvalues */
5129 if (!(ft & VT_ARRAY))
5130 r |= lvalue_type(ft);
5131 memset(&ad, 0, sizeof(AttributeDef));
5132 decl_initializer_alloc(ft, &ad, r, 1, 0, 0);
5133 } else {
5134 unary();
5135 gen_cast(ft);
5137 } else {
5138 gexpr();
5139 skip(')');
5141 } else if (t == '*') {
5142 unary();
5143 indir();
5144 } else if (t == '&') {
5145 unary();
5146 /* functions names must be treated as function pointers,
5147 except for unary '&' and sizeof. Since we consider that
5148 functions are not lvalues, we only have to handle it
5149 there and in function calls. */
5150 /* arrays can also be used although they are not lvalues */
5151 if ((vtop->t & VT_BTYPE) != VT_FUNC &&
5152 !(vtop->t & VT_ARRAY))
5153 test_lvalue();
5154 vtop->t = mk_pointer(vtop->t);
5155 gaddrof();
5156 } else
5157 if (t == '!') {
5158 unary();
5159 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST)
5160 vtop->c.i = !vtop->c.i;
5161 else if ((vtop->r & VT_VALMASK) == VT_CMP)
5162 vtop->c.i = vtop->c.i ^ 1;
5163 else
5164 vset(VT_INT, VT_JMP, gtst(1, 0));
5165 } else
5166 if (t == '~') {
5167 unary();
5168 vpushi(-1);
5169 gen_op('^');
5170 } else
5171 if (t == '+') {
5172 /* in order to force cast, we add zero */
5173 unary();
5174 if ((vtop->t & VT_BTYPE) == VT_PTR)
5175 error("pointer not accepted for unary plus");
5176 vpushi(0);
5177 gen_op('+');
5178 } else
5179 if (t == TOK_SIZEOF) {
5180 if (tok == '(') {
5181 next();
5182 if (parse_btype(&t, &ad)) {
5183 t = type_decl(&ad, &n, t, TYPE_ABSTRACT);
5184 } else {
5185 /* XXX: some code could be generated: add eval
5186 flag */
5187 gexpr();
5188 t = vtop->t;
5189 vpop();
5191 skip(')');
5192 } else {
5193 unary();
5194 t = vtop->t;
5195 vpop();
5197 vpushi(type_size(t, &t));
5198 } else
5199 if (t == TOK_INC || t == TOK_DEC) {
5200 unary();
5201 inc(0, t);
5202 } else if (t == '-') {
5203 vpushi(0);
5204 unary();
5205 gen_op('-');
5206 } else
5208 if (t < TOK_UIDENT)
5209 expect("identifier");
5210 s = sym_find(t);
5211 if (!s) {
5212 if (tok != '(')
5213 error("'%s' undeclared", get_tok_str(t, NULL));
5214 /* for simple function calls, we tolerate undeclared
5215 external reference to int() function */
5216 s = external_global_sym(t, func_old_type, 0);
5218 vset(s->t, s->r, s->c);
5219 /* if forward reference, we must point to s */
5220 if (vtop->r & VT_SYM) {
5221 vtop->sym = s;
5222 vtop->c.ul = 0;
5227 /* post operations */
5228 while (1) {
5229 if (tok == TOK_INC || tok == TOK_DEC) {
5230 inc(1, tok);
5231 next();
5232 } else if (tok == '.' || tok == TOK_ARROW) {
5233 /* field */
5234 if (tok == TOK_ARROW)
5235 indir();
5236 test_lvalue();
5237 gaddrof();
5238 next();
5239 /* expect pointer on structure */
5240 if ((vtop->t & VT_BTYPE) != VT_STRUCT)
5241 expect("struct or union");
5242 s = sym_find(((unsigned)vtop->t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
5243 /* find field */
5244 tok |= SYM_FIELD;
5245 while ((s = s->next) != NULL) {
5246 if (s->v == tok)
5247 break;
5249 if (!s)
5250 error("field not found");
5251 /* add field offset to pointer */
5252 vtop->t = char_pointer_type; /* change type to 'char *' */
5253 vpushi(s->c);
5254 gen_op('+');
5255 /* change type to field type, and set to lvalue */
5256 vtop->t = s->t;
5257 /* an array is never an lvalue */
5258 if (!(vtop->t & VT_ARRAY)) {
5259 vtop->r |= lvalue_type(vtop->t);
5260 /* if bound checking, the referenced pointer must be checked */
5261 if (do_bounds_check)
5262 vtop->r |= VT_MUSTBOUND;
5264 next();
5265 } else if (tok == '[') {
5266 next();
5267 gexpr();
5268 gen_op('+');
5269 indir();
5270 skip(']');
5271 } else if (tok == '(') {
5272 SValue ret;
5273 Sym *sa;
5275 /* function call */
5276 if ((vtop->t & VT_BTYPE) != VT_FUNC) {
5277 /* pointer test (no array accepted) */
5278 if ((vtop->t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
5279 vtop->t = pointed_type(vtop->t);
5280 if ((vtop->t & VT_BTYPE) != VT_FUNC)
5281 goto error_func;
5282 } else {
5283 error_func:
5284 expect("function pointer");
5286 } else {
5287 vtop->r &= ~VT_LVAL; /* no lvalue */
5289 /* get return type */
5290 s = sym_find((unsigned)vtop->t >> VT_STRUCT_SHIFT);
5291 save_regs(0); /* save used temporary registers */
5292 gfunc_start(&gf, s->r);
5293 next();
5294 sa = s->next; /* first parameter */
5295 #ifdef INVERT_FUNC_PARAMS
5297 int parlevel;
5298 Sym *args, *s1;
5299 ParseState saved_parse_state;
5300 TokenString str;
5302 /* read each argument and store it on a stack */
5303 args = NULL;
5304 if (tok != ')') {
5305 for(;;) {
5306 tok_str_new(&str);
5307 parlevel = 0;
5308 while ((parlevel > 0 || (tok != ')' && tok != ',')) &&
5309 tok != TOK_EOF) {
5310 if (tok == '(')
5311 parlevel++;
5312 else if (tok == ')')
5313 parlevel--;
5314 tok_str_add_tok(&str);
5315 next();
5317 tok_str_add(&str, -1); /* end of file added */
5318 tok_str_add(&str, 0);
5319 s1 = sym_push2(&args, 0, 0, (int)str.str);
5320 s1->next = sa; /* add reference to argument */
5321 if (sa)
5322 sa = sa->next;
5323 if (tok == ')')
5324 break;
5325 skip(',');
5329 /* now generate code in reverse order by reading the stack */
5330 save_parse_state(&saved_parse_state);
5331 while (args) {
5332 macro_ptr = (int *)args->c;
5333 next();
5334 expr_eq();
5335 if (tok != -1)
5336 expect("',' or ')'");
5337 gfunc_param_typed(&gf, s, args->next);
5338 s1 = args->prev;
5339 tok_str_free((int *)args->c);
5340 tcc_free(args);
5341 args = s1;
5343 restore_parse_state(&saved_parse_state);
5345 #endif
5346 /* compute first implicit argument if a structure is returned */
5347 if ((s->t & VT_BTYPE) == VT_STRUCT) {
5348 /* get some space for the returned structure */
5349 size = type_size(s->t, &align);
5350 loc = (loc - size) & -align;
5351 ret.t = s->t;
5352 ret.r = VT_LOCAL | VT_LVAL;
5353 /* pass it as 'int' to avoid structure arg passing
5354 problems */
5355 vset(VT_INT, VT_LOCAL, loc);
5356 ret.c = vtop->c;
5357 gfunc_param(&gf);
5358 } else {
5359 ret.t = s->t;
5360 ret.r2 = VT_CONST;
5361 /* return in register */
5362 if (is_float(ret.t)) {
5363 ret.r = REG_FRET;
5364 } else {
5365 if ((ret.t & VT_BTYPE) == VT_LLONG)
5366 ret.r2 = REG_LRET;
5367 ret.r = REG_IRET;
5369 ret.c.i = 0;
5371 #ifndef INVERT_FUNC_PARAMS
5372 if (tok != ')') {
5373 for(;;) {
5374 expr_eq();
5375 gfunc_param_typed(&gf, s, sa);
5376 if (sa)
5377 sa = sa->next;
5378 if (tok == ')')
5379 break;
5380 skip(',');
5383 #endif
5384 if (sa)
5385 error("too few arguments to function");
5386 skip(')');
5387 gfunc_call(&gf);
5388 /* return value */
5389 vsetc(ret.t, ret.r, &ret.c);
5390 vtop->r2 = ret.r2;
5391 } else {
5392 break;
5397 void uneq(void)
5399 int t;
5401 unary();
5402 if (tok == '=' ||
5403 (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
5404 tok == TOK_A_XOR || tok == TOK_A_OR ||
5405 tok == TOK_A_SHL || tok == TOK_A_SAR) {
5406 test_lvalue();
5407 t = tok;
5408 next();
5409 if (t == '=') {
5410 expr_eq();
5411 } else {
5412 vdup();
5413 expr_eq();
5414 gen_op(t & 0x7f);
5416 vstore();
5420 void sum(int l)
5422 int t;
5424 if (l == 0)
5425 uneq();
5426 else {
5427 sum(--l);
5428 while ((l == 0 && (tok == '*' || tok == '/' || tok == '%')) ||
5429 (l == 1 && (tok == '+' || tok == '-')) ||
5430 (l == 2 && (tok == TOK_SHL || tok == TOK_SAR)) ||
5431 (l == 3 && ((tok >= TOK_ULE && tok <= TOK_GT) ||
5432 tok == TOK_ULT || tok == TOK_UGE)) ||
5433 (l == 4 && (tok == TOK_EQ || tok == TOK_NE)) ||
5434 (l == 5 && tok == '&') ||
5435 (l == 6 && tok == '^') ||
5436 (l == 7 && tok == '|') ||
5437 (l == 8 && tok == TOK_LAND) ||
5438 (l == 9 && tok == TOK_LOR)) {
5439 t = tok;
5440 next();
5441 sum(l);
5442 gen_op(t);
5447 /* only used if non constant */
5448 void eand(void)
5450 int t;
5452 sum(8);
5453 t = 0;
5454 while (1) {
5455 if (tok != TOK_LAND) {
5456 if (t) {
5457 t = gtst(1, t);
5458 vset(VT_INT, VT_JMPI, t);
5460 break;
5462 t = gtst(1, t);
5463 next();
5464 sum(8);
5468 void eor(void)
5470 int t;
5472 eand();
5473 t = 0;
5474 while (1) {
5475 if (tok != TOK_LOR) {
5476 if (t) {
5477 t = gtst(0, t);
5478 vset(VT_INT, VT_JMP, t);
5480 break;
5482 t = gtst(0, t);
5483 next();
5484 eand();
5488 /* XXX: better constant handling */
5489 void expr_eq(void)
5491 int tt, u, r1, r2, rc, t1, t2, t, bt1, bt2;
5492 SValue sv;
5494 if (const_wanted) {
5495 int c1, c;
5496 sum(10);
5497 if (tok == '?') {
5498 c = vtop->c.i;
5499 vpop();
5500 next();
5501 gexpr();
5502 c1 = vtop->c.i;
5503 vpop();
5504 skip(':');
5505 expr_eq();
5506 if (c)
5507 vtop->c.i = c1;
5509 } else {
5510 eor();
5511 if (tok == '?') {
5512 next();
5513 save_regs(1); /* we need to save all registers here except
5514 at the top because it is a branch point */
5515 tt = gtst(1, 0);
5516 gexpr();
5517 t1 = vtop->t;
5518 bt1 = t1 & VT_BTYPE;
5519 sv = *vtop; /* save value to handle it later */
5520 vtop--; /* no vpop so that FP stack is not flushed */
5521 skip(':');
5522 u = gjmp(0);
5524 gsym(tt);
5525 expr_eq();
5526 t2 = vtop->t;
5528 bt2 = t2 & VT_BTYPE;
5529 /* cast operands to correct type according to ISOC rules */
5530 if (is_float(bt1) || is_float(bt2)) {
5531 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
5532 t = VT_LDOUBLE;
5533 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
5534 t = VT_DOUBLE;
5535 } else {
5536 t = VT_FLOAT;
5538 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
5539 /* cast to biggest op */
5540 t = VT_LLONG;
5541 /* convert to unsigned if it does not fit in a long long */
5542 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
5543 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
5544 t |= VT_UNSIGNED;
5545 } else if (bt1 == VT_PTR || bt2 == VT_PTR) {
5546 /* XXX: test pointer compatibility */
5547 t = t1;
5548 } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
5549 /* XXX: test structure compatibility */
5550 t = t1;
5551 } else if (bt1 == VT_VOID || bt2 == VT_VOID) {
5552 /* NOTE: as an extension, we accept void on only one side */
5553 t = VT_VOID;
5554 } else {
5555 /* integer operations */
5556 t = VT_INT;
5557 /* convert to unsigned if it does not fit in an integer */
5558 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
5559 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
5560 t |= VT_UNSIGNED;
5563 /* now we convert second operand */
5564 gen_cast(t);
5565 rc = RC_INT;
5566 if (is_float(t)) {
5567 rc = RC_FLOAT;
5568 } else if ((t & VT_BTYPE) == VT_LLONG) {
5569 /* for long longs, we use fixed registers to avoid having
5570 to handle a complicated move */
5571 rc = RC_IRET;
5573 r2 = gv(rc);
5574 /* this is horrible, but we must also convert first
5575 operand */
5576 tt = gjmp(0);
5577 gsym(u);
5578 /* put again first value and cast it */
5579 *vtop = sv;
5580 gen_cast(t);
5581 r1 = gv(rc);
5582 move_reg(r2, r1);
5583 vtop->r = r2;
5584 gsym(tt);
5589 void gexpr(void)
5591 while (1) {
5592 expr_eq();
5593 if (tok != ',')
5594 break;
5595 vpop();
5596 next();
5600 /* parse a constant expression and return value in vtop. */
5601 static void expr_const1(void)
5603 int a;
5604 a = const_wanted;
5605 const_wanted = 1;
5606 expr_eq();
5607 const_wanted = a;
5610 /* parse an integer constant and return its value. */
5611 static int expr_const(void)
5613 int c;
5614 expr_const1();
5615 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
5616 expect("constant expression");
5617 c = vtop->c.i;
5618 vpop();
5619 return c;
5622 /* return the label token if current token is a label, otherwise
5623 return zero */
5624 int is_label(void)
5626 int t;
5627 CValue c;
5629 /* fast test first */
5630 if (tok < TOK_UIDENT)
5631 return 0;
5632 /* no need to save tokc since we expect an identifier */
5633 t = tok;
5634 c = tokc;
5635 next();
5636 if (tok == ':') {
5637 next();
5638 return t;
5639 } else {
5640 /* XXX: may not work in all cases (macros ?) */
5641 tok1 = tok;
5642 tok1c = tokc;
5643 tok = t;
5644 tokc = c;
5645 return 0;
5649 void block(int *bsym, int *csym, int *case_sym, int *def_sym, int case_reg)
5651 int a, b, c, d;
5652 Sym *s;
5654 /* generate line number info */
5655 if (do_debug &&
5656 (last_line_num != file->line_num || last_ind != ind)) {
5657 put_stabn(N_SLINE, 0, file->line_num, ind - func_ind);
5658 last_ind = ind;
5659 last_line_num = file->line_num;
5662 if (tok == TOK_IF) {
5663 /* if test */
5664 next();
5665 skip('(');
5666 gexpr();
5667 skip(')');
5668 a = gtst(1, 0);
5669 block(bsym, csym, case_sym, def_sym, case_reg);
5670 c = tok;
5671 if (c == TOK_ELSE) {
5672 next();
5673 d = gjmp(0);
5674 gsym(a);
5675 block(bsym, csym, case_sym, def_sym, case_reg);
5676 gsym(d); /* patch else jmp */
5677 } else
5678 gsym(a);
5679 } else if (tok == TOK_WHILE) {
5680 next();
5681 d = ind;
5682 skip('(');
5683 gexpr();
5684 skip(')');
5685 a = gtst(1, 0);
5686 b = 0;
5687 block(&a, &b, case_sym, def_sym, case_reg);
5688 gjmp_addr(d);
5689 gsym(a);
5690 gsym_addr(b, d);
5691 } else if (tok == '{') {
5692 next();
5693 /* declarations */
5694 s = local_stack.top;
5695 while (tok != '}') {
5696 decl(VT_LOCAL);
5697 if (tok != '}')
5698 block(bsym, csym, case_sym, def_sym, case_reg);
5700 /* pop locally defined symbols */
5701 sym_pop(&local_stack, s);
5702 next();
5703 } else if (tok == TOK_RETURN) {
5704 next();
5705 if (tok != ';') {
5706 gexpr();
5707 gen_assign_cast(func_vt);
5708 if ((func_vt & VT_BTYPE) == VT_STRUCT) {
5709 /* if returning structure, must copy it to implicit
5710 first pointer arg location */
5711 vset(mk_pointer(func_vt), VT_LOCAL | VT_LVAL, func_vc);
5712 indir();
5713 vswap();
5714 /* copy structure value to pointer */
5715 vstore();
5716 } else if (is_float(func_vt)) {
5717 gv(RC_FRET);
5718 } else {
5719 gv(RC_IRET);
5721 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
5723 skip(';');
5724 rsym = gjmp(rsym); /* jmp */
5725 } else if (tok == TOK_BREAK) {
5726 /* compute jump */
5727 if (!bsym)
5728 error("cannot break");
5729 *bsym = gjmp(*bsym);
5730 next();
5731 skip(';');
5732 } else if (tok == TOK_CONTINUE) {
5733 /* compute jump */
5734 if (!csym)
5735 error("cannot continue");
5736 *csym = gjmp(*csym);
5737 next();
5738 skip(';');
5739 } else if (tok == TOK_FOR) {
5740 int e;
5741 next();
5742 skip('(');
5743 if (tok != ';') {
5744 gexpr();
5745 vpop();
5747 skip(';');
5748 d = ind;
5749 c = ind;
5750 a = 0;
5751 b = 0;
5752 if (tok != ';') {
5753 gexpr();
5754 a = gtst(1, 0);
5756 skip(';');
5757 if (tok != ')') {
5758 e = gjmp(0);
5759 c = ind;
5760 gexpr();
5761 vpop();
5762 gjmp_addr(d);
5763 gsym(e);
5765 skip(')');
5766 block(&a, &b, case_sym, def_sym, case_reg);
5767 gjmp_addr(c);
5768 gsym(a);
5769 gsym_addr(b, c);
5770 } else
5771 if (tok == TOK_DO) {
5772 next();
5773 a = 0;
5774 b = 0;
5775 d = ind;
5776 block(&a, &b, case_sym, def_sym, case_reg);
5777 skip(TOK_WHILE);
5778 skip('(');
5779 gsym(b);
5780 gexpr();
5781 c = gtst(0, 0);
5782 gsym_addr(c, d);
5783 skip(')');
5784 gsym(a);
5785 skip(';');
5786 } else
5787 if (tok == TOK_SWITCH) {
5788 next();
5789 skip('(');
5790 gexpr();
5791 /* XXX: other types than integer */
5792 case_reg = gv(RC_INT);
5793 vpop();
5794 skip(')');
5795 a = 0;
5796 b = gjmp(0); /* jump to first case */
5797 c = 0;
5798 block(&a, csym, &b, &c, case_reg);
5799 /* if no default, jmp after switch */
5800 if (c == 0)
5801 c = ind;
5802 /* default label */
5803 gsym_addr(b, c);
5804 /* break label */
5805 gsym(a);
5806 } else
5807 if (tok == TOK_CASE) {
5808 int v1, v2;
5809 if (!case_sym)
5810 expect("switch");
5811 next();
5812 v1 = expr_const();
5813 v2 = v1;
5814 if (gnu_ext && tok == TOK_DOTS) {
5815 next();
5816 v2 = expr_const();
5817 if (v2 < v1)
5818 warning("empty case range");
5820 /* since a case is like a label, we must skip it with a jmp */
5821 b = gjmp(0);
5822 gsym(*case_sym);
5823 vset(VT_INT, case_reg, 0);
5824 vpushi(v1);
5825 if (v1 == v2) {
5826 gen_op(TOK_EQ);
5827 *case_sym = gtst(1, 0);
5828 } else {
5829 gen_op(TOK_GE);
5830 *case_sym = gtst(1, 0);
5831 vset(VT_INT, case_reg, 0);
5832 vpushi(v2);
5833 gen_op(TOK_LE);
5834 *case_sym = gtst(1, *case_sym);
5836 gsym(b);
5837 skip(':');
5838 block(bsym, csym, case_sym, def_sym, case_reg);
5839 } else
5840 if (tok == TOK_DEFAULT) {
5841 next();
5842 skip(':');
5843 if (!def_sym)
5844 expect("switch");
5845 if (*def_sym)
5846 error("too many 'default'");
5847 *def_sym = ind;
5848 block(bsym, csym, case_sym, def_sym, case_reg);
5849 } else
5850 if (tok == TOK_GOTO) {
5851 next();
5852 s = sym_find1(&label_stack, tok);
5853 /* put forward definition if needed */
5854 if (!s)
5855 s = sym_push1(&label_stack, tok, LABEL_FORWARD, 0);
5856 /* label already defined */
5857 if (s->t & LABEL_FORWARD)
5858 s->c = gjmp(s->c);
5859 else
5860 gjmp_addr(s->c);
5861 next();
5862 skip(';');
5863 } else {
5864 b = is_label();
5865 if (b) {
5866 /* label case */
5867 s = sym_find1(&label_stack, b);
5868 if (s) {
5869 if (!(s->t & LABEL_FORWARD))
5870 error("multiple defined label");
5871 gsym(s->c);
5872 s->c = ind;
5873 s->t = 0;
5874 } else {
5875 sym_push1(&label_stack, b, 0, ind);
5877 /* we accept this, but it is a mistake */
5878 if (tok == '}')
5879 warning("deprecated use of label at end of compound statement");
5880 else
5881 block(bsym, csym, case_sym, def_sym, case_reg);
5882 } else {
5883 /* expression case */
5884 if (tok != ';') {
5885 gexpr();
5886 vpop();
5888 skip(';');
5893 /* t is the array or struct type. c is the array or struct
5894 address. cur_index/cur_field is the pointer to the current
5895 value. 'size_only' is true if only size info is needed (only used
5896 in arrays) */
5897 static void decl_designator(int t, Section *sec, unsigned long c,
5898 int *cur_index, Sym **cur_field,
5899 int size_only)
5901 Sym *s, *f;
5902 int notfirst, index, align, l;
5904 notfirst = 0;
5905 if (gnu_ext && (l = is_label()) != 0)
5906 goto struct_field;
5908 while (tok == '[' || tok == '.') {
5909 if (tok == '[') {
5910 if (!(t & VT_ARRAY))
5911 expect("array type");
5912 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
5913 next();
5914 index = expr_const();
5915 if (index < 0 || (s->c >= 0 && index >= s->c))
5916 expect("invalid index");
5917 skip(']');
5918 if (!notfirst)
5919 *cur_index = index;
5920 t = pointed_type(t);
5921 c += index * type_size(t, &align);
5922 } else {
5923 next();
5924 l = tok;
5925 next();
5926 struct_field:
5927 if ((t & VT_BTYPE) != VT_STRUCT)
5928 expect("struct/union type");
5929 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
5930 l |= SYM_FIELD;
5931 f = s->next;
5932 while (f) {
5933 if (f->v == l)
5934 break;
5935 f = f->next;
5937 if (!f)
5938 expect("field");
5939 if (!notfirst)
5940 *cur_field = f;
5941 t = f->t | (t & ~VT_TYPE);
5942 c += f->c;
5944 notfirst = 1;
5946 if (notfirst) {
5947 if (tok == '=') {
5948 next();
5949 } else {
5950 if (!gnu_ext)
5951 expect("=");
5953 } else {
5954 if (t & VT_ARRAY) {
5955 index = *cur_index;
5956 t = pointed_type(t);
5957 c += index * type_size(t, &align);
5958 } else {
5959 f = *cur_field;
5960 if (!f)
5961 error("too many field init");
5962 t = f->t | (t & ~VT_TYPE);
5963 c += f->c;
5966 decl_initializer(t, sec, c, 0, size_only);
5969 #define EXPR_VAL 0
5970 #define EXPR_CONST 1
5971 #define EXPR_ANY 2
5973 /* store a value or an expression directly in global data or in local array */
5974 static void init_putv(int t, Section *sec, unsigned long c,
5975 int v, int expr_type)
5977 int saved_global_expr, bt;
5978 void *ptr;
5980 switch(expr_type) {
5981 case EXPR_VAL:
5982 vpushi(v);
5983 break;
5984 case EXPR_CONST:
5985 /* compound literals must be allocated globally in this case */
5986 saved_global_expr = global_expr;
5987 global_expr = 1;
5988 expr_const1();
5989 global_expr = saved_global_expr;
5990 /* NOTE: symbols are accepted */
5991 if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST)
5992 error("initializer element is not constant");
5993 break;
5994 case EXPR_ANY:
5995 expr_eq();
5996 break;
5999 if (sec) {
6000 /* XXX: not portable */
6001 /* XXX: generate error if incorrect relocation */
6002 gen_assign_cast(t);
6003 bt = t & VT_BTYPE;
6004 ptr = sec->data + c;
6005 if ((vtop->r & VT_SYM) &&
6006 (bt == VT_BYTE ||
6007 bt == VT_SHORT ||
6008 bt == VT_DOUBLE ||
6009 bt == VT_LDOUBLE ||
6010 bt == VT_LLONG))
6011 error("initializer element is not computable at load time");
6012 switch(bt) {
6013 case VT_BYTE:
6014 *(char *)ptr = vtop->c.i;
6015 break;
6016 case VT_SHORT:
6017 *(short *)ptr = vtop->c.i;
6018 break;
6019 case VT_DOUBLE:
6020 *(double *)ptr = vtop->c.d;
6021 break;
6022 case VT_LDOUBLE:
6023 *(long double *)ptr = vtop->c.ld;
6024 break;
6025 case VT_LLONG:
6026 *(long long *)ptr = vtop->c.ll;
6027 break;
6028 default:
6029 if (vtop->r & VT_SYM) {
6030 greloc(sec, vtop->sym, c, R_DATA_32);
6032 *(int *)ptr = vtop->c.i;
6033 break;
6035 vtop--;
6036 } else {
6037 vset(t, VT_LOCAL, c);
6038 vswap();
6039 vstore();
6040 vpop();
6044 /* put zeros for variable based init */
6045 static void init_putz(int t, Section *sec, unsigned long c, int size)
6047 GFuncContext gf;
6049 if (sec) {
6050 /* nothing to do because globals are already set to zero */
6051 } else {
6052 gfunc_start(&gf, FUNC_CDECL);
6053 vpushi(size);
6054 gfunc_param(&gf);
6055 vpushi(0);
6056 gfunc_param(&gf);
6057 vset(VT_INT, VT_LOCAL, c);
6058 gfunc_param(&gf);
6059 vpush_global_sym(func_old_type, TOK_memset);
6060 gfunc_call(&gf);
6064 /* 't' contains the type and storage info. 'c' is the offset of the
6065 object in section 'sec'. If 'sec' is NULL, it means stack based
6066 allocation. 'first' is true if array '{' must be read (multi
6067 dimension implicit array init handling). 'size_only' is true if
6068 size only evaluation is wanted (only for arrays). */
6069 static void decl_initializer(int t, Section *sec, unsigned long c,
6070 int first, int size_only)
6072 int index, array_length, n, no_oblock, nb, parlevel, i;
6073 int t1, size1, align1, expr_type;
6074 Sym *s, *f;
6076 if (t & VT_ARRAY) {
6077 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
6078 n = s->c;
6079 array_length = 0;
6080 t1 = pointed_type(t);
6081 size1 = type_size(t1, &align1);
6083 no_oblock = 1;
6084 if ((first && tok != TOK_LSTR && tok != TOK_STR) ||
6085 tok == '{') {
6086 skip('{');
6087 no_oblock = 0;
6090 /* only parse strings here if correct type (otherwise: handle
6091 them as ((w)char *) expressions */
6092 if ((tok == TOK_LSTR &&
6093 (t1 & VT_BTYPE) == VT_INT) ||
6094 (tok == TOK_STR &&
6095 (t1 & VT_BTYPE) == VT_BYTE)) {
6096 while (tok == TOK_STR || tok == TOK_LSTR) {
6097 int cstr_len, ch;
6098 CString *cstr;
6100 cstr = tokc.cstr;
6101 /* compute maximum number of chars wanted */
6102 if (tok == TOK_STR)
6103 cstr_len = cstr->size;
6104 else
6105 cstr_len = cstr->size / sizeof(int);
6106 cstr_len--;
6107 nb = cstr_len;
6108 if (n >= 0 && nb > (n - array_length))
6109 nb = n - array_length;
6110 if (!size_only) {
6111 if (cstr_len > nb)
6112 warning("initializer-string for array is too long");
6113 for(i=0;i<nb;i++) {
6114 if (tok == TOK_STR)
6115 ch = ((unsigned char *)cstr->data)[i];
6116 else
6117 ch = ((int *)cstr->data)[i];
6118 init_putv(t1, sec, c + (array_length + i) * size1,
6119 ch, EXPR_VAL);
6122 array_length += nb;
6123 next();
6125 /* only add trailing zero if enough storage (no
6126 warning in this case since it is standard) */
6127 if (n < 0 || array_length < n) {
6128 if (!size_only) {
6129 init_putv(t1, sec, c + (array_length * size1), 0, EXPR_VAL);
6131 array_length++;
6133 } else {
6134 index = 0;
6135 while (tok != '}') {
6136 decl_designator(t, sec, c, &index, NULL, size_only);
6137 if (n >= 0 && index >= n)
6138 error("index too large");
6139 /* must put zero in holes (note that doing it that way
6140 ensures that it even works with designators) */
6141 if (!size_only && array_length < index) {
6142 init_putz(t1, sec, c + array_length * size1,
6143 (index - array_length) * size1);
6145 index++;
6146 if (index > array_length)
6147 array_length = index;
6148 /* special test for multi dimensional arrays (may not
6149 be strictly correct if designators are used at the
6150 same time) */
6151 if (index >= n && no_oblock)
6152 break;
6153 if (tok == '}')
6154 break;
6155 skip(',');
6158 if (!no_oblock)
6159 skip('}');
6160 /* put zeros at the end */
6161 if (!size_only && n >= 0 && array_length < n) {
6162 init_putz(t1, sec, c + array_length * size1,
6163 (n - array_length) * size1);
6165 /* patch type size if needed */
6166 if (n < 0)
6167 s->c = array_length;
6168 } else if ((t & VT_BTYPE) == VT_STRUCT && tok == '{') {
6169 /* XXX: union needs only one init */
6170 next();
6171 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
6172 f = s->next;
6173 array_length = 0;
6174 index = 0;
6175 n = s->c;
6176 while (tok != '}') {
6177 decl_designator(t, sec, c, NULL, &f, size_only);
6178 /* fill with zero between fields */
6179 index = f->c;
6180 if (!size_only && array_length < index) {
6181 init_putz(t, sec, c + array_length,
6182 index - array_length);
6184 index = index + type_size(f->t, &align1);
6185 if (index > array_length)
6186 array_length = index;
6187 if (tok == '}')
6188 break;
6189 skip(',');
6190 f = f->next;
6192 /* put zeros at the end */
6193 if (!size_only && array_length < n) {
6194 init_putz(t, sec, c + array_length,
6195 n - array_length);
6197 skip('}');
6198 } else if (tok == '{') {
6199 next();
6200 decl_initializer(t, sec, c, first, size_only);
6201 skip('}');
6202 } else if (size_only) {
6203 /* just skip expression */
6204 parlevel = 0;
6205 while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
6206 tok != -1) {
6207 if (tok == '(')
6208 parlevel++;
6209 else if (tok == ')')
6210 parlevel--;
6211 next();
6213 } else {
6214 /* currently, we always use constant expression for globals
6215 (may change for scripting case) */
6216 expr_type = EXPR_CONST;
6217 if (!sec)
6218 expr_type = EXPR_ANY;
6219 init_putv(t, sec, c, 0, expr_type);
6223 /* parse an initializer for type 't' if 'has_init' is non zero, and
6224 allocate space in local or global data space ('r' is either
6225 VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
6226 variable 'v' of scope 'scope' is declared before initializers are
6227 parsed. If 'v' is zero, then a reference to the new object is put
6228 in the value stack. If 'has_init' is 2, a special parsing is done
6229 to handle string constants. */
6230 static void decl_initializer_alloc(int t, AttributeDef *ad, int r,
6231 int has_init, int v, int scope)
6233 int size, align, addr, data_offset;
6234 int level;
6235 ParseState saved_parse_state;
6236 TokenString init_str;
6237 Section *sec;
6239 size = type_size(t, &align);
6240 /* If unknown size, we must evaluate it before
6241 evaluating initializers because
6242 initializers can generate global data too
6243 (e.g. string pointers or ISOC99 compound
6244 literals). It also simplifies local
6245 initializers handling */
6246 tok_str_new(&init_str);
6247 if (size < 0) {
6248 if (!has_init)
6249 error("unknown type size");
6250 /* get all init string */
6251 if (has_init == 2) {
6252 /* only get strings */
6253 while (tok == TOK_STR || tok == TOK_LSTR) {
6254 tok_str_add_tok(&init_str);
6255 next();
6257 } else {
6258 level = 0;
6259 while (level > 0 || (tok != ',' && tok != ';')) {
6260 if (tok < 0)
6261 error("unexpected end of file in initializer");
6262 tok_str_add_tok(&init_str);
6263 if (tok == '{')
6264 level++;
6265 else if (tok == '}') {
6266 if (level == 0)
6267 break;
6268 level--;
6270 next();
6273 tok_str_add(&init_str, -1);
6274 tok_str_add(&init_str, 0);
6276 /* compute size */
6277 save_parse_state(&saved_parse_state);
6279 macro_ptr = init_str.str;
6280 next();
6281 decl_initializer(t, NULL, 0, 1, 1);
6282 /* prepare second initializer parsing */
6283 macro_ptr = init_str.str;
6284 next();
6286 /* if still unknown size, error */
6287 size = type_size(t, &align);
6288 if (size < 0)
6289 error("unknown type size");
6291 /* take into account specified alignment if bigger */
6292 if (ad->aligned > align)
6293 align = ad->aligned;
6294 if ((r & VT_VALMASK) == VT_LOCAL) {
6295 sec = NULL;
6296 if (do_bounds_check && (t & VT_ARRAY))
6297 loc--;
6298 #ifdef TCC_TARGET_IL
6299 /* XXX: ugly patch to allocate local variables for IL, just
6300 for testing */
6301 addr = loc;
6302 loc++;
6303 #else
6304 loc = (loc - size) & -align;
6305 addr = loc;
6306 #endif
6307 /* handles bounds */
6308 /* XXX: currently, since we do only one pass, we cannot track
6309 '&' operators, so we add only arrays */
6310 if (do_bounds_check && (t & VT_ARRAY)) {
6311 unsigned long *bounds_ptr;
6312 /* add padding between regions */
6313 loc--;
6314 /* then add local bound info */
6315 bounds_ptr = section_ptr_add(lbounds_section, 2 * sizeof(unsigned long));
6316 bounds_ptr[0] = addr;
6317 bounds_ptr[1] = size;
6319 } else {
6320 /* compute section */
6321 sec = ad->section;
6322 if (!sec) {
6323 if (has_init)
6324 sec = data_section;
6325 else
6326 sec = bss_section;
6328 data_offset = sec->data_offset;
6329 data_offset = (data_offset + align - 1) & -align;
6330 addr = data_offset;
6331 /* very important to increment global pointer at this time
6332 because initializers themselves can create new initializers */
6333 data_offset += size;
6334 /* add padding if bound check */
6335 if (do_bounds_check)
6336 data_offset++;
6337 sec->data_offset = data_offset;
6338 /* allocate section space to put the data */
6339 if (sec->sh_type != SHT_NOBITS &&
6340 data_offset > sec->data_allocated)
6341 section_realloc(sec, data_offset);
6343 if (!sec) {
6344 if (v) {
6345 /* local variable */
6346 sym_push(v, t, r, addr);
6347 } else {
6348 /* push local reference */
6349 vset(t, r, addr);
6351 } else {
6352 Sym *sym;
6354 if (v) {
6355 if (scope == VT_CONST) {
6356 /* global scope: see if already defined */
6357 sym = sym_find(v);
6358 if (!sym)
6359 goto do_def;
6360 if (!is_compatible_types(sym->t, t))
6361 error("incompatible types for redefinition of '%s'",
6362 get_tok_str(v, NULL));
6363 if (!(sym->t & VT_EXTERN))
6364 error("redefinition of '%s'", get_tok_str(v, NULL));
6365 sym->t &= ~VT_EXTERN;
6366 } else {
6367 do_def:
6368 sym = sym_push(v, t, r | VT_SYM, 0);
6370 put_extern_sym(sym, sec, addr, size);
6371 } else {
6372 CValue cval;
6374 /* push global reference */
6375 sym = get_sym_ref(t, sec, addr, size);
6376 cval.ul = 0;
6377 vsetc(t, VT_CONST | VT_SYM, &cval);
6378 vtop->sym = sym;
6381 /* handles bounds now because the symbol must be defined
6382 before for the relocation */
6383 if (do_bounds_check) {
6384 unsigned long *bounds_ptr;
6386 greloc(bounds_section, sym, bounds_section->data_offset, R_DATA_32);
6387 /* then add global bound info */
6388 bounds_ptr = section_ptr_add(bounds_section, 2 * sizeof(long));
6389 bounds_ptr[0] = 0; /* relocated */
6390 bounds_ptr[1] = size;
6393 if (has_init) {
6394 decl_initializer(t, sec, addr, 1, 0);
6395 /* restore parse state if needed */
6396 if (init_str.str) {
6397 tok_str_free(init_str.str);
6398 restore_parse_state(&saved_parse_state);
6403 void put_func_debug(Sym *sym)
6405 char buf[512];
6407 /* stabs info */
6408 /* XXX: we put here a dummy type */
6409 snprintf(buf, sizeof(buf), "%s:%c1",
6410 funcname, sym->t & VT_STATIC ? 'f' : 'F');
6411 put_stabs_r(buf, N_FUN, 0, file->line_num, 0,
6412 cur_text_section, sym->c);
6413 last_ind = 0;
6414 last_line_num = 0;
6417 /* not finished : try to put some local vars in registers */
6418 //#define CONFIG_REG_VARS
6420 #ifdef CONFIG_REG_VARS
6421 void add_var_ref(int t)
6423 printf("%s:%d: &%s\n",
6424 file->filename, file->line_num,
6425 get_tok_str(t, NULL));
6428 /* first pass on a function with heuristic to extract variable usage
6429 and pointer references to local variables for register allocation */
6430 void analyse_function(void)
6432 int level, t;
6434 for(;;) {
6435 if (tok == -1)
6436 break;
6437 /* any symbol coming after '&' is considered as being a
6438 variable whose reference is taken. It is highly unaccurate
6439 but it is difficult to do better without a complete parse */
6440 if (tok == '&') {
6441 next();
6442 /* if '& number', then no need to examine next tokens */
6443 if (tok == TOK_CINT ||
6444 tok == TOK_CUINT ||
6445 tok == TOK_CLLONG ||
6446 tok == TOK_CULLONG) {
6447 continue;
6448 } else if (tok >= TOK_UIDENT) {
6449 /* if '& ident [' or '& ident ->', then ident address
6450 is not needed */
6451 t = tok;
6452 next();
6453 if (tok != '[' && tok != TOK_ARROW)
6454 add_var_ref(t);
6455 } else {
6456 level = 0;
6457 while (tok != '}' && tok != ';' &&
6458 !((tok == ',' || tok == ')') && level == 0)) {
6459 if (tok >= TOK_UIDENT) {
6460 add_var_ref(tok);
6461 } else if (tok == '(') {
6462 level++;
6463 } else if (tok == ')') {
6464 level--;
6466 next();
6469 } else {
6470 next();
6474 #endif
6476 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
6477 void decl(int l)
6479 int t, b, v, has_init, r;
6480 Sym *sym;
6481 AttributeDef ad;
6483 while (1) {
6484 if (!parse_btype(&b, &ad)) {
6485 /* skip redundant ';' */
6486 /* XXX: find more elegant solution */
6487 if (tok == ';') {
6488 next();
6489 continue;
6491 /* special test for old K&R protos without explicit int
6492 type. Only accepted when defining global data */
6493 if (l == VT_LOCAL || tok < TOK_DEFINE)
6494 break;
6495 b = VT_INT;
6497 if (((b & VT_BTYPE) == VT_ENUM ||
6498 (b & VT_BTYPE) == VT_STRUCT) &&
6499 tok == ';') {
6500 /* we accept no variable after */
6501 next();
6502 continue;
6504 while (1) { /* iterate thru each declaration */
6505 t = type_decl(&ad, &v, b, TYPE_DIRECT);
6506 #if 0
6508 char buf[500];
6509 type_to_str(buf, sizeof(buf), t, get_tok_str(v, NULL));
6510 printf("type = '%s'\n", buf);
6512 #endif
6513 if (tok == '{') {
6514 #ifdef CONFIG_REG_VARS
6515 TokenString func_str;
6516 ParseState saved_parse_state;
6517 int block_level;
6518 #endif
6520 if (l == VT_LOCAL)
6521 error("cannot use local functions");
6522 if (!(t & VT_FUNC))
6523 expect("function definition");
6525 #ifdef CONFIG_REG_VARS
6526 /* parse all function code and record it */
6528 tok_str_new(&func_str);
6530 block_level = 0;
6531 for(;;) {
6532 int t;
6533 if (tok == -1)
6534 error("unexpected end of file");
6535 tok_str_add_tok(&func_str);
6536 t = tok;
6537 next();
6538 if (t == '{') {
6539 block_level++;
6540 } else if (t == '}') {
6541 block_level--;
6542 if (block_level == 0)
6543 break;
6546 tok_str_add(&func_str, -1);
6547 tok_str_add(&func_str, 0);
6549 save_parse_state(&saved_parse_state);
6551 macro_ptr = func_str.str;
6552 next();
6553 analyse_function();
6554 #endif
6556 /* compute text section */
6557 cur_text_section = ad.section;
6558 if (!cur_text_section)
6559 cur_text_section = text_section;
6560 ind = cur_text_section->data_offset;
6561 funcname = get_tok_str(v, NULL);
6562 sym = sym_find(v);
6563 if (sym) {
6564 /* if symbol is already defined, then put complete type */
6565 sym->t = t;
6566 } else {
6567 /* put function symbol */
6568 sym = sym_push1(&global_stack, v, t, 0);
6570 /* NOTE: we patch the symbol size later */
6571 put_extern_sym(sym, cur_text_section, ind, 0);
6572 func_ind = ind;
6573 sym->r = VT_SYM | VT_CONST;
6574 /* put debug symbol */
6575 if (do_debug)
6576 put_func_debug(sym);
6577 /* push a dummy symbol to enable local sym storage */
6578 sym_push1(&local_stack, 0, 0, 0);
6579 gfunc_prolog(t);
6580 loc = 0;
6581 rsym = 0;
6582 #ifdef CONFIG_REG_VARS
6583 macro_ptr = func_str.str;
6584 next();
6585 #endif
6586 block(NULL, NULL, NULL, NULL, 0);
6587 gsym(rsym);
6588 gfunc_epilog();
6589 cur_text_section->data_offset = ind;
6590 sym_pop(&label_stack, NULL); /* reset label stack */
6591 sym_pop(&local_stack, NULL); /* reset local stack */
6592 /* end of function */
6593 /* patch symbol size */
6594 ((Elf32_Sym *)symtab_section->data)[sym->c].st_size =
6595 ind - func_ind;
6596 if (do_debug) {
6597 put_stabn(N_FUN, 0, 0, ind - func_ind);
6599 funcname = ""; /* for safety */
6600 func_vt = VT_VOID; /* for safety */
6601 ind = 0; /* for safety */
6603 #ifdef CONFIG_REG_VARS
6604 tok_str_free(func_str.str);
6605 restore_parse_state(&saved_parse_state);
6606 #endif
6607 break;
6608 } else {
6609 if (b & VT_TYPEDEF) {
6610 /* save typedefed type */
6611 /* XXX: test storage specifiers ? */
6612 sym_push(v, t | VT_TYPEDEF, 0, 0);
6613 } else if ((t & VT_BTYPE) == VT_FUNC) {
6614 /* external function definition */
6615 external_sym(v, t, 0);
6616 } else {
6617 /* not lvalue if array */
6618 r = 0;
6619 if (!(t & VT_ARRAY))
6620 r |= lvalue_type(t);
6621 if (b & VT_EXTERN) {
6622 /* external variable */
6623 external_sym(v, t, r);
6624 } else {
6625 if (t & VT_STATIC)
6626 r |= VT_CONST;
6627 else
6628 r |= l;
6629 has_init = (tok == '=');
6630 if (has_init)
6631 next();
6632 decl_initializer_alloc(t, &ad, r,
6633 has_init, v, l);
6636 if (tok != ',') {
6637 skip(';');
6638 break;
6640 next();
6646 /* compile the C file opened in 'file'. Return non zero if errors. */
6647 static int tcc_compile(TCCState *s)
6649 Sym *define_start, *sym;
6650 char buf[512];
6651 int p, section_sym;
6653 funcname = "";
6654 include_stack_ptr = include_stack;
6655 ifdef_stack_ptr = ifdef_stack;
6657 /* XXX: not ANSI compliant: bound checking says error */
6658 vtop = vstack - 1;
6659 anon_sym = SYM_FIRST_ANOM;
6661 /* file info: full path + filename */
6662 section_sym = 0; /* avoid warning */
6663 if (do_debug) {
6664 section_sym = put_elf_sym(symtab_section, 0, 0,
6665 ELF32_ST_INFO(STB_LOCAL, STT_SECTION), 0,
6666 text_section->sh_num, NULL);
6667 getcwd(buf, sizeof(buf));
6668 pstrcat(buf, sizeof(buf), "/");
6669 put_stabs_r(buf, N_SO, 0, 0,
6670 text_section->data_offset, text_section, section_sym);
6671 put_stabs_r(file->filename, N_SO, 0, 0,
6672 text_section->data_offset, text_section, section_sym);
6674 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
6675 symbols can be safely used */
6676 put_elf_sym(symtab_section, 0, 0,
6677 ELF32_ST_INFO(STB_LOCAL, STT_FILE), 0,
6678 SHN_ABS, file->filename);
6680 /* define common 'char *' type because it is often used internally
6681 for arrays and struct dereference */
6682 char_pointer_type = mk_pointer(VT_BYTE);
6683 /* define an old type function 'int func()' */
6684 p = anon_sym++;
6685 sym = sym_push(p, 0, FUNC_CDECL, FUNC_OLD);
6686 func_old_type = VT_FUNC | (p << VT_STRUCT_SHIFT);
6687 #if 0
6688 /* define 'void *alloca(unsigned int)' builtin function */
6690 Sym *s1;
6692 p = anon_sym++;
6693 sym = sym_push(p, mk_pointer(VT_VOID), FUNC_CDECL, FUNC_NEW);
6694 s1 = sym_push(0, VT_UNSIGNED | VT_INT, 0, 0);
6695 s1->next = NULL;
6696 sym->next = s1;
6697 sym_push(TOK_alloca, VT_FUNC | (p << VT_STRUCT_SHIFT), VT_CONST, 0);
6699 #endif
6701 define_start = define_stack.top;
6702 inp();
6703 ch = '\n'; /* needed to parse correctly first preprocessor command */
6704 next();
6705 decl(VT_CONST);
6706 if (tok != -1)
6707 expect("declaration");
6709 /* end of translation unit info */
6710 if (do_debug) {
6711 put_stabs_r(NULL, N_SO, 0, 0,
6712 text_section->data_offset, text_section, section_sym);
6715 /* reset define stack, but leave -Dsymbols (may be incorrect if
6716 they are undefined) */
6717 sym_pop(&define_stack, define_start);
6719 sym_pop(&global_stack, NULL);
6721 return 0;
6724 int tcc_compile_string(TCCState *s, const char *str)
6726 BufferedFile bf1, *bf = &bf1;
6727 int ret;
6729 /* init file structure */
6730 bf->fd = -1;
6731 bf->buf_ptr = (char *)str;
6732 bf->buf_end = (char *)str + strlen(bf->buffer);
6733 pstrcpy(bf->filename, sizeof(bf->filename), "<string>");
6734 bf->line_num = 1;
6735 file = bf;
6737 ret = tcc_compile(s);
6739 /* currently, no need to close */
6740 return ret;
6743 /* define a symbol. A value can also be provided with the '=' operator */
6744 void tcc_define_symbol(TCCState *s, const char *sym, const char *value)
6746 BufferedFile bf1, *bf = &bf1;
6748 pstrcpy(bf->buffer, IO_BUF_SIZE, sym);
6749 pstrcat(bf->buffer, IO_BUF_SIZE, " ");
6750 /* default value */
6751 if (!value)
6752 value = "1";
6753 pstrcat(bf->buffer, IO_BUF_SIZE, value);
6755 /* init file structure */
6756 bf->fd = -1;
6757 bf->buf_ptr = bf->buffer;
6758 bf->buf_end = bf->buffer + strlen(bf->buffer);
6759 bf->filename[0] = '\0';
6760 bf->line_num = 1;
6761 file = bf;
6763 include_stack_ptr = include_stack;
6765 /* parse with define parser */
6766 inp();
6767 ch = '\n'; /* needed to parse correctly first preprocessor command */
6768 next_nomacro();
6769 parse_define();
6770 file = NULL;
6773 void tcc_undefine_symbol(TCCState *s1, const char *sym)
6775 TokenSym *ts;
6776 Sym *s;
6777 ts = tok_alloc(sym, 0);
6778 s = sym_find1(&define_stack, tok);
6779 /* undefine symbol by putting an invalid name */
6780 if (s)
6781 sym_undef(&define_stack, s);
6784 #include "tccelf.c"
6786 /* print the position in the source file of PC value 'pc' by reading
6787 the stabs debug information */
6788 static void rt_printline(unsigned long wanted_pc)
6790 Stab_Sym *sym, *sym_end;
6791 char func_name[128], last_func_name[128];
6792 unsigned long func_addr, last_pc, pc;
6793 const char *incl_files[INCLUDE_STACK_SIZE];
6794 int incl_index, len, last_line_num, i;
6795 const char *str, *p;
6797 func_name[0] = '\0';
6798 func_addr = 0;
6799 incl_index = 0;
6800 last_func_name[0] = '\0';
6801 last_pc = 0xffffffff;
6802 last_line_num = 1;
6803 sym = (Stab_Sym *)stab_section->data + 1;
6804 sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset);
6805 while (sym < sym_end) {
6806 switch(sym->n_type) {
6807 /* function start or end */
6808 case N_FUN:
6809 if (sym->n_strx == 0) {
6810 func_name[0] = '\0';
6811 func_addr = 0;
6812 } else {
6813 str = stabstr_section->data + sym->n_strx;
6814 p = strchr(str, ':');
6815 if (!p) {
6816 pstrcpy(func_name, sizeof(func_name), str);
6817 } else {
6818 len = p - str;
6819 if (len > sizeof(func_name) - 1)
6820 len = sizeof(func_name) - 1;
6821 memcpy(func_name, str, len);
6822 func_name[len] = '\0';
6824 func_addr = sym->n_value;
6826 break;
6827 /* line number info */
6828 case N_SLINE:
6829 pc = sym->n_value + func_addr;
6830 if (wanted_pc >= last_pc && wanted_pc < pc)
6831 goto found;
6832 last_pc = pc;
6833 last_line_num = sym->n_desc;
6834 /* XXX: slow! */
6835 strcpy(last_func_name, func_name);
6836 break;
6837 /* include files */
6838 case N_BINCL:
6839 str = stabstr_section->data + sym->n_strx;
6840 add_incl:
6841 if (incl_index < INCLUDE_STACK_SIZE) {
6842 incl_files[incl_index++] = str;
6844 break;
6845 case N_EINCL:
6846 if (incl_index > 1)
6847 incl_index--;
6848 break;
6849 case N_SO:
6850 if (sym->n_strx == 0) {
6851 incl_index = 0; /* end of translation unit */
6852 } else {
6853 str = stabstr_section->data + sym->n_strx;
6854 /* do not add path */
6855 len = strlen(str);
6856 if (len > 0 && str[len - 1] != '/')
6857 goto add_incl;
6859 break;
6861 sym++;
6863 /* did not find line number info: */
6864 fprintf(stderr, "(no debug info, pc=0x%08lx): ", wanted_pc);
6865 return;
6866 found:
6867 for(i = 0; i < incl_index - 1; i++)
6868 fprintf(stderr, "In file included from %s\n",
6869 incl_files[i]);
6870 if (incl_index > 0) {
6871 fprintf(stderr, "%s:%d: ",
6872 incl_files[incl_index - 1], last_line_num);
6874 if (last_func_name[0] != '\0') {
6875 fprintf(stderr, "in function '%s()': ", last_func_name);
6879 /* emit a run time error at position 'pc' */
6880 void rt_error(unsigned long pc, const char *fmt, ...)
6882 va_list ap;
6883 va_start(ap, fmt);
6885 rt_printline(pc);
6886 vfprintf(stderr, fmt, ap);
6887 fprintf(stderr, "\n");
6888 exit(255);
6889 va_end(ap);
6892 #ifndef WIN32
6893 /* signal handler for fatal errors */
6894 static void sig_error(int signum, siginfo_t *siginf, void *puc)
6896 struct ucontext *uc = puc;
6897 unsigned long pc;
6899 #ifdef __i386__
6900 pc = uc->uc_mcontext.gregs[14];
6901 #else
6902 #error please put the right sigcontext field
6903 #endif
6905 switch(signum) {
6906 case SIGFPE:
6907 switch(siginf->si_code) {
6908 case FPE_INTDIV:
6909 case FPE_FLTDIV:
6910 rt_error(pc, "division by zero");
6911 break;
6912 default:
6913 rt_error(pc, "floating point exception");
6914 break;
6916 break;
6917 case SIGBUS:
6918 case SIGSEGV:
6919 rt_error(pc, "dereferencing invalid pointer");
6920 break;
6921 case SIGILL:
6922 rt_error(pc, "illegal instruction");
6923 break;
6924 case SIGABRT:
6925 rt_error(pc, "abort() called");
6926 break;
6927 default:
6928 rt_error(pc, "caught signal %d", signum);
6929 break;
6931 exit(255);
6933 #endif
6935 /* launch the compiled program with the given arguments */
6936 int tcc_run(TCCState *s1, int argc, char **argv)
6938 Section *s;
6939 int (*prog_main)(int, char **);
6940 int i;
6942 tcc_add_runtime(s1);
6944 relocate_common_syms();
6946 /* compute relocation address : section are relocated in place. We
6947 also alloc the bss space */
6948 for(i = 1; i < nb_sections; i++) {
6949 s = sections[i];
6950 if (s->sh_flags & SHF_ALLOC) {
6951 void *data;
6952 if (s->sh_type == SHT_NOBITS) {
6953 data = tcc_mallocz(s->data_offset);
6954 } else {
6955 data = s->data;
6957 s->sh_addr = (unsigned long)data;
6961 relocate_syms(1);
6963 /* relocate each section */
6964 for(i = 1; i < nb_sections; i++) {
6965 s = sections[i];
6966 if (s->reloc)
6967 relocate_section(s1, s);
6970 prog_main = (void *)get_elf_sym_val("main");
6972 if (do_debug) {
6973 #ifdef WIN32
6974 error("debug mode currently not available for Windows");
6975 #else
6976 struct sigaction sigact;
6977 /* install TCC signal handlers to print debug info on fatal
6978 runtime errors */
6979 sigact.sa_flags = SA_SIGINFO | SA_ONESHOT;
6980 sigact.sa_sigaction = sig_error;
6981 sigemptyset(&sigact.sa_mask);
6982 sigaction(SIGFPE, &sigact, NULL);
6983 sigaction(SIGILL, &sigact, NULL);
6984 sigaction(SIGSEGV, &sigact, NULL);
6985 sigaction(SIGBUS, &sigact, NULL);
6986 sigaction(SIGABRT, &sigact, NULL);
6987 #endif
6990 #ifdef CONFIG_TCC_BCHECK
6991 if (do_bounds_check) {
6992 void (*bound_init)(void);
6993 void **bound_error_func;
6995 /* set error function */
6996 bound_error_func = (void **)get_elf_sym_val("__bound_error_func");
6997 *bound_error_func = rt_error;
6999 /* XXX: use .init section so that it also work in binary ? */
7000 bound_init = (void *)get_elf_sym_val("__bound_init");
7001 bound_init();
7003 #endif
7004 return (*prog_main)(argc, argv);
7007 TCCState *tcc_new(void)
7009 char *p, *r;
7010 TCCState *s;
7012 s = tcc_malloc(sizeof(TCCState));
7013 if (!s)
7014 return NULL;
7015 s->output_type = TCC_OUTPUT_MEMORY;
7017 /* default include paths */
7018 tcc_add_sysinclude_path(s, "/usr/local/include");
7019 tcc_add_sysinclude_path(s, "/usr/include");
7020 tcc_add_sysinclude_path(s, CONFIG_TCC_PREFIX "/lib/tcc/include");
7022 /* add all tokens */
7023 tok_ident = TOK_IDENT;
7024 p = tcc_keywords;
7025 while (*p) {
7026 r = p;
7027 while (*r++);
7028 tok_alloc(p, r - p - 1);
7029 p = r;
7032 /* we add dummy defines for some special macros to speed up tests
7033 and to have working defined() */
7034 sym_push1(&define_stack, TOK___LINE__, MACRO_OBJ, 0);
7035 sym_push1(&define_stack, TOK___FILE__, MACRO_OBJ, 0);
7036 sym_push1(&define_stack, TOK___DATE__, MACRO_OBJ, 0);
7037 sym_push1(&define_stack, TOK___TIME__, MACRO_OBJ, 0);
7039 /* standard defines */
7040 tcc_define_symbol(s, "__STDC__", NULL);
7041 #if defined(TCC_TARGET_I386)
7042 tcc_define_symbol(s, "__i386__", NULL);
7043 #endif
7044 #if defined(linux)
7045 tcc_define_symbol(s, "linux", NULL);
7046 #endif
7047 /* tiny C specific defines */
7048 tcc_define_symbol(s, "__TINYC__", NULL);
7050 /* default library paths */
7051 tcc_add_library_path(s, "/usr/local/lib");
7052 tcc_add_library_path(s, "/usr/lib");
7053 tcc_add_library_path(s, "/lib");
7055 /* no section zero */
7056 dynarray_add((void ***)&sections, &nb_sections, NULL);
7058 /* create standard sections */
7059 text_section = new_section(".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
7060 data_section = new_section(".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
7061 bss_section = new_section(".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
7063 /* symbols are always generated for linking stage */
7064 symtab_section = new_symtab(".symtab", SHT_SYMTAB, 0,
7065 ".strtab",
7066 ".hashtab", SHF_PRIVATE);
7067 strtab_section = symtab_section->link;
7069 /* private symbol table for dynamic symbols */
7070 dynsymtab_section = new_symtab(".dynsymtab", SHT_SYMTAB, SHF_PRIVATE,
7071 ".dynstrtab",
7072 ".dynhashtab", SHF_PRIVATE);
7073 return s;
7076 void tcc_delete(TCCState *s)
7078 tcc_free(s);
7081 int tcc_add_include_path(TCCState *s, const char *pathname)
7083 char *pathname1;
7085 pathname1 = tcc_strdup(pathname);
7086 dynarray_add((void ***)&include_paths, &nb_include_paths, pathname1);
7087 return 0;
7090 int tcc_add_sysinclude_path(TCCState *s, const char *pathname)
7092 char *pathname1;
7094 pathname1 = tcc_strdup(pathname);
7095 dynarray_add((void ***)&sysinclude_paths, &nb_sysinclude_paths, pathname1);
7096 return 0;
7099 static int tcc_add_file_internal(TCCState *s, const char *filename, int flags)
7101 const char *ext;
7102 Elf32_Ehdr ehdr;
7103 int fd;
7104 BufferedFile *saved_file;
7106 /* find source file type with extension */
7107 ext = strrchr(filename, '.');
7108 if (ext)
7109 ext++;
7111 /* open the file */
7112 saved_file = file;
7113 file = tcc_open(filename);
7114 if (!file) {
7115 if (flags & AFF_PRINT_ERROR) {
7116 error("file '%s' not found", filename);
7117 } else {
7118 file = saved_file;
7119 return -1;
7123 if (!ext || !strcmp(ext, "c")) {
7124 /* C file assumed */
7125 tcc_compile(s);
7126 } else {
7127 fd = file->fd;
7128 /* assume executable format: auto guess file type */
7129 if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
7130 error("could not read header");
7131 lseek(fd, 0, SEEK_SET);
7133 if (ehdr.e_ident[0] == ELFMAG0 &&
7134 ehdr.e_ident[1] == ELFMAG1 &&
7135 ehdr.e_ident[2] == ELFMAG2 &&
7136 ehdr.e_ident[3] == ELFMAG3) {
7137 file->line_num = 0; /* do not display line number if error */
7138 if (ehdr.e_type == ET_REL) {
7139 tcc_load_object_file(s, fd, 0);
7140 } else if (ehdr.e_type == ET_DYN) {
7141 tcc_load_dll(s, fd, filename, (flags & AFF_REFERENCED_DLL) != 0);
7142 } else {
7143 error("unrecognized ELF file");
7145 } else if (memcmp((char *)&ehdr, ARMAG, 8) == 0) {
7146 file->line_num = 0; /* do not display line number if error */
7147 tcc_load_archive(s, fd);
7148 } else {
7149 /* as GNU ld, consider it is an ld script if not recognized */
7150 if (tcc_load_ldscript(s) < 0)
7151 error("unrecognized file type");
7154 tcc_close(file);
7155 file = saved_file;
7156 return 0;
7159 void tcc_add_file(TCCState *s, const char *filename)
7161 tcc_add_file_internal(s, filename, AFF_PRINT_ERROR);
7164 int tcc_add_library_path(TCCState *s, const char *pathname)
7166 char *pathname1;
7168 pathname1 = tcc_strdup(pathname);
7169 dynarray_add((void ***)&library_paths, &nb_library_paths, pathname1);
7170 return 0;
7173 /* find and load a dll. Return non zero if not found */
7174 /* XXX: add '-rpath' option support ? */
7175 static int tcc_add_dll(TCCState *s, const char *filename, int flags)
7177 char buf[1024];
7178 int i;
7180 for(i = 0; i < nb_library_paths; i++) {
7181 snprintf(buf, sizeof(buf), "%s/%s",
7182 library_paths[i], filename);
7183 if (tcc_add_file_internal(s, buf, flags) == 0)
7184 return 0;
7186 return -1;
7189 /* the library name is the same as the argument of the '-l' option */
7190 int tcc_add_library(TCCState *s, const char *libraryname)
7192 char buf[1024];
7193 int i;
7194 void *h;
7196 /* first we look for the dynamic library if not static linking */
7197 if (!static_link) {
7198 snprintf(buf, sizeof(buf), "lib%s.so", libraryname);
7199 /* if we output to memory, then we simply we dlopen(). */
7200 if (s->output_type == TCC_OUTPUT_MEMORY) {
7201 /* Since the libc is already loaded, we don't need to load it again */
7202 if (!strcmp(libraryname, "c"))
7203 return 0;
7204 h = dlopen(buf, RTLD_GLOBAL | RTLD_LAZY);
7205 if (h)
7206 return 0;
7207 } else {
7208 if (tcc_add_dll(s, buf, 0) == 0)
7209 return 0;
7213 /* then we look for the static library */
7214 for(i = 0; i < nb_library_paths; i++) {
7215 snprintf(buf, sizeof(buf), "%s/lib%s.a",
7216 library_paths[i], libraryname);
7217 if (tcc_add_file_internal(s, buf, 0) == 0)
7218 return 0;
7220 return -1;
7223 int tcc_add_symbol(TCCState *s, const char *name, unsigned long val)
7225 add_elf_sym(symtab_section, val, 0,
7226 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE),
7227 SHN_ABS, name);
7228 return 0;
7231 int tcc_set_output_type(TCCState *s, int output_type)
7233 s->output_type = output_type;
7235 /* if bound checking, then add corresponding sections */
7236 #ifdef CONFIG_TCC_BCHECK
7237 if (do_bounds_check) {
7238 /* define symbol */
7239 tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL);
7240 /* create bounds sections */
7241 bounds_section = new_section(".bounds",
7242 SHT_PROGBITS, SHF_ALLOC);
7243 lbounds_section = new_section(".lbounds",
7244 SHT_PROGBITS, SHF_ALLOC);
7246 #endif
7248 /* add debug sections */
7249 if (do_debug) {
7250 /* stab symbols */
7251 stab_section = new_section(".stab", SHT_PROGBITS, 0);
7252 stab_section->sh_entsize = sizeof(Stab_Sym);
7253 stabstr_section = new_section(".stabstr", SHT_STRTAB, 0);
7254 put_elf_str(stabstr_section, "");
7255 stab_section->link = stabstr_section;
7256 /* put first entry */
7257 put_stabs("", 0, 0, 0, 0);
7260 /* add libc crt1/crti objects */
7261 if (output_type == TCC_OUTPUT_EXE ||
7262 output_type == TCC_OUTPUT_DLL) {
7263 if (output_type != TCC_OUTPUT_DLL)
7264 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crt1.o");
7265 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crti.o");
7267 return 0;
7270 #if !defined(LIBTCC)
7272 void help(void)
7274 printf("tcc version 0.9.12 - Tiny C Compiler - Copyright (C) 2001, 2002 Fabrice Bellard\n"
7275 "usage: tcc [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
7276 " [-g] [-b] [-Ldir] [-llib] [-shared] [-static]\n"
7277 " [--] infile1 [infile2... --] [infile_args...]\n"
7278 "\n"
7279 "General options:\n"
7280 " -c compile only - generate an object file\n"
7281 " -o outfile set output filename\n"
7282 " -- allows multiples input files if no -o option given. Also\n"
7283 " separate input files from runtime arguments\n"
7284 " -Bdir set tcc internal library path\n"
7285 " -bench output compilation statistics\n"
7286 "Preprocessor options:\n"
7287 " -Idir add include path 'dir'\n"
7288 " -Dsym[=val] define 'sym' with value 'val'\n"
7289 " -Usym undefine 'sym'\n"
7290 "C compiler options:\n"
7291 " -g generate runtime debug info\n"
7292 #ifdef CONFIG_TCC_BCHECK
7293 " -b compile with built-in memory and bounds checker (implies -g)\n"
7294 #endif
7295 "Linker options:\n"
7296 " -Ldir add library path 'dir'\n"
7297 " -llib link with dynamic or static library 'lib'\n"
7298 " -shared generate a shared library\n"
7299 " -static static linking\n"
7300 " -r relocatable output\n"
7304 int main(int argc, char **argv)
7306 char *r, *outfile;
7307 int optind, output_type, multiple_files, i, reloc_output;
7308 TCCState *s;
7309 char **files;
7310 int nb_files, nb_libraries, nb_objfiles, dminus;
7311 char objfilename[1024];
7313 s = tcc_new();
7314 output_type = TCC_OUTPUT_MEMORY;
7316 optind = 1;
7317 outfile = NULL;
7318 multiple_files = 0;
7319 dminus = 0;
7320 files = NULL;
7321 nb_files = 0;
7322 nb_libraries = 0;
7323 reloc_output = 0;
7324 while (1) {
7325 if (optind >= argc) {
7326 if (nb_files == 0)
7327 goto show_help;
7328 else
7329 break;
7331 r = argv[optind++];
7332 if (r[0] != '-') {
7333 /* add a new file */
7334 dynarray_add((void ***)&files, &nb_files, r);
7335 if (!multiple_files) {
7336 optind--;
7337 /* argv[0] will be this file */
7338 break;
7340 } else if (r[1] == '-') {
7341 /* '--' enables multiple files input and also ends several file input */
7342 if (dminus && multiple_files) {
7343 optind--; /* argv[0] will be '--' */
7344 break;
7346 dminus = 1;
7347 multiple_files = 1;
7348 } else if (r[1] == 'h' || r[1] == '?') {
7349 show_help:
7350 help();
7351 return 1;
7352 } else if (r[1] == 'I') {
7353 if (tcc_add_include_path(s, r + 2) < 0)
7354 error("too many include paths");
7355 } else if (r[1] == 'D') {
7356 char *sym, *value;
7357 sym = r + 2;
7358 value = strchr(sym, '=');
7359 if (value) {
7360 *value = '\0';
7361 value++;
7363 tcc_define_symbol(s, sym, value);
7364 } else if (r[1] == 'U') {
7365 tcc_undefine_symbol(s, r + 2);
7366 } else if (r[1] == 'L') {
7367 tcc_add_library_path(s, r + 2);
7368 } else if (r[1] == 'B') {
7369 /* set tcc utilities path (mainly for tcc development) */
7370 tcc_lib_path = r + 2;
7371 } else if (r[1] == 'l') {
7372 dynarray_add((void ***)&files, &nb_files, r);
7373 nb_libraries++;
7374 } else if (!strcmp(r + 1, "bench")) {
7375 do_bench = 1;
7376 } else
7377 #ifdef CONFIG_TCC_BCHECK
7378 if (r[1] == 'b') {
7379 do_bounds_check = 1;
7380 do_debug = 1;
7381 } else
7382 #endif
7383 if (r[1] == 'g') {
7384 do_debug = 1;
7385 } else if (r[1] == 'c') {
7386 multiple_files = 1;
7387 output_type = TCC_OUTPUT_OBJ;
7388 } else if (!strcmp(r + 1, "static")) {
7389 static_link = 1;
7390 } else if (!strcmp(r + 1, "shared")) {
7391 output_type = TCC_OUTPUT_DLL;
7392 } else if (r[1] == 'o') {
7393 if (optind >= argc)
7394 goto show_help;
7395 multiple_files = 1;
7396 outfile = argv[optind++];
7397 } else if (r[1] == 'r') {
7398 /* generate a .o merging several output files */
7399 reloc_output = 1;
7400 output_type = TCC_OUTPUT_OBJ;
7401 } else {
7402 error("invalid option -- '%s'", r);
7406 nb_objfiles = nb_files - nb_libraries;
7408 /* if outfile provided without other options, we output an
7409 executable */
7410 if (outfile && output_type == TCC_OUTPUT_MEMORY)
7411 output_type = TCC_OUTPUT_EXE;
7413 /* check -c consistency : only single file handled. XXX: checks file type */
7414 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
7415 /* accepts only a single input file */
7416 if (nb_objfiles != 1)
7417 error("cannot specify multiple files with -c");
7418 if (nb_libraries != 0)
7419 error("cannot specify libraries with -c");
7422 /* compute default outfile name */
7423 if (output_type != TCC_OUTPUT_MEMORY && !outfile) {
7424 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
7425 char *ext;
7426 /* add .o extension */
7427 pstrcpy(objfilename, sizeof(objfilename) - 1, files[0]);
7428 ext = strrchr(objfilename, '.');
7429 if (!ext)
7430 goto default_outfile;
7431 strcpy(ext + 1, "o");
7432 } else {
7433 default_outfile:
7434 pstrcpy(objfilename, sizeof(objfilename), "a.out");
7436 outfile = objfilename;
7439 tcc_set_output_type(s, output_type);
7441 /* compile or add each files or library */
7442 for(i = 0;i < nb_files; i++) {
7443 const char *filename;
7445 filename = files[i];
7446 if (filename[0] == '-') {
7447 if (tcc_add_library(s, filename + 2) < 0)
7448 error("cannot find %s", filename);
7449 } else {
7450 tcc_add_file(s, filename);
7454 if (do_bench) {
7455 printf("total: %d idents, %d lines, %d bytes\n",
7456 tok_ident - TOK_IDENT, total_lines, total_bytes);
7457 #ifdef MEM_DEBUG
7458 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size, mem_max_size);
7459 #endif
7462 if (s->output_type != TCC_OUTPUT_MEMORY) {
7463 tcc_output_file(s, outfile);
7464 return 0;
7465 } else {
7466 return tcc_run(s, argc - optind, argv + optind);
7470 #endif