added better relocation support (needed for file output)
[tinycc.git] / tcc.c
blobab29cb13c592f73f8fda8344973040cabf0c9876
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 <malloc.h>
29 #include <unistd.h>
30 #include <fcntl.h>
31 #ifndef WIN32
32 #include <sys/ucontext.h>
33 #include <sys/mman.h>
34 #endif
35 #include "elf.h"
36 #include "stab.h"
37 #ifndef CONFIG_TCC_STATIC
38 #include <dlfcn.h>
39 #endif
41 #include "libtcc.h"
43 //#define DEBUG
44 /* preprocessor debug */
45 //#define PP_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 /* amount of virtual memory associated to a section (currently, we do
65 not realloc them) */
66 #define SECTION_VSIZE (1024 * 1024)
68 #define INCLUDE_STACK_SIZE 32
69 #define IFDEF_STACK_SIZE 64
70 #define VSTACK_SIZE 64
71 #define STRING_MAX_SIZE 1024
72 #define INCLUDE_PATHS_MAX 32
74 #define TOK_HASH_SIZE 2048 /* must be a power of two */
75 #define TOK_ALLOC_INCR 512 /* must be a power of two */
76 #define SYM_HASH_SIZE 1031
77 #define ELF_SYM_HASH_SIZE 2048 /* must be a power of two */
79 /* token symbol management */
80 typedef struct TokenSym {
81 struct TokenSym *hash_next;
82 int tok; /* token number */
83 int len;
84 char str[1];
85 } TokenSym;
87 /* constant value */
88 typedef union CValue {
89 long double ld;
90 double d;
91 float f;
92 int i;
93 unsigned int ui;
94 unsigned int ul; /* address (should be unsigned long on 64 bit cpu) */
95 long long ll;
96 unsigned long long ull;
97 struct TokenSym *ts;
98 struct Sym *sym;
99 int tab[1];
100 } CValue;
102 /* value on stack */
103 typedef struct SValue {
104 int t; /* type */
105 unsigned short r; /* register + flags */
106 unsigned short r2; /* second register, used for 'long long'
107 type. If not used, set to VT_CONST */
108 CValue c; /* constant, if VT_CONST */
109 } SValue;
111 /* symbol management */
112 typedef struct Sym {
113 int v; /* symbol token */
114 int t; /* associated type */
115 int r; /* associated register */
116 int c; /* associated number */
117 struct Sym *next; /* next related symbol */
118 struct Sym *prev; /* prev symbol in stack */
119 struct Sym *hash_next; /* next symbol in hash table */
120 } Sym;
122 typedef struct SymStack {
123 struct Sym *top;
124 struct Sym *hash[SYM_HASH_SIZE];
125 } SymStack;
127 /* section definition */
128 typedef struct Section {
129 unsigned char *data; /* section data */
130 unsigned char *data_ptr; /* current data pointer */
131 int sh_num; /* elf section number */
132 int sh_type; /* elf section type */
133 int sh_flags; /* elf section flags */
134 /* special flag to indicate that the section should not be linked to
135 the other ones */
136 #define SHF_PRIVATE 0x80000000
137 int sh_entsize; /* elf entry size */
138 unsigned long addr; /* address at which the section is relocated */
139 struct Section *link; /* link to another section */
140 struct Section *reloc; /* corresponding section for relocation, if any */
141 struct Section *reloc_sec;/* relocation: pointer to corresponding
142 data section */
143 struct Section *hash; /* hash table for symbols */
144 struct Section *next;
145 char name[64]; /* section name */
146 } Section;
148 /* GNUC attribute definition */
149 typedef struct AttributeDef {
150 int aligned;
151 Section *section;
152 unsigned char func_call; /* FUNC_CDECL or FUNC_STDCALL */
153 } AttributeDef;
155 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
156 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
157 #define SYM_FIRST_ANOM (1 << (31 - VT_STRUCT_SHIFT)) /* first anonymous sym */
159 /* stored in 'Sym.c' field */
160 #define FUNC_NEW 1 /* ansi function prototype */
161 #define FUNC_OLD 2 /* old function prototype */
162 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
164 /* stored in 'Sym.r' field */
165 #define FUNC_CDECL 0 /* standard c call */
166 #define FUNC_STDCALL 1 /* pascal c call */
168 /* field 'Sym.t' for macros */
169 #define MACRO_OBJ 0 /* object like macro */
170 #define MACRO_FUNC 1 /* function like macro */
172 /* field 'Sym.t' for labels */
173 #define LABEL_FORWARD 1 /* label is forward defined */
175 /* type_decl() types */
176 #define TYPE_ABSTRACT 1 /* type without variable */
177 #define TYPE_DIRECT 2 /* type with variable */
179 #define IO_BUF_SIZE 8192
181 typedef struct BufferedFile {
182 unsigned char *buf_ptr;
183 unsigned char *buf_end;
184 int fd;
185 int line_num; /* current line number - here to simply code */
186 char filename[1024]; /* current filename - here to simply code */
187 unsigned char buffer[IO_BUF_SIZE + 1]; /* extra size for CH_EOB char */
188 } BufferedFile;
190 #define CH_EOB 0 /* end of buffer or '\0' char in file */
191 #define CH_EOF (-1) /* end of file */
193 /* parsing state (used to save parser state to reparse part of the
194 source several times) */
195 typedef struct ParseState {
196 int *macro_ptr;
197 int line_num;
198 int tok;
199 CValue tokc;
200 } ParseState;
202 /* used to record tokens */
203 typedef struct TokenString {
204 int *str;
205 int len;
206 int last_line_num;
207 } TokenString;
209 /* parser */
210 struct BufferedFile *file;
211 int ch, ch1, tok, tok1;
212 CValue tokc, tok1c;
214 /* sections */
215 /* XXX: suppress first_section */
216 Section *first_section, **sections;
217 int nb_sections; /* number of sections, including first dummy section */
218 int nb_allocated_sections;
219 Section *text_section, *data_section, *bss_section; /* predefined sections */
220 Section *cur_text_section; /* current section where function code is
221 generated */
222 /* bound check related sections */
223 Section *bounds_section; /* contains global data bound description */
224 Section *lbounds_section; /* contains local data bound description */
225 /* symbol sections */
226 Section *symtab_section, *strtab_section, *hashtab_section;
228 /* debug sections */
229 Section *stab_section, *stabstr_section;
231 /* loc : local variable index
232 ind : output code index
233 rsym: return symbol
234 anon_sym: anonymous symbol index
236 int rsym, anon_sym,
237 prog, ind, loc, const_wanted;
238 int global_expr; /* true if compound literals must be allocated
239 globally (used during initializers parsing */
240 int func_vt, func_vc; /* current function return type (used by
241 return instruction) */
242 int last_line_num, last_ind, func_ind; /* debug last line number and pc */
243 int tok_ident;
244 TokenSym **table_ident;
245 TokenSym *hash_ident[TOK_HASH_SIZE];
246 char token_buf[STRING_MAX_SIZE + 1];
247 char *funcname;
248 SymStack define_stack, global_stack, local_stack, label_stack;
250 SValue vstack[VSTACK_SIZE], *vtop;
251 int *macro_ptr, *macro_ptr_allocated;
252 BufferedFile *include_stack[INCLUDE_STACK_SIZE], **include_stack_ptr;
253 int ifdef_stack[IFDEF_STACK_SIZE], *ifdef_stack_ptr;
254 char *include_paths[INCLUDE_PATHS_MAX];
255 int nb_include_paths;
256 int char_pointer_type;
258 /* compile with debug symbol (and use them if error during execution) */
259 int do_debug = 0;
261 /* compile with built-in memory and bounds checker */
262 int do_bounds_check = 0;
264 /* display benchmark infos */
265 int do_bench = 0;
266 int total_lines;
267 int total_bytes;
269 /* use GNU C extensions */
270 int gnu_ext = 1;
272 /* use Tiny C extensions */
273 int tcc_ext = 1;
275 struct TCCState {
276 int dummy;
279 /* The current value can be: */
280 #define VT_VALMASK 0x00ff
281 #define VT_CONST 0x00f0 /* constant in vc
282 (must be first non register value) */
283 #define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */
284 #define VT_LOCAL 0x00f2 /* offset on stack */
285 #define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */
286 #define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */
287 #define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */
288 #define VT_LVAL 0x0100 /* var is an lvalue */
289 #define VT_SYM 0x0200 /* a symbol value is added */
290 #define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for
291 char/short stored in integer registers) */
292 #define VT_MUSTBOUND 0x0800 /* bound checking must be done before
293 dereferencing value */
294 #define VT_BOUNDED 0x8000 /* value is bounded. The address of the
295 bounding function call point is in vc */
296 #define VT_LVAL_BYTE 0x1000 /* lvalue is a byte */
297 #define VT_LVAL_SHORT 0x2000 /* lvalue is a short */
298 #define VT_LVAL_UNSIGNED 0x4000 /* lvalue is unsigned */
299 #define VT_LVAL_TYPE (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)
301 /* types */
302 #define VT_STRUCT_SHIFT 16 /* structure/enum name shift (16 bits left) */
304 #define VT_INT 0 /* integer type */
305 #define VT_BYTE 1 /* signed byte type */
306 #define VT_SHORT 2 /* short type */
307 #define VT_VOID 3 /* void type */
308 #define VT_PTR 4 /* pointer */
309 #define VT_ENUM 5 /* enum definition */
310 #define VT_FUNC 6 /* function type */
311 #define VT_STRUCT 7 /* struct/union definition */
312 #define VT_FLOAT 8 /* IEEE float */
313 #define VT_DOUBLE 9 /* IEEE double */
314 #define VT_LDOUBLE 10 /* IEEE long double */
315 #define VT_BOOL 11 /* ISOC99 boolean type */
316 #define VT_LLONG 12 /* 64 bit integer */
317 #define VT_LONG 13 /* long integer (NEVER USED as type, only
318 during parsing) */
319 #define VT_BTYPE 0x000f /* mask for basic type */
320 #define VT_UNSIGNED 0x0010 /* unsigned type */
321 #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
322 #define VT_BITFIELD 0x0040 /* bitfield modifier */
324 /* storage */
325 #define VT_EXTERN 0x00000080 /* extern definition */
326 #define VT_STATIC 0x00000100 /* static variable */
327 #define VT_TYPEDEF 0x00000200 /* typedef definition */
329 /* type mask (except storage) */
330 #define VT_TYPE (~(VT_EXTERN | VT_STATIC | VT_TYPEDEF))
332 /* token values */
334 /* warning: the following compare tokens depend on i386 asm code */
335 #define TOK_ULT 0x92
336 #define TOK_UGE 0x93
337 #define TOK_EQ 0x94
338 #define TOK_NE 0x95
339 #define TOK_ULE 0x96
340 #define TOK_UGT 0x97
341 #define TOK_LT 0x9c
342 #define TOK_GE 0x9d
343 #define TOK_LE 0x9e
344 #define TOK_GT 0x9f
346 #define TOK_LAND 0xa0
347 #define TOK_LOR 0xa1
349 #define TOK_DEC 0xa2
350 #define TOK_MID 0xa3 /* inc/dec, to void constant */
351 #define TOK_INC 0xa4
352 #define TOK_UDIV 0xb0 /* unsigned division */
353 #define TOK_UMOD 0xb1 /* unsigned modulo */
354 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
355 #define TOK_CINT 0xb3 /* number in tokc */
356 #define TOK_CCHAR 0xb4 /* char constant in tokc */
357 #define TOK_STR 0xb5 /* pointer to string in tokc */
358 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
359 #define TOK_LCHAR 0xb7
360 #define TOK_LSTR 0xb8
361 #define TOK_CFLOAT 0xb9 /* float constant */
362 #define TOK_LINENUM 0xba /* line number info */
363 #define TOK_CDOUBLE 0xc0 /* double constant */
364 #define TOK_CLDOUBLE 0xc1 /* long double constant */
365 #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
366 #define TOK_ADDC1 0xc3 /* add with carry generation */
367 #define TOK_ADDC2 0xc4 /* add with carry use */
368 #define TOK_SUBC1 0xc5 /* add with carry generation */
369 #define TOK_SUBC2 0xc6 /* add with carry use */
370 #define TOK_CUINT 0xc8 /* unsigned int constant */
371 #define TOK_CLLONG 0xc9 /* long long constant */
372 #define TOK_CULLONG 0xca /* unsigned long long constant */
373 #define TOK_ARROW 0xcb
374 #define TOK_DOTS 0xcc /* three dots */
375 #define TOK_SHR 0xcd /* unsigned shift right */
377 #define TOK_SHL 0x01 /* shift left */
378 #define TOK_SAR 0x02 /* signed shift right */
380 /* assignement operators : normal operator or 0x80 */
381 #define TOK_A_MOD 0xa5
382 #define TOK_A_AND 0xa6
383 #define TOK_A_MUL 0xaa
384 #define TOK_A_ADD 0xab
385 #define TOK_A_SUB 0xad
386 #define TOK_A_DIV 0xaf
387 #define TOK_A_XOR 0xde
388 #define TOK_A_OR 0xfc
389 #define TOK_A_SHL 0x81
390 #define TOK_A_SAR 0x82
392 #define TOK_EOF (-1) /* end of file */
394 /* all identificators and strings have token above that */
395 #define TOK_IDENT 256
397 enum {
398 TOK_INT = TOK_IDENT,
399 TOK_VOID,
400 TOK_CHAR,
401 TOK_IF,
402 TOK_ELSE,
403 TOK_WHILE,
404 TOK_BREAK,
405 TOK_RETURN,
406 TOK_FOR,
407 TOK_EXTERN,
408 TOK_STATIC,
409 TOK_UNSIGNED,
410 TOK_GOTO,
411 TOK_DO,
412 TOK_CONTINUE,
413 TOK_SWITCH,
414 TOK_CASE,
416 /* ignored types Must have contiguous values */
417 TOK_CONST,
418 TOK_VOLATILE,
419 TOK_LONG,
420 TOK_REGISTER,
421 TOK_SIGNED,
422 TOK___SIGNED__, /* gcc keyword */
423 TOK_AUTO,
424 TOK_INLINE,
425 TOK___INLINE__, /* gcc keyword */
426 TOK_RESTRICT,
428 /* unsupported type */
429 TOK_FLOAT,
430 TOK_DOUBLE,
431 TOK_BOOL,
433 TOK_SHORT,
434 TOK_STRUCT,
435 TOK_UNION,
436 TOK_TYPEDEF,
437 TOK_DEFAULT,
438 TOK_ENUM,
439 TOK_SIZEOF,
440 TOK___ATTRIBUTE__,
442 /* preprocessor only */
443 TOK_UIDENT, /* first "user" ident (not keyword) */
444 TOK_DEFINE = TOK_UIDENT,
445 TOK_INCLUDE,
446 TOK_IFDEF,
447 TOK_IFNDEF,
448 TOK_ELIF,
449 TOK_ENDIF,
450 TOK_DEFINED,
451 TOK_UNDEF,
452 TOK_ERROR,
453 TOK_LINE,
454 TOK___LINE__,
455 TOK___FILE__,
456 TOK___DATE__,
457 TOK___TIME__,
458 TOK___VA_ARGS__,
460 /* special identifiers */
461 TOK___FUNC__,
462 TOK_MAIN,
463 /* attribute identifiers */
464 TOK_SECTION,
465 TOK___SECTION__,
466 TOK_ALIGNED,
467 TOK___ALIGNED__,
468 TOK_UNUSED,
469 TOK___UNUSED__,
470 TOK_CDECL,
471 TOK___CDECL,
472 TOK___CDECL__,
473 TOK_STDCALL,
474 TOK___STDCALL,
475 TOK___STDCALL__,
476 TOK_NORETURN,
477 TOK___NORETURN__,
480 char *tcc_keywords =
481 "int\0void\0char\0if\0else\0while\0break\0return\0for\0extern\0static\0"
482 "unsigned\0goto\0do\0continue\0switch\0case\0const\0volatile\0long\0"
483 "register\0signed\0__signed__\0auto\0inline\0__inline__\0restrict\0"
484 "float\0double\0_Bool\0short\0struct\0union\0typedef\0default\0enum\0"
485 "sizeof\0__attribute__\0"
486 /* the following are not keywords. They are included to ease parsing */
487 "define\0include\0ifdef\0ifndef\0elif\0endif\0"
488 "defined\0undef\0error\0line\0"
489 "__LINE__\0__FILE__\0__DATE__\0__TIME__\0__VA_ARGS__\0"
490 "__func__\0main\0"
491 /* attributes */
492 "section\0__section__\0aligned\0__aligned__\0unused\0__unused__\0"
493 "cdecl\0__cdecl\0__cdecl__\0stdcall\0__stdcall\0__stdcall__\0"
494 "noreturn\0__noreturn__\0"
497 #ifdef WIN32
498 #define snprintf _snprintf
499 #endif
501 #if defined(WIN32) || defined(TCC_UCLIBC)
502 /* currently incorrect */
503 long double strtold(const char *nptr, char **endptr)
505 return (long double)strtod(nptr, endptr);
507 float strtof(const char *nptr, char **endptr)
509 return (float)strtod(nptr, endptr);
511 #else
512 /* XXX: need to define this to use them in non ISOC99 context */
513 extern float strtof (const char *__nptr, char **__endptr);
514 extern long double strtold (const char *__nptr, char **__endptr);
515 #endif
517 char *pstrcpy(char *buf, int buf_size, const char *s);
518 char *pstrcat(char *buf, int buf_size, const char *s);
520 void sum(int l);
521 void next(void);
522 void next_nomacro(void);
523 int expr_const(void);
524 void expr_eq(void);
525 void gexpr(void);
526 void decl(int l);
527 void decl_initializer(int t, Section *sec, unsigned long c, int first, int size_only);
528 void decl_initializer_alloc(int t, AttributeDef *ad, int r, int has_init,
529 int v, int scope);
530 int gv(int rc);
531 void gv2(int rc1, int rc2);
532 void move_reg(int r, int s);
533 void save_regs(int n);
534 void save_reg(int r);
535 void vpop(void);
536 void vswap(void);
537 void vdup(void);
538 int get_reg(int rc);
540 void macro_subst(TokenString *tok_str,
541 Sym **nested_list, int *macro_str);
542 int save_reg_forced(int r);
543 void gen_op(int op);
544 void force_charshort_cast(int t);
545 void gen_cast(int t);
546 void vstore(void);
547 Sym *sym_find(int v);
548 Sym *sym_push(int v, int t, int r, int c);
550 /* type handling */
551 int type_size(int t, int *a);
552 int pointed_type(int t);
553 int pointed_size(int t);
554 int is_compatible_types(int t1, int t2);
555 int parse_btype(int *type_ptr, AttributeDef *ad);
556 int type_decl(AttributeDef *ad, int *v, int t, int td);
558 void error(const char *fmt, ...);
559 void rt_error(unsigned long pc, const char *fmt, ...);
560 void vpushi(int v);
561 void vset(int t, int r, int v);
562 void type_to_str(char *buf, int buf_size,
563 int t, const char *varstr);
564 char *get_tok_str(int v, CValue *cv);
566 /* section generation */
567 void put_extern_sym(Sym *sym, Section *section, unsigned long value);
568 void greloc(Section *s, Sym *sym, unsigned long addr, int type);
569 static int put_elf_str(Section *s, const char *sym);
570 static int put_elf_sym(Section *s,
571 unsigned long value, unsigned long size,
572 int info, int other, int shndx, const char *name);
573 static void put_elf_reloc(Section *s, unsigned long offset,
574 int type, int symbol);
575 static void put_stabs(const char *str, int type, int other, int desc, int value);
576 static void put_stabn(int type, int other, int desc, int value);
577 static void put_stabd(int type, int other, int desc);
579 /* true if float/double/long double type */
580 static inline int is_float(int t)
582 int bt;
583 bt = t & VT_BTYPE;
584 return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT;
587 #ifdef CONFIG_TCC_BCHECK
588 #include "bcheck.c"
589 #endif
591 #ifdef TCC_TARGET_I386
592 #include "i386-gen.c"
593 #endif
594 #ifdef TCC_TARGET_IL
595 #include "il-gen.c"
596 #endif
598 #ifdef CONFIG_TCC_STATIC
600 #define RTLD_LAZY 0x001
601 #define RTLD_NOW 0x002
602 #define RTLD_GLOBAL 0x100
604 /* dummy function for profiling */
605 void *dlopen(const char *filename, int flag)
607 return NULL;
610 const char *dlerror(void)
612 return "error";
615 typedef struct TCCSyms {
616 char *str;
617 void *ptr;
618 } TCCSyms;
620 #define TCCSYM(a) { #a, &a, },
622 /* add the symbol you want here if no dynamic linking is done */
623 static TCCSyms tcc_syms[] = {
624 TCCSYM(printf)
625 TCCSYM(fprintf)
626 TCCSYM(fopen)
627 TCCSYM(fclose)
628 { NULL, NULL },
631 void *dlsym(void *handle, const char *symbol)
633 TCCSyms *p;
634 p = tcc_syms;
635 while (p->str != NULL) {
636 if (!strcmp(p->str, symbol))
637 return p->ptr;
638 p++;
640 return NULL;
643 #endif
645 /********************************************************/
646 /* runtime library is there */
647 /* XXX: we suppose that the host compiler handles 'long long'. It
648 would not be difficult to suppress this assumption */
650 long long __divll(long long a, long long b)
652 return a / b;
655 long long __modll(long long a, long long b)
657 return a % b;
660 unsigned long long __divull(unsigned long long a, unsigned long long b)
662 return a / b;
665 unsigned long long __modull(unsigned long long a, unsigned long long b)
667 return a % b;
670 long long __sardi3(long long a, int b)
672 return a >> b;
675 unsigned long long __shrdi3(unsigned long long a, int b)
677 return a >> b;
680 long long __shldi3(long long a, int b)
682 return a << b;
685 float __ulltof(unsigned long long a)
687 return (float)a;
690 double __ulltod(unsigned long long a)
692 return (double)a;
695 long double __ulltold(unsigned long long a)
697 return (long double)a;
700 unsigned long long __ftoull(float a)
702 return (unsigned long long)a;
705 unsigned long long __dtoull(double a)
707 return (unsigned long long)a;
710 unsigned long long __ldtoull(long double a)
712 return (unsigned long long)a;
716 /********************************************************/
718 /* we use our own 'finite' function to avoid potential problems with
719 non standard math libs */
720 /* XXX: endianness dependant */
721 int ieee_finite(double d)
723 int *p = (int *)&d;
724 return ((unsigned)((p[1] | 0x800fffff) + 1)) >> 31;
727 /* copy a string and truncate it. */
728 char *pstrcpy(char *buf, int buf_size, const char *s)
730 char *q, *q_end;
731 int c;
733 if (buf_size > 0) {
734 q = buf;
735 q_end = buf + buf_size - 1;
736 while (q < q_end) {
737 c = *s++;
738 if (c == '\0')
739 break;
740 *q++ = c;
742 *q = '\0';
744 return buf;
747 /* strcat and truncate. */
748 char *pstrcat(char *buf, int buf_size, const char *s)
750 int len;
751 len = strlen(buf);
752 if (len < buf_size)
753 pstrcpy(buf + len, buf_size - len, s);
754 return buf;
757 Section *new_section(const char *name, int sh_type, int sh_flags)
759 Section *sec, **psec;
760 void *data;
762 sec = malloc(sizeof(Section));
763 if (!sec)
764 error("memory full");
765 memset(sec, 0, sizeof(Section));
766 pstrcpy(sec->name, sizeof(sec->name), name);
767 sec->sh_type = sh_type;
768 sec->sh_flags = sh_flags;
769 #ifdef WIN32
770 /* XXX: currently, a single malloc */
771 data = malloc(SECTION_VSIZE);
772 if (data == NULL)
773 error("could not alloc section '%s'", name);
774 #else
775 data = mmap(NULL, SECTION_VSIZE,
776 PROT_EXEC | PROT_READ | PROT_WRITE,
777 MAP_PRIVATE | MAP_ANONYMOUS,
778 -1, 0);
779 if (data == (void *)(-1))
780 error("could not mmap section '%s'", name);
781 #endif
782 sec->data = data;
783 sec->data_ptr = data;
785 if (!(sh_flags & SHF_PRIVATE)) {
786 /* only add section if not private */
788 psec = &first_section;
789 while (*psec != NULL)
790 psec = &(*psec)->next;
791 sec->next = NULL;
792 *psec = sec;
794 if ((nb_sections + 1) > nb_allocated_sections) {
795 if (nb_allocated_sections == 0)
796 nb_allocated_sections = 1;
797 nb_allocated_sections *= 2;
798 sections = realloc(sections,
799 nb_allocated_sections * sizeof(Section *));
800 if (!sections)
801 error("memory full");
803 sections[nb_sections] = sec;
804 sec->sh_num = nb_sections;
805 nb_sections++;
807 return sec;
810 /* return a reference to a section, and create it if it does not
811 exists */
812 Section *find_section(const char *name)
814 Section *sec;
816 for(sec = first_section; sec != NULL; sec = sec->next) {
817 if (!strcmp(name, sec->name))
818 return sec;
820 /* sections are created as PROGBITS */
821 return new_section(name, SHT_PROGBITS, SHF_ALLOC);
824 /* add a new relocation entry to symbol 'sym' in section 's' */
825 void greloc(Section *s, Sym *sym, unsigned long offset, int type)
827 if (!sym->c)
828 put_extern_sym(sym, NULL, 0);
829 /* now we can add ELF relocation info */
830 put_elf_reloc(s, offset, type, sym->c);
833 static inline int isid(int c)
835 return (c >= 'a' && c <= 'z') ||
836 (c >= 'A' && c <= 'Z') ||
837 c == '_';
840 static inline int isnum(int c)
842 return c >= '0' && c <= '9';
845 static inline int toup(int c)
847 if (ch >= 'a' && ch <= 'z')
848 return ch - 'a' + 'A';
849 else
850 return ch;
853 void printline(void)
855 BufferedFile **f;
856 if (file) {
857 for(f = include_stack; f < include_stack_ptr; f++)
858 fprintf(stderr, "In file included from %s:%d:\n",
859 (*f)->filename, (*f)->line_num);
860 fprintf(stderr, "%s:%d: ", file->filename, file->line_num);
861 } else {
862 fprintf(stderr, "tcc: ");
866 void error(const char *fmt, ...)
868 va_list ap;
869 va_start(ap, fmt);
870 printline();
871 vfprintf(stderr, fmt, ap);
872 fprintf(stderr, "\n");
873 exit(1);
874 va_end(ap);
877 void expect(const char *msg)
879 error("%s expected", msg);
882 void warning(const char *fmt, ...)
884 va_list ap;
886 va_start(ap, fmt);
887 printline();
888 fprintf(stderr, "warning: ");
889 vfprintf(stderr, fmt, ap);
890 fprintf(stderr, "\n");
891 va_end(ap);
894 void skip(int c)
896 if (tok != c)
897 error("'%c' expected", c);
898 next();
901 void test_lvalue(void)
903 if (!(vtop->r & VT_LVAL))
904 expect("lvalue");
907 TokenSym *tok_alloc(const char *str, int len)
909 TokenSym *ts, **pts, **ptable;
910 int h, i;
912 if (len <= 0)
913 len = strlen(str);
914 h = 1;
915 for(i=0;i<len;i++)
916 h = (h * 263 + ((unsigned char *)str)[i]) & (TOK_HASH_SIZE - 1);
918 pts = &hash_ident[h];
919 while (1) {
920 ts = *pts;
921 if (!ts)
922 break;
923 if (ts->len == len && !memcmp(ts->str, str, len))
924 return ts;
925 pts = &(ts->hash_next);
928 if (tok_ident >= SYM_FIRST_ANOM)
929 error("memory full");
931 /* expand token table if needed */
932 i = tok_ident - TOK_IDENT;
933 if ((i % TOK_ALLOC_INCR) == 0) {
934 ptable = realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *));
935 if (!ptable)
936 error("memory full");
937 table_ident = ptable;
940 ts = malloc(sizeof(TokenSym) + len);
941 if (!ts)
942 error("memory full");
943 table_ident[i] = ts;
944 ts->tok = tok_ident++;
945 ts->len = len;
946 ts->hash_next = NULL;
947 memcpy(ts->str, str, len + 1);
948 *pts = ts;
949 return ts;
952 void add_char(char **pp, int c)
954 char *p;
955 p = *pp;
956 if (c == '\'' || c == '\"' || c == '\\') {
957 /* XXX: could be more precise if char or string */
958 *p++ = '\\';
960 if (c >= 32 && c <= 126) {
961 *p++ = c;
962 } else {
963 *p++ = '\\';
964 if (c == '\n') {
965 *p++ = 'n';
966 } else {
967 *p++ = '0' + ((c >> 6) & 7);
968 *p++ = '0' + ((c >> 3) & 7);
969 *p++ = '0' + (c & 7);
972 *pp = p;
975 /* XXX: buffer overflow */
976 char *get_tok_str(int v, CValue *cv)
978 static char buf[STRING_MAX_SIZE + 1];
979 TokenSym *ts;
980 char *p;
981 int i;
983 if (v == TOK_CINT || v == TOK_CUINT) {
984 sprintf(buf, "%u", cv->ui);
985 return buf;
986 } else if (v == TOK_CCHAR || v == TOK_LCHAR) {
987 p = buf;
988 *p++ = '\'';
989 add_char(&p, cv->i);
990 *p++ = '\'';
991 *p = '\0';
992 return buf;
993 } else if (v == TOK_STR || v == TOK_LSTR) {
994 ts = cv->ts;
995 p = buf;
996 *p++ = '\"';
997 for(i=0;i<ts->len;i++)
998 add_char(&p, ts->str[i]);
999 *p++ = '\"';
1000 *p = '\0';
1001 return buf;
1002 } else if (v < TOK_IDENT) {
1003 p = buf;
1004 *p++ = v;
1005 *p = '\0';
1006 return buf;
1007 } else if (v < tok_ident) {
1008 return table_ident[v - TOK_IDENT]->str;
1009 } else {
1010 /* should never happen */
1011 return NULL;
1015 /* push, without hashing */
1016 Sym *sym_push2(Sym **ps, int v, int t, int c)
1018 Sym *s;
1019 s = malloc(sizeof(Sym));
1020 if (!s)
1021 error("memory full");
1022 s->v = v;
1023 s->t = t;
1024 s->c = c;
1025 s->next = NULL;
1026 /* add in stack */
1027 s->prev = *ps;
1028 *ps = s;
1029 return s;
1032 /* find a symbol and return its associated structure. 's' is the top
1033 of the symbol stack */
1034 Sym *sym_find2(Sym *s, int v)
1036 while (s) {
1037 if (s->v == v)
1038 return s;
1039 s = s->prev;
1041 return NULL;
1044 #define HASH_SYM(v) ((unsigned)(v) % SYM_HASH_SIZE)
1046 /* find a symbol and return its associated structure. 'st' is the
1047 symbol stack */
1048 Sym *sym_find1(SymStack *st, int v)
1050 Sym *s;
1052 s = st->hash[HASH_SYM(v)];
1053 while (s) {
1054 if (s->v == v)
1055 return s;
1056 s = s->hash_next;
1058 return NULL;
1061 Sym *sym_push1(SymStack *st, int v, int t, int c)
1063 Sym *s, **ps;
1064 s = sym_push2(&st->top, v, t, c);
1065 /* add in hash table */
1066 if (v) {
1067 ps = &st->hash[HASH_SYM(v)];
1068 s->hash_next = *ps;
1069 *ps = s;
1071 return s;
1074 /* find a symbol in the right symbol space */
1075 Sym *sym_find(int v)
1077 Sym *s;
1078 s = sym_find1(&local_stack, v);
1079 if (!s)
1080 s = sym_find1(&global_stack, v);
1081 return s;
1084 /* push a given symbol on the symbol stack */
1085 Sym *sym_push(int v, int t, int r, int c)
1087 Sym *s;
1088 if (local_stack.top)
1089 s = sym_push1(&local_stack, v, t, c);
1090 else
1091 s = sym_push1(&global_stack, v, t, c);
1092 s->r = r;
1093 return s;
1096 /* pop symbols until top reaches 'b' */
1097 void sym_pop(SymStack *st, Sym *b)
1099 Sym *s, *ss;
1101 s = st->top;
1102 while(s != b) {
1103 ss = s->prev;
1104 /* free hash table entry, except if symbol was freed (only
1105 used for #undef symbols) */
1106 if (s->v)
1107 st->hash[HASH_SYM(s->v)] = s->hash_next;
1108 free(s);
1109 s = ss;
1111 st->top = b;
1114 /* undefined a hashed symbol (used for #undef). Its name is set to
1115 zero */
1116 void sym_undef(SymStack *st, Sym *s)
1118 Sym **ss;
1119 ss = &st->hash[HASH_SYM(s->v)];
1120 while (*ss != NULL) {
1121 if (*ss == s)
1122 break;
1123 ss = &(*ss)->hash_next;
1125 *ss = s->hash_next;
1126 s->v = 0;
1129 /* I/O layer */
1131 BufferedFile *tcc_open(const char *filename)
1133 int fd;
1134 BufferedFile *bf;
1136 fd = open(filename, O_RDONLY);
1137 if (fd < 0)
1138 return NULL;
1139 bf = malloc(sizeof(BufferedFile));
1140 if (!bf) {
1141 close(fd);
1142 return NULL;
1144 bf->fd = fd;
1145 bf->buf_ptr = bf->buffer;
1146 bf->buf_end = bf->buffer;
1147 bf->buffer[0] = CH_EOB; /* put eob symbol */
1148 pstrcpy(bf->filename, sizeof(bf->filename), filename);
1149 bf->line_num = 1;
1150 // printf("opening '%s'\n", filename);
1151 return bf;
1154 void tcc_close(BufferedFile *bf)
1156 total_lines += bf->line_num;
1157 close(bf->fd);
1158 free(bf);
1161 /* read one char. MUST call tcc_fillbuf if CH_EOB is read */
1162 #define TCC_GETC(bf) (*(bf)->buf_ptr++)
1164 /* fill input buffer and return next char */
1165 int tcc_getc_slow(BufferedFile *bf)
1167 int len;
1168 /* only tries to read if really end of buffer */
1169 if (bf->buf_ptr >= bf->buf_end) {
1170 if (bf->fd != -1) {
1171 len = read(bf->fd, bf->buffer, IO_BUF_SIZE);
1172 if (len < 0)
1173 len = 0;
1174 } else {
1175 len = 0;
1177 total_bytes += len;
1178 bf->buf_ptr = bf->buffer;
1179 bf->buf_end = bf->buffer + len;
1180 *bf->buf_end = CH_EOB;
1182 if (bf->buf_ptr < bf->buf_end) {
1183 return *bf->buf_ptr++;
1184 } else {
1185 bf->buf_ptr = bf->buf_end;
1186 return CH_EOF;
1190 /* no need to put that inline */
1191 void handle_eob(void)
1193 for(;;) {
1194 ch1 = tcc_getc_slow(file);
1195 if (ch1 != CH_EOF)
1196 return;
1198 if (include_stack_ptr == include_stack)
1199 return;
1200 /* add end of include file debug info */
1201 if (do_debug) {
1202 put_stabd(N_EINCL, 0, 0);
1204 /* pop include stack */
1205 tcc_close(file);
1206 include_stack_ptr--;
1207 file = *include_stack_ptr;
1211 /* read next char from current input file */
1212 static inline void inp(void)
1214 ch1 = TCC_GETC(file);
1215 /* end of buffer/file handling */
1216 if (ch1 == CH_EOB)
1217 handle_eob();
1218 if (ch1 == '\n')
1219 file->line_num++;
1220 // printf("ch1=%c 0x%x\n", ch1, ch1);
1223 /* input with '\\n' handling */
1224 static inline void minp(void)
1226 redo:
1227 ch = ch1;
1228 inp();
1229 if (ch == '\\' && ch1 == '\n') {
1230 inp();
1231 goto redo;
1233 //printf("ch=%c 0x%x\n", ch, ch);
1237 /* same as minp, but also skip comments */
1238 void cinp(void)
1240 int c;
1242 if (ch1 == '/') {
1243 inp();
1244 if (ch1 == '/') {
1245 /* single line C++ comments */
1246 inp();
1247 while (ch1 != '\n' && ch1 != -1)
1248 inp();
1249 inp();
1250 ch = ' '; /* return space */
1251 } else if (ch1 == '*') {
1252 /* C comments */
1253 inp();
1254 while (ch1 != -1) {
1255 c = ch1;
1256 inp();
1257 if (c == '*' && ch1 == '/') {
1258 inp();
1259 ch = ' '; /* return space */
1260 break;
1263 } else {
1264 ch = '/';
1266 } else {
1267 minp();
1271 void skip_spaces(void)
1273 while (ch == ' ' || ch == '\t')
1274 cinp();
1277 /* skip block of text until #else, #elif or #endif. skip also pairs of
1278 #if/#endif */
1279 void preprocess_skip(void)
1281 int a;
1282 a = 0;
1283 while (1) {
1284 while (ch != '\n') {
1285 if (ch == -1)
1286 expect("#endif");
1287 cinp();
1289 cinp();
1290 skip_spaces();
1291 if (ch == '#') {
1292 cinp();
1293 next_nomacro();
1294 if (a == 0 &&
1295 (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
1296 break;
1297 if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
1298 a++;
1299 else if (tok == TOK_ENDIF)
1300 a--;
1305 /* ParseState handling */
1307 /* XXX: currently, no include file info is stored. Thus, we cannot display
1308 accurate messages if the function or data definition spans multiple
1309 files */
1311 /* save current parse state in 's' */
1312 void save_parse_state(ParseState *s)
1314 s->line_num = file->line_num;
1315 s->macro_ptr = macro_ptr;
1316 s->tok = tok;
1317 s->tokc = tokc;
1320 /* restore parse state from 's' */
1321 void restore_parse_state(ParseState *s)
1323 file->line_num = s->line_num;
1324 macro_ptr = s->macro_ptr;
1325 tok = s->tok;
1326 tokc = s->tokc;
1329 /* return the number of additionnal 'ints' necessary to store the
1330 token */
1331 static inline int tok_ext_size(int t)
1333 switch(t) {
1334 /* 4 bytes */
1335 case TOK_CINT:
1336 case TOK_CUINT:
1337 case TOK_CCHAR:
1338 case TOK_LCHAR:
1339 case TOK_STR:
1340 case TOK_LSTR:
1341 case TOK_CFLOAT:
1342 case TOK_LINENUM:
1343 return 1;
1344 case TOK_CDOUBLE:
1345 case TOK_CLLONG:
1346 case TOK_CULLONG:
1347 return 2;
1348 case TOK_CLDOUBLE:
1349 return LDOUBLE_SIZE / 4;
1350 default:
1351 return 0;
1355 /* token string handling */
1357 static inline void tok_str_new(TokenString *s)
1359 s->str = NULL;
1360 s->len = 0;
1361 s->last_line_num = -1;
1364 static void tok_str_add(TokenString *s, int t)
1366 int len, *str;
1368 len = s->len;
1369 str = s->str;
1370 if ((len & 63) == 0) {
1371 str = realloc(str, (len + 64) * sizeof(int));
1372 if (!str)
1373 return;
1374 s->str = str;
1376 str[len++] = t;
1377 s->len = len;
1380 static void tok_str_add2(TokenString *s, int t, CValue *cv)
1382 int n, i;
1383 tok_str_add(s, t);
1384 n = tok_ext_size(t);
1385 for(i=0;i<n;i++)
1386 tok_str_add(s, cv->tab[i]);
1389 /* add the current parse token in token string 's' */
1390 static void tok_str_add_tok(TokenString *s)
1392 CValue cval;
1394 /* save line number info */
1395 if (file->line_num != s->last_line_num) {
1396 s->last_line_num = file->line_num;
1397 cval.i = s->last_line_num;
1398 tok_str_add2(s, TOK_LINENUM, &cval);
1400 tok_str_add2(s, tok, &tokc);
1403 /* get a token from an integer array and increment pointer accordingly */
1404 static int tok_get(int **tok_str, CValue *cv)
1406 int *p, t, n, i;
1408 p = *tok_str;
1409 t = *p++;
1410 n = tok_ext_size(t);
1411 for(i=0;i<n;i++)
1412 cv->tab[i] = *p++;
1413 *tok_str = p;
1414 return t;
1417 /* eval an expression for #if/#elif */
1418 int expr_preprocess(void)
1420 int c, t;
1421 TokenString str;
1423 tok_str_new(&str);
1424 while (1) {
1425 skip_spaces();
1426 if (ch == '\n')
1427 break;
1428 next(); /* do macro subst */
1429 if (tok == TOK_DEFINED) {
1430 next_nomacro();
1431 t = tok;
1432 if (t == '(')
1433 next_nomacro();
1434 c = sym_find1(&define_stack, tok) != 0;
1435 if (t == '(')
1436 next_nomacro();
1437 tok = TOK_CINT;
1438 tokc.i = c;
1439 } else if (tok >= TOK_IDENT) {
1440 /* if undefined macro */
1441 tok = TOK_CINT;
1442 tokc.i = 0;
1444 tok_str_add_tok(&str);
1446 tok_str_add(&str, -1); /* simulate end of file */
1447 tok_str_add(&str, 0);
1448 /* now evaluate C constant expression */
1449 macro_ptr = str.str;
1450 next();
1451 c = expr_const();
1452 macro_ptr = NULL;
1453 free(str.str);
1454 return c != 0;
1457 #if defined(DEBUG) || defined(PP_DEBUG)
1458 void tok_print(int *str)
1460 int t;
1461 CValue cval;
1463 while (1) {
1464 t = tok_get(&str, &cval);
1465 if (!t)
1466 break;
1467 printf(" %s", get_tok_str(t, &cval));
1469 printf("\n");
1471 #endif
1473 /* parse after #define */
1474 void parse_define(void)
1476 Sym *s, *first, **ps;
1477 int v, t, varg, is_vaargs;
1478 TokenString str;
1480 v = tok;
1481 /* XXX: should check if same macro (ANSI) */
1482 first = NULL;
1483 t = MACRO_OBJ;
1484 /* '(' must be just after macro definition for MACRO_FUNC */
1485 if (ch == '(') {
1486 next_nomacro();
1487 next_nomacro();
1488 ps = &first;
1489 while (tok != ')') {
1490 varg = tok;
1491 next_nomacro();
1492 is_vaargs = 0;
1493 if (varg == TOK_DOTS) {
1494 varg = TOK___VA_ARGS__;
1495 is_vaargs = 1;
1496 } else if (tok == TOK_DOTS && gnu_ext) {
1497 is_vaargs = 1;
1498 next_nomacro();
1500 if (varg < TOK_IDENT)
1501 error("badly punctuated parameter list");
1502 s = sym_push1(&define_stack, varg | SYM_FIELD, is_vaargs, 0);
1503 *ps = s;
1504 ps = &s->next;
1505 if (tok != ',')
1506 break;
1507 next_nomacro();
1509 t = MACRO_FUNC;
1511 tok_str_new(&str);
1512 while (1) {
1513 skip_spaces();
1514 if (ch == '\n' || ch == -1)
1515 break;
1516 next_nomacro();
1517 tok_str_add2(&str, tok, &tokc);
1519 tok_str_add(&str, 0);
1520 #ifdef PP_DEBUG
1521 printf("define %s %d: ", get_tok_str(v, NULL), t);
1522 tok_print(str);
1523 #endif
1524 s = sym_push1(&define_stack, v, t, (int)str.str);
1525 s->next = first;
1528 void preprocess(void)
1530 int size, i, c;
1531 char buf[1024], *q, *p;
1532 char buf1[1024];
1533 BufferedFile *f;
1534 Sym *s;
1536 cinp();
1537 next_nomacro();
1538 redo:
1539 if (tok == TOK_DEFINE) {
1540 next_nomacro();
1541 parse_define();
1542 } else if (tok == TOK_UNDEF) {
1543 next_nomacro();
1544 s = sym_find1(&define_stack, tok);
1545 /* undefine symbol by putting an invalid name */
1546 if (s)
1547 sym_undef(&define_stack, s);
1548 } else if (tok == TOK_INCLUDE) {
1549 skip_spaces();
1550 if (ch == '<') {
1551 c = '>';
1552 goto read_name;
1553 } else if (ch == '\"') {
1554 c = ch;
1555 read_name:
1556 minp();
1557 q = buf;
1558 while (ch != c && ch != '\n' && ch != -1) {
1559 if ((q - buf) < sizeof(buf) - 1)
1560 *q++ = ch;
1561 minp();
1563 *q = '\0';
1564 } else {
1565 next();
1566 if (tok != TOK_STR)
1567 error("#include syntax error");
1568 pstrcpy(buf, sizeof(buf), get_tok_str(tok, &tokc));
1569 c = '\"';
1571 /* eat all spaces and comments after include */
1572 /* XXX: slightly incorrect */
1573 while (ch1 != '\n' && ch1 != -1)
1574 inp();
1576 if (include_stack_ptr >= include_stack + INCLUDE_STACK_SIZE)
1577 error("memory full");
1578 if (c == '\"') {
1579 /* first search in current dir if "header.h" */
1580 size = 0;
1581 p = strrchr(file->filename, '/');
1582 if (p)
1583 size = p + 1 - file->filename;
1584 if (size > sizeof(buf1) - 1)
1585 size = sizeof(buf1) - 1;
1586 memcpy(buf1, file->filename, size);
1587 buf1[size] = '\0';
1588 pstrcat(buf1, sizeof(buf1), buf);
1589 f = tcc_open(buf1);
1590 if (f)
1591 goto found;
1593 /* now search in standard include path */
1594 for(i=nb_include_paths - 1;i>=0;i--) {
1595 strcpy(buf1, include_paths[i]);
1596 strcat(buf1, "/");
1597 strcat(buf1, buf);
1598 f = tcc_open(buf1);
1599 if (f)
1600 goto found;
1602 error("include file '%s' not found", buf);
1603 f = NULL;
1604 found:
1605 /* push current file in stack */
1606 /* XXX: fix current line init */
1607 *include_stack_ptr++ = file;
1608 file = f;
1609 /* add include file debug info */
1610 if (do_debug) {
1611 put_stabs(file->filename, N_BINCL, 0, 0, 0);
1613 } else if (tok == TOK_IFNDEF) {
1614 c = 1;
1615 goto do_ifdef;
1616 } else if (tok == TOK_IF) {
1617 c = expr_preprocess();
1618 goto do_if;
1619 } else if (tok == TOK_IFDEF) {
1620 c = 0;
1621 do_ifdef:
1622 next_nomacro();
1623 c = (sym_find1(&define_stack, tok) != 0) ^ c;
1624 do_if:
1625 if (ifdef_stack_ptr >= ifdef_stack + IFDEF_STACK_SIZE)
1626 error("memory full");
1627 *ifdef_stack_ptr++ = c;
1628 goto test_skip;
1629 } else if (tok == TOK_ELSE) {
1630 if (ifdef_stack_ptr == ifdef_stack)
1631 error("#else without matching #if");
1632 if (ifdef_stack_ptr[-1] & 2)
1633 error("#else after #else");
1634 c = (ifdef_stack_ptr[-1] ^= 3);
1635 goto test_skip;
1636 } else if (tok == TOK_ELIF) {
1637 if (ifdef_stack_ptr == ifdef_stack)
1638 error("#elif without matching #if");
1639 c = ifdef_stack_ptr[-1];
1640 if (c > 1)
1641 error("#elif after #else");
1642 /* last #if/#elif expression was true: we skip */
1643 if (c == 1)
1644 goto skip;
1645 c = expr_preprocess();
1646 ifdef_stack_ptr[-1] = c;
1647 test_skip:
1648 if (!(c & 1)) {
1649 skip:
1650 preprocess_skip();
1651 goto redo;
1653 } else if (tok == TOK_ENDIF) {
1654 if (ifdef_stack_ptr == ifdef_stack)
1655 error("#endif without matching #if");
1656 ifdef_stack_ptr--;
1657 } else if (tok == TOK_LINE) {
1658 next();
1659 if (tok != TOK_CINT)
1660 error("#line");
1661 file->line_num = tokc.i;
1662 skip_spaces();
1663 if (ch != '\n') {
1664 next();
1665 if (tok != TOK_STR)
1666 error("#line");
1667 pstrcpy(file->filename, sizeof(file->filename),
1668 get_tok_str(tok, &tokc));
1670 } else if (tok == TOK_ERROR) {
1671 error("#error");
1673 /* ignore other preprocess commands or #! for C scripts */
1674 while (ch != '\n' && ch != -1)
1675 cinp();
1678 /* read a number in base b */
1679 int getn(b)
1681 int n, t;
1682 n = 0;
1683 while (1) {
1684 if (ch >= 'a' && ch <= 'f')
1685 t = ch - 'a' + 10;
1686 else if (ch >= 'A' && ch <= 'F')
1687 t = ch - 'A' + 10;
1688 else if (isnum(ch))
1689 t = ch - '0';
1690 else
1691 break;
1692 if (t < 0 || t >= b)
1693 break;
1694 n = n * b + t;
1695 cinp();
1697 return n;
1700 /* read a character for string or char constant and eval escape codes */
1701 int getq()
1703 int c;
1705 c = ch;
1706 minp();
1707 if (c == '\\') {
1708 if (isnum(ch)) {
1709 /* at most three octal digits */
1710 c = ch - '0';
1711 minp();
1712 if (isnum(ch)) {
1713 c = c * 8 + ch - '0';
1714 minp();
1715 if (isnum(ch)) {
1716 c = c * 8 + ch - '0';
1717 minp();
1720 return c;
1721 } else if (ch == 'x') {
1722 minp();
1723 return getn(16);
1724 } else {
1725 if (ch == 'a')
1726 c = '\a';
1727 else if (ch == 'b')
1728 c = '\b';
1729 else if (ch == 'f')
1730 c = '\f';
1731 else if (ch == 'n')
1732 c = '\n';
1733 else if (ch == 'r')
1734 c = '\r';
1735 else if (ch == 't')
1736 c = '\t';
1737 else if (ch == 'v')
1738 c = '\v';
1739 else if (ch == 'e' && gnu_ext)
1740 c = 27;
1741 else if (ch == '\'' || ch == '\"' || ch == '\\' || ch == '?')
1742 c = ch;
1743 else
1744 error("invalid escaped char");
1745 minp();
1748 return c;
1751 /* we use 64 bit numbers */
1752 #define BN_SIZE 2
1754 /* bn = (bn << shift) | or_val */
1755 void bn_lshift(unsigned int *bn, int shift, int or_val)
1757 int i;
1758 unsigned int v;
1759 for(i=0;i<BN_SIZE;i++) {
1760 v = bn[i];
1761 bn[i] = (v << shift) | or_val;
1762 or_val = v >> (32 - shift);
1766 void bn_zero(unsigned int *bn)
1768 int i;
1769 for(i=0;i<BN_SIZE;i++) {
1770 bn[i] = 0;
1774 void parse_number(void)
1776 int b, t, shift, frac_bits, s, exp_val;
1777 char *q;
1778 unsigned int bn[BN_SIZE];
1779 double d;
1781 /* number */
1782 q = token_buf;
1783 t = ch;
1784 cinp();
1785 *q++ = t;
1786 b = 10;
1787 if (t == '.') {
1788 /* special dot handling */
1789 if (ch >= '0' && ch <= '9') {
1790 goto float_frac_parse;
1791 } else if (ch == '.') {
1792 cinp();
1793 if (ch != '.')
1794 expect("'.'");
1795 cinp();
1796 tok = TOK_DOTS;
1797 } else {
1798 /* dots */
1799 tok = t;
1801 return;
1802 } else if (t == '0') {
1803 if (ch == 'x' || ch == 'X') {
1804 q--;
1805 cinp();
1806 b = 16;
1807 } else if (tcc_ext && (ch == 'b' || ch == 'B')) {
1808 q--;
1809 cinp();
1810 b = 2;
1813 /* parse all digits. cannot check octal numbers at this stage
1814 because of floating point constants */
1815 while (1) {
1816 if (ch >= 'a' && ch <= 'f')
1817 t = ch - 'a' + 10;
1818 else if (ch >= 'A' && ch <= 'F')
1819 t = ch - 'A' + 10;
1820 else if (isnum(ch))
1821 t = ch - '0';
1822 else
1823 break;
1824 if (t >= b)
1825 break;
1826 if (q >= token_buf + STRING_MAX_SIZE) {
1827 num_too_long:
1828 error("number too long");
1830 *q++ = ch;
1831 cinp();
1833 if (ch == '.' ||
1834 ((ch == 'e' || ch == 'E') && b == 10) ||
1835 ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
1836 if (b != 10) {
1837 /* NOTE: strtox should support that for hexa numbers, but
1838 non ISOC99 libcs do not support it, so we prefer to do
1839 it by hand */
1840 /* hexadecimal or binary floats */
1841 /* XXX: handle overflows */
1842 *q = '\0';
1843 if (b == 16)
1844 shift = 4;
1845 else
1846 shift = 2;
1847 bn_zero(bn);
1848 q = token_buf;
1849 while (1) {
1850 t = *q++;
1851 if (t == '\0') {
1852 break;
1853 } else if (t >= 'a') {
1854 t = t - 'a' + 10;
1855 } else if (t >= 'A') {
1856 t = t - 'A' + 10;
1857 } else {
1858 t = t - '0';
1860 bn_lshift(bn, shift, t);
1862 frac_bits = 0;
1863 if (ch == '.') {
1864 cinp();
1865 while (1) {
1866 t = ch;
1867 if (t >= 'a' && t <= 'f') {
1868 t = t - 'a' + 10;
1869 } else if (t >= 'A' && t <= 'F') {
1870 t = t - 'A' + 10;
1871 } else if (t >= '0' && t <= '9') {
1872 t = t - '0';
1873 } else {
1874 break;
1876 if (t >= b)
1877 error("invalid digit");
1878 bn_lshift(bn, shift, t);
1879 frac_bits += shift;
1880 cinp();
1883 if (ch != 'p' && ch != 'P')
1884 error("exponent expected");
1885 cinp();
1886 s = 1;
1887 exp_val = 0;
1888 if (ch == '+') {
1889 cinp();
1890 } else if (ch == '-') {
1891 s = -1;
1892 cinp();
1894 if (ch < '0' || ch > '9')
1895 error("exponent digits expected");
1896 while (ch >= '0' && ch <= '9') {
1897 exp_val = exp_val * 10 + ch - '0';
1898 cinp();
1900 exp_val = exp_val * s;
1902 /* now we can generate the number */
1903 /* XXX: should patch directly float number */
1904 d = (double)bn[1] * 4294967296.0 + (double)bn[0];
1905 d = ldexp(d, exp_val - frac_bits);
1906 t = toup(ch);
1907 if (t == 'F') {
1908 cinp();
1909 tok = TOK_CFLOAT;
1910 /* float : should handle overflow */
1911 tokc.f = (float)d;
1912 } else if (t == 'L') {
1913 cinp();
1914 tok = TOK_CLDOUBLE;
1915 /* XXX: not large enough */
1916 tokc.ld = (long double)d;
1917 } else {
1918 tok = TOK_CDOUBLE;
1919 tokc.d = d;
1921 } else {
1922 /* decimal floats */
1923 if (ch == '.') {
1924 if (q >= token_buf + STRING_MAX_SIZE)
1925 goto num_too_long;
1926 *q++ = ch;
1927 cinp();
1928 float_frac_parse:
1929 while (ch >= '0' && ch <= '9') {
1930 if (q >= token_buf + STRING_MAX_SIZE)
1931 goto num_too_long;
1932 *q++ = ch;
1933 cinp();
1936 if (ch == 'e' || ch == 'E') {
1937 if (q >= token_buf + STRING_MAX_SIZE)
1938 goto num_too_long;
1939 *q++ = ch;
1940 cinp();
1941 if (ch == '-' || ch == '+') {
1942 if (q >= token_buf + STRING_MAX_SIZE)
1943 goto num_too_long;
1944 *q++ = ch;
1945 cinp();
1947 if (ch < '0' || ch > '9')
1948 error("exponent digits expected");
1949 while (ch >= '0' && ch <= '9') {
1950 if (q >= token_buf + STRING_MAX_SIZE)
1951 goto num_too_long;
1952 *q++ = ch;
1953 cinp();
1956 *q = '\0';
1957 t = toup(ch);
1958 errno = 0;
1959 if (t == 'F') {
1960 cinp();
1961 tok = TOK_CFLOAT;
1962 tokc.f = strtof(token_buf, NULL);
1963 } else if (t == 'L') {
1964 cinp();
1965 tok = TOK_CLDOUBLE;
1966 tokc.ld = strtold(token_buf, NULL);
1967 } else {
1968 tok = TOK_CDOUBLE;
1969 tokc.d = strtod(token_buf, NULL);
1972 } else {
1973 unsigned long long n, n1;
1974 int lcount;
1976 /* integer number */
1977 *q = '\0';
1978 q = token_buf;
1979 if (b == 10 && *q == '0') {
1980 b = 8;
1981 q++;
1983 n = 0;
1984 while(1) {
1985 t = *q++;
1986 /* no need for checks except for base 10 / 8 errors */
1987 if (t == '\0') {
1988 break;
1989 } else if (t >= 'a') {
1990 t = t - 'a' + 10;
1991 } else if (t >= 'A') {
1992 t = t - 'A' + 10;
1993 } else {
1994 t = t - '0';
1995 if (t >= b)
1996 error("invalid digit");
1998 n1 = n;
1999 n = n * b + t;
2000 /* detect overflow */
2001 if (n < n1)
2002 error("integer constant overflow");
2005 /* XXX: not exactly ANSI compliant */
2006 if ((n & 0xffffffff00000000LL) != 0) {
2007 if ((n >> 63) != 0)
2008 tok = TOK_CULLONG;
2009 else
2010 tok = TOK_CLLONG;
2011 } else if (n > 0x7fffffff) {
2012 tok = TOK_CUINT;
2013 } else {
2014 tok = TOK_CINT;
2016 lcount = 0;
2017 for(;;) {
2018 t = toup(ch);
2019 if (t == 'L') {
2020 if (lcount >= 2)
2021 error("three 'l' in integer constant");
2022 lcount++;
2023 if (lcount == 2) {
2024 if (tok == TOK_CINT)
2025 tok = TOK_CLLONG;
2026 else if (tok == TOK_CUINT)
2027 tok = TOK_CULLONG;
2029 cinp();
2030 } else if (t == 'U') {
2031 if (tok == TOK_CINT)
2032 tok = TOK_CUINT;
2033 else if (tok == TOK_CLLONG)
2034 tok = TOK_CULLONG;
2035 cinp();
2036 } else {
2037 break;
2040 if (tok == TOK_CINT || tok == TOK_CUINT)
2041 tokc.ui = n;
2042 else
2043 tokc.ull = n;
2048 /* return next token without macro substitution */
2049 void next_nomacro1(void)
2051 int b;
2052 char *q;
2053 TokenSym *ts;
2055 /* skip spaces */
2056 while(1) {
2057 while (ch == '\n') {
2058 cinp();
2059 while (ch == ' ' || ch == '\t')
2060 cinp();
2061 if (ch == '#') {
2062 /* preprocessor command if # at start of line after
2063 spaces */
2064 preprocess();
2067 if (ch != ' ' && ch != '\t' && ch != '\f')
2068 break;
2069 cinp();
2071 if (isid(ch)) {
2072 q = token_buf;
2073 *q++ = ch;
2074 cinp();
2075 if (q[-1] == 'L') {
2076 if (ch == '\'') {
2077 tok = TOK_LCHAR;
2078 goto char_const;
2080 if (ch == '\"') {
2081 tok = TOK_LSTR;
2082 goto str_const;
2085 while (isid(ch) || isnum(ch)) {
2086 if (q >= token_buf + STRING_MAX_SIZE)
2087 error("ident too long");
2088 *q++ = ch;
2089 cinp();
2091 *q = '\0';
2092 ts = tok_alloc(token_buf, q - token_buf);
2093 tok = ts->tok;
2094 } else if (isnum(ch) || ch == '.') {
2095 parse_number();
2096 } else if (ch == '\'') {
2097 tok = TOK_CCHAR;
2098 char_const:
2099 minp();
2100 tokc.i = getq();
2101 if (ch != '\'')
2102 expect("\'");
2103 minp();
2104 } else if (ch == '\"') {
2105 tok = TOK_STR;
2106 str_const:
2107 minp();
2108 q = token_buf;
2109 while (ch != '\"') {
2110 b = getq();
2111 if (ch == -1)
2112 error("unterminated string");
2113 if (q >= token_buf + STRING_MAX_SIZE)
2114 error("string too long");
2115 *q++ = b;
2117 *q = '\0';
2118 tokc.ts = tok_alloc(token_buf, q - token_buf);
2119 minp();
2120 } else {
2121 q = "<=\236>=\235!=\225&&\240||\241++\244--\242==\224<<\1>>\2+=\253-=\255*=\252/=\257%=\245&=\246^=\336|=\374->\313..\250##\266";
2122 /* two chars */
2123 tok = ch;
2124 cinp();
2125 while (*q) {
2126 if (*q == tok && q[1] == ch) {
2127 cinp();
2128 tok = q[2] & 0xff;
2129 /* three chars tests */
2130 if (tok == TOK_SHL || tok == TOK_SAR) {
2131 if (ch == '=') {
2132 tok = tok | 0x80;
2133 cinp();
2135 } else if (tok == TOK_DOTS) {
2136 if (ch != '.')
2137 error("parse error");
2138 cinp();
2140 return;
2142 q = q + 3;
2144 /* single char substitutions */
2145 if (tok == '<')
2146 tok = TOK_LT;
2147 else if (tok == '>')
2148 tok = TOK_GT;
2152 /* return next token without macro substitution. Can read input from
2153 macro_ptr buffer */
2154 void next_nomacro()
2156 if (macro_ptr) {
2157 redo:
2158 tok = *macro_ptr;
2159 if (tok) {
2160 tok = tok_get(&macro_ptr, &tokc);
2161 if (tok == TOK_LINENUM) {
2162 file->line_num = tokc.i;
2163 goto redo;
2166 } else {
2167 next_nomacro1();
2171 /* substitute args in macro_str and return allocated string */
2172 int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
2174 int *st, last_tok, t, notfirst;
2175 Sym *s;
2176 TokenSym *ts;
2177 CValue cval;
2178 TokenString str;
2180 tok_str_new(&str);
2181 last_tok = 0;
2182 while(1) {
2183 t = tok_get(&macro_str, &cval);
2184 if (!t)
2185 break;
2186 if (t == '#') {
2187 /* stringize */
2188 t = tok_get(&macro_str, &cval);
2189 if (!t)
2190 break;
2191 s = sym_find2(args, t);
2192 if (s) {
2193 token_buf[0] = '\0';
2194 st = (int *)s->c;
2195 notfirst = 0;
2196 while (*st) {
2197 if (notfirst)
2198 pstrcat(token_buf, sizeof(token_buf), " ");
2199 t = tok_get(&st, &cval);
2200 pstrcat(token_buf, sizeof(token_buf), get_tok_str(t, &cval));
2201 notfirst = 1;
2203 #ifdef PP_DEBUG
2204 printf("stringize: %s\n", token_buf);
2205 #endif
2206 /* add string */
2207 ts = tok_alloc(token_buf, 0);
2208 cval.ts = ts;
2209 tok_str_add2(&str, TOK_STR, &cval);
2210 } else {
2211 tok_str_add2(&str, t, &cval);
2213 } else if (t >= TOK_IDENT) {
2214 s = sym_find2(args, t);
2215 if (s) {
2216 st = (int *)s->c;
2217 /* if '##' is present before or after, no arg substitution */
2218 if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) {
2219 /* special case for var arg macros : ## eats the
2220 ',' if empty VA_ARGS riable. */
2221 /* XXX: test of the ',' is not 100%
2222 reliable. should fix it to avoid security
2223 problems */
2224 if (gnu_ext && s->t && *st == 0 &&
2225 last_tok == TOK_TWOSHARPS &&
2226 str.len >= 2&& str.str[str.len - 2] == ',') {
2227 /* suppress ',' '##' */
2228 str.len -= 2;
2229 } else {
2230 while (*st)
2231 tok_str_add(&str, *st++);
2233 } else {
2234 macro_subst(&str, nested_list, st);
2236 } else {
2237 tok_str_add(&str, t);
2239 } else {
2240 tok_str_add2(&str, t, &cval);
2242 last_tok = t;
2244 tok_str_add(&str, 0);
2245 return str.str;
2248 /* handle the '##' operator */
2249 int *macro_twosharps(int *macro_str)
2251 TokenSym *ts;
2252 int *macro_ptr1;
2253 int t;
2254 char *p;
2255 CValue cval;
2256 TokenString macro_str1;
2258 tok_str_new(&macro_str1);
2259 tok = 0;
2260 while (1) {
2261 next_nomacro();
2262 if (tok == 0)
2263 break;
2264 while (*macro_ptr == TOK_TWOSHARPS) {
2265 macro_ptr++;
2266 macro_ptr1 = macro_ptr;
2267 t = *macro_ptr;
2268 if (t) {
2269 t = tok_get(&macro_ptr, &cval);
2270 /* XXX: we handle only most common cases:
2271 ident + ident or ident + number */
2272 if (tok >= TOK_IDENT &&
2273 (t >= TOK_IDENT || t == TOK_CINT)) {
2274 p = get_tok_str(tok, &tokc);
2275 pstrcpy(token_buf, sizeof(token_buf), p);
2276 p = get_tok_str(t, &cval);
2277 pstrcat(token_buf, sizeof(token_buf), p);
2278 ts = tok_alloc(token_buf, 0);
2279 tok = ts->tok; /* modify current token */
2280 } else {
2281 /* cannot merge tokens: skip '##' */
2282 macro_ptr = macro_ptr1;
2283 break;
2287 tok_str_add2(&macro_str1, tok, &tokc);
2289 tok_str_add(&macro_str1, 0);
2290 return macro_str1.str;
2293 /* do macro substitution of macro_str and add result to
2294 (tok_str,tok_len). If macro_str is NULL, then input stream token is
2295 substituted. 'nested_list' is the list of all macros we got inside
2296 to avoid recursing. */
2297 void macro_subst(TokenString *tok_str,
2298 Sym **nested_list, int *macro_str)
2300 Sym *s, *args, *sa, *sa1;
2301 int parlevel, *mstr, t, *saved_macro_ptr;
2302 int mstr_allocated, *macro_str1;
2303 CValue cval;
2304 TokenString str;
2306 saved_macro_ptr = macro_ptr;
2307 macro_ptr = macro_str;
2308 macro_str1 = NULL;
2309 if (macro_str) {
2310 /* first scan for '##' operator handling */
2311 macro_str1 = macro_twosharps(macro_str);
2312 macro_ptr = macro_str1;
2315 while (1) {
2316 next_nomacro();
2317 if (tok == 0)
2318 break;
2319 /* special macros */
2320 if (tok == TOK___LINE__) {
2321 cval.i = file->line_num;
2322 tok_str_add2(tok_str, TOK_CINT, &cval);
2323 } else if (tok == TOK___FILE__) {
2324 cval.ts = tok_alloc(file->filename, 0);
2325 tok_str_add2(tok_str, TOK_STR, &cval);
2326 } else if (tok == TOK___DATE__) {
2327 cval.ts = tok_alloc("Jan 1 1970", 0);
2328 tok_str_add2(tok_str, TOK_STR, &cval);
2329 } else if (tok == TOK___TIME__) {
2330 cval.ts = tok_alloc("00:00:00", 0);
2331 tok_str_add2(tok_str, TOK_STR, &cval);
2332 } else if ((s = sym_find1(&define_stack, tok)) != NULL) {
2333 /* if symbol is a macro, prepare substitution */
2334 /* if nested substitution, do nothing */
2335 if (sym_find2(*nested_list, tok))
2336 goto no_subst;
2337 mstr = (int *)s->c;
2338 mstr_allocated = 0;
2339 if (s->t == MACRO_FUNC) {
2340 /* NOTE: we do not use next_nomacro to avoid eating the
2341 next token. XXX: find better solution */
2342 if (macro_ptr) {
2343 t = *macro_ptr;
2344 } else {
2345 while (ch == ' ' || ch == '\t' || ch == '\n')
2346 cinp();
2347 t = ch;
2349 if (t != '(') /* no macro subst */
2350 goto no_subst;
2352 /* argument macro */
2353 next_nomacro();
2354 next_nomacro();
2355 args = NULL;
2356 sa = s->next;
2357 /* NOTE: empty args are allowed, except if no args */
2358 for(;;) {
2359 /* handle '()' case */
2360 if (!args && tok == ')')
2361 break;
2362 if (!sa)
2363 error("macro '%s' used with too many args",
2364 get_tok_str(s->v, 0));
2365 tok_str_new(&str);
2366 parlevel = 0;
2367 /* NOTE: non zero sa->t indicates VA_ARGS */
2368 while ((parlevel > 0 ||
2369 (tok != ')' &&
2370 (tok != ',' || sa->t))) &&
2371 tok != -1) {
2372 if (tok == '(')
2373 parlevel++;
2374 else if (tok == ')')
2375 parlevel--;
2376 tok_str_add2(&str, tok, &tokc);
2377 next_nomacro();
2379 tok_str_add(&str, 0);
2380 sym_push2(&args, sa->v & ~SYM_FIELD, sa->t, (int)str.str);
2381 sa = sa->next;
2382 if (tok == ')') {
2383 /* special case for gcc var args: add an empty
2384 var arg argument if it is omitted */
2385 if (sa && sa->t && gnu_ext)
2386 continue;
2387 else
2388 break;
2390 if (tok != ',')
2391 expect(",");
2392 next_nomacro();
2394 if (sa) {
2395 error("macro '%s' used with too few args",
2396 get_tok_str(s->v, 0));
2399 /* now subst each arg */
2400 mstr = macro_arg_subst(nested_list, mstr, args);
2401 /* free memory */
2402 sa = args;
2403 while (sa) {
2404 sa1 = sa->prev;
2405 free((int *)sa->c);
2406 free(sa);
2407 sa = sa1;
2409 mstr_allocated = 1;
2411 sym_push2(nested_list, s->v, 0, 0);
2412 macro_subst(tok_str, nested_list, mstr);
2413 /* pop nested defined symbol */
2414 sa1 = *nested_list;
2415 *nested_list = sa1->prev;
2416 free(sa1);
2417 if (mstr_allocated)
2418 free(mstr);
2419 } else {
2420 no_subst:
2421 /* no need to add if reading input stream */
2422 if (!macro_str)
2423 return;
2424 tok_str_add2(tok_str, tok, &tokc);
2426 /* only replace one macro while parsing input stream */
2427 if (!macro_str)
2428 return;
2430 macro_ptr = saved_macro_ptr;
2431 if (macro_str1)
2432 free(macro_str1);
2435 /* return next token with macro substitution */
2436 void next(void)
2438 Sym *nested_list;
2439 TokenString str;
2441 /* special 'ungettok' case for label parsing */
2442 if (tok1) {
2443 tok = tok1;
2444 tokc = tok1c;
2445 tok1 = 0;
2446 } else {
2447 redo:
2448 if (!macro_ptr) {
2449 /* if not reading from macro substituted string, then try
2450 to substitute */
2451 /* XXX: optimize non macro case */
2452 tok_str_new(&str);
2453 nested_list = NULL;
2454 macro_subst(&str, &nested_list, NULL);
2455 if (str.str) {
2456 tok_str_add(&str, 0);
2457 macro_ptr = str.str;
2458 macro_ptr_allocated = str.str;
2459 goto redo;
2461 if (tok == 0)
2462 goto redo;
2463 } else {
2464 next_nomacro();
2465 if (tok == 0) {
2466 /* end of macro string: free it */
2467 free(macro_ptr_allocated);
2468 macro_ptr = NULL;
2469 goto redo;
2473 #if defined(DEBUG)
2474 printf("token = %s\n", get_tok_str(tok, tokc));
2475 #endif
2478 void swap(int *p, int *q)
2480 int t;
2481 t = *p;
2482 *p = *q;
2483 *q = t;
2486 void vsetc(int t, int r, CValue *vc)
2488 if (vtop >= vstack + VSTACK_SIZE)
2489 error("memory full");
2490 /* cannot let cpu flags if other instruction are generated */
2491 /* XXX: VT_JMP test too ? */
2492 if ((vtop->r & VT_VALMASK) == VT_CMP)
2493 gv(RC_INT);
2494 vtop++;
2495 vtop->t = t;
2496 vtop->r = r;
2497 vtop->r2 = VT_CONST;
2498 vtop->c = *vc;
2501 /* push integer constant */
2502 void vpushi(int v)
2504 CValue cval;
2505 cval.i = v;
2506 vsetc(VT_INT, VT_CONST, &cval);
2509 /* push a reference to a section offset by adding a dummy symbol */
2510 void vpush_ref(int t, Section *sec, unsigned long offset)
2512 int v;
2513 Sym *sym;
2514 CValue cval;
2516 v = anon_sym++;
2517 sym = sym_push1(&global_stack, v, t | VT_STATIC, 0);
2518 sym->r = VT_CONST | VT_SYM;
2519 put_extern_sym(sym, sec, offset);
2520 cval.sym = sym;
2521 vsetc(t, VT_CONST | VT_SYM, &cval);
2524 void vset(int t, int r, int v)
2526 CValue cval;
2528 cval.i = v;
2529 vsetc(t, r, &cval);
2532 void vswap(void)
2534 SValue tmp;
2536 tmp = vtop[0];
2537 vtop[0] = vtop[-1];
2538 vtop[-1] = tmp;
2541 void vpushv(SValue *v)
2543 if (vtop >= vstack + VSTACK_SIZE)
2544 error("memory full");
2545 vtop++;
2546 *vtop = *v;
2549 void vdup(void)
2551 vpushv(vtop);
2554 /* save r to the memory stack, and mark it as being free */
2555 void save_reg(int r)
2557 int l, i, saved, t, size, align;
2558 SValue *p, sv;
2560 /* modify all stack values */
2561 saved = 0;
2562 l = 0;
2563 for(p=vstack;p<=vtop;p++) {
2564 i = p->r & VT_VALMASK;
2565 if ((p->r & VT_VALMASK) == r ||
2566 (p->r2 & VT_VALMASK) == r) {
2567 /* must save value on stack if not already done */
2568 if (!saved) {
2569 /* store register in the stack */
2570 t = p->t;
2571 if ((p->r & VT_LVAL) ||
2572 (!is_float(t) && (t & VT_BTYPE) != VT_LLONG))
2573 t = VT_INT;
2574 size = type_size(t, &align);
2575 loc = (loc - size) & -align;
2576 sv.t = t;
2577 sv.r = VT_LOCAL | VT_LVAL;
2578 sv.c.ul = loc;
2579 store(r, &sv);
2580 #ifdef TCC_TARGET_I386
2581 /* x86 specific: need to pop fp register ST0 if saved */
2582 if (r == REG_ST0) {
2583 o(0xd9dd); /* fstp %st(1) */
2585 #endif
2586 /* special long long case */
2587 if ((t & VT_BTYPE) == VT_LLONG) {
2588 sv.c.ul += 4;
2589 store(p->r2, &sv);
2591 l = loc;
2592 saved = 1;
2594 /* mark that stack entry as being saved on the stack */
2595 if (p->r & VT_LVAL)
2596 t = VT_LLOCAL;
2597 else
2598 t = VT_LOCAL;
2599 p->r = VT_LVAL | t;
2600 p->r2 = VT_CONST;
2601 p->c.ul = l;
2606 /* find a free register of class 'rc'. If none, save one register */
2607 int get_reg(int rc)
2609 int r;
2610 SValue *p;
2612 /* find a free register */
2613 for(r=0;r<NB_REGS;r++) {
2614 if (reg_classes[r] & rc) {
2615 for(p=vstack;p<=vtop;p++) {
2616 if ((p->r & VT_VALMASK) == r ||
2617 (p->r2 & VT_VALMASK) == r)
2618 goto notfound;
2620 return r;
2622 notfound: ;
2625 /* no register left : free the first one on the stack (VERY
2626 IMPORTANT to start from the bottom to ensure that we don't
2627 spill registers used in gen_opi()) */
2628 for(p=vstack;p<=vtop;p++) {
2629 r = p->r & VT_VALMASK;
2630 if (r < VT_CONST && (reg_classes[r] & rc)) {
2631 save_reg(r);
2632 break;
2635 return r;
2638 /* save registers up to (vtop - n) stack entry */
2639 void save_regs(int n)
2641 int r;
2642 SValue *p, *p1;
2643 p1 = vtop - n;
2644 for(p = vstack;p <= p1; p++) {
2645 r = p->r & VT_VALMASK;
2646 if (r < VT_CONST) {
2647 save_reg(r);
2652 /* move register 's' to 'r', and flush previous value of r to memory
2653 if needed */
2654 void move_reg(int r, int s)
2656 SValue sv;
2658 if (r != s) {
2659 save_reg(r);
2660 sv.t = VT_INT;
2661 sv.r = s;
2662 sv.c.ul = 0;
2663 load(r, &sv);
2667 /* get address of vtop (vtop MUST BE an lvalue) */
2668 void gaddrof(void)
2670 vtop->r &= ~VT_LVAL;
2671 /* tricky: if saved lvalue, then we can go back to lvalue */
2672 if ((vtop->r & VT_VALMASK) == VT_LLOCAL)
2673 vtop->r = (vtop->r & ~VT_VALMASK) | VT_LOCAL | VT_LVAL;
2676 #ifdef CONFIG_TCC_BCHECK
2677 /* generate lvalue bound code */
2678 void gbound(void)
2680 int lval_type;
2682 vtop->r &= ~VT_MUSTBOUND;
2683 /* if lvalue, then use checking code before dereferencing */
2684 if (vtop->r & VT_LVAL) {
2685 /* if not VT_BOUNDED value, then make one */
2686 if (!(vtop->r & VT_BOUNDED)) {
2687 lval_type = vtop->r & (VT_LVAL_TYPE | VT_LVAL);
2688 gaddrof();
2689 vpushi(0);
2690 gen_bounded_ptr_add();
2691 vtop->r |= lval_type;
2693 /* then check for dereferencing */
2694 gen_bounded_ptr_deref();
2697 #endif
2699 /* store vtop a register belonging to class 'rc'. lvalues are
2700 converted to values. Cannot be used if cannot be converted to
2701 register value (such as structures). */
2702 int gv(int rc)
2704 int r, r2, rc2, bit_pos, bit_size, size, align, i, data_offset;
2705 unsigned long long ll;
2707 /* NOTE: get_reg can modify vstack[] */
2708 if (vtop->t & VT_BITFIELD) {
2709 bit_pos = (vtop->t >> VT_STRUCT_SHIFT) & 0x3f;
2710 bit_size = (vtop->t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
2711 /* remove bit field info to avoid loops */
2712 vtop->t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
2713 /* generate shifts */
2714 vpushi(32 - (bit_pos + bit_size));
2715 gen_op(TOK_SHL);
2716 vpushi(32 - bit_size);
2717 /* NOTE: transformed to SHR if unsigned */
2718 gen_op(TOK_SAR);
2719 r = gv(rc);
2720 } else {
2721 if (is_float(vtop->t) &&
2722 (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
2723 /* CPUs usually cannot use float constants, so we store them
2724 generically in data segment */
2725 size = type_size(vtop->t, &align);
2726 data_offset = (int)data_section->data_ptr;
2727 data_offset = (data_offset + align - 1) & -align;
2728 /* XXX: not portable yet */
2729 size = size >> 2;
2730 for(i=0;i<size;i++)
2731 ((int *)data_offset)[i] = vtop->c.tab[i];
2732 vtop->r |= VT_LVAL;
2733 vtop->c.ul = data_offset;
2734 data_offset += size << 2;
2735 data_section->data_ptr = (unsigned char *)data_offset;
2737 #ifdef CONFIG_TCC_BCHECK
2738 if (vtop->r & VT_MUSTBOUND)
2739 gbound();
2740 #endif
2742 r = vtop->r & VT_VALMASK;
2743 /* need to reload if:
2744 - constant
2745 - lvalue (need to dereference pointer)
2746 - already a register, but not in the right class */
2747 if (r >= VT_CONST ||
2748 (vtop->r & VT_LVAL) ||
2749 !(reg_classes[r] & rc) ||
2750 ((vtop->t & VT_BTYPE) == VT_LLONG &&
2751 !(reg_classes[vtop->r2] & rc))) {
2752 r = get_reg(rc);
2753 if ((vtop->t & VT_BTYPE) == VT_LLONG) {
2754 /* two register type load : expand to two words
2755 temporarily */
2756 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
2757 /* load constant */
2758 ll = vtop->c.ull;
2759 vtop->c.ui = ll; /* first word */
2760 load(r, vtop);
2761 vtop->r = r; /* save register value */
2762 vpushi(ll >> 32); /* second word */
2763 } else if (r >= VT_CONST ||
2764 (vtop->r & VT_LVAL)) {
2765 /* load from memory */
2766 load(r, vtop);
2767 vdup();
2768 vtop[-1].r = r; /* save register value */
2769 /* increment pointer to get second word */
2770 vtop->t = VT_INT;
2771 gaddrof();
2772 vpushi(4);
2773 gen_op('+');
2774 vtop->r |= VT_LVAL;
2775 } else {
2776 /* move registers */
2777 load(r, vtop);
2778 vdup();
2779 vtop[-1].r = r; /* save register value */
2780 vtop->r = vtop[-1].r2;
2782 /* allocate second register */
2783 rc2 = RC_INT;
2784 if (rc == RC_IRET)
2785 rc2 = RC_LRET;
2786 r2 = get_reg(rc2);
2787 load(r2, vtop);
2788 vpop();
2789 /* write second register */
2790 vtop->r2 = r2;
2791 } else if ((vtop->r & VT_LVAL) && !is_float(vtop->t)) {
2792 int t1, t;
2793 /* lvalue of scalar type : need to use lvalue type
2794 because of possible cast */
2795 t = vtop->t;
2796 t1 = t;
2797 /* compute memory access type */
2798 if (vtop->r & VT_LVAL_BYTE)
2799 t = VT_BYTE;
2800 else if (vtop->r & VT_LVAL_SHORT)
2801 t = VT_SHORT;
2802 if (vtop->r & VT_LVAL_UNSIGNED)
2803 t |= VT_UNSIGNED;
2804 vtop->t = t;
2805 load(r, vtop);
2806 /* restore wanted type */
2807 vtop->t = t1;
2808 } else {
2809 /* one register type load */
2810 load(r, vtop);
2813 vtop->r = r;
2815 return r;
2818 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
2819 void gv2(int rc1, int rc2)
2821 /* generate more generic register first */
2822 if (rc1 <= rc2) {
2823 vswap();
2824 gv(rc1);
2825 vswap();
2826 gv(rc2);
2827 /* test if reload is needed for first register */
2828 if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
2829 vswap();
2830 gv(rc1);
2831 vswap();
2833 } else {
2834 gv(rc2);
2835 vswap();
2836 gv(rc1);
2837 vswap();
2838 /* test if reload is needed for first register */
2839 if ((vtop[0].r & VT_VALMASK) >= VT_CONST) {
2840 gv(rc2);
2845 /* expand long long on stack in two int registers */
2846 void lexpand(void)
2848 int u;
2850 u = vtop->t & VT_UNSIGNED;
2851 gv(RC_INT);
2852 vdup();
2853 vtop[0].r = vtop[-1].r2;
2854 vtop[0].r2 = VT_CONST;
2855 vtop[-1].r2 = VT_CONST;
2856 vtop[0].t = VT_INT | u;
2857 vtop[-1].t = VT_INT | u;
2860 /* build a long long from two ints */
2861 void lbuild(int t)
2863 gv2(RC_INT, RC_INT);
2864 vtop[-1].r2 = vtop[0].r;
2865 vtop[-1].t = t;
2866 vpop();
2869 /* rotate n first stack elements to the bottom */
2870 void vrotb(int n)
2872 int i;
2873 SValue tmp;
2875 tmp = vtop[-n + 1];
2876 for(i=-n+1;i!=0;i++)
2877 vtop[i] = vtop[i+1];
2878 vtop[0] = tmp;
2881 /* pop stack value */
2882 void vpop(void)
2884 int v;
2885 v = vtop->r & VT_VALMASK;
2886 #ifdef TCC_TARGET_I386
2887 /* for x86, we need to pop the FP stack */
2888 if (v == REG_ST0) {
2889 o(0xd9dd); /* fstp %st(1) */
2890 } else
2891 #endif
2892 if (v == VT_JMP || v == VT_JMPI) {
2893 /* need to put correct jump if && or || without test */
2894 gsym(vtop->c.ul);
2896 vtop--;
2899 /* convert stack entry to register and duplicate its value in another
2900 register */
2901 void gv_dup(void)
2903 int rc, t, r, r1;
2904 SValue sv;
2906 t = vtop->t;
2907 if ((t & VT_BTYPE) == VT_LLONG) {
2908 lexpand();
2909 gv_dup();
2910 vswap();
2911 vrotb(3);
2912 gv_dup();
2913 vrotb(4);
2914 /* stack: H L L1 H1 */
2915 lbuild(t);
2916 vrotb(3);
2917 vrotb(3);
2918 vswap();
2919 lbuild(t);
2920 vswap();
2921 } else {
2922 /* duplicate value */
2923 rc = RC_INT;
2924 sv.t = VT_INT;
2925 if (is_float(t)) {
2926 rc = RC_FLOAT;
2927 sv.t = t;
2929 r = gv(rc);
2930 r1 = get_reg(rc);
2931 sv.r = r;
2932 sv.c.ul = 0;
2933 load(r1, &sv); /* move r to r1 */
2934 vdup();
2935 /* duplicates value */
2936 vtop->r = r1;
2940 /* generate CPU independent (unsigned) long long operations */
2941 void gen_opl(int op)
2943 int t, a, b, op1, c, i;
2944 void *func;
2945 GFuncContext gf;
2946 SValue tmp;
2948 switch(op) {
2949 case '/':
2950 case TOK_PDIV:
2951 func = __divll;
2952 goto gen_func;
2953 case TOK_UDIV:
2954 func = __divull;
2955 goto gen_func;
2956 case '%':
2957 func = __modll;
2958 goto gen_func;
2959 case TOK_UMOD:
2960 func = __modull;
2961 gen_func:
2962 /* call generic long long function */
2963 gfunc_start(&gf, FUNC_CDECL);
2964 gfunc_param(&gf);
2965 gfunc_param(&gf);
2966 vpushi((int)func);
2967 gfunc_call(&gf);
2968 vpushi(0);
2969 vtop->r = REG_IRET;
2970 vtop->r2 = REG_LRET;
2971 break;
2972 case '^':
2973 case '&':
2974 case '|':
2975 case '*':
2976 case '+':
2977 case '-':
2978 t = vtop->t;
2979 vswap();
2980 lexpand();
2981 vrotb(3);
2982 lexpand();
2983 /* stack: L1 H1 L2 H2 */
2984 tmp = vtop[0];
2985 vtop[0] = vtop[-3];
2986 vtop[-3] = tmp;
2987 tmp = vtop[-2];
2988 vtop[-2] = vtop[-3];
2989 vtop[-3] = tmp;
2990 vswap();
2991 /* stack: H1 H2 L1 L2 */
2992 if (op == '*') {
2993 vpushv(vtop - 1);
2994 vpushv(vtop - 1);
2995 gen_op(TOK_UMULL);
2996 lexpand();
2997 /* stack: H1 H2 L1 L2 ML MH */
2998 for(i=0;i<4;i++)
2999 vrotb(6);
3000 /* stack: ML MH H1 H2 L1 L2 */
3001 tmp = vtop[0];
3002 vtop[0] = vtop[-2];
3003 vtop[-2] = tmp;
3004 /* stack: ML MH H1 L2 H2 L1 */
3005 gen_op('*');
3006 vrotb(3);
3007 vrotb(3);
3008 gen_op('*');
3009 /* stack: ML MH M1 M2 */
3010 gen_op('+');
3011 gen_op('+');
3012 } else if (op == '+' || op == '-') {
3013 /* XXX: add non carry method too (for MIPS or alpha) */
3014 if (op == '+')
3015 op1 = TOK_ADDC1;
3016 else
3017 op1 = TOK_SUBC1;
3018 gen_op(op1);
3019 /* stack: H1 H2 (L1 op L2) */
3020 vrotb(3);
3021 vrotb(3);
3022 gen_op(op1 + 1); /* TOK_xxxC2 */
3023 } else {
3024 gen_op(op);
3025 /* stack: H1 H2 (L1 op L2) */
3026 vrotb(3);
3027 vrotb(3);
3028 /* stack: (L1 op L2) H1 H2 */
3029 gen_op(op);
3030 /* stack: (L1 op L2) (H1 op H2) */
3032 /* stack: L H */
3033 lbuild(t);
3034 break;
3035 case TOK_SAR:
3036 case TOK_SHR:
3037 case TOK_SHL:
3038 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
3039 t = vtop[-1].t;
3040 vswap();
3041 lexpand();
3042 vrotb(3);
3043 /* stack: L H shift */
3044 c = (int)vtop->c.i;
3045 /* constant: simpler */
3046 /* NOTE: all comments are for SHL. the other cases are
3047 done by swaping words */
3048 vpop();
3049 if (op != TOK_SHL)
3050 vswap();
3051 if (c >= 32) {
3052 /* stack: L H */
3053 vpop();
3054 if (c > 32) {
3055 vpushi(c - 32);
3056 gen_op(op);
3058 if (op != TOK_SAR) {
3059 vpushi(0);
3060 } else {
3061 gv_dup();
3062 vpushi(31);
3063 gen_op(TOK_SAR);
3065 vswap();
3066 } else {
3067 vswap();
3068 gv_dup();
3069 /* stack: H L L */
3070 vpushi(c);
3071 gen_op(op);
3072 vswap();
3073 vpushi(32 - c);
3074 if (op == TOK_SHL)
3075 gen_op(TOK_SHR);
3076 else
3077 gen_op(TOK_SHL);
3078 vrotb(3);
3079 /* stack: L L H */
3080 vpushi(c);
3081 gen_op(op);
3082 gen_op('|');
3084 if (op != TOK_SHL)
3085 vswap();
3086 lbuild(t);
3087 } else {
3088 /* XXX: should provide a faster fallback on x86 ? */
3089 switch(op) {
3090 case TOK_SAR:
3091 func = __sardi3;
3092 goto gen_func;
3093 case TOK_SHR:
3094 func = __shrdi3;
3095 goto gen_func;
3096 case TOK_SHL:
3097 func = __shldi3;
3098 goto gen_func;
3101 break;
3102 default:
3103 /* compare operations */
3104 t = vtop->t;
3105 vswap();
3106 lexpand();
3107 vrotb(3);
3108 lexpand();
3109 /* stack: L1 H1 L2 H2 */
3110 tmp = vtop[-1];
3111 vtop[-1] = vtop[-2];
3112 vtop[-2] = tmp;
3113 /* stack: L1 L2 H1 H2 */
3114 /* compare high */
3115 op1 = op;
3116 /* when values are equal, we need to compare low words. since
3117 the jump is inverted, we invert the test too. */
3118 if (op1 == TOK_LT)
3119 op1 = TOK_LE;
3120 else if (op1 == TOK_GT)
3121 op1 = TOK_GE;
3122 else if (op1 == TOK_ULT)
3123 op1 = TOK_ULE;
3124 else if (op1 == TOK_UGT)
3125 op1 = TOK_UGE;
3126 a = 0;
3127 b = 0;
3128 gen_op(op1);
3129 if (op1 != TOK_NE) {
3130 a = gtst(1, 0);
3132 if (op != TOK_EQ) {
3133 /* generate non equal test */
3134 /* XXX: NOT PORTABLE yet */
3135 if (a == 0) {
3136 b = gtst(0, 0);
3137 } else {
3138 #ifdef TCC_TARGET_I386
3139 b = psym(0x850f, 0);
3140 #else
3141 error("not implemented");
3142 #endif
3145 /* compare low */
3146 gen_op(op);
3147 a = gtst(1, a);
3148 gsym(b);
3149 vset(VT_INT, VT_JMPI, a);
3150 break;
3154 /* handle integer constant optimizations and various machine
3155 independant opt */
3156 void gen_opic(int op)
3158 int fc, c1, c2, n;
3159 SValue *v1, *v2;
3161 v1 = vtop - 1;
3162 v2 = vtop;
3163 /* currently, we cannot do computations with forward symbols */
3164 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
3165 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
3166 if (c1 && c2) {
3167 fc = v2->c.i;
3168 switch(op) {
3169 case '+': v1->c.i += fc; break;
3170 case '-': v1->c.i -= fc; break;
3171 case '&': v1->c.i &= fc; break;
3172 case '^': v1->c.i ^= fc; break;
3173 case '|': v1->c.i |= fc; break;
3174 case '*': v1->c.i *= fc; break;
3176 case TOK_PDIV:
3177 case '/':
3178 case '%':
3179 case TOK_UDIV:
3180 case TOK_UMOD:
3181 /* if division by zero, generate explicit division */
3182 if (fc == 0) {
3183 if (const_wanted)
3184 error("division by zero in constant");
3185 goto general_case;
3187 switch(op) {
3188 default: v1->c.i /= fc; break;
3189 case '%': v1->c.i %= fc; break;
3190 case TOK_UDIV: v1->c.i = (unsigned)v1->c.i / fc; break;
3191 case TOK_UMOD: v1->c.i = (unsigned)v1->c.i % fc; break;
3193 break;
3194 case TOK_SHL: v1->c.i <<= fc; break;
3195 case TOK_SHR: v1->c.i = (unsigned)v1->c.i >> fc; break;
3196 case TOK_SAR: v1->c.i >>= fc; break;
3197 /* tests */
3198 case TOK_ULT: v1->c.i = (unsigned)v1->c.i < (unsigned)fc; break;
3199 case TOK_UGE: v1->c.i = (unsigned)v1->c.i >= (unsigned)fc; break;
3200 case TOK_EQ: v1->c.i = v1->c.i == fc; break;
3201 case TOK_NE: v1->c.i = v1->c.i != fc; break;
3202 case TOK_ULE: v1->c.i = (unsigned)v1->c.i <= (unsigned)fc; break;
3203 case TOK_UGT: v1->c.i = (unsigned)v1->c.i > (unsigned)fc; break;
3204 case TOK_LT: v1->c.i = v1->c.i < fc; break;
3205 case TOK_GE: v1->c.i = v1->c.i >= fc; break;
3206 case TOK_LE: v1->c.i = v1->c.i <= fc; break;
3207 case TOK_GT: v1->c.i = v1->c.i > fc; break;
3208 /* logical */
3209 case TOK_LAND: v1->c.i = v1->c.i && fc; break;
3210 case TOK_LOR: v1->c.i = v1->c.i || fc; break;
3211 default:
3212 goto general_case;
3214 vtop--;
3215 } else {
3216 /* if commutative ops, put c2 as constant */
3217 if (c1 && (op == '+' || op == '&' || op == '^' ||
3218 op == '|' || op == '*')) {
3219 vswap();
3220 swap(&c1, &c2);
3222 fc = vtop->c.i;
3223 if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
3224 op == TOK_PDIV) &&
3225 fc == 1) ||
3226 ((op == '+' || op == '-' || op == '|' || op == '^' ||
3227 op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
3228 fc == 0) ||
3229 (op == '&' &&
3230 fc == -1))) {
3231 /* nothing to do */
3232 vtop--;
3233 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
3234 /* try to use shifts instead of muls or divs */
3235 if (fc > 0 && (fc & (fc - 1)) == 0) {
3236 n = -1;
3237 while (fc) {
3238 fc >>= 1;
3239 n++;
3241 vtop->c.i = n;
3242 if (op == '*')
3243 op = TOK_SHL;
3244 else if (op == TOK_PDIV)
3245 op = TOK_SAR;
3246 else
3247 op = TOK_SHR;
3249 goto general_case;
3250 } else {
3251 general_case:
3252 /* call low level op generator */
3253 gen_opi(op);
3258 /* generate a floating point operation with constant propagation */
3259 void gen_opif(int op)
3261 int c1, c2;
3262 SValue *v1, *v2;
3263 long double f1, f2;
3265 v1 = vtop - 1;
3266 v2 = vtop;
3267 /* currently, we cannot do computations with forward symbols */
3268 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
3269 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
3270 if (c1 && c2) {
3271 if (v1->t == VT_FLOAT) {
3272 f1 = v1->c.f;
3273 f2 = v2->c.f;
3274 } else if (v1->t == VT_DOUBLE) {
3275 f1 = v1->c.d;
3276 f2 = v2->c.d;
3277 } else {
3278 f1 = v1->c.ld;
3279 f2 = v2->c.ld;
3282 /* NOTE: we only do constant propagation if finite number (not
3283 NaN or infinity) (ANSI spec) */
3284 if (!ieee_finite(f1) || !ieee_finite(f2))
3285 goto general_case;
3287 switch(op) {
3288 case '+': f1 += f2; break;
3289 case '-': f1 -= f2; break;
3290 case '*': f1 *= f2; break;
3291 case '/':
3292 if (f2 == 0.0) {
3293 if (const_wanted)
3294 error("division by zero in constant");
3295 goto general_case;
3297 f1 /= f2;
3298 break;
3299 /* XXX: also handles tests ? */
3300 default:
3301 goto general_case;
3303 /* XXX: overflow test ? */
3304 if (v1->t == VT_FLOAT) {
3305 v1->c.f = f1;
3306 } else if (v1->t == VT_DOUBLE) {
3307 v1->c.d = f1;
3308 } else {
3309 v1->c.ld = f1;
3311 vtop--;
3312 } else {
3313 general_case:
3314 gen_opf(op);
3319 int pointed_size(int t)
3321 return type_size(pointed_type(t), &t);
3324 #if 0
3325 void check_pointer_types(SValue *p1, SValue *p2)
3327 char buf1[256], buf2[256];
3328 int t1, t2;
3329 t1 = p1->t;
3330 t2 = p2->t;
3331 if (!is_compatible_types(t1, t2)) {
3332 type_to_str(buf1, sizeof(buf1), t1, NULL);
3333 type_to_str(buf2, sizeof(buf2), t2, NULL);
3334 error("incompatible pointers '%s' and '%s'", buf1, buf2);
3337 #endif
3339 /* generic gen_op: handles types problems */
3340 void gen_op(int op)
3342 int u, t1, t2, bt1, bt2, t;
3344 t1 = vtop[-1].t;
3345 t2 = vtop[0].t;
3346 bt1 = t1 & VT_BTYPE;
3347 bt2 = t2 & VT_BTYPE;
3349 if (bt1 == VT_PTR || bt2 == VT_PTR) {
3350 /* at least one operand is a pointer */
3351 /* relationnal op: must be both pointers */
3352 if (op >= TOK_ULT && op <= TOK_GT) {
3353 // check_pointer_types(vtop, vtop - 1);
3354 /* pointers are handled are unsigned */
3355 t = VT_INT | VT_UNSIGNED;
3356 goto std_op;
3358 /* if both pointers, then it must be the '-' op */
3359 if ((t1 & VT_BTYPE) == VT_PTR &&
3360 (t2 & VT_BTYPE) == VT_PTR) {
3361 if (op != '-')
3362 error("cannot use pointers here");
3363 // check_pointer_types(vtop - 1, vtop);
3364 /* XXX: check that types are compatible */
3365 u = pointed_size(t1);
3366 gen_opic(op);
3367 /* set to integer type */
3368 vtop->t = VT_INT;
3369 vpushi(u);
3370 gen_op(TOK_PDIV);
3371 } else {
3372 /* exactly one pointer : must be '+' or '-'. */
3373 if (op != '-' && op != '+')
3374 error("cannot use pointers here");
3375 /* Put pointer as first operand */
3376 if ((t2 & VT_BTYPE) == VT_PTR) {
3377 vswap();
3378 swap(&t1, &t2);
3380 /* XXX: cast to int ? (long long case) */
3381 vpushi(pointed_size(vtop[-1].t));
3382 gen_op('*');
3383 #ifdef CONFIG_TCC_BCHECK
3384 /* if evaluating constant expression, no code should be
3385 generated, so no bound check */
3386 if (do_bounds_check && !const_wanted) {
3387 /* if bounded pointers, we generate a special code to
3388 test bounds */
3389 if (op == '-') {
3390 vpushi(0);
3391 vswap();
3392 gen_op('-');
3394 gen_bounded_ptr_add();
3395 } else
3396 #endif
3398 gen_opic(op);
3400 /* put again type if gen_opic() swaped operands */
3401 vtop->t = t1;
3403 } else if (is_float(bt1) || is_float(bt2)) {
3404 /* compute bigger type and do implicit casts */
3405 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
3406 t = VT_LDOUBLE;
3407 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
3408 t = VT_DOUBLE;
3409 } else {
3410 t = VT_FLOAT;
3412 /* floats can only be used for a few operations */
3413 if (op != '+' && op != '-' && op != '*' && op != '/' &&
3414 (op < TOK_ULT || op > TOK_GT))
3415 error("invalid operands for binary operation");
3416 goto std_op;
3417 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
3418 /* cast to biggest op */
3419 t = VT_LLONG;
3420 /* convert to unsigned if it does not fit in a long long */
3421 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
3422 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
3423 t |= VT_UNSIGNED;
3424 goto std_op;
3425 } else {
3426 /* integer operations */
3427 t = VT_INT;
3428 /* convert to unsigned if it does not fit in an integer */
3429 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
3430 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
3431 t |= VT_UNSIGNED;
3432 std_op:
3433 /* XXX: currently, some unsigned operations are explicit, so
3434 we modify them here */
3435 if (t & VT_UNSIGNED) {
3436 if (op == TOK_SAR)
3437 op = TOK_SHR;
3438 else if (op == '/')
3439 op = TOK_UDIV;
3440 else if (op == '%')
3441 op = TOK_UMOD;
3442 else if (op == TOK_LT)
3443 op = TOK_ULT;
3444 else if (op == TOK_GT)
3445 op = TOK_UGT;
3446 else if (op == TOK_LE)
3447 op = TOK_ULE;
3448 else if (op == TOK_GE)
3449 op = TOK_UGE;
3451 vswap();
3452 gen_cast(t);
3453 vswap();
3454 /* special case for shifts and long long: we keep the shift as
3455 an integer */
3456 if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL)
3457 gen_cast(VT_INT);
3458 else
3459 gen_cast(t);
3460 if (is_float(t))
3461 gen_opif(op);
3462 else if ((t & VT_BTYPE) == VT_LLONG)
3463 gen_opl(op);
3464 else
3465 gen_opic(op);
3466 if (op >= TOK_ULT && op <= TOK_GT) {
3467 /* relationnal op: the result is an int */
3468 vtop->t = VT_INT;
3469 } else {
3470 vtop->t = t;
3475 /* generic itof for unsigned long long case */
3476 void gen_cvt_itof1(int t)
3478 GFuncContext gf;
3480 if ((vtop->t & (VT_BTYPE | VT_UNSIGNED)) ==
3481 (VT_LLONG | VT_UNSIGNED)) {
3483 gfunc_start(&gf, FUNC_CDECL);
3484 gfunc_param(&gf);
3485 if (t == VT_FLOAT)
3486 vpushi((int)&__ulltof);
3487 else if (t == VT_DOUBLE)
3488 vpushi((int)&__ulltod);
3489 else
3490 vpushi((int)&__ulltold);
3491 gfunc_call(&gf);
3492 vpushi(0);
3493 vtop->r = REG_FRET;
3494 } else {
3495 gen_cvt_itof(t);
3499 /* generic ftoi for unsigned long long case */
3500 void gen_cvt_ftoi1(int t)
3502 GFuncContext gf;
3503 int st;
3505 if (t == (VT_LLONG | VT_UNSIGNED)) {
3506 /* not handled natively */
3507 gfunc_start(&gf, FUNC_CDECL);
3508 st = vtop->t & VT_BTYPE;
3509 gfunc_param(&gf);
3510 if (st == VT_FLOAT)
3511 vpushi((int)&__ftoull);
3512 else if (st == VT_DOUBLE)
3513 vpushi((int)&__dtoull);
3514 else
3515 vpushi((int)&__ldtoull);
3516 gfunc_call(&gf);
3517 vpushi(0);
3518 vtop->r = REG_IRET;
3519 vtop->r2 = REG_LRET;
3520 } else {
3521 gen_cvt_ftoi(t);
3525 /* force char or short cast */
3526 void force_charshort_cast(int t)
3528 int bits, dbt;
3529 dbt = t & VT_BTYPE;
3530 /* XXX: add optimization if lvalue : just change type and offset */
3531 if (dbt == VT_BYTE)
3532 bits = 8;
3533 else
3534 bits = 16;
3535 if (t & VT_UNSIGNED) {
3536 vpushi((1 << bits) - 1);
3537 gen_op('&');
3538 } else {
3539 bits = 32 - bits;
3540 vpushi(bits);
3541 gen_op(TOK_SHL);
3542 vpushi(bits);
3543 gen_op(TOK_SAR);
3547 /* cast 'vtop' to 't' type */
3548 void gen_cast(int t)
3550 int sbt, dbt, sf, df, c;
3552 /* special delayed cast for char/short */
3553 /* XXX: in some cases (multiple cascaded casts), it may still
3554 be incorrect */
3555 if (vtop->r & VT_MUSTCAST) {
3556 vtop->r &= ~VT_MUSTCAST;
3557 force_charshort_cast(vtop->t);
3560 dbt = t & (VT_BTYPE | VT_UNSIGNED);
3561 sbt = vtop->t & (VT_BTYPE | VT_UNSIGNED);
3563 if (sbt != dbt) {
3564 sf = is_float(sbt);
3565 df = is_float(dbt);
3566 c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
3567 if (sf && df) {
3568 /* convert from fp to fp */
3569 if (c) {
3570 /* constant case: we can do it now */
3571 /* XXX: in ISOC, cannot do it if error in convert */
3572 if (dbt == VT_FLOAT && sbt == VT_DOUBLE)
3573 vtop->c.f = (float)vtop->c.d;
3574 else if (dbt == VT_FLOAT && sbt == VT_LDOUBLE)
3575 vtop->c.f = (float)vtop->c.ld;
3576 else if (dbt == VT_DOUBLE && sbt == VT_FLOAT)
3577 vtop->c.d = (double)vtop->c.f;
3578 else if (dbt == VT_DOUBLE && sbt == VT_LDOUBLE)
3579 vtop->c.d = (double)vtop->c.ld;
3580 else if (dbt == VT_LDOUBLE && sbt == VT_FLOAT)
3581 vtop->c.ld = (long double)vtop->c.f;
3582 else if (dbt == VT_LDOUBLE && sbt == VT_DOUBLE)
3583 vtop->c.ld = (long double)vtop->c.d;
3584 } else {
3585 /* non constant case: generate code */
3586 gen_cvt_ftof(dbt);
3588 } else if (df) {
3589 /* convert int to fp */
3590 if (c) {
3591 switch(sbt) {
3592 case VT_LLONG | VT_UNSIGNED:
3593 case VT_LLONG:
3594 /* XXX: add const cases for long long */
3595 goto do_itof;
3596 case VT_INT | VT_UNSIGNED:
3597 switch(dbt) {
3598 case VT_FLOAT: vtop->c.f = (float)vtop->c.ui; break;
3599 case VT_DOUBLE: vtop->c.d = (double)vtop->c.ui; break;
3600 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.ui; break;
3602 break;
3603 default:
3604 switch(dbt) {
3605 case VT_FLOAT: vtop->c.f = (float)vtop->c.i; break;
3606 case VT_DOUBLE: vtop->c.d = (double)vtop->c.i; break;
3607 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.i; break;
3609 break;
3611 } else {
3612 do_itof:
3613 gen_cvt_itof1(dbt);
3615 } else if (sf) {
3616 /* convert fp to int */
3617 /* we handle char/short/etc... with generic code */
3618 if (dbt != (VT_INT | VT_UNSIGNED) &&
3619 dbt != (VT_LLONG | VT_UNSIGNED) &&
3620 dbt != VT_LLONG)
3621 dbt = VT_INT;
3622 if (c) {
3623 switch(dbt) {
3624 case VT_LLONG | VT_UNSIGNED:
3625 case VT_LLONG:
3626 /* XXX: add const cases for long long */
3627 goto do_ftoi;
3628 case VT_INT | VT_UNSIGNED:
3629 switch(sbt) {
3630 case VT_FLOAT: vtop->c.ui = (unsigned int)vtop->c.d; break;
3631 case VT_DOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
3632 case VT_LDOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
3634 break;
3635 default:
3636 /* int case */
3637 switch(sbt) {
3638 case VT_FLOAT: vtop->c.i = (int)vtop->c.d; break;
3639 case VT_DOUBLE: vtop->c.i = (int)vtop->c.d; break;
3640 case VT_LDOUBLE: vtop->c.i = (int)vtop->c.d; break;
3642 break;
3644 } else {
3645 do_ftoi:
3646 gen_cvt_ftoi1(dbt);
3648 if (dbt == VT_INT && (t & (VT_BTYPE | VT_UNSIGNED)) != dbt) {
3649 /* additionnal cast for char/short/bool... */
3650 vtop->t = dbt;
3651 gen_cast(t);
3653 } else if ((dbt & VT_BTYPE) == VT_LLONG) {
3654 if ((sbt & VT_BTYPE) != VT_LLONG) {
3655 /* scalar to long long */
3656 if (c) {
3657 if (sbt == (VT_INT | VT_UNSIGNED))
3658 vtop->c.ll = vtop->c.ui;
3659 else
3660 vtop->c.ll = vtop->c.i;
3661 } else {
3662 /* machine independant conversion */
3663 gv(RC_INT);
3664 /* generate high word */
3665 if (sbt == (VT_INT | VT_UNSIGNED)) {
3666 vpushi(0);
3667 gv(RC_INT);
3668 } else {
3669 gv_dup();
3670 vpushi(31);
3671 gen_op(TOK_SAR);
3673 /* patch second register */
3674 vtop[-1].r2 = vtop->r;
3675 vpop();
3678 } else if (dbt == VT_BOOL) {
3679 /* scalar to bool */
3680 vpushi(0);
3681 gen_op(TOK_NE);
3682 } else if ((dbt & VT_BTYPE) == VT_BYTE ||
3683 (dbt & VT_BTYPE) == VT_SHORT) {
3684 force_charshort_cast(t);
3685 } else if ((dbt & VT_BTYPE) == VT_INT) {
3686 /* scalar to int */
3687 if (sbt == VT_LLONG) {
3688 /* from long long: just take low order word */
3689 lexpand();
3690 vpop();
3692 /* if lvalue and single word type, nothing to do because
3693 the lvalue already contains the real type size (see
3694 VT_LVAL_xxx constants) */
3697 vtop->t = t;
3700 /* return type size. Put alignment at 'a' */
3701 int type_size(int t, int *a)
3703 Sym *s;
3704 int bt;
3706 bt = t & VT_BTYPE;
3707 if (bt == VT_STRUCT) {
3708 /* struct/union */
3709 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
3710 *a = 4; /* XXX: cannot store it yet. Doing that is safe */
3711 return s->c;
3712 } else if (bt == VT_PTR) {
3713 if (t & VT_ARRAY) {
3714 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
3715 return type_size(s->t, a) * s->c;
3716 } else {
3717 *a = PTR_SIZE;
3718 return PTR_SIZE;
3720 } else if (bt == VT_LDOUBLE) {
3721 *a = LDOUBLE_ALIGN;
3722 return LDOUBLE_SIZE;
3723 } else if (bt == VT_DOUBLE || bt == VT_LLONG) {
3724 *a = 8;
3725 return 8;
3726 } else if (bt == VT_INT || bt == VT_ENUM || bt == VT_FLOAT) {
3727 *a = 4;
3728 return 4;
3729 } else if (bt == VT_SHORT) {
3730 *a = 2;
3731 return 2;
3732 } else {
3733 /* char, void, function, _Bool */
3734 *a = 1;
3735 return 1;
3739 /* return the pointed type of t */
3740 int pointed_type(int t)
3742 Sym *s;
3743 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
3744 return s->t | (t & ~VT_TYPE);
3747 int mk_pointer(int t)
3749 int p;
3750 p = anon_sym++;
3751 sym_push(p, t, 0, -1);
3752 return VT_PTR | (p << VT_STRUCT_SHIFT) | (t & ~VT_TYPE);
3755 int is_compatible_types(int t1, int t2)
3757 Sym *s1, *s2;
3758 int bt1, bt2;
3760 t1 &= VT_TYPE;
3761 t2 &= VT_TYPE;
3762 bt1 = t1 & VT_BTYPE;
3763 bt2 = t2 & VT_BTYPE;
3764 if (bt1 == VT_PTR) {
3765 t1 = pointed_type(t1);
3766 /* if function, then convert implicitely to function pointer */
3767 if (bt2 != VT_FUNC) {
3768 if (bt2 != VT_PTR)
3769 return 0;
3770 t2 = pointed_type(t2);
3772 /* void matches everything */
3773 t1 &= VT_TYPE;
3774 t2 &= VT_TYPE;
3775 if (t1 == VT_VOID || t2 == VT_VOID)
3776 return 1;
3777 return is_compatible_types(t1, t2);
3778 } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
3779 return (t2 == t1);
3780 } else if (bt1 == VT_FUNC) {
3781 if (bt2 != VT_FUNC)
3782 return 0;
3783 s1 = sym_find(((unsigned)t1 >> VT_STRUCT_SHIFT));
3784 s2 = sym_find(((unsigned)t2 >> VT_STRUCT_SHIFT));
3785 if (!is_compatible_types(s1->t, s2->t))
3786 return 0;
3787 /* XXX: not complete */
3788 if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
3789 return 1;
3790 if (s1->c != s2->c)
3791 return 0;
3792 while (s1 != NULL) {
3793 if (s2 == NULL)
3794 return 0;
3795 if (!is_compatible_types(s1->t, s2->t))
3796 return 0;
3797 s1 = s1->next;
3798 s2 = s2->next;
3800 if (s2)
3801 return 0;
3802 return 1;
3803 } else {
3804 /* XXX: not complete */
3805 return 1;
3809 /* print a type. If 'varstr' is not NULL, then the variable is also
3810 printed in the type */
3811 /* XXX: union */
3812 /* XXX: add array and function pointers */
3813 void type_to_str(char *buf, int buf_size,
3814 int t, const char *varstr)
3816 int bt, v;
3817 Sym *s, *sa;
3818 char buf1[256];
3819 const char *tstr;
3821 t = t & VT_TYPE;
3822 bt = t & VT_BTYPE;
3823 buf[0] = '\0';
3824 if (t & VT_UNSIGNED)
3825 pstrcat(buf, buf_size, "unsigned ");
3826 switch(bt) {
3827 case VT_VOID:
3828 tstr = "void";
3829 goto add_tstr;
3830 case VT_BOOL:
3831 tstr = "_Bool";
3832 goto add_tstr;
3833 case VT_BYTE:
3834 tstr = "char";
3835 goto add_tstr;
3836 case VT_SHORT:
3837 tstr = "short";
3838 goto add_tstr;
3839 case VT_INT:
3840 tstr = "int";
3841 goto add_tstr;
3842 case VT_LONG:
3843 tstr = "long";
3844 goto add_tstr;
3845 case VT_LLONG:
3846 tstr = "long long";
3847 goto add_tstr;
3848 case VT_FLOAT:
3849 tstr = "float";
3850 goto add_tstr;
3851 case VT_DOUBLE:
3852 tstr = "double";
3853 goto add_tstr;
3854 case VT_LDOUBLE:
3855 tstr = "long double";
3856 add_tstr:
3857 pstrcat(buf, buf_size, tstr);
3858 break;
3859 case VT_ENUM:
3860 case VT_STRUCT:
3861 if (bt == VT_STRUCT)
3862 tstr = "struct ";
3863 else
3864 tstr = "enum ";
3865 pstrcat(buf, buf_size, tstr);
3866 v = (unsigned)t >> VT_STRUCT_SHIFT;
3867 if (v >= SYM_FIRST_ANOM)
3868 pstrcat(buf, buf_size, "<anonymous>");
3869 else
3870 pstrcat(buf, buf_size, get_tok_str(v, NULL));
3871 break;
3872 case VT_FUNC:
3873 s = sym_find((unsigned)t >> VT_STRUCT_SHIFT);
3874 type_to_str(buf, buf_size, s->t, varstr);
3875 pstrcat(buf, buf_size, "(");
3876 sa = s->next;
3877 while (sa != NULL) {
3878 type_to_str(buf1, sizeof(buf1), sa->t, NULL);
3879 pstrcat(buf, buf_size, buf1);
3880 sa = sa->next;
3881 if (sa)
3882 pstrcat(buf, buf_size, ", ");
3884 pstrcat(buf, buf_size, ")");
3885 goto no_var;
3886 case VT_PTR:
3887 s = sym_find((unsigned)t >> VT_STRUCT_SHIFT);
3888 pstrcpy(buf1, sizeof(buf1), "*");
3889 if (varstr)
3890 pstrcat(buf1, sizeof(buf1), varstr);
3891 type_to_str(buf, buf_size, s->t, buf1);
3892 goto no_var;
3894 if (varstr) {
3895 pstrcat(buf, buf_size, " ");
3896 pstrcat(buf, buf_size, varstr);
3898 no_var: ;
3901 /* verify type compatibility to store vtop in 'dt' type, and generate
3902 casts if needed. */
3903 void gen_assign_cast(int dt)
3905 int st;
3906 char buf1[256], buf2[256];
3908 st = vtop->t; /* source type */
3909 if ((dt & VT_BTYPE) == VT_PTR) {
3910 /* special cases for pointers */
3911 /* a function is implicitely a function pointer */
3912 if ((st & VT_BTYPE) == VT_FUNC) {
3913 if (!is_compatible_types(pointed_type(dt), st))
3914 goto error;
3915 else
3916 goto type_ok;
3918 /* '0' can also be a pointer */
3919 if ((st & VT_BTYPE) == VT_INT &&
3920 ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) &&
3921 vtop->c.i == 0)
3922 goto type_ok;
3924 if (!is_compatible_types(dt, st)) {
3925 error:
3926 type_to_str(buf1, sizeof(buf1), st, NULL);
3927 type_to_str(buf2, sizeof(buf2), dt, NULL);
3928 error("cannot cast '%s' to '%s'", buf1, buf2);
3930 type_ok:
3931 gen_cast(dt);
3934 /* store vtop in lvalue pushed on stack */
3935 void vstore(void)
3937 int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
3938 GFuncContext gf;
3940 ft = vtop[-1].t;
3941 sbt = vtop->t & VT_BTYPE;
3942 dbt = ft & VT_BTYPE;
3943 if (((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
3944 (sbt == VT_INT && dbt == VT_SHORT)) {
3945 /* optimize char/short casts */
3946 delayed_cast = VT_MUSTCAST;
3947 vtop->t = ft & VT_TYPE;
3948 } else {
3949 delayed_cast = 0;
3950 gen_assign_cast(ft & VT_TYPE);
3953 if (sbt == VT_STRUCT) {
3954 /* if structure, only generate pointer */
3955 /* structure assignment : generate memcpy */
3956 /* XXX: optimize if small size */
3957 vdup();
3958 gfunc_start(&gf, FUNC_CDECL);
3959 /* type size */
3960 size = type_size(vtop->t, &align);
3961 vpushi(size);
3962 gfunc_param(&gf);
3963 /* source */
3964 vtop->t = VT_INT;
3965 gaddrof();
3966 gfunc_param(&gf);
3967 /* destination */
3968 vswap();
3969 vtop->t = VT_INT;
3970 gaddrof();
3971 gfunc_param(&gf);
3973 save_regs(0);
3974 vpushi((int)&memcpy);
3975 gfunc_call(&gf);
3976 /* leave source on stack */
3977 } else if (ft & VT_BITFIELD) {
3978 /* bitfield store handling */
3979 bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
3980 bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
3981 /* remove bit field info to avoid loops */
3982 vtop[-1].t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
3984 /* duplicate destination */
3985 vdup();
3986 vtop[-1] = vtop[-2];
3988 /* mask and shift source */
3989 vpushi((1 << bit_size) - 1);
3990 gen_op('&');
3991 vpushi(bit_pos);
3992 gen_op(TOK_SHL);
3993 /* load destination, mask and or with source */
3994 vswap();
3995 vpushi(~(((1 << bit_size) - 1) << bit_pos));
3996 gen_op('&');
3997 gen_op('|');
3998 /* store result */
3999 vstore();
4000 } else {
4001 #ifdef CONFIG_TCC_BCHECK
4002 /* bound check case */
4003 if (vtop[-1].r & VT_MUSTBOUND) {
4004 vswap();
4005 gbound();
4006 vswap();
4008 #endif
4009 rc = RC_INT;
4010 if (is_float(ft))
4011 rc = RC_FLOAT;
4012 r = gv(rc); /* generate value */
4013 /* if lvalue was saved on stack, must read it */
4014 if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
4015 SValue sv;
4016 t = get_reg(RC_INT);
4017 sv.t = VT_INT;
4018 sv.r = VT_LOCAL | VT_LVAL;
4019 sv.c.ul = vtop[-1].c.ul;
4020 load(t, &sv);
4021 vtop[-1].r = t | VT_LVAL;
4023 store(r, vtop - 1);
4024 /* two word case handling : store second register at word + 4 */
4025 if ((ft & VT_BTYPE) == VT_LLONG) {
4026 vswap();
4027 /* convert to int to increment easily */
4028 vtop->t = VT_INT;
4029 gaddrof();
4030 vpushi(4);
4031 gen_op('+');
4032 vtop->r |= VT_LVAL;
4033 vswap();
4034 /* XXX: it works because r2 is spilled last ! */
4035 store(vtop->r2, vtop - 1);
4037 vswap();
4038 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
4039 vtop->r |= delayed_cast;
4043 /* post defines POST/PRE add. c is the token ++ or -- */
4044 void inc(int post, int c)
4046 test_lvalue();
4047 vdup(); /* save lvalue */
4048 if (post) {
4049 gv_dup(); /* duplicate value */
4050 vrotb(3);
4051 vrotb(3);
4053 /* add constant */
4054 vpushi(c - TOK_MID);
4055 gen_op('+');
4056 vstore(); /* store value */
4057 if (post)
4058 vpop(); /* if post op, return saved value */
4061 /* Parse GNUC __attribute__ extension. Currently, the following
4062 extensions are recognized:
4063 - aligned(n) : set data/function alignment.
4064 - section(x) : generate data/code in this section.
4065 - unused : currently ignored, but may be used someday.
4067 void parse_attribute(AttributeDef *ad)
4069 int t, n;
4071 next();
4072 skip('(');
4073 skip('(');
4074 while (tok != ')') {
4075 if (tok < TOK_IDENT)
4076 expect("attribute name");
4077 t = tok;
4078 next();
4079 switch(t) {
4080 case TOK_SECTION:
4081 case TOK___SECTION__:
4082 skip('(');
4083 if (tok != TOK_STR)
4084 expect("section name");
4085 ad->section = find_section(tokc.ts->str);
4086 next();
4087 skip(')');
4088 break;
4089 case TOK_ALIGNED:
4090 case TOK___ALIGNED__:
4091 skip('(');
4092 n = expr_const();
4093 if (n <= 0 || (n & (n - 1)) != 0)
4094 error("alignment must be a positive power of two");
4095 ad->aligned = n;
4096 skip(')');
4097 break;
4098 case TOK_UNUSED:
4099 case TOK___UNUSED__:
4100 /* currently, no need to handle it because tcc does not
4101 track unused objects */
4102 break;
4103 case TOK_NORETURN:
4104 case TOK___NORETURN__:
4105 /* currently, no need to handle it because tcc does not
4106 track unused objects */
4107 break;
4108 case TOK_CDECL:
4109 case TOK___CDECL:
4110 case TOK___CDECL__:
4111 ad->func_call = FUNC_CDECL;
4112 break;
4113 case TOK_STDCALL:
4114 case TOK___STDCALL:
4115 case TOK___STDCALL__:
4116 ad->func_call = FUNC_STDCALL;
4117 break;
4118 default:
4119 warning("'%s' attribute ignored", get_tok_str(t, NULL));
4120 /* skip parameters */
4121 /* XXX: skip parenthesis too */
4122 if (tok == '(') {
4123 next();
4124 while (tok != ')' && tok != -1)
4125 next();
4126 next();
4128 break;
4130 if (tok != ',')
4131 break;
4132 next();
4134 skip(')');
4135 skip(')');
4138 /* enum/struct/union declaration */
4139 int struct_decl(int u)
4141 int a, t, b, v, size, align, maxalign, c, offset;
4142 int bit_size, bit_pos, bsize, bt, lbit_pos;
4143 Sym *s, *ss, **ps;
4144 AttributeDef ad;
4146 a = tok; /* save decl type */
4147 next();
4148 if (tok != '{') {
4149 v = tok;
4150 next();
4151 /* struct already defined ? return it */
4152 /* XXX: check consistency */
4153 s = sym_find(v | SYM_STRUCT);
4154 if (s) {
4155 if (s->t != a)
4156 error("invalid type");
4157 goto do_decl;
4159 } else {
4160 v = anon_sym++;
4162 s = sym_push(v | SYM_STRUCT, a, 0, 0);
4163 /* put struct/union/enum name in type */
4164 do_decl:
4165 u = u | (v << VT_STRUCT_SHIFT);
4167 if (tok == '{') {
4168 next();
4169 if (s->c)
4170 error("struct/union/enum already defined");
4171 /* cannot be empty */
4172 c = 0;
4173 maxalign = 0;
4174 ps = &s->next;
4175 bit_pos = 0;
4176 offset = 0;
4177 while (1) {
4178 if (a == TOK_ENUM) {
4179 v = tok;
4180 next();
4181 if (tok == '=') {
4182 next();
4183 c = expr_const();
4185 /* enum symbols have static storage */
4186 sym_push(v, VT_STATIC | VT_INT, VT_CONST, c);
4187 if (tok == ',')
4188 next();
4189 c++;
4190 } else {
4191 parse_btype(&b, &ad);
4192 while (1) {
4193 bit_size = -1;
4194 v = 0;
4195 if (tok != ':') {
4196 t = type_decl(&ad, &v, b, TYPE_DIRECT);
4197 if ((t & VT_BTYPE) == VT_FUNC ||
4198 (t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN)))
4199 error("invalid type for '%s'",
4200 get_tok_str(v, NULL));
4201 } else {
4202 t = b;
4204 if (tok == ':') {
4205 next();
4206 bit_size = expr_const();
4207 /* XXX: handle v = 0 case for messages */
4208 if (bit_size < 0)
4209 error("negative width in bit-field '%s'",
4210 get_tok_str(v, NULL));
4211 if (v && bit_size == 0)
4212 error("zero width for bit-field '%s'",
4213 get_tok_str(v, NULL));
4215 size = type_size(t, &align);
4216 lbit_pos = 0;
4217 if (bit_size >= 0) {
4218 bt = t & VT_BTYPE;
4219 if (bt != VT_INT &&
4220 bt != VT_BYTE &&
4221 bt != VT_SHORT)
4222 error("bitfields must have scalar type");
4223 bsize = size * 8;
4224 if (bit_size > bsize) {
4225 error("width of '%s' exceeds its type",
4226 get_tok_str(v, NULL));
4227 } else if (bit_size == bsize) {
4228 /* no need for bit fields */
4229 bit_pos = 0;
4230 } else if (bit_size == 0) {
4231 /* XXX: what to do if only padding in a
4232 structure ? */
4233 /* zero size: means to pad */
4234 if (bit_pos > 0)
4235 bit_pos = bsize;
4236 } else {
4237 /* we do not have enough room ? */
4238 if ((bit_pos + bit_size) > bsize)
4239 bit_pos = 0;
4240 lbit_pos = bit_pos;
4241 /* XXX: handle LSB first */
4242 t |= VT_BITFIELD |
4243 (bit_pos << VT_STRUCT_SHIFT) |
4244 (bit_size << (VT_STRUCT_SHIFT + 6));
4245 bit_pos += bit_size;
4247 } else {
4248 bit_pos = 0;
4250 if (v) {
4251 /* add new memory data only if starting
4252 bit field */
4253 if (lbit_pos == 0) {
4254 if (a == TOK_STRUCT) {
4255 c = (c + align - 1) & -align;
4256 offset = c;
4257 c += size;
4258 } else {
4259 offset = 0;
4260 if (size > c)
4261 c = size;
4263 if (align > maxalign)
4264 maxalign = align;
4266 #if 0
4267 printf("add field %s offset=%d",
4268 get_tok_str(v, NULL), offset);
4269 if (t & VT_BITFIELD) {
4270 printf(" pos=%d size=%d",
4271 (t >> VT_STRUCT_SHIFT) & 0x3f,
4272 (t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
4274 printf("\n");
4275 #endif
4276 ss = sym_push(v | SYM_FIELD, t, 0, offset);
4277 *ps = ss;
4278 ps = &ss->next;
4280 if (tok == ';' || tok == -1)
4281 break;
4282 skip(',');
4284 skip(';');
4286 if (tok == '}')
4287 break;
4289 skip('}');
4290 /* size for struct/union, dummy for enum */
4291 s->c = (c + maxalign - 1) & -maxalign;
4293 return u;
4296 /* return 0 if no type declaration. otherwise, return the basic type
4297 and skip it.
4299 int parse_btype(int *type_ptr, AttributeDef *ad)
4301 int t, u, type_found;
4302 Sym *s;
4304 memset(ad, 0, sizeof(AttributeDef));
4305 type_found = 0;
4306 t = 0;
4307 while(1) {
4308 switch(tok) {
4309 /* basic types */
4310 case TOK_CHAR:
4311 u = VT_BYTE;
4312 basic_type:
4313 next();
4314 basic_type1:
4315 if ((t & VT_BTYPE) != 0)
4316 error("too many basic types");
4317 t |= u;
4318 break;
4319 case TOK_VOID:
4320 u = VT_VOID;
4321 goto basic_type;
4322 case TOK_SHORT:
4323 u = VT_SHORT;
4324 goto basic_type;
4325 case TOK_INT:
4326 next();
4327 break;
4328 case TOK_LONG:
4329 next();
4330 if ((t & VT_BTYPE) == VT_DOUBLE) {
4331 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
4332 } else if ((t & VT_BTYPE) == VT_LONG) {
4333 t = (t & ~VT_BTYPE) | VT_LLONG;
4334 } else {
4335 u = VT_LONG;
4336 goto basic_type1;
4338 break;
4339 case TOK_BOOL:
4340 u = VT_BOOL;
4341 goto basic_type;
4342 case TOK_FLOAT:
4343 u = VT_FLOAT;
4344 goto basic_type;
4345 case TOK_DOUBLE:
4346 next();
4347 if ((t & VT_BTYPE) == VT_LONG) {
4348 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
4349 } else {
4350 u = VT_DOUBLE;
4351 goto basic_type1;
4353 break;
4354 case TOK_ENUM:
4355 u = struct_decl(VT_ENUM);
4356 goto basic_type1;
4357 case TOK_STRUCT:
4358 case TOK_UNION:
4359 u = struct_decl(VT_STRUCT);
4360 goto basic_type1;
4362 /* type modifiers */
4363 case TOK_CONST:
4364 case TOK_VOLATILE:
4365 case TOK_REGISTER:
4366 case TOK_SIGNED:
4367 case TOK___SIGNED__:
4368 case TOK_AUTO:
4369 case TOK_INLINE:
4370 case TOK___INLINE__:
4371 case TOK_RESTRICT:
4372 next();
4373 break;
4374 case TOK_UNSIGNED:
4375 t |= VT_UNSIGNED;
4376 next();
4377 break;
4379 /* storage */
4380 case TOK_EXTERN:
4381 t |= VT_EXTERN;
4382 next();
4383 break;
4384 case TOK_STATIC:
4385 t |= VT_STATIC;
4386 next();
4387 break;
4388 case TOK_TYPEDEF:
4389 t |= VT_TYPEDEF;
4390 next();
4391 break;
4392 /* GNUC attribute */
4393 case TOK___ATTRIBUTE__:
4394 parse_attribute(ad);
4395 break;
4396 default:
4397 s = sym_find(tok);
4398 if (!s || !(s->t & VT_TYPEDEF))
4399 goto the_end;
4400 t |= (s->t & ~VT_TYPEDEF);
4401 next();
4402 break;
4404 type_found = 1;
4406 the_end:
4407 /* long is never used as type */
4408 if ((t & VT_BTYPE) == VT_LONG)
4409 t = (t & ~VT_BTYPE) | VT_INT;
4410 *type_ptr = t;
4411 return type_found;
4414 int post_type(int t, AttributeDef *ad)
4416 int p, n, pt, l, t1;
4417 Sym **plast, *s, *first;
4418 AttributeDef ad1;
4420 if (tok == '(') {
4421 /* function declaration */
4422 next();
4423 l = 0;
4424 first = NULL;
4425 plast = &first;
4426 while (tok != ')') {
4427 /* read param name and compute offset */
4428 if (l != FUNC_OLD) {
4429 if (!parse_btype(&pt, &ad1)) {
4430 if (l) {
4431 error("invalid type");
4432 } else {
4433 l = FUNC_OLD;
4434 goto old_proto;
4437 l = FUNC_NEW;
4438 if ((pt & VT_BTYPE) == VT_VOID && tok == ')')
4439 break;
4440 pt = type_decl(&ad1, &n, pt, TYPE_DIRECT | TYPE_ABSTRACT);
4441 if ((pt & VT_BTYPE) == VT_VOID)
4442 error("parameter declared as void");
4443 } else {
4444 old_proto:
4445 n = tok;
4446 pt = VT_INT;
4447 next();
4449 /* array must be transformed to pointer according to ANSI C */
4450 pt &= ~VT_ARRAY;
4451 s = sym_push(n | SYM_FIELD, pt, 0, 0);
4452 *plast = s;
4453 plast = &s->next;
4454 if (tok == ',') {
4455 next();
4456 if (l == FUNC_NEW && tok == TOK_DOTS) {
4457 l = FUNC_ELLIPSIS;
4458 next();
4459 break;
4463 /* if no parameters, then old type prototype */
4464 if (l == 0)
4465 l = FUNC_OLD;
4466 skip(')');
4467 t1 = t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN);
4468 t = post_type(t & ~(VT_TYPEDEF | VT_STATIC | VT_EXTERN), ad);
4469 /* we push a anonymous symbol which will contain the function prototype */
4470 p = anon_sym++;
4471 s = sym_push(p, t, ad->func_call, l);
4472 s->next = first;
4473 t = t1 | VT_FUNC | (p << VT_STRUCT_SHIFT);
4474 } else if (tok == '[') {
4475 /* array definition */
4476 next();
4477 n = -1;
4478 if (tok != ']') {
4479 n = expr_const();
4480 if (n < 0)
4481 error("invalid array size");
4483 skip(']');
4484 /* parse next post type */
4485 t1 = t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN);
4486 t = post_type(t & ~(VT_TYPEDEF | VT_STATIC | VT_EXTERN), ad);
4488 /* we push a anonymous symbol which will contain the array
4489 element type */
4490 p = anon_sym++;
4491 sym_push(p, t, 0, n);
4492 t = t1 | VT_ARRAY | VT_PTR | (p << VT_STRUCT_SHIFT);
4494 return t;
4497 /* Read a type declaration (except basic type), and return the
4498 type. 'td' is a bitmask indicating which kind of type decl is
4499 expected. 't' should contain the basic type. 'ad' is the attribute
4500 definition of the basic type. It can be modified by type_decl(). */
4501 int type_decl(AttributeDef *ad, int *v, int t, int td)
4503 int u, p;
4504 Sym *s;
4506 while (tok == '*') {
4507 next();
4508 while (tok == TOK_CONST || tok == TOK_VOLATILE || tok == TOK_RESTRICT)
4509 next();
4510 t = mk_pointer(t);
4513 /* recursive type */
4514 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
4515 if (tok == '(') {
4516 next();
4517 /* XXX: this is not correct to modify 'ad' at this point, but
4518 the syntax is not clear */
4519 if (tok == TOK___ATTRIBUTE__)
4520 parse_attribute(ad);
4521 u = type_decl(ad, v, 0, td);
4522 skip(')');
4523 } else {
4524 u = 0;
4525 /* type identifier */
4526 if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
4527 *v = tok;
4528 next();
4529 } else {
4530 if (!(td & TYPE_ABSTRACT))
4531 expect("identifier");
4532 *v = 0;
4535 /* append t at the end of u */
4536 t = post_type(t, ad);
4537 if (tok == TOK___ATTRIBUTE__)
4538 parse_attribute(ad);
4539 if (!u)
4540 return t;
4541 p = u;
4542 while(1) {
4543 s = sym_find((unsigned)p >> VT_STRUCT_SHIFT);
4544 p = s->t;
4545 if (!p) {
4546 s->t = t;
4547 break;
4550 return u;
4553 /* define a new external reference to a symbol 'v' of type 'u' */
4554 Sym *external_sym(int v, int u, int r)
4556 Sym *s;
4558 s = sym_find(v);
4559 if (!s) {
4560 /* push forward reference */
4561 s = sym_push1(&global_stack,
4562 v, u | VT_EXTERN, 0);
4563 s->r = r | VT_CONST | VT_SYM;
4565 return s;
4568 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
4569 static int lvalue_type(int t)
4571 int bt, r;
4572 r = VT_LVAL;
4573 bt = t & VT_BTYPE;
4574 if (bt == VT_BYTE)
4575 r |= VT_LVAL_BYTE;
4576 else if (bt == VT_SHORT)
4577 r |= VT_LVAL_SHORT;
4578 else
4579 return r;
4580 if (t & VT_UNSIGNED)
4581 r |= VT_LVAL_UNSIGNED;
4582 return r;
4585 /* indirection with full error checking and bound check */
4586 static void indir(void)
4588 if ((vtop->t & VT_BTYPE) != VT_PTR)
4589 expect("pointer");
4590 if (vtop->r & VT_LVAL)
4591 gv(RC_INT);
4592 vtop->t = pointed_type(vtop->t);
4593 /* an array is never an lvalue */
4594 if (!(vtop->t & VT_ARRAY)) {
4595 vtop->r |= lvalue_type(vtop->t);
4596 /* if bound checking, the referenced pointer must be checked */
4597 if (do_bounds_check)
4598 vtop->r |= VT_MUSTBOUND;
4602 /* pass a parameter to a function and do type checking and casting */
4603 void gfunc_param_typed(GFuncContext *gf, Sym *func, Sym *arg)
4605 int func_type;
4606 func_type = func->c;
4607 if (func_type == FUNC_OLD ||
4608 (func_type == FUNC_ELLIPSIS && arg == NULL)) {
4609 /* default casting : only need to convert float to double */
4610 if ((vtop->t & VT_BTYPE) == VT_FLOAT)
4611 gen_cast(VT_DOUBLE);
4612 } else if (arg == NULL) {
4613 error("too many arguments to function");
4614 } else {
4615 gen_assign_cast(arg->t);
4617 gfunc_param(gf);
4620 void unary(void)
4622 int n, t, ft, fc, p, align, size, r, data_offset;
4623 Sym *s;
4624 GFuncContext gf;
4625 AttributeDef ad;
4627 if (tok == TOK_CINT || tok == TOK_CCHAR || tok == TOK_LCHAR) {
4628 vpushi(tokc.i);
4629 next();
4630 } else if (tok == TOK_CUINT) {
4631 vsetc(VT_INT | VT_UNSIGNED, VT_CONST, &tokc);
4632 next();
4633 } else if (tok == TOK_CLLONG) {
4634 vsetc(VT_LLONG, VT_CONST, &tokc);
4635 next();
4636 } else if (tok == TOK_CULLONG) {
4637 vsetc(VT_LLONG | VT_UNSIGNED, VT_CONST, &tokc);
4638 next();
4639 } else if (tok == TOK_CFLOAT) {
4640 vsetc(VT_FLOAT, VT_CONST, &tokc);
4641 next();
4642 } else if (tok == TOK_CDOUBLE) {
4643 vsetc(VT_DOUBLE, VT_CONST, &tokc);
4644 next();
4645 } else if (tok == TOK_CLDOUBLE) {
4646 vsetc(VT_LDOUBLE, VT_CONST, &tokc);
4647 next();
4648 } else if (tok == TOK___FUNC__) {
4649 /* special function name identifier */
4650 /* generate (char *) type */
4651 data_offset = data_section->data_ptr - data_section->data;
4652 vpush_ref(mk_pointer(VT_BYTE), data_section, data_offset);
4653 strcpy(data_section->data + data_offset, funcname);
4654 data_offset += strlen(funcname) + 1;
4655 data_section->data_ptr = data_section->data + data_offset;
4656 next();
4657 } else if (tok == TOK_LSTR) {
4658 t = VT_INT;
4659 goto str_init;
4660 } else if (tok == TOK_STR) {
4661 /* string parsing */
4662 t = VT_BYTE;
4663 str_init:
4664 type_size(t, &align);
4665 data_offset = data_section->data_ptr - data_section->data;
4666 data_offset = (data_offset + align - 1) & -align;
4667 fc = data_offset;
4668 /* we must declare it as an array first to use initializer parser */
4669 t = VT_ARRAY | mk_pointer(t);
4670 decl_initializer(t, data_section, data_offset, 1, 0);
4671 data_offset += type_size(t, &align);
4672 /* put it as pointer */
4673 vpush_ref(t & ~VT_ARRAY, data_section, fc);
4674 data_section->data_ptr = data_section->data + data_offset;
4675 } else {
4676 t = tok;
4677 next();
4678 if (t == '(') {
4679 /* cast ? */
4680 if (parse_btype(&t, &ad)) {
4681 ft = type_decl(&ad, &n, t, TYPE_ABSTRACT);
4682 skip(')');
4683 /* check ISOC99 compound literal */
4684 if (tok == '{') {
4685 /* data is allocated locally by default */
4686 if (global_expr)
4687 r = VT_CONST;
4688 else
4689 r = VT_LOCAL;
4690 /* all except arrays are lvalues */
4691 if (!(ft & VT_ARRAY))
4692 r |= lvalue_type(ft);
4693 memset(&ad, 0, sizeof(AttributeDef));
4694 decl_initializer_alloc(ft, &ad, r, 1, 0, 0);
4695 } else {
4696 unary();
4697 gen_cast(ft);
4699 } else {
4700 gexpr();
4701 skip(')');
4703 } else if (t == '*') {
4704 unary();
4705 indir();
4706 } else if (t == '&') {
4707 unary();
4708 /* functions names must be treated as function pointers,
4709 except for unary '&' and sizeof. Since we consider that
4710 functions are not lvalues, we only have to handle it
4711 there and in function calls. */
4712 /* arrays can also be used although they are not lvalues */
4713 if ((vtop->t & VT_BTYPE) != VT_FUNC &&
4714 !(vtop->t & VT_ARRAY))
4715 test_lvalue();
4716 vtop->t = mk_pointer(vtop->t);
4717 gaddrof();
4718 } else
4719 if (t == '!') {
4720 unary();
4721 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST)
4722 vtop->c.i = !vtop->c.i;
4723 else if ((vtop->r & VT_VALMASK) == VT_CMP)
4724 vtop->c.i = vtop->c.i ^ 1;
4725 else
4726 vset(VT_INT, VT_JMP, gtst(1, 0));
4727 } else
4728 if (t == '~') {
4729 unary();
4730 vpushi(-1);
4731 gen_op('^');
4732 } else
4733 if (t == '+') {
4734 unary();
4735 } else
4736 if (t == TOK_SIZEOF) {
4737 if (tok == '(') {
4738 next();
4739 if (parse_btype(&t, &ad)) {
4740 t = type_decl(&ad, &n, t, TYPE_ABSTRACT);
4741 } else {
4742 /* XXX: some code could be generated: add eval
4743 flag */
4744 gexpr();
4745 t = vtop->t;
4746 vpop();
4748 skip(')');
4749 } else {
4750 unary();
4751 t = vtop->t;
4752 vpop();
4754 vpushi(type_size(t, &t));
4755 } else
4756 if (t == TOK_INC || t == TOK_DEC) {
4757 unary();
4758 inc(0, t);
4759 } else if (t == '-') {
4760 vpushi(0);
4761 unary();
4762 gen_op('-');
4763 } else
4765 if (t < TOK_UIDENT)
4766 expect("identifier");
4767 s = sym_find(t);
4768 if (!s) {
4769 if (tok != '(')
4770 error("'%s' undeclared", get_tok_str(t, NULL));
4771 /* for simple function calls, we tolerate undeclared
4772 external reference */
4773 p = anon_sym++;
4774 sym_push1(&global_stack, p, 0, FUNC_OLD);
4775 /* int() function */
4776 s = external_sym(t, VT_FUNC | (p << VT_STRUCT_SHIFT), 0);
4778 vset(s->t, s->r, s->c);
4779 /* if forward reference, we must point to s */
4780 if (vtop->r & VT_SYM)
4781 vtop->c.sym = s;
4785 /* post operations */
4786 while (1) {
4787 if (tok == TOK_INC || tok == TOK_DEC) {
4788 inc(1, tok);
4789 next();
4790 } else if (tok == '.' || tok == TOK_ARROW) {
4791 /* field */
4792 if (tok == TOK_ARROW)
4793 indir();
4794 test_lvalue();
4795 gaddrof();
4796 next();
4797 /* expect pointer on structure */
4798 if ((vtop->t & VT_BTYPE) != VT_STRUCT)
4799 expect("struct or union");
4800 s = sym_find(((unsigned)vtop->t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
4801 /* find field */
4802 tok |= SYM_FIELD;
4803 while ((s = s->next) != NULL) {
4804 if (s->v == tok)
4805 break;
4807 if (!s)
4808 error("field not found");
4809 /* add field offset to pointer */
4810 vtop->t = char_pointer_type; /* change type to 'char *' */
4811 vpushi(s->c);
4812 gen_op('+');
4813 /* change type to field type, and set to lvalue */
4814 vtop->t = s->t;
4815 /* an array is never an lvalue */
4816 if (!(vtop->t & VT_ARRAY))
4817 vtop->r |= lvalue_type(vtop->t);
4818 next();
4819 } else if (tok == '[') {
4820 next();
4821 gexpr();
4822 gen_op('+');
4823 indir();
4824 skip(']');
4825 } else if (tok == '(') {
4826 SValue ret;
4827 Sym *sa;
4829 /* function call */
4830 if ((vtop->t & VT_BTYPE) != VT_FUNC) {
4831 /* pointer test (no array accepted) */
4832 if ((vtop->t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
4833 vtop->t = pointed_type(vtop->t);
4834 if ((vtop->t & VT_BTYPE) != VT_FUNC)
4835 goto error_func;
4836 } else {
4837 error_func:
4838 expect("function pointer");
4840 } else {
4841 vtop->r &= ~VT_LVAL; /* no lvalue */
4843 /* get return type */
4844 s = sym_find((unsigned)vtop->t >> VT_STRUCT_SHIFT);
4845 save_regs(0); /* save used temporary registers */
4846 gfunc_start(&gf, s->r);
4847 next();
4848 sa = s->next; /* first parameter */
4849 #ifdef INVERT_FUNC_PARAMS
4851 int parlevel;
4852 Sym *args, *s1;
4853 ParseState saved_parse_state;
4854 TokenString str;
4856 /* read each argument and store it on a stack */
4857 /* XXX: merge it with macro args ? */
4858 args = NULL;
4859 if (tok != ')') {
4860 for(;;) {
4861 tok_str_new(&str);
4862 parlevel = 0;
4863 while ((parlevel > 0 || (tok != ')' && tok != ',')) &&
4864 tok != -1) {
4865 if (tok == '(')
4866 parlevel++;
4867 else if (tok == ')')
4868 parlevel--;
4869 tok_str_add_tok(&str);
4870 next();
4872 tok_str_add(&str, -1); /* end of file added */
4873 tok_str_add(&str, 0);
4874 s1 = sym_push2(&args, 0, 0, (int)str.str);
4875 s1->next = sa; /* add reference to argument */
4876 if (sa)
4877 sa = sa->next;
4878 if (tok == ')')
4879 break;
4880 skip(',');
4884 /* now generate code in reverse order by reading the stack */
4885 save_parse_state(&saved_parse_state);
4886 while (args) {
4887 macro_ptr = (int *)args->c;
4888 next();
4889 expr_eq();
4890 if (tok != -1)
4891 expect("',' or ')'");
4892 gfunc_param_typed(&gf, s, args->next);
4893 s1 = args->prev;
4894 free((int *)args->c);
4895 free(args);
4896 args = s1;
4898 restore_parse_state(&saved_parse_state);
4900 #endif
4901 /* compute first implicit argument if a structure is returned */
4902 if ((s->t & VT_BTYPE) == VT_STRUCT) {
4903 /* get some space for the returned structure */
4904 size = type_size(s->t, &align);
4905 loc = (loc - size) & -align;
4906 ret.t = s->t;
4907 ret.r = VT_LOCAL | VT_LVAL;
4908 /* pass it as 'int' to avoid structure arg passing
4909 problems */
4910 vset(VT_INT, VT_LOCAL, loc);
4911 ret.c = vtop->c;
4912 gfunc_param(&gf);
4913 } else {
4914 ret.t = s->t;
4915 ret.r2 = VT_CONST;
4916 /* return in register */
4917 if (is_float(ret.t)) {
4918 ret.r = REG_FRET;
4919 } else {
4920 if ((ret.t & VT_BTYPE) == VT_LLONG)
4921 ret.r2 = REG_LRET;
4922 ret.r = REG_IRET;
4924 ret.c.i = 0;
4926 #ifndef INVERT_FUNC_PARAMS
4927 if (tok != ')') {
4928 for(;;) {
4929 expr_eq();
4930 gfunc_param_typed(&gf, s, sa);
4931 if (sa)
4932 sa = sa->next;
4933 if (tok == ')')
4934 break;
4935 skip(',');
4938 #endif
4939 if (sa)
4940 error("too few arguments to function");
4941 skip(')');
4942 gfunc_call(&gf);
4943 /* return value */
4944 vsetc(ret.t, ret.r, &ret.c);
4945 vtop->r2 = ret.r2;
4946 } else {
4947 break;
4952 void uneq(void)
4954 int t;
4956 unary();
4957 if (tok == '=' ||
4958 (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
4959 tok == TOK_A_XOR || tok == TOK_A_OR ||
4960 tok == TOK_A_SHL || tok == TOK_A_SAR) {
4961 test_lvalue();
4962 t = tok;
4963 next();
4964 if (t == '=') {
4965 expr_eq();
4966 } else {
4967 vdup();
4968 expr_eq();
4969 gen_op(t & 0x7f);
4971 vstore();
4975 void sum(int l)
4977 int t;
4979 if (l == 0)
4980 uneq();
4981 else {
4982 sum(--l);
4983 while ((l == 0 && (tok == '*' || tok == '/' || tok == '%')) ||
4984 (l == 1 && (tok == '+' || tok == '-')) ||
4985 (l == 2 && (tok == TOK_SHL || tok == TOK_SAR)) ||
4986 (l == 3 && ((tok >= TOK_ULE && tok <= TOK_GT) ||
4987 tok == TOK_ULT || tok == TOK_UGE)) ||
4988 (l == 4 && (tok == TOK_EQ || tok == TOK_NE)) ||
4989 (l == 5 && tok == '&') ||
4990 (l == 6 && tok == '^') ||
4991 (l == 7 && tok == '|') ||
4992 (l == 8 && tok == TOK_LAND) ||
4993 (l == 9 && tok == TOK_LOR)) {
4994 t = tok;
4995 next();
4996 sum(l);
4997 gen_op(t);
5002 /* only used if non constant */
5003 void eand(void)
5005 int t;
5007 sum(8);
5008 t = 0;
5009 while (1) {
5010 if (tok != TOK_LAND) {
5011 if (t) {
5012 t = gtst(1, t);
5013 vset(VT_INT, VT_JMPI, t);
5015 break;
5017 t = gtst(1, t);
5018 next();
5019 sum(8);
5023 void eor(void)
5025 int t;
5027 eand();
5028 t = 0;
5029 while (1) {
5030 if (tok != TOK_LOR) {
5031 if (t) {
5032 t = gtst(0, t);
5033 vset(VT_INT, VT_JMP, t);
5035 break;
5037 t = gtst(0, t);
5038 next();
5039 eand();
5043 /* XXX: better constant handling */
5044 void expr_eq(void)
5046 int t, u, c, r1, r2, rc;
5048 if (const_wanted) {
5049 sum(10);
5050 if (tok == '?') {
5051 c = vtop->c.i;
5052 vpop();
5053 next();
5054 gexpr();
5055 t = vtop->c.i;
5056 vpop();
5057 skip(':');
5058 expr_eq();
5059 if (c)
5060 vtop->c.i = t;
5062 } else {
5063 eor();
5064 if (tok == '?') {
5065 next();
5066 save_regs(1); /* we need to save all registers here except
5067 at the top because it is a branch point */
5068 t = gtst(1, 0);
5069 gexpr();
5070 /* XXX: long long handling ? */
5071 rc = RC_INT;
5072 if (is_float(vtop->t))
5073 rc = RC_FLOAT;
5074 r1 = gv(rc);
5075 vtop--; /* no vpop so that FP stack is not flushed */
5076 skip(':');
5077 u = gjmp(0);
5079 gsym(t);
5080 expr_eq();
5081 r2 = gv(rc);
5082 move_reg(r1, r2);
5083 vtop->r = r1;
5084 gsym(u);
5089 void gexpr(void)
5091 while (1) {
5092 expr_eq();
5093 if (tok != ',')
5094 break;
5095 vpop();
5096 next();
5100 /* parse a constant expression and return value in vtop */
5101 void expr_const1(void)
5103 int a;
5104 a = const_wanted;
5105 const_wanted = 1;
5106 expr_eq();
5107 if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST)
5108 expect("constant");
5109 const_wanted = a;
5112 /* parse an integer constant and return its value */
5113 int expr_const(void)
5115 int c;
5116 expr_const1();
5117 c = vtop->c.i;
5118 vpop();
5119 return c;
5122 /* return the label token if current token is a label, otherwise
5123 return zero */
5124 int is_label(void)
5126 int t;
5127 CValue c;
5129 /* fast test first */
5130 if (tok < TOK_UIDENT)
5131 return 0;
5132 /* no need to save tokc since we expect an identifier */
5133 t = tok;
5134 c = tokc;
5135 next();
5136 if (tok == ':') {
5137 next();
5138 return t;
5139 } else {
5140 /* XXX: may not work in all cases (macros ?) */
5141 tok1 = tok;
5142 tok1c = tokc;
5143 tok = t;
5144 tokc = c;
5145 return 0;
5149 void block(int *bsym, int *csym, int *case_sym, int *def_sym, int case_reg)
5151 int a, b, c, d;
5152 Sym *s;
5154 /* generate line number info */
5155 if (do_debug &&
5156 (last_line_num != file->line_num || last_ind != ind)) {
5157 put_stabn(N_SLINE, 0, file->line_num, ind - func_ind);
5158 last_ind = ind;
5159 last_line_num = file->line_num;
5162 if (tok == TOK_IF) {
5163 /* if test */
5164 next();
5165 skip('(');
5166 gexpr();
5167 skip(')');
5168 a = gtst(1, 0);
5169 block(bsym, csym, case_sym, def_sym, case_reg);
5170 c = tok;
5171 if (c == TOK_ELSE) {
5172 next();
5173 d = gjmp(0);
5174 gsym(a);
5175 block(bsym, csym, case_sym, def_sym, case_reg);
5176 gsym(d); /* patch else jmp */
5177 } else
5178 gsym(a);
5179 } else if (tok == TOK_WHILE) {
5180 next();
5181 d = ind;
5182 skip('(');
5183 gexpr();
5184 skip(')');
5185 a = gtst(1, 0);
5186 b = 0;
5187 block(&a, &b, case_sym, def_sym, case_reg);
5188 gjmp_addr(d);
5189 gsym(a);
5190 gsym_addr(b, d);
5191 } else if (tok == '{') {
5192 next();
5193 /* declarations */
5194 s = local_stack.top;
5195 while (tok != '}') {
5196 decl(VT_LOCAL);
5197 if (tok != '}')
5198 block(bsym, csym, case_sym, def_sym, case_reg);
5200 /* pop locally defined symbols */
5201 sym_pop(&local_stack, s);
5202 next();
5203 } else if (tok == TOK_RETURN) {
5204 next();
5205 if (tok != ';') {
5206 gexpr();
5207 gen_assign_cast(func_vt);
5208 if ((func_vt & VT_BTYPE) == VT_STRUCT) {
5209 /* if returning structure, must copy it to implicit
5210 first pointer arg location */
5211 vset(mk_pointer(func_vt), VT_LOCAL | VT_LVAL, func_vc);
5212 indir();
5213 vswap();
5214 /* copy structure value to pointer */
5215 vstore();
5216 } else if (is_float(func_vt)) {
5217 gv(RC_FRET);
5218 } else {
5219 gv(RC_IRET);
5221 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
5223 skip(';');
5224 rsym = gjmp(rsym); /* jmp */
5225 } else if (tok == TOK_BREAK) {
5226 /* compute jump */
5227 if (!bsym)
5228 error("cannot break");
5229 *bsym = gjmp(*bsym);
5230 next();
5231 skip(';');
5232 } else if (tok == TOK_CONTINUE) {
5233 /* compute jump */
5234 if (!csym)
5235 error("cannot continue");
5236 *csym = gjmp(*csym);
5237 next();
5238 skip(';');
5239 } else if (tok == TOK_FOR) {
5240 int e;
5241 next();
5242 skip('(');
5243 if (tok != ';') {
5244 gexpr();
5245 vpop();
5247 skip(';');
5248 d = ind;
5249 c = ind;
5250 a = 0;
5251 b = 0;
5252 if (tok != ';') {
5253 gexpr();
5254 a = gtst(1, 0);
5256 skip(';');
5257 if (tok != ')') {
5258 e = gjmp(0);
5259 c = ind;
5260 gexpr();
5261 vpop();
5262 gjmp_addr(d);
5263 gsym(e);
5265 skip(')');
5266 block(&a, &b, case_sym, def_sym, case_reg);
5267 gjmp_addr(c);
5268 gsym(a);
5269 gsym_addr(b, c);
5270 } else
5271 if (tok == TOK_DO) {
5272 next();
5273 a = 0;
5274 b = 0;
5275 d = ind;
5276 block(&a, &b, case_sym, def_sym, case_reg);
5277 skip(TOK_WHILE);
5278 skip('(');
5279 gsym(b);
5280 gexpr();
5281 c = gtst(0, 0);
5282 gsym_addr(c, d);
5283 skip(')');
5284 gsym(a);
5285 skip(';');
5286 } else
5287 if (tok == TOK_SWITCH) {
5288 next();
5289 skip('(');
5290 gexpr();
5291 /* XXX: other types than integer */
5292 case_reg = gv(RC_INT);
5293 vpop();
5294 skip(')');
5295 a = 0;
5296 b = gjmp(0); /* jump to first case */
5297 c = 0;
5298 block(&a, csym, &b, &c, case_reg);
5299 /* if no default, jmp after switch */
5300 if (c == 0)
5301 c = ind;
5302 /* default label */
5303 gsym_addr(b, c);
5304 /* break label */
5305 gsym(a);
5306 } else
5307 if (tok == TOK_CASE) {
5308 int v1, v2;
5309 if (!case_sym)
5310 expect("switch");
5311 next();
5312 v1 = expr_const();
5313 v2 = v1;
5314 if (gnu_ext && tok == TOK_DOTS) {
5315 next();
5316 v2 = expr_const();
5317 if (v2 < v1)
5318 warning("empty case range");
5320 /* since a case is like a label, we must skip it with a jmp */
5321 b = gjmp(0);
5322 gsym(*case_sym);
5323 vset(VT_INT, case_reg, 0);
5324 vpushi(v1);
5325 if (v1 == v2) {
5326 gen_op(TOK_EQ);
5327 *case_sym = gtst(1, 0);
5328 } else {
5329 gen_op(TOK_GE);
5330 *case_sym = gtst(1, 0);
5331 vset(VT_INT, case_reg, 0);
5332 vpushi(v2);
5333 gen_op(TOK_LE);
5334 *case_sym = gtst(1, *case_sym);
5336 gsym(b);
5337 skip(':');
5338 block(bsym, csym, case_sym, def_sym, case_reg);
5339 } else
5340 if (tok == TOK_DEFAULT) {
5341 next();
5342 skip(':');
5343 if (!def_sym)
5344 expect("switch");
5345 if (*def_sym)
5346 error("too many 'default'");
5347 *def_sym = ind;
5348 block(bsym, csym, case_sym, def_sym, case_reg);
5349 } else
5350 if (tok == TOK_GOTO) {
5351 next();
5352 s = sym_find1(&label_stack, tok);
5353 /* put forward definition if needed */
5354 if (!s)
5355 s = sym_push1(&label_stack, tok, LABEL_FORWARD, 0);
5356 /* label already defined */
5357 if (s->t & LABEL_FORWARD)
5358 s->c = gjmp(s->c);
5359 else
5360 gjmp_addr(s->c);
5361 next();
5362 skip(';');
5363 } else {
5364 b = is_label();
5365 if (b) {
5366 /* label case */
5367 s = sym_find1(&label_stack, b);
5368 if (s) {
5369 if (!(s->t & LABEL_FORWARD))
5370 error("multiple defined label");
5371 gsym(s->c);
5372 s->c = ind;
5373 s->t = 0;
5374 } else {
5375 sym_push1(&label_stack, b, 0, ind);
5377 /* we accept this, but it is a mistake */
5378 if (tok == '}')
5379 warning("deprecated use of label at end of compound statement");
5380 else
5381 block(bsym, csym, case_sym, def_sym, case_reg);
5382 } else {
5383 /* expression case */
5384 if (tok != ';') {
5385 gexpr();
5386 vpop();
5388 skip(';');
5393 /* t is the array or struct type. c is the array or struct
5394 address. cur_index/cur_field is the pointer to the current
5395 value. 'size_only' is true if only size info is needed (only used
5396 in arrays) */
5397 void decl_designator(int t, Section *sec, unsigned long c,
5398 int *cur_index, Sym **cur_field,
5399 int size_only)
5401 Sym *s, *f;
5402 int notfirst, index, align, l;
5404 notfirst = 0;
5405 if (gnu_ext && (l = is_label()) != 0)
5406 goto struct_field;
5408 while (tok == '[' || tok == '.') {
5409 if (tok == '[') {
5410 if (!(t & VT_ARRAY))
5411 expect("array type");
5412 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
5413 next();
5414 index = expr_const();
5415 if (index < 0 || (s->c >= 0 && index >= s->c))
5416 expect("invalid index");
5417 skip(']');
5418 if (!notfirst)
5419 *cur_index = index;
5420 t = pointed_type(t);
5421 c += index * type_size(t, &align);
5422 } else {
5423 next();
5424 l = tok;
5425 next();
5426 struct_field:
5427 if ((t & VT_BTYPE) != VT_STRUCT)
5428 expect("struct/union type");
5429 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
5430 l |= SYM_FIELD;
5431 f = s->next;
5432 while (f) {
5433 if (f->v == l)
5434 break;
5435 f = f->next;
5437 if (!f)
5438 expect("field");
5439 if (!notfirst)
5440 *cur_field = f;
5441 t = f->t | (t & ~VT_TYPE);
5442 c += f->c;
5444 notfirst = 1;
5446 if (notfirst) {
5447 if (tok == '=') {
5448 next();
5449 } else {
5450 if (!gnu_ext)
5451 expect("=");
5453 } else {
5454 if (t & VT_ARRAY) {
5455 index = *cur_index;
5456 t = pointed_type(t);
5457 c += index * type_size(t, &align);
5458 } else {
5459 f = *cur_field;
5460 if (!f)
5461 error("too many field init");
5462 t = f->t | (t & ~VT_TYPE);
5463 c += f->c;
5466 decl_initializer(t, sec, c, 0, size_only);
5469 #define EXPR_VAL 0
5470 #define EXPR_CONST 1
5471 #define EXPR_ANY 2
5473 /* store a value or an expression directly in global data or in local array */
5474 void init_putv(int t, Section *sec, unsigned long c,
5475 int v, int expr_type)
5477 int saved_global_expr, bt;
5478 void *ptr;
5480 switch(expr_type) {
5481 case EXPR_VAL:
5482 vpushi(v);
5483 break;
5484 case EXPR_CONST:
5485 /* compound literals must be allocated globally in this case */
5486 saved_global_expr = global_expr;
5487 global_expr = 1;
5488 expr_const1();
5489 global_expr = saved_global_expr;
5490 break;
5491 case EXPR_ANY:
5492 expr_eq();
5493 break;
5496 if (sec) {
5497 /* XXX: not portable */
5498 /* XXX: generate error if incorrect relocation */
5499 gen_assign_cast(t);
5500 bt = t & VT_BTYPE;
5501 ptr = sec->data + c;
5502 if ((vtop->r & VT_SYM) &&
5503 (bt == VT_BYTE ||
5504 bt == VT_SHORT ||
5505 bt == VT_DOUBLE ||
5506 bt == VT_LDOUBLE ||
5507 bt == VT_LLONG))
5508 error("initializer element is not computable at load time");
5509 switch(bt) {
5510 case VT_BYTE:
5511 *(char *)ptr = vtop->c.i;
5512 break;
5513 case VT_SHORT:
5514 *(short *)ptr = vtop->c.i;
5515 break;
5516 case VT_DOUBLE:
5517 *(double *)ptr = vtop->c.d;
5518 break;
5519 case VT_LDOUBLE:
5520 *(long double *)ptr = vtop->c.ld;
5521 break;
5522 case VT_LLONG:
5523 *(long long *)ptr = vtop->c.ll;
5524 break;
5525 default:
5526 if (vtop->r & VT_SYM) {
5527 greloc(sec, vtop->c.sym, c, R_DATA_32);
5528 *(int *)ptr = 0;
5529 } else {
5530 *(int *)ptr = vtop->c.i;
5532 break;
5534 vtop--;
5535 } else {
5536 vset(t, VT_LOCAL, c);
5537 vswap();
5538 vstore();
5539 vpop();
5543 /* put zeros for variable based init */
5544 void init_putz(int t, Section *sec, unsigned long c, int size)
5546 GFuncContext gf;
5548 if (sec) {
5549 /* nothing to do because globals are already set to zero */
5550 } else {
5551 gfunc_start(&gf, FUNC_CDECL);
5552 vpushi(size);
5553 gfunc_param(&gf);
5554 vpushi(0);
5555 gfunc_param(&gf);
5556 vset(VT_INT, VT_LOCAL, c);
5557 gfunc_param(&gf);
5558 vpushi((int)&memset);
5559 gfunc_call(&gf);
5563 /* 't' contains the type and storage info. 'c' is the offset of the
5564 object in section 'sec'. If 'sec' is NULL, it means stack based
5565 allocation. 'first' is true if array '{' must be read (multi
5566 dimension implicit array init handling). 'size_only' is true if
5567 size only evaluation is wanted (only for arrays). */
5568 void decl_initializer(int t, Section *sec, unsigned long c, int first, int size_only)
5570 int index, array_length, n, no_oblock, nb, parlevel, i;
5571 int t1, size1, align1, expr_type;
5572 Sym *s, *f;
5573 TokenSym *ts;
5575 if (t & VT_ARRAY) {
5576 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
5577 n = s->c;
5578 array_length = 0;
5579 t1 = pointed_type(t);
5580 size1 = type_size(t1, &align1);
5582 no_oblock = 1;
5583 if ((first && tok != TOK_LSTR && tok != TOK_STR) ||
5584 tok == '{') {
5585 skip('{');
5586 no_oblock = 0;
5589 /* only parse strings here if correct type (otherwise: handle
5590 them as ((w)char *) expressions */
5591 if ((tok == TOK_LSTR &&
5592 (t1 & VT_BTYPE) == VT_INT) ||
5593 (tok == TOK_STR &&
5594 (t1 & VT_BTYPE) == VT_BYTE)) {
5595 /* XXX: move multiple string parsing in parser ? */
5596 while (tok == TOK_STR || tok == TOK_LSTR) {
5597 ts = tokc.ts;
5598 /* compute maximum number of chars wanted */
5599 nb = ts->len;
5600 if (n >= 0 && nb > (n - array_length))
5601 nb = n - array_length;
5602 if (!size_only) {
5603 if (ts->len > nb)
5604 warning("initializer-string for array is too long");
5605 for(i=0;i<nb;i++) {
5606 init_putv(t1, sec, c + (array_length + i) * size1,
5607 ts->str[i], EXPR_VAL);
5610 array_length += nb;
5611 next();
5613 /* only add trailing zero if enough storage (no
5614 warning in this case since it is standard) */
5615 if (n < 0 || array_length < n) {
5616 if (!size_only) {
5617 init_putv(t1, sec, c + (array_length * size1), 0, EXPR_VAL);
5619 array_length++;
5621 } else {
5622 index = 0;
5623 while (tok != '}') {
5624 decl_designator(t, sec, c, &index, NULL, size_only);
5625 if (n >= 0 && index >= n)
5626 error("index too large");
5627 /* must put zero in holes (note that doing it that way
5628 ensures that it even works with designators) */
5629 if (!size_only && array_length < index) {
5630 init_putz(t1, sec, c + array_length * size1,
5631 (index - array_length) * size1);
5633 index++;
5634 if (index > array_length)
5635 array_length = index;
5636 /* special test for multi dimensional arrays (may not
5637 be strictly correct if designators are used at the
5638 same time) */
5639 if (index >= n && no_oblock)
5640 break;
5641 if (tok == '}')
5642 break;
5643 skip(',');
5646 if (!no_oblock)
5647 skip('}');
5648 /* put zeros at the end */
5649 if (!size_only && n >= 0 && array_length < n) {
5650 init_putz(t1, sec, c + array_length * size1,
5651 (n - array_length) * size1);
5653 /* patch type size if needed */
5654 if (n < 0)
5655 s->c = array_length;
5656 } else if ((t & VT_BTYPE) == VT_STRUCT && tok == '{') {
5657 /* XXX: union needs only one init */
5658 next();
5659 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
5660 f = s->next;
5661 array_length = 0;
5662 index = 0;
5663 n = s->c;
5664 while (tok != '}') {
5665 decl_designator(t, sec, c, NULL, &f, size_only);
5666 /* fill with zero between fields */
5667 index = f->c;
5668 if (!size_only && array_length < index) {
5669 init_putz(t, sec, c + array_length,
5670 index - array_length);
5672 index = index + type_size(f->t, &align1);
5673 if (index > array_length)
5674 array_length = index;
5675 if (tok == '}')
5676 break;
5677 skip(',');
5678 f = f->next;
5680 /* put zeros at the end */
5681 if (!size_only && array_length < n) {
5682 init_putz(t, sec, c + array_length,
5683 n - array_length);
5685 skip('}');
5686 } else if (tok == '{') {
5687 next();
5688 decl_initializer(t, sec, c, first, size_only);
5689 skip('}');
5690 } else if (size_only) {
5691 /* just skip expression */
5692 parlevel = 0;
5693 while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
5694 tok != -1) {
5695 if (tok == '(')
5696 parlevel++;
5697 else if (tok == ')')
5698 parlevel--;
5699 next();
5701 } else {
5702 /* currently, we always use constant expression for globals
5703 (may change for scripting case) */
5704 expr_type = EXPR_CONST;
5705 if (!sec)
5706 expr_type = EXPR_ANY;
5707 init_putv(t, sec, c, 0, expr_type);
5711 /* parse an initializer for type 't' if 'has_init' is true, and
5712 allocate space in local or global data space ('r' is either
5713 VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
5714 variable 'v' of scope 'scope' is declared before initializers are
5715 parsed. If 'v' is zero, then a reference to the new object is put
5716 in the value stack. */
5717 void decl_initializer_alloc(int t, AttributeDef *ad, int r, int has_init,
5718 int v, int scope)
5720 int size, align, addr, data_offset;
5721 int level;
5722 ParseState saved_parse_state;
5723 TokenString init_str;
5724 Section *sec;
5726 size = type_size(t, &align);
5727 /* If unknown size, we must evaluate it before
5728 evaluating initializers because
5729 initializers can generate global data too
5730 (e.g. string pointers or ISOC99 compound
5731 literals). It also simplifies local
5732 initializers handling */
5733 tok_str_new(&init_str);
5734 if (size < 0) {
5735 if (!has_init)
5736 error("unknown type size");
5737 /* get all init string */
5738 level = 0;
5739 while (level > 0 || (tok != ',' && tok != ';')) {
5740 if (tok < 0)
5741 error("unexpected end of file in initializer");
5742 tok_str_add_tok(&init_str);
5743 if (tok == '{')
5744 level++;
5745 else if (tok == '}') {
5746 if (level == 0)
5747 break;
5748 level--;
5750 next();
5752 tok_str_add(&init_str, -1);
5753 tok_str_add(&init_str, 0);
5755 /* compute size */
5756 save_parse_state(&saved_parse_state);
5758 macro_ptr = init_str.str;
5759 next();
5760 decl_initializer(t, NULL, 0, 1, 1);
5761 /* prepare second initializer parsing */
5762 macro_ptr = init_str.str;
5763 next();
5765 /* if still unknown size, error */
5766 size = type_size(t, &align);
5767 if (size < 0)
5768 error("unknown type size");
5770 /* take into account specified alignment if bigger */
5771 if (ad->aligned > align)
5772 align = ad->aligned;
5773 if ((r & VT_VALMASK) == VT_LOCAL) {
5774 sec = NULL;
5775 if (do_bounds_check && (t & VT_ARRAY))
5776 loc--;
5777 #ifdef TCC_TARGET_IL
5778 /* XXX: ugly patch to allocate local variables for IL, just
5779 for testing */
5780 addr = loc;
5781 loc++;
5782 #else
5783 loc = (loc - size) & -align;
5784 addr = loc;
5785 #endif
5786 /* handles bounds */
5787 /* XXX: currently, since we do only one pass, we cannot track
5788 '&' operators, so we add only arrays */
5789 if (do_bounds_check && (t & VT_ARRAY)) {
5790 int *bounds_ptr;
5791 /* add padding between regions */
5792 loc--;
5793 /* then add local bound info */
5794 bounds_ptr = (int *)lbounds_section->data_ptr;
5795 *bounds_ptr++ = addr;
5796 *bounds_ptr++ = size;
5797 lbounds_section->data_ptr = (unsigned char *)bounds_ptr;
5799 } else {
5800 /* compute section */
5801 sec = ad->section;
5802 if (!sec) {
5803 if (has_init)
5804 sec = data_section;
5805 else
5806 sec = bss_section;
5808 data_offset = sec->data_ptr - sec->data;
5809 data_offset = (data_offset + align - 1) & -align;
5810 addr = data_offset;
5811 /* very important to increment global pointer at this time
5812 because initializers themselves can create new initializers */
5813 data_offset += size;
5814 /* handles bounds */
5815 if (do_bounds_check) {
5816 int *bounds_ptr;
5817 /* first, we need to add at least one byte between each region */
5818 data_offset++;
5819 /* then add global bound info */
5820 bounds_ptr = (int *)bounds_section->data_ptr;
5821 /* XXX: add relocation */
5822 *bounds_ptr++ = addr + (unsigned long)sec->data;
5823 *bounds_ptr++ = size;
5824 bounds_section->data_ptr = (unsigned char *)bounds_ptr;
5826 sec->data_ptr = sec->data + data_offset;
5828 if (v) {
5829 Sym *sym;
5831 if (!sec) {
5832 /* local variable */
5833 sym_push(v, t, r, addr);
5834 } else {
5835 if (scope == VT_CONST) {
5836 /* global scope: see if already defined */
5837 sym = sym_find(v);
5838 if (!sym)
5839 goto do_def;
5840 if (!is_compatible_types(sym->t, t))
5841 error("incompatible types for redefinition of '%s'",
5842 get_tok_str(v, NULL));
5843 if (!(sym->t & VT_EXTERN))
5844 error("redefinition of '%s'", get_tok_str(v, NULL));
5845 sym->t &= ~VT_EXTERN;
5846 } else {
5847 do_def:
5848 sym = sym_push(v, t, r | VT_SYM, 0);
5850 put_extern_sym(sym, sec, addr);
5852 } else {
5853 if (!sec) {
5854 /* push local reference */
5855 vset(t, r, addr);
5856 } else {
5857 /* push global reference */
5858 vpush_ref(t, sec, addr);
5861 if (has_init) {
5862 decl_initializer(t, sec, addr, 1, 0);
5863 /* restore parse state if needed */
5864 if (init_str.str) {
5865 free(init_str.str);
5866 restore_parse_state(&saved_parse_state);
5871 void put_func_debug(int t)
5873 char buf[512];
5875 /* stabs info */
5876 /* XXX: we put here a dummy type */
5877 snprintf(buf, sizeof(buf), "%s:%c1",
5878 funcname, t & VT_STATIC ? 'f' : 'F');
5879 put_stabs(buf, N_FUN, 0, file->line_num, ind);
5880 func_ind = ind;
5881 last_ind = 0;
5882 last_line_num = 0;
5885 /* not finished : try to put some local vars in registers */
5886 //#define CONFIG_REG_VARS
5888 #ifdef CONFIG_REG_VARS
5889 void add_var_ref(int t)
5891 printf("%s:%d: &%s\n",
5892 file->filename, file->line_num,
5893 get_tok_str(t, NULL));
5896 /* first pass on a function with heuristic to extract variable usage
5897 and pointer references to local variables for register allocation */
5898 void analyse_function(void)
5900 int level, t;
5902 for(;;) {
5903 if (tok == -1)
5904 break;
5905 /* any symbol coming after '&' is considered as being a
5906 variable whose reference is taken. It is highly unaccurate
5907 but it is difficult to do better without a complete parse */
5908 if (tok == '&') {
5909 next();
5910 /* if '& number', then no need to examine next tokens */
5911 if (tok == TOK_CINT ||
5912 tok == TOK_CUINT ||
5913 tok == TOK_CLLONG ||
5914 tok == TOK_CULLONG) {
5915 continue;
5916 } else if (tok >= TOK_UIDENT) {
5917 /* if '& ident [' or '& ident ->', then ident address
5918 is not needed */
5919 t = tok;
5920 next();
5921 if (tok != '[' && tok != TOK_ARROW)
5922 add_var_ref(t);
5923 } else {
5924 level = 0;
5925 while (tok != '}' && tok != ';' &&
5926 !((tok == ',' || tok == ')') && level == 0)) {
5927 if (tok >= TOK_UIDENT) {
5928 add_var_ref(tok);
5929 } else if (tok == '(') {
5930 level++;
5931 } else if (tok == ')') {
5932 level--;
5934 next();
5937 } else {
5938 next();
5942 #endif
5944 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
5945 void decl(int l)
5947 int t, b, v, has_init, r;
5948 Sym *sym;
5949 AttributeDef ad;
5951 while (1) {
5952 if (!parse_btype(&b, &ad)) {
5953 /* skip redundant ';' */
5954 /* XXX: find more elegant solution */
5955 if (tok == ';') {
5956 next();
5957 continue;
5959 /* special test for old K&R protos without explicit int
5960 type. Only accepted when defining global data */
5961 if (l == VT_LOCAL || tok < TOK_DEFINE)
5962 break;
5963 b = VT_INT;
5965 if (((b & VT_BTYPE) == VT_ENUM ||
5966 (b & VT_BTYPE) == VT_STRUCT) &&
5967 tok == ';') {
5968 /* we accept no variable after */
5969 next();
5970 continue;
5972 while (1) { /* iterate thru each declaration */
5973 t = type_decl(&ad, &v, b, TYPE_DIRECT);
5974 #if 0
5976 char buf[500];
5977 type_to_str(buf, sizeof(buf), t, get_tok_str(v, NULL));
5978 printf("type = '%s'\n", buf);
5980 #endif
5981 if (tok == '{') {
5982 #ifdef CONFIG_REG_VARS
5983 TokenString func_str;
5984 ParseState saved_parse_state;
5985 int block_level;
5986 #endif
5988 if (l == VT_LOCAL)
5989 error("cannot use local functions");
5990 if (!(t & VT_FUNC))
5991 expect("function definition");
5993 #ifdef CONFIG_REG_VARS
5994 /* parse all function code and record it */
5996 tok_str_new(&func_str);
5998 block_level = 0;
5999 for(;;) {
6000 int t;
6001 if (tok == -1)
6002 error("unexpected end of file");
6003 tok_str_add_tok(&func_str);
6004 t = tok;
6005 next();
6006 if (t == '{') {
6007 block_level++;
6008 } else if (t == '}') {
6009 block_level--;
6010 if (block_level == 0)
6011 break;
6014 tok_str_add(&func_str, -1);
6015 tok_str_add(&func_str, 0);
6017 save_parse_state(&saved_parse_state);
6019 macro_ptr = func_str.str;
6020 next();
6021 analyse_function();
6022 #endif
6024 /* compute text section */
6025 cur_text_section = ad.section;
6026 if (!cur_text_section)
6027 cur_text_section = text_section;
6028 ind = (int)cur_text_section->data_ptr;
6029 funcname = get_tok_str(v, NULL);
6030 sym = sym_find(v);
6031 if (sym) {
6032 /* if symbol is already defined, then put complete type */
6033 sym->t = t;
6034 } else {
6035 /* put function symbol */
6036 sym = sym_push1(&global_stack, v, t, 0);
6038 put_extern_sym(sym, cur_text_section,
6039 ind - (int)cur_text_section->data);
6040 sym->r = VT_SYM | VT_CONST;
6041 /* put debug symbol */
6042 if (do_debug)
6043 put_func_debug(t);
6044 /* push a dummy symbol to enable local sym storage */
6045 sym_push1(&local_stack, 0, 0, 0);
6046 gfunc_prolog(t);
6047 loc = 0;
6048 rsym = 0;
6049 #ifdef CONFIG_REG_VARS
6050 macro_ptr = func_str.str;
6051 next();
6052 #endif
6053 block(NULL, NULL, NULL, NULL, 0);
6054 gsym(rsym);
6055 gfunc_epilog();
6056 cur_text_section->data_ptr = (unsigned char *)ind;
6057 sym_pop(&label_stack, NULL); /* reset label stack */
6058 sym_pop(&local_stack, NULL); /* reset local stack */
6059 /* end of function */
6060 if (do_debug) {
6061 put_stabn(N_FUN, 0, 0, ind - func_ind);
6063 funcname = ""; /* for safety */
6064 func_vt = VT_VOID; /* for safety */
6065 ind = 0; /* for safety */
6067 #ifdef CONFIG_REG_VARS
6068 free(func_str.str);
6069 restore_parse_state(&saved_parse_state);
6070 #endif
6071 break;
6072 } else {
6073 if (b & VT_TYPEDEF) {
6074 /* save typedefed type */
6075 /* XXX: test storage specifiers ? */
6076 sym_push(v, t | VT_TYPEDEF, 0, 0);
6077 } else if ((t & VT_BTYPE) == VT_FUNC) {
6078 /* external function definition */
6079 external_sym(v, t, 0);
6080 } else {
6081 /* not lvalue if array */
6082 r = 0;
6083 if (!(t & VT_ARRAY))
6084 r |= lvalue_type(t);
6085 if (b & VT_EXTERN) {
6086 /* external variable */
6087 external_sym(v, t, r);
6088 } else {
6089 if (t & VT_STATIC)
6090 r |= VT_CONST;
6091 else
6092 r |= l;
6093 has_init = (tok == '=');
6094 if (has_init)
6095 next();
6096 decl_initializer_alloc(t, &ad, r,
6097 has_init, v, l);
6100 if (tok != ',') {
6101 skip(';');
6102 break;
6104 next();
6110 /* compile the C file opened in 'file'. Return non zero if errors. */
6111 int tcc_compile(TCCState *s)
6113 Sym *define_start;
6114 char buf[512];
6116 funcname = "";
6117 include_stack_ptr = include_stack;
6118 ifdef_stack_ptr = ifdef_stack;
6120 vtop = vstack - 1;
6121 anon_sym = SYM_FIRST_ANOM;
6123 /* file info: full path + filename */
6124 if (do_debug) {
6125 getcwd(buf, sizeof(buf));
6126 pstrcat(buf, sizeof(buf), "/");
6127 put_stabs(buf, N_SO, 0, 0, (unsigned long)text_section->data_ptr);
6128 put_stabs(file->filename, N_SO, 0, 0,
6129 (unsigned long)text_section->data_ptr);
6131 /* define common 'char *' type because it is often used internally
6132 for arrays and struct dereference */
6133 char_pointer_type = mk_pointer(VT_BYTE);
6135 define_start = define_stack.top;
6136 inp();
6137 ch = '\n'; /* needed to parse correctly first preprocessor command */
6138 next();
6139 decl(VT_CONST);
6140 if (tok != -1)
6141 expect("declaration");
6143 /* end of translation unit info */
6144 if (do_debug) {
6145 put_stabn(N_SO, 0, 0, (unsigned long)text_section->data_ptr);
6148 /* reset define stack, but leave -Dsymbols (may be incorrect if
6149 they are undefined) */
6150 sym_pop(&define_stack, define_start);
6152 sym_pop(&global_stack, NULL);
6154 return 0;
6157 int tcc_compile_file(TCCState *s, const char *filename1)
6159 int ret;
6160 file = tcc_open(filename1);
6161 if (!file)
6162 error("file '%s' not found", filename1);
6163 ret = tcc_compile(s);
6164 tcc_close(file);
6165 return ret;
6168 int tcc_compile_string(TCCState *s, const char *str)
6170 BufferedFile bf1, *bf = &bf1;
6171 int ret;
6173 /* init file structure */
6174 bf->fd = -1;
6175 bf->buf_ptr = (char *)str;
6176 bf->buf_end = (char *)str + strlen(bf->buffer);
6177 pstrcpy(bf->filename, sizeof(bf->filename), "<string>");
6178 bf->line_num = 1;
6179 file = bf;
6181 ret = tcc_compile(s);
6183 /* currently, no need to close */
6184 return ret;
6187 /* define a symbol. A value can also be provided with the '=' operator */
6188 void tcc_define_symbol(TCCState *s, const char *sym, const char *value)
6190 BufferedFile bf1, *bf = &bf1;
6192 pstrcpy(bf->buffer, IO_BUF_SIZE, sym);
6193 pstrcat(bf->buffer, IO_BUF_SIZE, " ");
6194 /* default value */
6195 if (!value)
6196 value = "1";
6197 pstrcat(bf->buffer, IO_BUF_SIZE, value);
6199 /* init file structure */
6200 bf->fd = -1;
6201 bf->buf_ptr = bf->buffer;
6202 bf->buf_end = bf->buffer + strlen(bf->buffer);
6203 bf->filename[0] = '\0';
6204 bf->line_num = 1;
6205 file = bf;
6207 include_stack_ptr = include_stack;
6209 /* parse with define parser */
6210 inp();
6211 ch = '\n'; /* needed to parse correctly first preprocessor command */
6212 next_nomacro();
6213 parse_define();
6214 file = NULL;
6217 void tcc_undefine_symbol(TCCState *s1, const char *sym)
6219 TokenSym *ts;
6220 Sym *s;
6221 ts = tok_alloc(sym, 0);
6222 s = sym_find1(&define_stack, tok);
6223 /* undefine symbol by putting an invalid name */
6224 if (s)
6225 sym_undef(&define_stack, s);
6228 /* open a dynamic library so that its symbol are available for
6229 compiled programs */
6230 /* XXX: open the lib only to actually run the program */
6231 int tcc_add_dll(TCCState *s, const char *library_name)
6233 void *h;
6235 h = dlopen(library_name, RTLD_GLOBAL | RTLD_LAZY);
6236 if (!h)
6237 error((char *)dlerror());
6238 return 0;
6241 static int put_elf_str(Section *s, const char *sym)
6243 int c, offset;
6244 offset = s->data_ptr - s->data;
6245 for(;;) {
6246 c = *sym++;
6247 *s->data_ptr++ = c;
6248 if (c == '\0')
6249 break;
6251 return offset;
6254 /* elf symbol hashing function */
6255 static unsigned long elf_hash(const unsigned char *name)
6257 unsigned long h = 0, g;
6259 while (*name) {
6260 h = (h << 4) + *name++;
6261 g = h & 0xf0000000;
6262 if (g)
6263 h ^= g >> 24;
6264 h &= ~g;
6266 return h;
6269 /* return the symbol number */
6270 static int put_elf_sym(Section *s,
6271 unsigned long value, unsigned long size,
6272 int info, int other, int shndx, const char *name)
6274 int name_offset, nbuckets, h, sym_index;
6275 Elf32_Sym *sym;
6276 Section *hs;
6278 sym = (Elf32_Sym *)s->data_ptr;
6279 if (name)
6280 name_offset = put_elf_str(s->link, name);
6281 else
6282 name_offset = 0;
6283 /* XXX: endianness */
6284 sym->st_name = name_offset;
6285 sym->st_value = value;
6286 sym->st_size = size;
6287 sym->st_info = info;
6288 sym->st_other = other;
6289 sym->st_shndx = shndx;
6290 sym_index = sym - (Elf32_Sym *)s->data;
6291 hs = s->hash;
6292 if (hs && ELF32_ST_BIND(info) == STB_GLOBAL) {
6293 /* add another hashing entry */
6294 nbuckets = ((int *)hs->data)[0];
6295 ((int *)hs->data)[1]++;
6296 h = elf_hash(name) % nbuckets;
6297 ((int *)hs->data)[2 + nbuckets + sym_index] = ((int *)hs->data)[2 + h];
6298 ((int *)hs->data)[2 + h] = sym_index;
6300 s->data_ptr += sizeof(Elf32_Sym);
6301 return sym_index;
6304 /* find global ELF symbol 'name' and return its index. Return 0 if not
6305 found. */
6306 static int find_elf_sym(Section *s, const char *name)
6308 Elf32_Sym *sym;
6309 Section *hs;
6310 int nbuckets, sym_index, h;
6311 const char *name1;
6313 hs = s->hash;
6314 if (!hs)
6315 return 0;
6316 nbuckets = ((int *)hs->data)[0];
6317 h = elf_hash(name) % nbuckets;
6318 sym_index = ((int *)hs->data)[2 + h];
6319 while (sym_index != 0) {
6320 sym = &((Elf32_Sym *)s->data)[sym_index];
6321 name1 = s->link->data + sym->st_name;
6322 if (!strcmp(name, name1))
6323 return sym_index;
6324 sym_index = ((int *)hs->data)[2 + nbuckets + sym_index];
6326 return 0;
6329 /* update sym->c so that it points to an external symbol in section
6330 'section' with value 'value' */
6331 /* XXX: get rid of put_elf_sym */
6332 void put_extern_sym(Sym *sym, Section *section, unsigned long value)
6334 int sym_type, sym_bind, sh_num;
6335 Elf32_Sym *esym;
6336 const char *name;
6338 if (section)
6339 sh_num = section->sh_num;
6340 else
6341 sh_num = SHN_UNDEF;
6342 if (!sym->c) {
6343 if ((sym->t & VT_BTYPE) == VT_FUNC)
6344 sym_type = STT_FUNC;
6345 else
6346 sym_type = STT_OBJECT;
6347 if (sym->t & VT_STATIC)
6348 sym_bind = STB_LOCAL;
6349 else
6350 sym_bind = STB_GLOBAL;
6351 /* if the symbol is global, then we look if it is already
6352 defined */
6353 /* NOTE: name can be NULL if anonymous symbol */
6354 name = get_tok_str(sym->v, NULL);
6355 if (sym_bind == STB_GLOBAL) {
6356 sym->c = find_elf_sym(symtab_section, name);
6357 if (!sym->c)
6358 goto do_def;
6359 /* check if not defined */
6360 if (section) {
6361 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
6362 if (esym->st_shndx != SHN_UNDEF)
6363 error("'%s' defined twice", name);
6364 esym->st_shndx = sh_num;
6365 esym->st_value = value;
6367 } else {
6368 do_def:
6369 sym->c = put_elf_sym(symtab_section, value, 0,
6370 ELF32_ST_INFO(sym_bind, sym_type), 0,
6371 sh_num, name);
6373 } else {
6374 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
6375 esym->st_value = value;
6376 esym->st_shndx = sh_num;
6380 /* put relocation */
6381 static void put_elf_reloc(Section *s, unsigned long offset,
6382 int type, int symbol)
6384 char buf[256];
6385 Section *sr;
6386 Elf32_Rel *rel;
6388 sr = s->reloc;
6389 if (!sr) {
6390 /* if no relocation section, create it */
6391 snprintf(buf, sizeof(buf), ".rel%s", s->name);
6392 sr = new_section(buf, SHT_REL, 0);
6393 sr->sh_entsize = sizeof(Elf32_Rel);
6394 sr->link = symtab_section;
6395 sr->reloc_sec = s;
6396 s->reloc = sr;
6398 rel = (Elf32_Rel *)sr->data_ptr;
6399 /* XXX: endianness */
6400 rel->r_offset = offset;
6401 rel->r_info = ELF32_R_INFO(symbol, type);
6402 sr->data_ptr += sizeof(Elf32_Rel);
6405 /* put stab debug information */
6407 typedef struct {
6408 unsigned long n_strx; /* index into string table of name */
6409 unsigned char n_type; /* type of symbol */
6410 unsigned char n_other; /* misc info (usually empty) */
6411 unsigned short n_desc; /* description field */
6412 unsigned long n_value; /* value of symbol */
6413 } Stab_Sym;
6415 static void put_stabs(const char *str, int type, int other, int desc, int value)
6417 Stab_Sym *sym;
6419 sym = (Stab_Sym *)stab_section->data_ptr;
6420 if (str) {
6421 sym->n_strx = put_elf_str(stabstr_section, str);
6422 } else {
6423 sym->n_strx = 0;
6425 sym->n_type = type;
6426 sym->n_other = other;
6427 sym->n_desc = desc;
6428 sym->n_value = value;
6430 stab_section->data_ptr += sizeof(Stab_Sym);
6433 static void put_stabn(int type, int other, int desc, int value)
6435 put_stabs(NULL, type, other, desc, value);
6438 static void put_stabd(int type, int other, int desc)
6440 put_stabs(NULL, type, other, desc, 0);
6443 /* output an ELF file (currently, only for testing) */
6444 /* XXX: generate dynamic reloc info + DLL tables */
6445 /* XXX: generate startup code */
6446 /* XXX: better program header generation */
6447 /* XXX: handle realloc'ed sections (instead of mmaping them) */
6448 int tcc_output_file(TCCState *s, const char *filename, int file_type)
6450 Elf32_Ehdr ehdr;
6451 FILE *f;
6452 int shnum, i, phnum, file_offset, offset, size, j;
6453 Section *sec, *strsec;
6454 Elf32_Shdr *shdr, *sh;
6455 Elf32_Phdr *phdr, *ph;
6457 memset(&ehdr, 0, sizeof(ehdr));
6459 /* we add a section for symbols */
6460 strsec = new_section(".shstrtab", SHT_STRTAB, 0);
6461 put_elf_str(strsec, "");
6463 /* count number of sections and compute number of program segments */
6464 shnum = 1; /* section index zero is reserved */
6465 phnum = 0;
6466 for(sec = first_section; sec != NULL; sec = sec->next) {
6467 shnum++;
6468 if ((sec->sh_flags & SHF_ALLOC) &&
6469 file_type != TCC_FILE_OBJ)
6470 phnum++;
6472 /* allocate section headers */
6473 shdr = malloc(shnum * sizeof(Elf32_Shdr));
6474 if (!shdr)
6475 error("memory full");
6476 memset(shdr, 0, shnum * sizeof(Elf32_Shdr));
6478 /* allocate program segment headers */
6479 phdr = malloc(phnum * sizeof(Elf32_Phdr));
6480 if (!phdr)
6481 error("memory full");
6482 memset(phdr, 0, phnum * sizeof(Elf32_Phdr));
6484 /* XXX: find correct load order */
6485 file_offset = sizeof(Elf32_Ehdr) + phnum * sizeof(Elf32_Phdr);
6486 for(sec = first_section, i = 1; sec != NULL; sec = sec->next, i++) {
6487 sh = &shdr[i];
6488 sh->sh_name = put_elf_str(strsec, sec->name);
6489 sh->sh_type = sec->sh_type;
6490 sh->sh_flags = sec->sh_flags;
6491 sh->sh_entsize = sec->sh_entsize;
6492 if (sec->link)
6493 sh->sh_link = sec->link->sh_num;
6494 if (sec->reloc_sec)
6495 sh->sh_info = sec->reloc_sec->sh_num;
6496 if (sh->sh_type == SHT_STRTAB) {
6497 sh->sh_addralign = 1;
6498 } else if (sh->sh_type == SHT_SYMTAB ||
6499 (sh->sh_flags & SHF_ALLOC) == 0) {
6500 sh->sh_addralign = 4;
6501 } else {
6502 sh->sh_addr = (Elf32_Word)sec->data;
6503 sh->sh_addralign = 4096;
6505 sh->sh_size = (Elf32_Word)sec->data_ptr - (Elf32_Word)sec->data;
6506 /* align to section start */
6507 file_offset = (file_offset + sh->sh_addralign - 1) &
6508 ~(sh->sh_addralign - 1);
6509 sh->sh_offset = file_offset;
6510 file_offset += sh->sh_size;
6512 /* build program headers (simplistic - not fully correct) */
6513 if (phnum > 0) {
6514 j = 0;
6515 for(i=1;i<shnum;i++) {
6516 sh = &shdr[i];
6517 if (sh->sh_type == SHT_PROGBITS &&
6518 (sh->sh_flags & SHF_ALLOC) != 0) {
6519 ph = &phdr[j++];
6520 ph->p_type = PT_LOAD;
6521 ph->p_offset = sh->sh_offset;
6522 ph->p_vaddr = sh->sh_addr;
6523 ph->p_paddr = ph->p_vaddr;
6524 ph->p_filesz = sh->sh_size;
6525 ph->p_memsz = sh->sh_size;
6526 ph->p_flags = PF_R;
6527 if (sh->sh_flags & SHF_WRITE)
6528 ph->p_flags |= PF_W;
6529 if (sh->sh_flags & SHF_EXECINSTR)
6530 ph->p_flags |= PF_X;
6531 ph->p_align = sh->sh_addralign;
6536 /* align to 4 */
6537 file_offset = (file_offset + 3) & -4;
6539 /* fill header */
6540 ehdr.e_ident[0] = ELFMAG0;
6541 ehdr.e_ident[1] = ELFMAG1;
6542 ehdr.e_ident[2] = ELFMAG2;
6543 ehdr.e_ident[3] = ELFMAG3;
6544 ehdr.e_ident[4] = ELFCLASS32;
6545 ehdr.e_ident[5] = ELFDATA2LSB;
6546 ehdr.e_ident[6] = EV_CURRENT;
6547 switch(file_type) {
6548 default:
6549 case TCC_FILE_EXE:
6550 ehdr.e_type = ET_EXEC;
6551 break;
6552 case TCC_FILE_DLL:
6553 ehdr.e_type = ET_DYN;
6554 break;
6555 case TCC_FILE_OBJ:
6556 ehdr.e_type = ET_REL;
6557 break;
6559 ehdr.e_machine = EM_386;
6560 ehdr.e_version = EV_CURRENT;
6561 ehdr.e_entry = 0; /* XXX: patch it */
6562 ehdr.e_phoff = sizeof(Elf32_Ehdr);
6563 ehdr.e_shoff = file_offset;
6564 ehdr.e_ehsize = sizeof(Elf32_Ehdr);
6565 ehdr.e_phentsize = sizeof(Elf32_Phdr);
6566 ehdr.e_phnum = phnum;
6567 ehdr.e_shentsize = sizeof(Elf32_Shdr);
6568 ehdr.e_shnum = shnum;
6569 ehdr.e_shstrndx = shnum - 1;
6571 /* write elf file */
6572 f = fopen(filename, "w");
6573 if (!f)
6574 error("could not write '%s'", filename);
6575 fwrite(&ehdr, 1, sizeof(Elf32_Ehdr), f);
6576 fwrite(phdr, 1, phnum * sizeof(Elf32_Phdr), f);
6577 offset = sizeof(Elf32_Ehdr) + phnum * sizeof(Elf32_Phdr);
6578 for(sec = first_section, i = 1; sec != NULL; sec = sec->next, i++) {
6579 sh = &shdr[i];
6580 while (offset < sh->sh_offset) {
6581 fputc(0, f);
6582 offset++;
6584 size = sec->data_ptr - sec->data;
6585 fwrite(sec->data, 1, size, f);
6586 offset += size;
6588 while (offset < ehdr.e_shoff) {
6589 fputc(0, f);
6590 offset++;
6592 fwrite(shdr, 1, shnum * sizeof(Elf32_Shdr), f);
6593 fclose(f);
6595 free(shdr);
6596 free(phdr);
6597 return 0;
6600 /* print the position in the source file of PC value 'pc' by reading
6601 the stabs debug information */
6602 static void rt_printline(unsigned long wanted_pc)
6604 Stab_Sym *sym, *sym_end;
6605 char func_name[128];
6606 unsigned long func_addr, last_pc, pc;
6607 const char *incl_files[INCLUDE_STACK_SIZE];
6608 int incl_index, len, last_line_num, i;
6609 const char *str, *p;
6611 func_name[0] = '\0';
6612 func_addr = 0;
6613 incl_index = 0;
6614 last_pc = 0xffffffff;
6615 last_line_num = 1;
6616 sym = (Stab_Sym *)stab_section->data + 1;
6617 sym_end = (Stab_Sym *)stab_section->data_ptr;
6618 while (sym < sym_end) {
6619 switch(sym->n_type) {
6620 /* function start or end */
6621 case N_FUN:
6622 if (sym->n_strx == 0) {
6623 func_name[0] = '\0';
6624 func_addr = 0;
6625 } else {
6626 str = stabstr_section->data + sym->n_strx;
6627 p = strchr(str, ':');
6628 if (!p) {
6629 pstrcpy(func_name, sizeof(func_name), str);
6630 } else {
6631 len = p - str;
6632 if (len > sizeof(func_name) - 1)
6633 len = sizeof(func_name) - 1;
6634 memcpy(func_name, str, len);
6635 func_name[len] = '\0';
6637 func_addr = sym->n_value;
6639 break;
6640 /* line number info */
6641 case N_SLINE:
6642 pc = sym->n_value + func_addr;
6643 if (wanted_pc >= last_pc && wanted_pc < pc)
6644 goto found;
6645 last_pc = pc;
6646 last_line_num = sym->n_desc;
6647 break;
6648 /* include files */
6649 case N_BINCL:
6650 str = stabstr_section->data + sym->n_strx;
6651 add_incl:
6652 if (incl_index < INCLUDE_STACK_SIZE) {
6653 incl_files[incl_index++] = str;
6655 break;
6656 case N_EINCL:
6657 if (incl_index > 1)
6658 incl_index--;
6659 break;
6660 case N_SO:
6661 if (sym->n_strx == 0) {
6662 incl_index = 0; /* end of translation unit */
6663 } else {
6664 str = stabstr_section->data + sym->n_strx;
6665 /* do not add path */
6666 len = strlen(str);
6667 if (len > 0 && str[len - 1] != '/')
6668 goto add_incl;
6670 break;
6672 sym++;
6674 /* did not find line number info: */
6675 fprintf(stderr, "(no debug info, pc=0x%08lx): ", wanted_pc);
6676 return;
6677 found:
6678 for(i = 0; i < incl_index - 1; i++)
6679 fprintf(stderr, "In file included from %s\n",
6680 incl_files[i]);
6681 if (incl_index > 0) {
6682 fprintf(stderr, "%s:%d: ",
6683 incl_files[incl_index - 1], last_line_num);
6685 if (func_name[0] != '\0') {
6686 fprintf(stderr, "in function '%s()': ", func_name);
6690 /* emit a run time error at position 'pc' */
6691 void rt_error(unsigned long pc, const char *fmt, ...)
6693 va_list ap;
6694 va_start(ap, fmt);
6696 rt_printline(pc);
6697 vfprintf(stderr, fmt, ap);
6698 fprintf(stderr, "\n");
6699 exit(255);
6700 va_end(ap);
6703 #ifndef WIN32
6704 /* signal handler for fatal errors */
6705 static void sig_error(int signum, siginfo_t *siginf, void *puc)
6707 struct ucontext *uc = puc;
6708 unsigned long pc;
6710 #ifdef __i386__
6711 pc = uc->uc_mcontext.gregs[14];
6712 #else
6713 #error please put the right sigcontext field
6714 #endif
6716 switch(signum) {
6717 case SIGFPE:
6718 switch(siginf->si_code) {
6719 case FPE_INTDIV:
6720 case FPE_FLTDIV:
6721 rt_error(pc, "division by zero");
6722 break;
6723 default:
6724 rt_error(pc, "floating point exception");
6725 break;
6727 break;
6728 case SIGBUS:
6729 case SIGSEGV:
6730 rt_error(pc, "dereferencing invalid pointer");
6731 break;
6732 case SIGILL:
6733 rt_error(pc, "illegal instruction");
6734 break;
6735 case SIGABRT:
6736 rt_error(pc, "abort() called");
6737 break;
6738 default:
6739 rt_error(pc, "caught signal %d", signum);
6740 break;
6742 exit(255);
6744 #endif
6746 static void *resolve_sym(const char *sym)
6748 #ifdef CONFIG_TCC_BCHECK
6749 if (do_bounds_check) {
6750 void *ptr;
6751 ptr = bound_resolve_sym(sym);
6752 if (ptr)
6753 return ptr;
6755 #endif
6756 return dlsym(NULL, sym);
6759 static void resolve_extern_syms(void)
6761 unsigned long addr;
6762 Elf32_Sym *sym;
6763 const char *name;
6765 for(sym = (Elf32_Sym *)symtab_section->data + 1;
6766 sym < (Elf32_Sym *)symtab_section->data_ptr;
6767 sym++) {
6768 if (sym->st_shndx == SHN_UNDEF) {
6769 name = symtab_section->link->data + sym->st_name;
6770 addr = (unsigned long)resolve_sym(name);
6771 if (!addr)
6772 error("unresolved external reference '%s'", name);
6773 sym->st_value = addr;
6774 sym->st_shndx = SHN_ABS;
6779 static unsigned long get_sym_val(int sym_index)
6781 unsigned long val;
6782 Elf32_Sym *sym;
6784 sym = &((Elf32_Sym *)symtab_section->data)[sym_index];
6785 val = sym->st_value;
6786 if (sym->st_shndx != SHN_ABS)
6787 val += sections[sym->st_shndx]->addr;
6788 return val;
6791 /* relocate sections */
6792 static void relocate_section(Section *s)
6794 Section *sr;
6795 Elf32_Rel *rel;
6796 int type;
6797 unsigned char *ptr;
6798 unsigned long val;
6800 sr = s->reloc;
6801 if (!sr)
6802 return;
6803 for(rel = (Elf32_Rel *)sr->data;
6804 rel < (Elf32_Rel *)sr->data_ptr;
6805 rel++) {
6806 ptr = s->data + rel->r_offset;
6807 val = get_sym_val(ELF32_R_SYM(rel->r_info));
6808 type = ELF32_R_TYPE(rel->r_info);
6809 greloc_patch(ptr, s->addr + rel->r_offset, val, type);
6813 /* relocate all the code and data */
6814 static void relocate_program(void)
6816 Section *s;
6818 /* compute relocation address : section are relocated in place */
6819 for(s = first_section; s != NULL; s = s->next) {
6820 if (s->sh_type == SHT_PROGBITS)
6821 s->addr = (unsigned long)s->data;
6824 /* relocate each section */
6825 for(s = first_section; s != NULL; s = s->next) {
6826 if (s->sh_type == SHT_PROGBITS)
6827 relocate_section(s);
6831 /* launch the compiled program with the given arguments */
6832 int tcc_run(TCCState *s1, int argc, char **argv)
6834 int (*prog_main)(int, char **);
6835 int sym_index;
6837 resolve_extern_syms();
6839 relocate_program();
6841 sym_index = find_elf_sym(symtab_section, "main");
6842 if (!sym_index)
6843 error("main() not defined");
6844 prog_main = (void *)get_sym_val(sym_index);
6846 if (do_debug) {
6847 #ifdef WIN32
6848 error("debug mode currently not available for Windows");
6849 #else
6850 struct sigaction sigact;
6851 /* install TCC signal handlers to print debug info on fatal
6852 runtime errors */
6853 sigact.sa_flags = SA_SIGINFO | SA_ONESHOT;
6854 sigact.sa_sigaction = sig_error;
6855 sigemptyset(&sigact.sa_mask);
6856 sigaction(SIGFPE, &sigact, NULL);
6857 sigaction(SIGILL, &sigact, NULL);
6858 sigaction(SIGSEGV, &sigact, NULL);
6859 sigaction(SIGBUS, &sigact, NULL);
6860 sigaction(SIGABRT, &sigact, NULL);
6861 #endif
6864 #ifdef CONFIG_TCC_BCHECK
6865 if (do_bounds_check) {
6866 int *p, *p_end;
6867 __bound_init();
6868 /* add all known static regions */
6869 p = (int *)bounds_section->data;
6870 p_end = (int *)bounds_section->data_ptr;
6871 while (p < p_end) {
6872 __bound_new_region((void *)p[0], p[1]);
6873 p += 2;
6876 #endif
6878 return (*prog_main)(argc, argv);
6881 TCCState *tcc_new(void)
6883 char *p, *r;
6884 TCCState *s;
6886 s = malloc(sizeof(TCCState));
6887 if (!s)
6888 return NULL;
6890 /* default include paths */
6891 nb_include_paths = 0;
6892 tcc_add_include_path(s, "/usr/include");
6893 tcc_add_include_path(s, CONFIG_TCC_PREFIX "/lib/tcc/include");
6895 /* add all tokens */
6896 tok_ident = TOK_IDENT;
6897 p = tcc_keywords;
6898 while (*p) {
6899 r = p;
6900 while (*r++);
6901 tok_alloc(p, r - p - 1);
6902 p = r;
6905 /* standard defines */
6906 tcc_define_symbol(s, "__STDC__", NULL);
6907 #ifdef __i386__
6908 tcc_define_symbol(s, "__i386__", NULL);
6909 #endif
6910 /* tiny C specific defines */
6911 tcc_define_symbol(s, "__TINYC__", NULL);
6913 /* create standard sections */
6914 nb_sections = 1;
6915 text_section = new_section(".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
6916 data_section = new_section(".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
6917 /* XXX: should change type to SHT_NOBITS */
6918 bss_section = new_section(".bss", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
6920 /* symbols are always generated for linking stage */
6921 symtab_section = new_section(".symtab", SHT_SYMTAB, 0);
6922 symtab_section->sh_entsize = sizeof(Elf32_Sym);
6923 strtab_section = new_section(".strtab", SHT_STRTAB, 0);
6924 put_elf_str(strtab_section, "");
6925 symtab_section->link = strtab_section;
6926 put_elf_sym(symtab_section, 0, 0, 0, 0, 0, NULL);
6928 /* private hash table for extern symbols */
6929 hashtab_section = new_section(".hashtab", SHT_HASH, SHF_PRIVATE);
6930 ((int *)hashtab_section->data)[0] = ELF_SYM_HASH_SIZE;
6931 ((int *)hashtab_section->data)[1] = 1;
6932 hashtab_section->data_ptr += (2 + ELF_SYM_HASH_SIZE + 1) * 4;
6933 symtab_section->hash = hashtab_section;
6934 return s;
6937 void tcc_delete(TCCState *s)
6939 free(s);
6942 int tcc_add_include_path(TCCState *s, const char *pathname)
6944 char *pathname1;
6946 if (nb_include_paths >= INCLUDE_PATHS_MAX)
6947 return -1;
6948 pathname1 = strdup(pathname);
6949 if (!pathname1)
6950 return -1;
6951 include_paths[nb_include_paths++] = pathname1;
6952 return 0;
6955 #if !defined(LIBTCC)
6957 void help(void)
6959 printf("tcc version 0.9.8 - Tiny C Compiler - Copyright (C) 2001, 2002 Fabrice Bellard\n"
6960 "usage: tcc [-Idir] [-Dsym[=val]] [-Usym] [-llib] [-g] [-b]\n"
6961 " [-i infile] [-bench] infile [infile_args...]\n"
6962 "\n"
6963 "-Idir : add include path 'dir'\n"
6964 "-Dsym[=val] : define 'sym' with value 'val'\n"
6965 "-Usym : undefine 'sym'\n"
6966 "-llib : link with dynamic library 'lib'\n"
6967 "-g : generate runtime debug info\n"
6968 #ifdef CONFIG_TCC_BCHECK
6969 "-b : compile with built-in memory and bounds checker (implies -g)\n"
6970 #endif
6971 "-i infile : compile infile\n"
6972 "-bench : output compilation statistics\n"
6976 int main(int argc, char **argv)
6978 char *r, *outfile;
6979 int optind, file_type;
6980 TCCState *s;
6982 s = tcc_new();
6983 file_type = TCC_FILE_EXE;
6985 optind = 1;
6986 outfile = NULL;
6987 while (1) {
6988 if (optind >= argc) {
6989 show_help:
6990 help();
6991 return 1;
6993 r = argv[optind];
6994 if (r[0] != '-')
6995 break;
6996 optind++;
6997 if (r[1] == 'I') {
6998 if (tcc_add_include_path(s, r + 2) < 0)
6999 error("too many include paths");
7000 } else if (r[1] == 'D') {
7001 char *sym, *value;
7002 sym = r + 2;
7003 value = strchr(sym, '=');
7004 if (value) {
7005 *value = '\0';
7006 value++;
7008 tcc_define_symbol(s, sym, value);
7009 } else if (r[1] == 'U') {
7010 tcc_undefine_symbol(s, r + 2);
7011 } else if (r[1] == 'l') {
7012 char buf[1024];
7013 snprintf(buf, sizeof(buf), "lib%s.so", r + 2);
7014 tcc_add_dll(s, buf);
7015 } else if (r[1] == 'i') {
7016 if (optind >= argc)
7017 goto show_help;
7018 tcc_compile_file(s, argv[optind++]);
7019 } else if (!strcmp(r + 1, "bench")) {
7020 do_bench = 1;
7021 #ifdef CONFIG_TCC_BCHECK
7022 } else if (r[1] == 'b') {
7023 if (!do_bounds_check) {
7024 do_bounds_check = 1;
7025 /* define symbol */
7026 tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL);
7027 /* create bounds sections */
7028 bounds_section = new_section(".bounds",
7029 SHT_PROGBITS, SHF_ALLOC);
7030 lbounds_section = new_section(".lbounds",
7031 SHT_PROGBITS, SHF_ALLOC);
7032 /* debug is implied */
7033 goto debug_opt;
7035 #endif
7036 } else if (r[1] == 'g') {
7037 #ifdef CONFIG_TCC_BCHECK
7038 debug_opt:
7039 #endif
7040 if (!do_debug) {
7041 do_debug = 1;
7043 /* stab symbols */
7044 stab_section = new_section(".stab", SHT_PROGBITS, 0);
7045 stab_section->sh_entsize = sizeof(Stab_Sym);
7046 stabstr_section = new_section(".stabstr", SHT_STRTAB, 0);
7047 put_elf_str(stabstr_section, "");
7048 stab_section->link = stabstr_section;
7049 /* put first entry */
7050 put_stabs("", 0, 0, 0, 0);
7052 } else
7053 /* the following options are only for testing, so not
7054 documented */
7055 if (r[1] == 'c') {
7056 file_type = TCC_FILE_OBJ;
7057 } else if (!strcmp(r + 1, "shared")) {
7058 file_type = TCC_FILE_DLL;
7059 } else if (r[1] == 'o') {
7060 if (optind >= argc)
7061 goto show_help;
7062 outfile = argv[optind++];
7063 } else {
7064 error("invalid option -- '%s'", r);
7068 tcc_compile_file(s, argv[optind]);
7070 if (do_bench) {
7071 printf("total: %d idents, %d lines, %d bytes\n",
7072 tok_ident - TOK_IDENT, total_lines, total_bytes);
7075 if (outfile) {
7076 tcc_output_file(s, outfile, file_type);
7077 return 0;
7078 } else {
7079 return tcc_run(s, argc - optind, argv + optind);
7083 #endif