added object file reading support
[tinycc.git] / tcc.c
blobd6100c5199873d5677db012bb7bd0a19c20eeb84
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
78 #define ELF_DYNSYM_HASH_SIZE 32
80 /* token symbol management */
81 typedef struct TokenSym {
82 struct TokenSym *hash_next;
83 int tok; /* token number */
84 int len;
85 char str[1];
86 } TokenSym;
88 /* constant value */
89 typedef union CValue {
90 long double ld;
91 double d;
92 float f;
93 int i;
94 unsigned int ui;
95 unsigned int ul; /* address (should be unsigned long on 64 bit cpu) */
96 long long ll;
97 unsigned long long ull;
98 struct TokenSym *ts;
99 struct Sym *sym;
100 int tab[1];
101 } CValue;
103 /* value on stack */
104 typedef struct SValue {
105 int t; /* type */
106 unsigned short r; /* register + flags */
107 unsigned short r2; /* second register, used for 'long long'
108 type. If not used, set to VT_CONST */
109 CValue c; /* constant, if VT_CONST */
110 } SValue;
112 /* symbol management */
113 typedef struct Sym {
114 int v; /* symbol token */
115 int t; /* associated type */
116 int r; /* associated register */
117 int c; /* associated number */
118 struct Sym *next; /* next related symbol */
119 struct Sym *prev; /* prev symbol in stack */
120 struct Sym *hash_next; /* next symbol in hash table */
121 } Sym;
123 typedef struct SymStack {
124 struct Sym *top;
125 struct Sym *hash[SYM_HASH_SIZE];
126 } SymStack;
128 /* section definition */
129 /* XXX: use directly ELF structure for parameters ? */
130 /* special flag to indicate that the section should not be linked to
131 the other ones */
132 #define SHF_PRIVATE 0x80000000
134 typedef struct Section {
135 unsigned char *data; /* section data */
136 unsigned char *data_ptr; /* current data pointer */
137 int sh_name; /* elf section name (only used during output) */
138 int sh_num; /* elf section number */
139 int sh_type; /* elf section type */
140 int sh_flags; /* elf section flags */
141 int sh_info; /* elf section info */
142 int sh_addralign; /* elf section alignment */
143 int sh_entsize; /* elf entry size */
144 unsigned long sh_size; /* section size (only used during output) */
145 unsigned long sh_addr; /* address at which the section is relocated */
146 unsigned long sh_offset; /* address at which the section is relocated */
147 struct Section *link; /* link to another section */
148 struct Section *reloc; /* corresponding section for relocation, if any */
149 struct Section *hash; /* hash table for symbols */
150 struct Section *next;
151 char name[64]; /* section name */
152 } Section;
154 /* GNUC attribute definition */
155 typedef struct AttributeDef {
156 int aligned;
157 Section *section;
158 unsigned char func_call; /* FUNC_CDECL or FUNC_STDCALL */
159 } AttributeDef;
161 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
162 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
163 #define SYM_FIRST_ANOM (1 << (31 - VT_STRUCT_SHIFT)) /* first anonymous sym */
165 /* stored in 'Sym.c' field */
166 #define FUNC_NEW 1 /* ansi function prototype */
167 #define FUNC_OLD 2 /* old function prototype */
168 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
170 /* stored in 'Sym.r' field */
171 #define FUNC_CDECL 0 /* standard c call */
172 #define FUNC_STDCALL 1 /* pascal c call */
174 /* field 'Sym.t' for macros */
175 #define MACRO_OBJ 0 /* object like macro */
176 #define MACRO_FUNC 1 /* function like macro */
178 /* field 'Sym.t' for labels */
179 #define LABEL_FORWARD 1 /* label is forward defined */
181 /* type_decl() types */
182 #define TYPE_ABSTRACT 1 /* type without variable */
183 #define TYPE_DIRECT 2 /* type with variable */
185 #define IO_BUF_SIZE 8192
187 typedef struct BufferedFile {
188 unsigned char *buf_ptr;
189 unsigned char *buf_end;
190 int fd;
191 int line_num; /* current line number - here to simply code */
192 char filename[1024]; /* current filename - here to simply code */
193 unsigned char buffer[IO_BUF_SIZE + 1]; /* extra size for CH_EOB char */
194 } BufferedFile;
196 #define CH_EOB 0 /* end of buffer or '\0' char in file */
197 #define CH_EOF (-1) /* end of file */
199 /* parsing state (used to save parser state to reparse part of the
200 source several times) */
201 typedef struct ParseState {
202 int *macro_ptr;
203 int line_num;
204 int tok;
205 CValue tokc;
206 } ParseState;
208 /* used to record tokens */
209 typedef struct TokenString {
210 int *str;
211 int len;
212 int last_line_num;
213 } TokenString;
215 /* parser */
216 struct BufferedFile *file;
217 int ch, ch1, tok, tok1;
218 CValue tokc, tok1c;
220 /* sections */
221 /* XXX: suppress first_section */
222 Section *first_section, **sections;
223 int nb_sections; /* number of sections, including first dummy section */
224 int nb_allocated_sections;
225 Section *text_section, *data_section, *bss_section; /* predefined sections */
226 Section *cur_text_section; /* current section where function code is
227 generated */
228 /* bound check related sections */
229 Section *bounds_section; /* contains global data bound description */
230 Section *lbounds_section; /* contains local data bound description */
231 /* symbol sections */
232 Section *symtab_section, *strtab_section;
234 /* debug sections */
235 Section *stab_section, *stabstr_section;
237 /* loc : local variable index
238 ind : output code index
239 rsym: return symbol
240 anon_sym: anonymous symbol index
242 int rsym, anon_sym,
243 prog, ind, loc, const_wanted;
244 int global_expr; /* true if compound literals must be allocated
245 globally (used during initializers parsing */
246 int func_vt, func_vc; /* current function return type (used by
247 return instruction) */
248 int last_line_num, last_ind, func_ind; /* debug last line number and pc */
249 int tok_ident;
250 TokenSym **table_ident;
251 TokenSym *hash_ident[TOK_HASH_SIZE];
252 char token_buf[STRING_MAX_SIZE + 1];
253 char *funcname;
254 SymStack define_stack, global_stack, local_stack, label_stack;
256 SValue vstack[VSTACK_SIZE], *vtop;
257 int *macro_ptr, *macro_ptr_allocated;
258 BufferedFile *include_stack[INCLUDE_STACK_SIZE], **include_stack_ptr;
259 int ifdef_stack[IFDEF_STACK_SIZE], *ifdef_stack_ptr;
260 char *include_paths[INCLUDE_PATHS_MAX];
261 int nb_include_paths;
262 int char_pointer_type;
264 /* compile with debug symbol (and use them if error during execution) */
265 int do_debug = 0;
267 /* compile with built-in memory and bounds checker */
268 int do_bounds_check = 0;
270 /* display benchmark infos */
271 int do_bench = 0;
272 int total_lines;
273 int total_bytes;
275 /* use GNU C extensions */
276 int gnu_ext = 1;
278 /* use Tiny C extensions */
279 int tcc_ext = 1;
281 /* if true, static linking is performed */
282 int static_link = 0;
284 struct TCCState {
285 int dummy;
288 /* The current value can be: */
289 #define VT_VALMASK 0x00ff
290 #define VT_CONST 0x00f0 /* constant in vc
291 (must be first non register value) */
292 #define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */
293 #define VT_LOCAL 0x00f2 /* offset on stack */
294 #define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */
295 #define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */
296 #define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */
297 #define VT_LVAL 0x0100 /* var is an lvalue */
298 #define VT_SYM 0x0200 /* a symbol value is added */
299 #define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for
300 char/short stored in integer registers) */
301 #define VT_MUSTBOUND 0x0800 /* bound checking must be done before
302 dereferencing value */
303 #define VT_BOUNDED 0x8000 /* value is bounded. The address of the
304 bounding function call point is in vc */
305 #define VT_LVAL_BYTE 0x1000 /* lvalue is a byte */
306 #define VT_LVAL_SHORT 0x2000 /* lvalue is a short */
307 #define VT_LVAL_UNSIGNED 0x4000 /* lvalue is unsigned */
308 #define VT_LVAL_TYPE (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)
310 /* types */
311 #define VT_STRUCT_SHIFT 16 /* structure/enum name shift (16 bits left) */
313 #define VT_INT 0 /* integer type */
314 #define VT_BYTE 1 /* signed byte type */
315 #define VT_SHORT 2 /* short type */
316 #define VT_VOID 3 /* void type */
317 #define VT_PTR 4 /* pointer */
318 #define VT_ENUM 5 /* enum definition */
319 #define VT_FUNC 6 /* function type */
320 #define VT_STRUCT 7 /* struct/union definition */
321 #define VT_FLOAT 8 /* IEEE float */
322 #define VT_DOUBLE 9 /* IEEE double */
323 #define VT_LDOUBLE 10 /* IEEE long double */
324 #define VT_BOOL 11 /* ISOC99 boolean type */
325 #define VT_LLONG 12 /* 64 bit integer */
326 #define VT_LONG 13 /* long integer (NEVER USED as type, only
327 during parsing) */
328 #define VT_BTYPE 0x000f /* mask for basic type */
329 #define VT_UNSIGNED 0x0010 /* unsigned type */
330 #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
331 #define VT_BITFIELD 0x0040 /* bitfield modifier */
333 /* storage */
334 #define VT_EXTERN 0x00000080 /* extern definition */
335 #define VT_STATIC 0x00000100 /* static variable */
336 #define VT_TYPEDEF 0x00000200 /* typedef definition */
338 /* type mask (except storage) */
339 #define VT_TYPE (~(VT_EXTERN | VT_STATIC | VT_TYPEDEF))
341 /* token values */
343 /* warning: the following compare tokens depend on i386 asm code */
344 #define TOK_ULT 0x92
345 #define TOK_UGE 0x93
346 #define TOK_EQ 0x94
347 #define TOK_NE 0x95
348 #define TOK_ULE 0x96
349 #define TOK_UGT 0x97
350 #define TOK_LT 0x9c
351 #define TOK_GE 0x9d
352 #define TOK_LE 0x9e
353 #define TOK_GT 0x9f
355 #define TOK_LAND 0xa0
356 #define TOK_LOR 0xa1
358 #define TOK_DEC 0xa2
359 #define TOK_MID 0xa3 /* inc/dec, to void constant */
360 #define TOK_INC 0xa4
361 #define TOK_UDIV 0xb0 /* unsigned division */
362 #define TOK_UMOD 0xb1 /* unsigned modulo */
363 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
364 #define TOK_CINT 0xb3 /* number in tokc */
365 #define TOK_CCHAR 0xb4 /* char constant in tokc */
366 #define TOK_STR 0xb5 /* pointer to string in tokc */
367 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
368 #define TOK_LCHAR 0xb7
369 #define TOK_LSTR 0xb8
370 #define TOK_CFLOAT 0xb9 /* float constant */
371 #define TOK_LINENUM 0xba /* line number info */
372 #define TOK_CDOUBLE 0xc0 /* double constant */
373 #define TOK_CLDOUBLE 0xc1 /* long double constant */
374 #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
375 #define TOK_ADDC1 0xc3 /* add with carry generation */
376 #define TOK_ADDC2 0xc4 /* add with carry use */
377 #define TOK_SUBC1 0xc5 /* add with carry generation */
378 #define TOK_SUBC2 0xc6 /* add with carry use */
379 #define TOK_CUINT 0xc8 /* unsigned int constant */
380 #define TOK_CLLONG 0xc9 /* long long constant */
381 #define TOK_CULLONG 0xca /* unsigned long long constant */
382 #define TOK_ARROW 0xcb
383 #define TOK_DOTS 0xcc /* three dots */
384 #define TOK_SHR 0xcd /* unsigned shift right */
386 #define TOK_SHL 0x01 /* shift left */
387 #define TOK_SAR 0x02 /* signed shift right */
389 /* assignement operators : normal operator or 0x80 */
390 #define TOK_A_MOD 0xa5
391 #define TOK_A_AND 0xa6
392 #define TOK_A_MUL 0xaa
393 #define TOK_A_ADD 0xab
394 #define TOK_A_SUB 0xad
395 #define TOK_A_DIV 0xaf
396 #define TOK_A_XOR 0xde
397 #define TOK_A_OR 0xfc
398 #define TOK_A_SHL 0x81
399 #define TOK_A_SAR 0x82
401 #define TOK_EOF (-1) /* end of file */
403 /* all identificators and strings have token above that */
404 #define TOK_IDENT 256
406 enum {
407 TOK_INT = TOK_IDENT,
408 TOK_VOID,
409 TOK_CHAR,
410 TOK_IF,
411 TOK_ELSE,
412 TOK_WHILE,
413 TOK_BREAK,
414 TOK_RETURN,
415 TOK_FOR,
416 TOK_EXTERN,
417 TOK_STATIC,
418 TOK_UNSIGNED,
419 TOK_GOTO,
420 TOK_DO,
421 TOK_CONTINUE,
422 TOK_SWITCH,
423 TOK_CASE,
425 /* ignored types Must have contiguous values */
426 TOK_CONST,
427 TOK_VOLATILE,
428 TOK_LONG,
429 TOK_REGISTER,
430 TOK_SIGNED,
431 TOK___SIGNED__, /* gcc keyword */
432 TOK_AUTO,
433 TOK_INLINE,
434 TOK___INLINE__, /* gcc keyword */
435 TOK_RESTRICT,
437 /* unsupported type */
438 TOK_FLOAT,
439 TOK_DOUBLE,
440 TOK_BOOL,
442 TOK_SHORT,
443 TOK_STRUCT,
444 TOK_UNION,
445 TOK_TYPEDEF,
446 TOK_DEFAULT,
447 TOK_ENUM,
448 TOK_SIZEOF,
449 TOK___ATTRIBUTE__,
451 /* preprocessor only */
452 TOK_UIDENT, /* first "user" ident (not keyword) */
453 TOK_DEFINE = TOK_UIDENT,
454 TOK_INCLUDE,
455 TOK_IFDEF,
456 TOK_IFNDEF,
457 TOK_ELIF,
458 TOK_ENDIF,
459 TOK_DEFINED,
460 TOK_UNDEF,
461 TOK_ERROR,
462 TOK_LINE,
463 TOK___LINE__,
464 TOK___FILE__,
465 TOK___DATE__,
466 TOK___TIME__,
467 TOK___VA_ARGS__,
469 /* special identifiers */
470 TOK___FUNC__,
471 TOK_MAIN,
472 /* attribute identifiers */
473 TOK_SECTION,
474 TOK___SECTION__,
475 TOK_ALIGNED,
476 TOK___ALIGNED__,
477 TOK_UNUSED,
478 TOK___UNUSED__,
479 TOK_CDECL,
480 TOK___CDECL,
481 TOK___CDECL__,
482 TOK_STDCALL,
483 TOK___STDCALL,
484 TOK___STDCALL__,
485 TOK_NORETURN,
486 TOK___NORETURN__,
489 char *tcc_keywords =
490 "int\0void\0char\0if\0else\0while\0break\0return\0for\0extern\0static\0"
491 "unsigned\0goto\0do\0continue\0switch\0case\0const\0volatile\0long\0"
492 "register\0signed\0__signed__\0auto\0inline\0__inline__\0restrict\0"
493 "float\0double\0_Bool\0short\0struct\0union\0typedef\0default\0enum\0"
494 "sizeof\0__attribute__\0"
495 /* the following are not keywords. They are included to ease parsing */
496 "define\0include\0ifdef\0ifndef\0elif\0endif\0"
497 "defined\0undef\0error\0line\0"
498 "__LINE__\0__FILE__\0__DATE__\0__TIME__\0__VA_ARGS__\0"
499 "__func__\0main\0"
500 /* attributes */
501 "section\0__section__\0aligned\0__aligned__\0unused\0__unused__\0"
502 "cdecl\0__cdecl\0__cdecl__\0stdcall\0__stdcall\0__stdcall__\0"
503 "noreturn\0__noreturn__\0"
506 #ifdef WIN32
507 #define snprintf _snprintf
508 #endif
510 #if defined(WIN32) || defined(TCC_UCLIBC)
511 /* currently incorrect */
512 long double strtold(const char *nptr, char **endptr)
514 return (long double)strtod(nptr, endptr);
516 float strtof(const char *nptr, char **endptr)
518 return (float)strtod(nptr, endptr);
520 #else
521 /* XXX: need to define this to use them in non ISOC99 context */
522 extern float strtof (const char *__nptr, char **__endptr);
523 extern long double strtold (const char *__nptr, char **__endptr);
524 #endif
526 char *pstrcpy(char *buf, int buf_size, const char *s);
527 char *pstrcat(char *buf, int buf_size, const char *s);
529 void sum(int l);
530 void next(void);
531 void next_nomacro(void);
532 int expr_const(void);
533 void expr_eq(void);
534 void gexpr(void);
535 void decl(int l);
536 void decl_initializer(int t, Section *sec, unsigned long c, int first, int size_only);
537 void decl_initializer_alloc(int t, AttributeDef *ad, int r, int has_init,
538 int v, int scope);
539 int gv(int rc);
540 void gv2(int rc1, int rc2);
541 void move_reg(int r, int s);
542 void save_regs(int n);
543 void save_reg(int r);
544 void vpop(void);
545 void vswap(void);
546 void vdup(void);
547 int get_reg(int rc);
549 void macro_subst(TokenString *tok_str,
550 Sym **nested_list, int *macro_str);
551 int save_reg_forced(int r);
552 void gen_op(int op);
553 void force_charshort_cast(int t);
554 void gen_cast(int t);
555 void vstore(void);
556 Sym *sym_find(int v);
557 Sym *sym_push(int v, int t, int r, int c);
559 /* type handling */
560 int type_size(int t, int *a);
561 int pointed_type(int t);
562 int pointed_size(int t);
563 int is_compatible_types(int t1, int t2);
564 int parse_btype(int *type_ptr, AttributeDef *ad);
565 int type_decl(AttributeDef *ad, int *v, int t, int td);
567 void error(const char *fmt, ...);
568 void rt_error(unsigned long pc, const char *fmt, ...);
569 void vpushi(int v);
570 void vset(int t, int r, int v);
571 void type_to_str(char *buf, int buf_size,
572 int t, const char *varstr);
573 char *get_tok_str(int v, CValue *cv);
575 /* section generation */
576 void put_extern_sym(Sym *sym, Section *section, unsigned long value);
577 void greloc(Section *s, Sym *sym, unsigned long addr, int type);
578 static int put_elf_str(Section *s, const char *sym);
579 static int put_elf_sym(Section *s,
580 unsigned long value, unsigned long size,
581 int info, int other, int shndx, const char *name);
582 static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
583 int type, int symbol);
584 static void put_stabs(const char *str, int type, int other, int desc, int value);
585 static void put_stabn(int type, int other, int desc, int value);
586 static void put_stabd(int type, int other, int desc);
588 /* true if float/double/long double type */
589 static inline int is_float(int t)
591 int bt;
592 bt = t & VT_BTYPE;
593 return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT;
596 #ifdef CONFIG_TCC_BCHECK
597 #include "bcheck.c"
598 #endif
600 #ifdef TCC_TARGET_I386
601 #include "i386-gen.c"
602 #endif
603 #ifdef TCC_TARGET_IL
604 #include "il-gen.c"
605 #endif
607 #ifdef CONFIG_TCC_STATIC
609 #define RTLD_LAZY 0x001
610 #define RTLD_NOW 0x002
611 #define RTLD_GLOBAL 0x100
613 /* dummy function for profiling */
614 void *dlopen(const char *filename, int flag)
616 return NULL;
619 const char *dlerror(void)
621 return "error";
624 typedef struct TCCSyms {
625 char *str;
626 void *ptr;
627 } TCCSyms;
629 #define TCCSYM(a) { #a, &a, },
631 /* add the symbol you want here if no dynamic linking is done */
632 static TCCSyms tcc_syms[] = {
633 TCCSYM(printf)
634 TCCSYM(fprintf)
635 TCCSYM(fopen)
636 TCCSYM(fclose)
637 { NULL, NULL },
640 void *dlsym(void *handle, const char *symbol)
642 TCCSyms *p;
643 p = tcc_syms;
644 while (p->str != NULL) {
645 if (!strcmp(p->str, symbol))
646 return p->ptr;
647 p++;
649 return NULL;
652 #endif
654 /********************************************************/
655 /* runtime library is there */
656 /* XXX: we suppose that the host compiler handles 'long long'. It
657 would not be difficult to suppress this assumption */
659 long long __divll(long long a, long long b)
661 return a / b;
664 long long __modll(long long a, long long b)
666 return a % b;
669 unsigned long long __divull(unsigned long long a, unsigned long long b)
671 return a / b;
674 unsigned long long __modull(unsigned long long a, unsigned long long b)
676 return a % b;
679 long long __sardi3(long long a, int b)
681 return a >> b;
684 unsigned long long __shrdi3(unsigned long long a, int b)
686 return a >> b;
689 long long __shldi3(long long a, int b)
691 return a << b;
694 float __ulltof(unsigned long long a)
696 return (float)a;
699 double __ulltod(unsigned long long a)
701 return (double)a;
704 long double __ulltold(unsigned long long a)
706 return (long double)a;
709 unsigned long long __ftoull(float a)
711 return (unsigned long long)a;
714 unsigned long long __dtoull(double a)
716 return (unsigned long long)a;
719 unsigned long long __ldtoull(long double a)
721 return (unsigned long long)a;
725 /********************************************************/
727 /* we use our own 'finite' function to avoid potential problems with
728 non standard math libs */
729 /* XXX: endianness dependant */
730 int ieee_finite(double d)
732 int *p = (int *)&d;
733 return ((unsigned)((p[1] | 0x800fffff) + 1)) >> 31;
736 /* copy a string and truncate it. */
737 char *pstrcpy(char *buf, int buf_size, const char *s)
739 char *q, *q_end;
740 int c;
742 if (buf_size > 0) {
743 q = buf;
744 q_end = buf + buf_size - 1;
745 while (q < q_end) {
746 c = *s++;
747 if (c == '\0')
748 break;
749 *q++ = c;
751 *q = '\0';
753 return buf;
756 /* strcat and truncate. */
757 char *pstrcat(char *buf, int buf_size, const char *s)
759 int len;
760 len = strlen(buf);
761 if (len < buf_size)
762 pstrcpy(buf + len, buf_size - len, s);
763 return buf;
766 Section *new_section(const char *name, int sh_type, int sh_flags)
768 Section *sec, **psec;
769 void *data;
771 sec = malloc(sizeof(Section));
772 if (!sec)
773 error("memory full");
774 memset(sec, 0, sizeof(Section));
775 pstrcpy(sec->name, sizeof(sec->name), name);
776 sec->sh_type = sh_type;
777 sec->sh_flags = sh_flags;
778 switch(sh_type) {
779 case SHT_HASH:
780 case SHT_REL:
781 case SHT_DYNSYM:
782 case SHT_SYMTAB:
783 case SHT_DYNAMIC:
784 sec->sh_addralign = 4;
785 break;
786 case SHT_STRTAB:
787 sec->sh_addralign = 1;
788 break;
789 default:
790 sec->sh_addralign = 32; /* default conservative alignment */
791 break;
793 #ifdef WIN32
794 /* XXX: currently, a single malloc */
795 data = malloc(SECTION_VSIZE);
796 if (data == NULL)
797 error("could not alloc section '%s'", name);
798 #else
799 data = mmap(NULL, SECTION_VSIZE,
800 PROT_EXEC | PROT_READ | PROT_WRITE,
801 MAP_PRIVATE | MAP_ANONYMOUS,
802 -1, 0);
803 if (data == (void *)(-1))
804 error("could not mmap section '%s'", name);
805 #endif
806 sec->data = data;
807 sec->data_ptr = data;
809 if (!(sh_flags & SHF_PRIVATE)) {
810 /* only add section if not private */
812 psec = &first_section;
813 while (*psec != NULL)
814 psec = &(*psec)->next;
815 sec->next = NULL;
816 *psec = sec;
818 if ((nb_sections + 1) > nb_allocated_sections) {
819 if (nb_allocated_sections == 0)
820 nb_allocated_sections = 1;
821 nb_allocated_sections *= 2;
822 sections = realloc(sections,
823 nb_allocated_sections * sizeof(Section *));
824 if (!sections)
825 error("memory full");
827 sections[nb_sections] = sec;
828 sec->sh_num = nb_sections;
829 nb_sections++;
831 return sec;
834 /* return a reference to a section, and create it if it does not
835 exists */
836 Section *find_section(const char *name)
838 Section *sec;
840 for(sec = first_section; sec != NULL; sec = sec->next) {
841 if (!strcmp(name, sec->name))
842 return sec;
844 /* sections are created as PROGBITS */
845 return new_section(name, SHT_PROGBITS, SHF_ALLOC);
848 /* add a new relocation entry to symbol 'sym' in section 's' */
849 void greloc(Section *s, Sym *sym, unsigned long offset, int type)
851 if (!sym->c)
852 put_extern_sym(sym, NULL, 0);
853 /* now we can add ELF relocation info */
854 put_elf_reloc(symtab_section, s, offset, type, sym->c);
857 static inline int isid(int c)
859 return (c >= 'a' && c <= 'z') ||
860 (c >= 'A' && c <= 'Z') ||
861 c == '_';
864 static inline int isnum(int c)
866 return c >= '0' && c <= '9';
869 static inline int toup(int c)
871 if (ch >= 'a' && ch <= 'z')
872 return ch - 'a' + 'A';
873 else
874 return ch;
877 void printline(void)
879 BufferedFile **f;
880 if (file) {
881 for(f = include_stack; f < include_stack_ptr; f++)
882 fprintf(stderr, "In file included from %s:%d:\n",
883 (*f)->filename, (*f)->line_num);
884 fprintf(stderr, "%s:%d: ", file->filename, file->line_num);
885 } else {
886 fprintf(stderr, "tcc: ");
890 void error(const char *fmt, ...)
892 va_list ap;
893 va_start(ap, fmt);
894 printline();
895 vfprintf(stderr, fmt, ap);
896 fprintf(stderr, "\n");
897 exit(1);
898 va_end(ap);
901 void expect(const char *msg)
903 error("%s expected", msg);
906 void warning(const char *fmt, ...)
908 va_list ap;
910 va_start(ap, fmt);
911 printline();
912 fprintf(stderr, "warning: ");
913 vfprintf(stderr, fmt, ap);
914 fprintf(stderr, "\n");
915 va_end(ap);
918 void skip(int c)
920 if (tok != c)
921 error("'%c' expected", c);
922 next();
925 void test_lvalue(void)
927 if (!(vtop->r & VT_LVAL))
928 expect("lvalue");
931 TokenSym *tok_alloc(const char *str, int len)
933 TokenSym *ts, **pts, **ptable;
934 int h, i;
936 if (len <= 0)
937 len = strlen(str);
938 h = 1;
939 for(i=0;i<len;i++)
940 h = (h * 263 + ((unsigned char *)str)[i]) & (TOK_HASH_SIZE - 1);
942 pts = &hash_ident[h];
943 while (1) {
944 ts = *pts;
945 if (!ts)
946 break;
947 if (ts->len == len && !memcmp(ts->str, str, len))
948 return ts;
949 pts = &(ts->hash_next);
952 if (tok_ident >= SYM_FIRST_ANOM)
953 error("memory full");
955 /* expand token table if needed */
956 i = tok_ident - TOK_IDENT;
957 if ((i % TOK_ALLOC_INCR) == 0) {
958 ptable = realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *));
959 if (!ptable)
960 error("memory full");
961 table_ident = ptable;
964 ts = malloc(sizeof(TokenSym) + len);
965 if (!ts)
966 error("memory full");
967 table_ident[i] = ts;
968 ts->tok = tok_ident++;
969 ts->len = len;
970 ts->hash_next = NULL;
971 memcpy(ts->str, str, len + 1);
972 *pts = ts;
973 return ts;
976 void add_char(char **pp, int c)
978 char *p;
979 p = *pp;
980 if (c == '\'' || c == '\"' || c == '\\') {
981 /* XXX: could be more precise if char or string */
982 *p++ = '\\';
984 if (c >= 32 && c <= 126) {
985 *p++ = c;
986 } else {
987 *p++ = '\\';
988 if (c == '\n') {
989 *p++ = 'n';
990 } else {
991 *p++ = '0' + ((c >> 6) & 7);
992 *p++ = '0' + ((c >> 3) & 7);
993 *p++ = '0' + (c & 7);
996 *pp = p;
999 /* XXX: buffer overflow */
1000 char *get_tok_str(int v, CValue *cv)
1002 static char buf[STRING_MAX_SIZE + 1];
1003 TokenSym *ts;
1004 char *p;
1005 int i;
1007 if (v == TOK_CINT || v == TOK_CUINT) {
1008 sprintf(buf, "%u", cv->ui);
1009 return buf;
1010 } else if (v == TOK_CCHAR || v == TOK_LCHAR) {
1011 p = buf;
1012 *p++ = '\'';
1013 add_char(&p, cv->i);
1014 *p++ = '\'';
1015 *p = '\0';
1016 return buf;
1017 } else if (v == TOK_STR || v == TOK_LSTR) {
1018 ts = cv->ts;
1019 p = buf;
1020 *p++ = '\"';
1021 for(i=0;i<ts->len;i++)
1022 add_char(&p, ts->str[i]);
1023 *p++ = '\"';
1024 *p = '\0';
1025 return buf;
1026 } else if (v < TOK_IDENT) {
1027 p = buf;
1028 *p++ = v;
1029 *p = '\0';
1030 return buf;
1031 } else if (v < tok_ident) {
1032 return table_ident[v - TOK_IDENT]->str;
1033 } else if (v >= SYM_FIRST_ANOM) {
1034 /* special name for anonymous symbol */
1035 sprintf(buf, "L.%u", v - SYM_FIRST_ANOM);
1036 return buf;
1037 } else {
1038 /* should never happen */
1039 return NULL;
1043 /* push, without hashing */
1044 Sym *sym_push2(Sym **ps, int v, int t, int c)
1046 Sym *s;
1047 s = malloc(sizeof(Sym));
1048 if (!s)
1049 error("memory full");
1050 s->v = v;
1051 s->t = t;
1052 s->c = c;
1053 s->next = NULL;
1054 /* add in stack */
1055 s->prev = *ps;
1056 *ps = s;
1057 return s;
1060 /* find a symbol and return its associated structure. 's' is the top
1061 of the symbol stack */
1062 Sym *sym_find2(Sym *s, int v)
1064 while (s) {
1065 if (s->v == v)
1066 return s;
1067 s = s->prev;
1069 return NULL;
1072 #define HASH_SYM(v) ((unsigned)(v) % SYM_HASH_SIZE)
1074 /* find a symbol and return its associated structure. 'st' is the
1075 symbol stack */
1076 Sym *sym_find1(SymStack *st, int v)
1078 Sym *s;
1080 s = st->hash[HASH_SYM(v)];
1081 while (s) {
1082 if (s->v == v)
1083 return s;
1084 s = s->hash_next;
1086 return NULL;
1089 Sym *sym_push1(SymStack *st, int v, int t, int c)
1091 Sym *s, **ps;
1092 s = sym_push2(&st->top, v, t, c);
1093 /* add in hash table */
1094 if (v) {
1095 ps = &st->hash[HASH_SYM(v)];
1096 s->hash_next = *ps;
1097 *ps = s;
1099 return s;
1102 /* find a symbol in the right symbol space */
1103 Sym *sym_find(int v)
1105 Sym *s;
1106 s = sym_find1(&local_stack, v);
1107 if (!s)
1108 s = sym_find1(&global_stack, v);
1109 return s;
1112 /* push a given symbol on the symbol stack */
1113 Sym *sym_push(int v, int t, int r, int c)
1115 Sym *s;
1116 if (local_stack.top)
1117 s = sym_push1(&local_stack, v, t, c);
1118 else
1119 s = sym_push1(&global_stack, v, t, c);
1120 s->r = r;
1121 return s;
1124 /* pop symbols until top reaches 'b' */
1125 void sym_pop(SymStack *st, Sym *b)
1127 Sym *s, *ss;
1129 s = st->top;
1130 while(s != b) {
1131 ss = s->prev;
1132 /* free hash table entry, except if symbol was freed (only
1133 used for #undef symbols) */
1134 if (s->v)
1135 st->hash[HASH_SYM(s->v)] = s->hash_next;
1136 free(s);
1137 s = ss;
1139 st->top = b;
1142 /* undefined a hashed symbol (used for #undef). Its name is set to
1143 zero */
1144 void sym_undef(SymStack *st, Sym *s)
1146 Sym **ss;
1147 ss = &st->hash[HASH_SYM(s->v)];
1148 while (*ss != NULL) {
1149 if (*ss == s)
1150 break;
1151 ss = &(*ss)->hash_next;
1153 *ss = s->hash_next;
1154 s->v = 0;
1157 /* I/O layer */
1159 BufferedFile *tcc_open(const char *filename)
1161 int fd;
1162 BufferedFile *bf;
1164 fd = open(filename, O_RDONLY);
1165 if (fd < 0)
1166 return NULL;
1167 bf = malloc(sizeof(BufferedFile));
1168 if (!bf) {
1169 close(fd);
1170 return NULL;
1172 bf->fd = fd;
1173 bf->buf_ptr = bf->buffer;
1174 bf->buf_end = bf->buffer;
1175 bf->buffer[0] = CH_EOB; /* put eob symbol */
1176 pstrcpy(bf->filename, sizeof(bf->filename), filename);
1177 bf->line_num = 1;
1178 // printf("opening '%s'\n", filename);
1179 return bf;
1182 void tcc_close(BufferedFile *bf)
1184 total_lines += bf->line_num;
1185 close(bf->fd);
1186 free(bf);
1189 /* read one char. MUST call tcc_fillbuf if CH_EOB is read */
1190 #define TCC_GETC(bf) (*(bf)->buf_ptr++)
1192 /* fill input buffer and return next char */
1193 int tcc_getc_slow(BufferedFile *bf)
1195 int len;
1196 /* only tries to read if really end of buffer */
1197 if (bf->buf_ptr >= bf->buf_end) {
1198 if (bf->fd != -1) {
1199 len = read(bf->fd, bf->buffer, IO_BUF_SIZE);
1200 if (len < 0)
1201 len = 0;
1202 } else {
1203 len = 0;
1205 total_bytes += len;
1206 bf->buf_ptr = bf->buffer;
1207 bf->buf_end = bf->buffer + len;
1208 *bf->buf_end = CH_EOB;
1210 if (bf->buf_ptr < bf->buf_end) {
1211 return *bf->buf_ptr++;
1212 } else {
1213 bf->buf_ptr = bf->buf_end;
1214 return CH_EOF;
1218 /* no need to put that inline */
1219 void handle_eob(void)
1221 for(;;) {
1222 ch1 = tcc_getc_slow(file);
1223 if (ch1 != CH_EOF)
1224 return;
1226 if (include_stack_ptr == include_stack)
1227 return;
1228 /* add end of include file debug info */
1229 if (do_debug) {
1230 put_stabd(N_EINCL, 0, 0);
1232 /* pop include stack */
1233 tcc_close(file);
1234 include_stack_ptr--;
1235 file = *include_stack_ptr;
1239 /* read next char from current input file */
1240 static inline void inp(void)
1242 ch1 = TCC_GETC(file);
1243 /* end of buffer/file handling */
1244 if (ch1 == CH_EOB)
1245 handle_eob();
1246 if (ch1 == '\n')
1247 file->line_num++;
1248 // printf("ch1=%c 0x%x\n", ch1, ch1);
1251 /* input with '\\n' handling */
1252 static inline void minp(void)
1254 redo:
1255 ch = ch1;
1256 inp();
1257 if (ch == '\\' && ch1 == '\n') {
1258 inp();
1259 goto redo;
1261 //printf("ch=%c 0x%x\n", ch, ch);
1265 /* same as minp, but also skip comments */
1266 void cinp(void)
1268 int c;
1270 if (ch1 == '/') {
1271 inp();
1272 if (ch1 == '/') {
1273 /* single line C++ comments */
1274 inp();
1275 while (ch1 != '\n' && ch1 != -1)
1276 inp();
1277 inp();
1278 ch = ' '; /* return space */
1279 } else if (ch1 == '*') {
1280 /* C comments */
1281 inp();
1282 while (ch1 != -1) {
1283 c = ch1;
1284 inp();
1285 if (c == '*' && ch1 == '/') {
1286 inp();
1287 ch = ' '; /* return space */
1288 break;
1291 } else {
1292 ch = '/';
1294 } else {
1295 minp();
1299 void skip_spaces(void)
1301 while (ch == ' ' || ch == '\t')
1302 cinp();
1305 /* skip block of text until #else, #elif or #endif. skip also pairs of
1306 #if/#endif */
1307 void preprocess_skip(void)
1309 int a;
1310 a = 0;
1311 while (1) {
1312 while (ch != '\n') {
1313 if (ch == -1)
1314 expect("#endif");
1315 cinp();
1317 cinp();
1318 skip_spaces();
1319 if (ch == '#') {
1320 cinp();
1321 next_nomacro();
1322 if (a == 0 &&
1323 (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
1324 break;
1325 if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
1326 a++;
1327 else if (tok == TOK_ENDIF)
1328 a--;
1333 /* ParseState handling */
1335 /* XXX: currently, no include file info is stored. Thus, we cannot display
1336 accurate messages if the function or data definition spans multiple
1337 files */
1339 /* save current parse state in 's' */
1340 void save_parse_state(ParseState *s)
1342 s->line_num = file->line_num;
1343 s->macro_ptr = macro_ptr;
1344 s->tok = tok;
1345 s->tokc = tokc;
1348 /* restore parse state from 's' */
1349 void restore_parse_state(ParseState *s)
1351 file->line_num = s->line_num;
1352 macro_ptr = s->macro_ptr;
1353 tok = s->tok;
1354 tokc = s->tokc;
1357 /* return the number of additionnal 'ints' necessary to store the
1358 token */
1359 static inline int tok_ext_size(int t)
1361 switch(t) {
1362 /* 4 bytes */
1363 case TOK_CINT:
1364 case TOK_CUINT:
1365 case TOK_CCHAR:
1366 case TOK_LCHAR:
1367 case TOK_STR:
1368 case TOK_LSTR:
1369 case TOK_CFLOAT:
1370 case TOK_LINENUM:
1371 return 1;
1372 case TOK_CDOUBLE:
1373 case TOK_CLLONG:
1374 case TOK_CULLONG:
1375 return 2;
1376 case TOK_CLDOUBLE:
1377 return LDOUBLE_SIZE / 4;
1378 default:
1379 return 0;
1383 /* token string handling */
1385 static inline void tok_str_new(TokenString *s)
1387 s->str = NULL;
1388 s->len = 0;
1389 s->last_line_num = -1;
1392 static void tok_str_add(TokenString *s, int t)
1394 int len, *str;
1396 len = s->len;
1397 str = s->str;
1398 if ((len & 63) == 0) {
1399 str = realloc(str, (len + 64) * sizeof(int));
1400 if (!str)
1401 return;
1402 s->str = str;
1404 str[len++] = t;
1405 s->len = len;
1408 static void tok_str_add2(TokenString *s, int t, CValue *cv)
1410 int n, i;
1411 tok_str_add(s, t);
1412 n = tok_ext_size(t);
1413 for(i=0;i<n;i++)
1414 tok_str_add(s, cv->tab[i]);
1417 /* add the current parse token in token string 's' */
1418 static void tok_str_add_tok(TokenString *s)
1420 CValue cval;
1422 /* save line number info */
1423 if (file->line_num != s->last_line_num) {
1424 s->last_line_num = file->line_num;
1425 cval.i = s->last_line_num;
1426 tok_str_add2(s, TOK_LINENUM, &cval);
1428 tok_str_add2(s, tok, &tokc);
1431 /* get a token from an integer array and increment pointer accordingly */
1432 static int tok_get(int **tok_str, CValue *cv)
1434 int *p, t, n, i;
1436 p = *tok_str;
1437 t = *p++;
1438 n = tok_ext_size(t);
1439 for(i=0;i<n;i++)
1440 cv->tab[i] = *p++;
1441 *tok_str = p;
1442 return t;
1445 /* eval an expression for #if/#elif */
1446 int expr_preprocess(void)
1448 int c, t;
1449 TokenString str;
1451 tok_str_new(&str);
1452 while (1) {
1453 skip_spaces();
1454 if (ch == '\n')
1455 break;
1456 next(); /* do macro subst */
1457 if (tok == TOK_DEFINED) {
1458 next_nomacro();
1459 t = tok;
1460 if (t == '(')
1461 next_nomacro();
1462 c = sym_find1(&define_stack, tok) != 0;
1463 if (t == '(')
1464 next_nomacro();
1465 tok = TOK_CINT;
1466 tokc.i = c;
1467 } else if (tok >= TOK_IDENT) {
1468 /* if undefined macro */
1469 tok = TOK_CINT;
1470 tokc.i = 0;
1472 tok_str_add_tok(&str);
1474 tok_str_add(&str, -1); /* simulate end of file */
1475 tok_str_add(&str, 0);
1476 /* now evaluate C constant expression */
1477 macro_ptr = str.str;
1478 next();
1479 c = expr_const();
1480 macro_ptr = NULL;
1481 free(str.str);
1482 return c != 0;
1485 #if defined(DEBUG) || defined(PP_DEBUG)
1486 void tok_print(int *str)
1488 int t;
1489 CValue cval;
1491 while (1) {
1492 t = tok_get(&str, &cval);
1493 if (!t)
1494 break;
1495 printf(" %s", get_tok_str(t, &cval));
1497 printf("\n");
1499 #endif
1501 /* parse after #define */
1502 void parse_define(void)
1504 Sym *s, *first, **ps;
1505 int v, t, varg, is_vaargs;
1506 TokenString str;
1508 v = tok;
1509 /* XXX: should check if same macro (ANSI) */
1510 first = NULL;
1511 t = MACRO_OBJ;
1512 /* '(' must be just after macro definition for MACRO_FUNC */
1513 if (ch == '(') {
1514 next_nomacro();
1515 next_nomacro();
1516 ps = &first;
1517 while (tok != ')') {
1518 varg = tok;
1519 next_nomacro();
1520 is_vaargs = 0;
1521 if (varg == TOK_DOTS) {
1522 varg = TOK___VA_ARGS__;
1523 is_vaargs = 1;
1524 } else if (tok == TOK_DOTS && gnu_ext) {
1525 is_vaargs = 1;
1526 next_nomacro();
1528 if (varg < TOK_IDENT)
1529 error("badly punctuated parameter list");
1530 s = sym_push1(&define_stack, varg | SYM_FIELD, is_vaargs, 0);
1531 *ps = s;
1532 ps = &s->next;
1533 if (tok != ',')
1534 break;
1535 next_nomacro();
1537 t = MACRO_FUNC;
1539 tok_str_new(&str);
1540 while (1) {
1541 skip_spaces();
1542 if (ch == '\n' || ch == -1)
1543 break;
1544 next_nomacro();
1545 tok_str_add2(&str, tok, &tokc);
1547 tok_str_add(&str, 0);
1548 #ifdef PP_DEBUG
1549 printf("define %s %d: ", get_tok_str(v, NULL), t);
1550 tok_print(str);
1551 #endif
1552 s = sym_push1(&define_stack, v, t, (int)str.str);
1553 s->next = first;
1556 void preprocess(void)
1558 int size, i, c;
1559 char buf[1024], *q, *p;
1560 char buf1[1024];
1561 BufferedFile *f;
1562 Sym *s;
1564 cinp();
1565 next_nomacro();
1566 redo:
1567 if (tok == TOK_DEFINE) {
1568 next_nomacro();
1569 parse_define();
1570 } else if (tok == TOK_UNDEF) {
1571 next_nomacro();
1572 s = sym_find1(&define_stack, tok);
1573 /* undefine symbol by putting an invalid name */
1574 if (s)
1575 sym_undef(&define_stack, s);
1576 } else if (tok == TOK_INCLUDE) {
1577 skip_spaces();
1578 if (ch == '<') {
1579 c = '>';
1580 goto read_name;
1581 } else if (ch == '\"') {
1582 c = ch;
1583 read_name:
1584 minp();
1585 q = buf;
1586 while (ch != c && ch != '\n' && ch != -1) {
1587 if ((q - buf) < sizeof(buf) - 1)
1588 *q++ = ch;
1589 minp();
1591 *q = '\0';
1592 } else {
1593 next();
1594 if (tok != TOK_STR)
1595 error("#include syntax error");
1596 pstrcpy(buf, sizeof(buf), get_tok_str(tok, &tokc));
1597 c = '\"';
1599 /* eat all spaces and comments after include */
1600 /* XXX: slightly incorrect */
1601 while (ch1 != '\n' && ch1 != -1)
1602 inp();
1604 if (include_stack_ptr >= include_stack + INCLUDE_STACK_SIZE)
1605 error("memory full");
1606 if (c == '\"') {
1607 /* first search in current dir if "header.h" */
1608 size = 0;
1609 p = strrchr(file->filename, '/');
1610 if (p)
1611 size = p + 1 - file->filename;
1612 if (size > sizeof(buf1) - 1)
1613 size = sizeof(buf1) - 1;
1614 memcpy(buf1, file->filename, size);
1615 buf1[size] = '\0';
1616 pstrcat(buf1, sizeof(buf1), buf);
1617 f = tcc_open(buf1);
1618 if (f)
1619 goto found;
1621 /* now search in standard include path */
1622 for(i=nb_include_paths - 1;i>=0;i--) {
1623 strcpy(buf1, include_paths[i]);
1624 strcat(buf1, "/");
1625 strcat(buf1, buf);
1626 f = tcc_open(buf1);
1627 if (f)
1628 goto found;
1630 error("include file '%s' not found", buf);
1631 f = NULL;
1632 found:
1633 /* push current file in stack */
1634 /* XXX: fix current line init */
1635 *include_stack_ptr++ = file;
1636 file = f;
1637 /* add include file debug info */
1638 if (do_debug) {
1639 put_stabs(file->filename, N_BINCL, 0, 0, 0);
1641 } else if (tok == TOK_IFNDEF) {
1642 c = 1;
1643 goto do_ifdef;
1644 } else if (tok == TOK_IF) {
1645 c = expr_preprocess();
1646 goto do_if;
1647 } else if (tok == TOK_IFDEF) {
1648 c = 0;
1649 do_ifdef:
1650 next_nomacro();
1651 c = (sym_find1(&define_stack, tok) != 0) ^ c;
1652 do_if:
1653 if (ifdef_stack_ptr >= ifdef_stack + IFDEF_STACK_SIZE)
1654 error("memory full");
1655 *ifdef_stack_ptr++ = c;
1656 goto test_skip;
1657 } else if (tok == TOK_ELSE) {
1658 if (ifdef_stack_ptr == ifdef_stack)
1659 error("#else without matching #if");
1660 if (ifdef_stack_ptr[-1] & 2)
1661 error("#else after #else");
1662 c = (ifdef_stack_ptr[-1] ^= 3);
1663 goto test_skip;
1664 } else if (tok == TOK_ELIF) {
1665 if (ifdef_stack_ptr == ifdef_stack)
1666 error("#elif without matching #if");
1667 c = ifdef_stack_ptr[-1];
1668 if (c > 1)
1669 error("#elif after #else");
1670 /* last #if/#elif expression was true: we skip */
1671 if (c == 1)
1672 goto skip;
1673 c = expr_preprocess();
1674 ifdef_stack_ptr[-1] = c;
1675 test_skip:
1676 if (!(c & 1)) {
1677 skip:
1678 preprocess_skip();
1679 goto redo;
1681 } else if (tok == TOK_ENDIF) {
1682 if (ifdef_stack_ptr == ifdef_stack)
1683 error("#endif without matching #if");
1684 ifdef_stack_ptr--;
1685 } else if (tok == TOK_LINE) {
1686 next();
1687 if (tok != TOK_CINT)
1688 error("#line");
1689 file->line_num = tokc.i;
1690 skip_spaces();
1691 if (ch != '\n') {
1692 next();
1693 if (tok != TOK_STR)
1694 error("#line");
1695 pstrcpy(file->filename, sizeof(file->filename),
1696 get_tok_str(tok, &tokc));
1698 } else if (tok == TOK_ERROR) {
1699 error("#error");
1701 /* ignore other preprocess commands or #! for C scripts */
1702 while (ch != '\n' && ch != -1)
1703 cinp();
1706 /* read a number in base b */
1707 int getn(b)
1709 int n, t;
1710 n = 0;
1711 while (1) {
1712 if (ch >= 'a' && ch <= 'f')
1713 t = ch - 'a' + 10;
1714 else if (ch >= 'A' && ch <= 'F')
1715 t = ch - 'A' + 10;
1716 else if (isnum(ch))
1717 t = ch - '0';
1718 else
1719 break;
1720 if (t < 0 || t >= b)
1721 break;
1722 n = n * b + t;
1723 cinp();
1725 return n;
1728 /* read a character for string or char constant and eval escape codes */
1729 int getq()
1731 int c;
1733 c = ch;
1734 minp();
1735 if (c == '\\') {
1736 if (isnum(ch)) {
1737 /* at most three octal digits */
1738 c = ch - '0';
1739 minp();
1740 if (isnum(ch)) {
1741 c = c * 8 + ch - '0';
1742 minp();
1743 if (isnum(ch)) {
1744 c = c * 8 + ch - '0';
1745 minp();
1748 return c;
1749 } else if (ch == 'x') {
1750 minp();
1751 return getn(16);
1752 } else {
1753 if (ch == 'a')
1754 c = '\a';
1755 else if (ch == 'b')
1756 c = '\b';
1757 else if (ch == 'f')
1758 c = '\f';
1759 else if (ch == 'n')
1760 c = '\n';
1761 else if (ch == 'r')
1762 c = '\r';
1763 else if (ch == 't')
1764 c = '\t';
1765 else if (ch == 'v')
1766 c = '\v';
1767 else if (ch == 'e' && gnu_ext)
1768 c = 27;
1769 else if (ch == '\'' || ch == '\"' || ch == '\\' || ch == '?')
1770 c = ch;
1771 else
1772 error("invalid escaped char");
1773 minp();
1776 return c;
1779 /* we use 64 bit numbers */
1780 #define BN_SIZE 2
1782 /* bn = (bn << shift) | or_val */
1783 void bn_lshift(unsigned int *bn, int shift, int or_val)
1785 int i;
1786 unsigned int v;
1787 for(i=0;i<BN_SIZE;i++) {
1788 v = bn[i];
1789 bn[i] = (v << shift) | or_val;
1790 or_val = v >> (32 - shift);
1794 void bn_zero(unsigned int *bn)
1796 int i;
1797 for(i=0;i<BN_SIZE;i++) {
1798 bn[i] = 0;
1802 void parse_number(void)
1804 int b, t, shift, frac_bits, s, exp_val;
1805 char *q;
1806 unsigned int bn[BN_SIZE];
1807 double d;
1809 /* number */
1810 q = token_buf;
1811 t = ch;
1812 cinp();
1813 *q++ = t;
1814 b = 10;
1815 if (t == '.') {
1816 /* special dot handling */
1817 if (ch >= '0' && ch <= '9') {
1818 goto float_frac_parse;
1819 } else if (ch == '.') {
1820 cinp();
1821 if (ch != '.')
1822 expect("'.'");
1823 cinp();
1824 tok = TOK_DOTS;
1825 } else {
1826 /* dots */
1827 tok = t;
1829 return;
1830 } else if (t == '0') {
1831 if (ch == 'x' || ch == 'X') {
1832 q--;
1833 cinp();
1834 b = 16;
1835 } else if (tcc_ext && (ch == 'b' || ch == 'B')) {
1836 q--;
1837 cinp();
1838 b = 2;
1841 /* parse all digits. cannot check octal numbers at this stage
1842 because of floating point constants */
1843 while (1) {
1844 if (ch >= 'a' && ch <= 'f')
1845 t = ch - 'a' + 10;
1846 else if (ch >= 'A' && ch <= 'F')
1847 t = ch - 'A' + 10;
1848 else if (isnum(ch))
1849 t = ch - '0';
1850 else
1851 break;
1852 if (t >= b)
1853 break;
1854 if (q >= token_buf + STRING_MAX_SIZE) {
1855 num_too_long:
1856 error("number too long");
1858 *q++ = ch;
1859 cinp();
1861 if (ch == '.' ||
1862 ((ch == 'e' || ch == 'E') && b == 10) ||
1863 ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
1864 if (b != 10) {
1865 /* NOTE: strtox should support that for hexa numbers, but
1866 non ISOC99 libcs do not support it, so we prefer to do
1867 it by hand */
1868 /* hexadecimal or binary floats */
1869 /* XXX: handle overflows */
1870 *q = '\0';
1871 if (b == 16)
1872 shift = 4;
1873 else
1874 shift = 2;
1875 bn_zero(bn);
1876 q = token_buf;
1877 while (1) {
1878 t = *q++;
1879 if (t == '\0') {
1880 break;
1881 } else if (t >= 'a') {
1882 t = t - 'a' + 10;
1883 } else if (t >= 'A') {
1884 t = t - 'A' + 10;
1885 } else {
1886 t = t - '0';
1888 bn_lshift(bn, shift, t);
1890 frac_bits = 0;
1891 if (ch == '.') {
1892 cinp();
1893 while (1) {
1894 t = ch;
1895 if (t >= 'a' && t <= 'f') {
1896 t = t - 'a' + 10;
1897 } else if (t >= 'A' && t <= 'F') {
1898 t = t - 'A' + 10;
1899 } else if (t >= '0' && t <= '9') {
1900 t = t - '0';
1901 } else {
1902 break;
1904 if (t >= b)
1905 error("invalid digit");
1906 bn_lshift(bn, shift, t);
1907 frac_bits += shift;
1908 cinp();
1911 if (ch != 'p' && ch != 'P')
1912 error("exponent expected");
1913 cinp();
1914 s = 1;
1915 exp_val = 0;
1916 if (ch == '+') {
1917 cinp();
1918 } else if (ch == '-') {
1919 s = -1;
1920 cinp();
1922 if (ch < '0' || ch > '9')
1923 error("exponent digits expected");
1924 while (ch >= '0' && ch <= '9') {
1925 exp_val = exp_val * 10 + ch - '0';
1926 cinp();
1928 exp_val = exp_val * s;
1930 /* now we can generate the number */
1931 /* XXX: should patch directly float number */
1932 d = (double)bn[1] * 4294967296.0 + (double)bn[0];
1933 d = ldexp(d, exp_val - frac_bits);
1934 t = toup(ch);
1935 if (t == 'F') {
1936 cinp();
1937 tok = TOK_CFLOAT;
1938 /* float : should handle overflow */
1939 tokc.f = (float)d;
1940 } else if (t == 'L') {
1941 cinp();
1942 tok = TOK_CLDOUBLE;
1943 /* XXX: not large enough */
1944 tokc.ld = (long double)d;
1945 } else {
1946 tok = TOK_CDOUBLE;
1947 tokc.d = d;
1949 } else {
1950 /* decimal floats */
1951 if (ch == '.') {
1952 if (q >= token_buf + STRING_MAX_SIZE)
1953 goto num_too_long;
1954 *q++ = ch;
1955 cinp();
1956 float_frac_parse:
1957 while (ch >= '0' && ch <= '9') {
1958 if (q >= token_buf + STRING_MAX_SIZE)
1959 goto num_too_long;
1960 *q++ = ch;
1961 cinp();
1964 if (ch == 'e' || ch == 'E') {
1965 if (q >= token_buf + STRING_MAX_SIZE)
1966 goto num_too_long;
1967 *q++ = ch;
1968 cinp();
1969 if (ch == '-' || ch == '+') {
1970 if (q >= token_buf + STRING_MAX_SIZE)
1971 goto num_too_long;
1972 *q++ = ch;
1973 cinp();
1975 if (ch < '0' || ch > '9')
1976 error("exponent digits expected");
1977 while (ch >= '0' && ch <= '9') {
1978 if (q >= token_buf + STRING_MAX_SIZE)
1979 goto num_too_long;
1980 *q++ = ch;
1981 cinp();
1984 *q = '\0';
1985 t = toup(ch);
1986 errno = 0;
1987 if (t == 'F') {
1988 cinp();
1989 tok = TOK_CFLOAT;
1990 tokc.f = strtof(token_buf, NULL);
1991 } else if (t == 'L') {
1992 cinp();
1993 tok = TOK_CLDOUBLE;
1994 tokc.ld = strtold(token_buf, NULL);
1995 } else {
1996 tok = TOK_CDOUBLE;
1997 tokc.d = strtod(token_buf, NULL);
2000 } else {
2001 unsigned long long n, n1;
2002 int lcount;
2004 /* integer number */
2005 *q = '\0';
2006 q = token_buf;
2007 if (b == 10 && *q == '0') {
2008 b = 8;
2009 q++;
2011 n = 0;
2012 while(1) {
2013 t = *q++;
2014 /* no need for checks except for base 10 / 8 errors */
2015 if (t == '\0') {
2016 break;
2017 } else if (t >= 'a') {
2018 t = t - 'a' + 10;
2019 } else if (t >= 'A') {
2020 t = t - 'A' + 10;
2021 } else {
2022 t = t - '0';
2023 if (t >= b)
2024 error("invalid digit");
2026 n1 = n;
2027 n = n * b + t;
2028 /* detect overflow */
2029 if (n < n1)
2030 error("integer constant overflow");
2033 /* XXX: not exactly ANSI compliant */
2034 if ((n & 0xffffffff00000000LL) != 0) {
2035 if ((n >> 63) != 0)
2036 tok = TOK_CULLONG;
2037 else
2038 tok = TOK_CLLONG;
2039 } else if (n > 0x7fffffff) {
2040 tok = TOK_CUINT;
2041 } else {
2042 tok = TOK_CINT;
2044 lcount = 0;
2045 for(;;) {
2046 t = toup(ch);
2047 if (t == 'L') {
2048 if (lcount >= 2)
2049 error("three 'l' in integer constant");
2050 lcount++;
2051 if (lcount == 2) {
2052 if (tok == TOK_CINT)
2053 tok = TOK_CLLONG;
2054 else if (tok == TOK_CUINT)
2055 tok = TOK_CULLONG;
2057 cinp();
2058 } else if (t == 'U') {
2059 if (tok == TOK_CINT)
2060 tok = TOK_CUINT;
2061 else if (tok == TOK_CLLONG)
2062 tok = TOK_CULLONG;
2063 cinp();
2064 } else {
2065 break;
2068 if (tok == TOK_CINT || tok == TOK_CUINT)
2069 tokc.ui = n;
2070 else
2071 tokc.ull = n;
2076 /* return next token without macro substitution */
2077 void next_nomacro1(void)
2079 int b;
2080 char *q;
2081 TokenSym *ts;
2083 /* skip spaces */
2084 while(1) {
2085 while (ch == '\n') {
2086 cinp();
2087 while (ch == ' ' || ch == '\t')
2088 cinp();
2089 if (ch == '#') {
2090 /* preprocessor command if # at start of line after
2091 spaces */
2092 preprocess();
2095 if (ch != ' ' && ch != '\t' && ch != '\f')
2096 break;
2097 cinp();
2099 if (isid(ch)) {
2100 q = token_buf;
2101 *q++ = ch;
2102 cinp();
2103 if (q[-1] == 'L') {
2104 if (ch == '\'') {
2105 tok = TOK_LCHAR;
2106 goto char_const;
2108 if (ch == '\"') {
2109 tok = TOK_LSTR;
2110 goto str_const;
2113 while (isid(ch) || isnum(ch)) {
2114 if (q >= token_buf + STRING_MAX_SIZE)
2115 error("ident too long");
2116 *q++ = ch;
2117 cinp();
2119 *q = '\0';
2120 ts = tok_alloc(token_buf, q - token_buf);
2121 tok = ts->tok;
2122 } else if (isnum(ch) || ch == '.') {
2123 parse_number();
2124 } else if (ch == '\'') {
2125 tok = TOK_CCHAR;
2126 char_const:
2127 minp();
2128 tokc.i = getq();
2129 if (ch != '\'')
2130 expect("\'");
2131 minp();
2132 } else if (ch == '\"') {
2133 tok = TOK_STR;
2134 str_const:
2135 minp();
2136 q = token_buf;
2137 while (ch != '\"') {
2138 b = getq();
2139 if (ch == -1)
2140 error("unterminated string");
2141 if (q >= token_buf + STRING_MAX_SIZE)
2142 error("string too long");
2143 *q++ = b;
2145 *q = '\0';
2146 tokc.ts = tok_alloc(token_buf, q - token_buf);
2147 minp();
2148 } else {
2149 q = "<=\236>=\235!=\225&&\240||\241++\244--\242==\224<<\1>>\2+=\253-=\255*=\252/=\257%=\245&=\246^=\336|=\374->\313..\250##\266";
2150 /* two chars */
2151 tok = ch;
2152 cinp();
2153 while (*q) {
2154 if (*q == tok && q[1] == ch) {
2155 cinp();
2156 tok = q[2] & 0xff;
2157 /* three chars tests */
2158 if (tok == TOK_SHL || tok == TOK_SAR) {
2159 if (ch == '=') {
2160 tok = tok | 0x80;
2161 cinp();
2163 } else if (tok == TOK_DOTS) {
2164 if (ch != '.')
2165 error("parse error");
2166 cinp();
2168 return;
2170 q = q + 3;
2172 /* single char substitutions */
2173 if (tok == '<')
2174 tok = TOK_LT;
2175 else if (tok == '>')
2176 tok = TOK_GT;
2180 /* return next token without macro substitution. Can read input from
2181 macro_ptr buffer */
2182 void next_nomacro()
2184 if (macro_ptr) {
2185 redo:
2186 tok = *macro_ptr;
2187 if (tok) {
2188 tok = tok_get(&macro_ptr, &tokc);
2189 if (tok == TOK_LINENUM) {
2190 file->line_num = tokc.i;
2191 goto redo;
2194 } else {
2195 next_nomacro1();
2199 /* substitute args in macro_str and return allocated string */
2200 int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
2202 int *st, last_tok, t, notfirst;
2203 Sym *s;
2204 TokenSym *ts;
2205 CValue cval;
2206 TokenString str;
2208 tok_str_new(&str);
2209 last_tok = 0;
2210 while(1) {
2211 t = tok_get(&macro_str, &cval);
2212 if (!t)
2213 break;
2214 if (t == '#') {
2215 /* stringize */
2216 t = tok_get(&macro_str, &cval);
2217 if (!t)
2218 break;
2219 s = sym_find2(args, t);
2220 if (s) {
2221 token_buf[0] = '\0';
2222 st = (int *)s->c;
2223 notfirst = 0;
2224 while (*st) {
2225 if (notfirst)
2226 pstrcat(token_buf, sizeof(token_buf), " ");
2227 t = tok_get(&st, &cval);
2228 pstrcat(token_buf, sizeof(token_buf), get_tok_str(t, &cval));
2229 notfirst = 1;
2231 #ifdef PP_DEBUG
2232 printf("stringize: %s\n", token_buf);
2233 #endif
2234 /* add string */
2235 ts = tok_alloc(token_buf, 0);
2236 cval.ts = ts;
2237 tok_str_add2(&str, TOK_STR, &cval);
2238 } else {
2239 tok_str_add2(&str, t, &cval);
2241 } else if (t >= TOK_IDENT) {
2242 s = sym_find2(args, t);
2243 if (s) {
2244 st = (int *)s->c;
2245 /* if '##' is present before or after, no arg substitution */
2246 if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) {
2247 /* special case for var arg macros : ## eats the
2248 ',' if empty VA_ARGS riable. */
2249 /* XXX: test of the ',' is not 100%
2250 reliable. should fix it to avoid security
2251 problems */
2252 if (gnu_ext && s->t && *st == 0 &&
2253 last_tok == TOK_TWOSHARPS &&
2254 str.len >= 2&& str.str[str.len - 2] == ',') {
2255 /* suppress ',' '##' */
2256 str.len -= 2;
2257 } else {
2258 while (*st)
2259 tok_str_add(&str, *st++);
2261 } else {
2262 macro_subst(&str, nested_list, st);
2264 } else {
2265 tok_str_add(&str, t);
2267 } else {
2268 tok_str_add2(&str, t, &cval);
2270 last_tok = t;
2272 tok_str_add(&str, 0);
2273 return str.str;
2276 /* handle the '##' operator */
2277 int *macro_twosharps(int *macro_str)
2279 TokenSym *ts;
2280 int *macro_ptr1;
2281 int t;
2282 char *p;
2283 CValue cval;
2284 TokenString macro_str1;
2286 tok_str_new(&macro_str1);
2287 tok = 0;
2288 while (1) {
2289 next_nomacro();
2290 if (tok == 0)
2291 break;
2292 while (*macro_ptr == TOK_TWOSHARPS) {
2293 macro_ptr++;
2294 macro_ptr1 = macro_ptr;
2295 t = *macro_ptr;
2296 if (t) {
2297 t = tok_get(&macro_ptr, &cval);
2298 /* XXX: we handle only most common cases:
2299 ident + ident or ident + number */
2300 if (tok >= TOK_IDENT &&
2301 (t >= TOK_IDENT || t == TOK_CINT)) {
2302 p = get_tok_str(tok, &tokc);
2303 pstrcpy(token_buf, sizeof(token_buf), p);
2304 p = get_tok_str(t, &cval);
2305 pstrcat(token_buf, sizeof(token_buf), p);
2306 ts = tok_alloc(token_buf, 0);
2307 tok = ts->tok; /* modify current token */
2308 } else {
2309 /* cannot merge tokens: skip '##' */
2310 macro_ptr = macro_ptr1;
2311 break;
2315 tok_str_add2(&macro_str1, tok, &tokc);
2317 tok_str_add(&macro_str1, 0);
2318 return macro_str1.str;
2321 /* do macro substitution of macro_str and add result to
2322 (tok_str,tok_len). If macro_str is NULL, then input stream token is
2323 substituted. 'nested_list' is the list of all macros we got inside
2324 to avoid recursing. */
2325 void macro_subst(TokenString *tok_str,
2326 Sym **nested_list, int *macro_str)
2328 Sym *s, *args, *sa, *sa1;
2329 int parlevel, *mstr, t, *saved_macro_ptr;
2330 int mstr_allocated, *macro_str1;
2331 CValue cval;
2332 TokenString str;
2334 saved_macro_ptr = macro_ptr;
2335 macro_ptr = macro_str;
2336 macro_str1 = NULL;
2337 if (macro_str) {
2338 /* first scan for '##' operator handling */
2339 macro_str1 = macro_twosharps(macro_str);
2340 macro_ptr = macro_str1;
2343 while (1) {
2344 next_nomacro();
2345 if (tok == 0)
2346 break;
2347 /* special macros */
2348 if (tok == TOK___LINE__) {
2349 cval.i = file->line_num;
2350 tok_str_add2(tok_str, TOK_CINT, &cval);
2351 } else if (tok == TOK___FILE__) {
2352 cval.ts = tok_alloc(file->filename, 0);
2353 tok_str_add2(tok_str, TOK_STR, &cval);
2354 } else if (tok == TOK___DATE__) {
2355 cval.ts = tok_alloc("Jan 1 1970", 0);
2356 tok_str_add2(tok_str, TOK_STR, &cval);
2357 } else if (tok == TOK___TIME__) {
2358 cval.ts = tok_alloc("00:00:00", 0);
2359 tok_str_add2(tok_str, TOK_STR, &cval);
2360 } else if ((s = sym_find1(&define_stack, tok)) != NULL) {
2361 /* if symbol is a macro, prepare substitution */
2362 /* if nested substitution, do nothing */
2363 if (sym_find2(*nested_list, tok))
2364 goto no_subst;
2365 mstr = (int *)s->c;
2366 mstr_allocated = 0;
2367 if (s->t == MACRO_FUNC) {
2368 /* NOTE: we do not use next_nomacro to avoid eating the
2369 next token. XXX: find better solution */
2370 if (macro_ptr) {
2371 t = *macro_ptr;
2372 } else {
2373 while (ch == ' ' || ch == '\t' || ch == '\n')
2374 cinp();
2375 t = ch;
2377 if (t != '(') /* no macro subst */
2378 goto no_subst;
2380 /* argument macro */
2381 next_nomacro();
2382 next_nomacro();
2383 args = NULL;
2384 sa = s->next;
2385 /* NOTE: empty args are allowed, except if no args */
2386 for(;;) {
2387 /* handle '()' case */
2388 if (!args && tok == ')')
2389 break;
2390 if (!sa)
2391 error("macro '%s' used with too many args",
2392 get_tok_str(s->v, 0));
2393 tok_str_new(&str);
2394 parlevel = 0;
2395 /* NOTE: non zero sa->t indicates VA_ARGS */
2396 while ((parlevel > 0 ||
2397 (tok != ')' &&
2398 (tok != ',' || sa->t))) &&
2399 tok != -1) {
2400 if (tok == '(')
2401 parlevel++;
2402 else if (tok == ')')
2403 parlevel--;
2404 tok_str_add2(&str, tok, &tokc);
2405 next_nomacro();
2407 tok_str_add(&str, 0);
2408 sym_push2(&args, sa->v & ~SYM_FIELD, sa->t, (int)str.str);
2409 sa = sa->next;
2410 if (tok == ')') {
2411 /* special case for gcc var args: add an empty
2412 var arg argument if it is omitted */
2413 if (sa && sa->t && gnu_ext)
2414 continue;
2415 else
2416 break;
2418 if (tok != ',')
2419 expect(",");
2420 next_nomacro();
2422 if (sa) {
2423 error("macro '%s' used with too few args",
2424 get_tok_str(s->v, 0));
2427 /* now subst each arg */
2428 mstr = macro_arg_subst(nested_list, mstr, args);
2429 /* free memory */
2430 sa = args;
2431 while (sa) {
2432 sa1 = sa->prev;
2433 free((int *)sa->c);
2434 free(sa);
2435 sa = sa1;
2437 mstr_allocated = 1;
2439 sym_push2(nested_list, s->v, 0, 0);
2440 macro_subst(tok_str, nested_list, mstr);
2441 /* pop nested defined symbol */
2442 sa1 = *nested_list;
2443 *nested_list = sa1->prev;
2444 free(sa1);
2445 if (mstr_allocated)
2446 free(mstr);
2447 } else {
2448 no_subst:
2449 /* no need to add if reading input stream */
2450 if (!macro_str)
2451 return;
2452 tok_str_add2(tok_str, tok, &tokc);
2454 /* only replace one macro while parsing input stream */
2455 if (!macro_str)
2456 return;
2458 macro_ptr = saved_macro_ptr;
2459 if (macro_str1)
2460 free(macro_str1);
2463 /* return next token with macro substitution */
2464 void next(void)
2466 Sym *nested_list;
2467 TokenString str;
2469 /* special 'ungettok' case for label parsing */
2470 if (tok1) {
2471 tok = tok1;
2472 tokc = tok1c;
2473 tok1 = 0;
2474 } else {
2475 redo:
2476 if (!macro_ptr) {
2477 /* if not reading from macro substituted string, then try
2478 to substitute */
2479 /* XXX: optimize non macro case */
2480 tok_str_new(&str);
2481 nested_list = NULL;
2482 macro_subst(&str, &nested_list, NULL);
2483 if (str.str) {
2484 tok_str_add(&str, 0);
2485 macro_ptr = str.str;
2486 macro_ptr_allocated = str.str;
2487 goto redo;
2489 if (tok == 0)
2490 goto redo;
2491 } else {
2492 next_nomacro();
2493 if (tok == 0) {
2494 /* end of macro string: free it */
2495 free(macro_ptr_allocated);
2496 macro_ptr = NULL;
2497 goto redo;
2501 #if defined(DEBUG)
2502 printf("token = %s\n", get_tok_str(tok, tokc));
2503 #endif
2506 void swap(int *p, int *q)
2508 int t;
2509 t = *p;
2510 *p = *q;
2511 *q = t;
2514 void vsetc(int t, int r, CValue *vc)
2516 if (vtop >= vstack + VSTACK_SIZE)
2517 error("memory full");
2518 /* cannot let cpu flags if other instruction are generated */
2519 /* XXX: VT_JMP test too ? */
2520 if ((vtop->r & VT_VALMASK) == VT_CMP)
2521 gv(RC_INT);
2522 vtop++;
2523 vtop->t = t;
2524 vtop->r = r;
2525 vtop->r2 = VT_CONST;
2526 vtop->c = *vc;
2529 /* push integer constant */
2530 void vpushi(int v)
2532 CValue cval;
2533 cval.i = v;
2534 vsetc(VT_INT, VT_CONST, &cval);
2537 /* push a reference to a section offset by adding a dummy symbol */
2538 void vpush_ref(int t, Section *sec, unsigned long offset)
2540 int v;
2541 Sym *sym;
2542 CValue cval;
2544 v = anon_sym++;
2545 sym = sym_push1(&global_stack, v, t | VT_STATIC, 0);
2546 sym->r = VT_CONST | VT_SYM;
2547 put_extern_sym(sym, sec, offset);
2548 cval.sym = sym;
2549 vsetc(t, VT_CONST | VT_SYM, &cval);
2552 void vset(int t, int r, int v)
2554 CValue cval;
2556 cval.i = v;
2557 vsetc(t, r, &cval);
2560 void vswap(void)
2562 SValue tmp;
2564 tmp = vtop[0];
2565 vtop[0] = vtop[-1];
2566 vtop[-1] = tmp;
2569 void vpushv(SValue *v)
2571 if (vtop >= vstack + VSTACK_SIZE)
2572 error("memory full");
2573 vtop++;
2574 *vtop = *v;
2577 void vdup(void)
2579 vpushv(vtop);
2582 /* save r to the memory stack, and mark it as being free */
2583 void save_reg(int r)
2585 int l, i, saved, t, size, align;
2586 SValue *p, sv;
2588 /* modify all stack values */
2589 saved = 0;
2590 l = 0;
2591 for(p=vstack;p<=vtop;p++) {
2592 i = p->r & VT_VALMASK;
2593 if ((p->r & VT_VALMASK) == r ||
2594 (p->r2 & VT_VALMASK) == r) {
2595 /* must save value on stack if not already done */
2596 if (!saved) {
2597 /* store register in the stack */
2598 t = p->t;
2599 if ((p->r & VT_LVAL) ||
2600 (!is_float(t) && (t & VT_BTYPE) != VT_LLONG))
2601 t = VT_INT;
2602 size = type_size(t, &align);
2603 loc = (loc - size) & -align;
2604 sv.t = t;
2605 sv.r = VT_LOCAL | VT_LVAL;
2606 sv.c.ul = loc;
2607 store(r, &sv);
2608 #ifdef TCC_TARGET_I386
2609 /* x86 specific: need to pop fp register ST0 if saved */
2610 if (r == REG_ST0) {
2611 o(0xd9dd); /* fstp %st(1) */
2613 #endif
2614 /* special long long case */
2615 if ((t & VT_BTYPE) == VT_LLONG) {
2616 sv.c.ul += 4;
2617 store(p->r2, &sv);
2619 l = loc;
2620 saved = 1;
2622 /* mark that stack entry as being saved on the stack */
2623 if (p->r & VT_LVAL)
2624 t = VT_LLOCAL;
2625 else
2626 t = VT_LOCAL;
2627 p->r = VT_LVAL | t;
2628 p->r2 = VT_CONST;
2629 p->c.ul = l;
2634 /* find a free register of class 'rc'. If none, save one register */
2635 int get_reg(int rc)
2637 int r;
2638 SValue *p;
2640 /* find a free register */
2641 for(r=0;r<NB_REGS;r++) {
2642 if (reg_classes[r] & rc) {
2643 for(p=vstack;p<=vtop;p++) {
2644 if ((p->r & VT_VALMASK) == r ||
2645 (p->r2 & VT_VALMASK) == r)
2646 goto notfound;
2648 return r;
2650 notfound: ;
2653 /* no register left : free the first one on the stack (VERY
2654 IMPORTANT to start from the bottom to ensure that we don't
2655 spill registers used in gen_opi()) */
2656 for(p=vstack;p<=vtop;p++) {
2657 r = p->r & VT_VALMASK;
2658 if (r < VT_CONST && (reg_classes[r] & rc)) {
2659 save_reg(r);
2660 break;
2663 return r;
2666 /* save registers up to (vtop - n) stack entry */
2667 void save_regs(int n)
2669 int r;
2670 SValue *p, *p1;
2671 p1 = vtop - n;
2672 for(p = vstack;p <= p1; p++) {
2673 r = p->r & VT_VALMASK;
2674 if (r < VT_CONST) {
2675 save_reg(r);
2680 /* move register 's' to 'r', and flush previous value of r to memory
2681 if needed */
2682 void move_reg(int r, int s)
2684 SValue sv;
2686 if (r != s) {
2687 save_reg(r);
2688 sv.t = VT_INT;
2689 sv.r = s;
2690 sv.c.ul = 0;
2691 load(r, &sv);
2695 /* get address of vtop (vtop MUST BE an lvalue) */
2696 void gaddrof(void)
2698 vtop->r &= ~VT_LVAL;
2699 /* tricky: if saved lvalue, then we can go back to lvalue */
2700 if ((vtop->r & VT_VALMASK) == VT_LLOCAL)
2701 vtop->r = (vtop->r & ~VT_VALMASK) | VT_LOCAL | VT_LVAL;
2704 #ifdef CONFIG_TCC_BCHECK
2705 /* generate lvalue bound code */
2706 void gbound(void)
2708 int lval_type;
2710 vtop->r &= ~VT_MUSTBOUND;
2711 /* if lvalue, then use checking code before dereferencing */
2712 if (vtop->r & VT_LVAL) {
2713 /* if not VT_BOUNDED value, then make one */
2714 if (!(vtop->r & VT_BOUNDED)) {
2715 lval_type = vtop->r & (VT_LVAL_TYPE | VT_LVAL);
2716 gaddrof();
2717 vpushi(0);
2718 gen_bounded_ptr_add();
2719 vtop->r |= lval_type;
2721 /* then check for dereferencing */
2722 gen_bounded_ptr_deref();
2725 #endif
2727 /* store vtop a register belonging to class 'rc'. lvalues are
2728 converted to values. Cannot be used if cannot be converted to
2729 register value (such as structures). */
2730 int gv(int rc)
2732 int r, r2, rc2, bit_pos, bit_size, size, align, i, data_offset;
2733 unsigned long long ll;
2735 /* NOTE: get_reg can modify vstack[] */
2736 if (vtop->t & VT_BITFIELD) {
2737 bit_pos = (vtop->t >> VT_STRUCT_SHIFT) & 0x3f;
2738 bit_size = (vtop->t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
2739 /* remove bit field info to avoid loops */
2740 vtop->t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
2741 /* generate shifts */
2742 vpushi(32 - (bit_pos + bit_size));
2743 gen_op(TOK_SHL);
2744 vpushi(32 - bit_size);
2745 /* NOTE: transformed to SHR if unsigned */
2746 gen_op(TOK_SAR);
2747 r = gv(rc);
2748 } else {
2749 if (is_float(vtop->t) &&
2750 (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
2751 int v;
2752 Sym *sym;
2754 /* XXX: unify with initializers handling ? */
2755 /* CPUs usually cannot use float constants, so we store them
2756 generically in data segment */
2757 size = type_size(vtop->t, &align);
2758 data_offset = data_section->data_ptr - data_section->data;
2759 data_offset = (data_offset + align - 1) & -align;
2760 /* XXX: not portable yet */
2761 size = size >> 2;
2762 for(i=0;i<size;i++)
2763 ((int *)(data_section->data + data_offset))[i] = vtop->c.tab[i];
2765 v = anon_sym++;
2766 sym = sym_push1(&global_stack, v, vtop->t | VT_STATIC, 0);
2767 sym->r = VT_CONST | VT_SYM;
2768 put_extern_sym(sym, data_section, data_offset);
2770 vtop->r |= VT_LVAL | VT_SYM;
2771 vtop->c.sym = sym;
2772 data_offset += size << 2;
2773 data_section->data_ptr = data_section->data + data_offset;
2775 #ifdef CONFIG_TCC_BCHECK
2776 if (vtop->r & VT_MUSTBOUND)
2777 gbound();
2778 #endif
2780 r = vtop->r & VT_VALMASK;
2781 /* need to reload if:
2782 - constant
2783 - lvalue (need to dereference pointer)
2784 - already a register, but not in the right class */
2785 if (r >= VT_CONST ||
2786 (vtop->r & VT_LVAL) ||
2787 !(reg_classes[r] & rc) ||
2788 ((vtop->t & VT_BTYPE) == VT_LLONG &&
2789 !(reg_classes[vtop->r2] & rc))) {
2790 r = get_reg(rc);
2791 if ((vtop->t & VT_BTYPE) == VT_LLONG) {
2792 /* two register type load : expand to two words
2793 temporarily */
2794 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
2795 /* load constant */
2796 ll = vtop->c.ull;
2797 vtop->c.ui = ll; /* first word */
2798 load(r, vtop);
2799 vtop->r = r; /* save register value */
2800 vpushi(ll >> 32); /* second word */
2801 } else if (r >= VT_CONST ||
2802 (vtop->r & VT_LVAL)) {
2803 /* load from memory */
2804 load(r, vtop);
2805 vdup();
2806 vtop[-1].r = r; /* save register value */
2807 /* increment pointer to get second word */
2808 vtop->t = VT_INT;
2809 gaddrof();
2810 vpushi(4);
2811 gen_op('+');
2812 vtop->r |= VT_LVAL;
2813 } else {
2814 /* move registers */
2815 load(r, vtop);
2816 vdup();
2817 vtop[-1].r = r; /* save register value */
2818 vtop->r = vtop[-1].r2;
2820 /* allocate second register */
2821 rc2 = RC_INT;
2822 if (rc == RC_IRET)
2823 rc2 = RC_LRET;
2824 r2 = get_reg(rc2);
2825 load(r2, vtop);
2826 vpop();
2827 /* write second register */
2828 vtop->r2 = r2;
2829 } else if ((vtop->r & VT_LVAL) && !is_float(vtop->t)) {
2830 int t1, t;
2831 /* lvalue of scalar type : need to use lvalue type
2832 because of possible cast */
2833 t = vtop->t;
2834 t1 = t;
2835 /* compute memory access type */
2836 if (vtop->r & VT_LVAL_BYTE)
2837 t = VT_BYTE;
2838 else if (vtop->r & VT_LVAL_SHORT)
2839 t = VT_SHORT;
2840 if (vtop->r & VT_LVAL_UNSIGNED)
2841 t |= VT_UNSIGNED;
2842 vtop->t = t;
2843 load(r, vtop);
2844 /* restore wanted type */
2845 vtop->t = t1;
2846 } else {
2847 /* one register type load */
2848 load(r, vtop);
2851 vtop->r = r;
2853 return r;
2856 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
2857 void gv2(int rc1, int rc2)
2859 /* generate more generic register first */
2860 if (rc1 <= rc2) {
2861 vswap();
2862 gv(rc1);
2863 vswap();
2864 gv(rc2);
2865 /* test if reload is needed for first register */
2866 if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
2867 vswap();
2868 gv(rc1);
2869 vswap();
2871 } else {
2872 gv(rc2);
2873 vswap();
2874 gv(rc1);
2875 vswap();
2876 /* test if reload is needed for first register */
2877 if ((vtop[0].r & VT_VALMASK) >= VT_CONST) {
2878 gv(rc2);
2883 /* expand long long on stack in two int registers */
2884 void lexpand(void)
2886 int u;
2888 u = vtop->t & VT_UNSIGNED;
2889 gv(RC_INT);
2890 vdup();
2891 vtop[0].r = vtop[-1].r2;
2892 vtop[0].r2 = VT_CONST;
2893 vtop[-1].r2 = VT_CONST;
2894 vtop[0].t = VT_INT | u;
2895 vtop[-1].t = VT_INT | u;
2898 /* build a long long from two ints */
2899 void lbuild(int t)
2901 gv2(RC_INT, RC_INT);
2902 vtop[-1].r2 = vtop[0].r;
2903 vtop[-1].t = t;
2904 vpop();
2907 /* rotate n first stack elements to the bottom */
2908 void vrotb(int n)
2910 int i;
2911 SValue tmp;
2913 tmp = vtop[-n + 1];
2914 for(i=-n+1;i!=0;i++)
2915 vtop[i] = vtop[i+1];
2916 vtop[0] = tmp;
2919 /* pop stack value */
2920 void vpop(void)
2922 int v;
2923 v = vtop->r & VT_VALMASK;
2924 #ifdef TCC_TARGET_I386
2925 /* for x86, we need to pop the FP stack */
2926 if (v == REG_ST0) {
2927 o(0xd9dd); /* fstp %st(1) */
2928 } else
2929 #endif
2930 if (v == VT_JMP || v == VT_JMPI) {
2931 /* need to put correct jump if && or || without test */
2932 gsym(vtop->c.ul);
2934 vtop--;
2937 /* convert stack entry to register and duplicate its value in another
2938 register */
2939 void gv_dup(void)
2941 int rc, t, r, r1;
2942 SValue sv;
2944 t = vtop->t;
2945 if ((t & VT_BTYPE) == VT_LLONG) {
2946 lexpand();
2947 gv_dup();
2948 vswap();
2949 vrotb(3);
2950 gv_dup();
2951 vrotb(4);
2952 /* stack: H L L1 H1 */
2953 lbuild(t);
2954 vrotb(3);
2955 vrotb(3);
2956 vswap();
2957 lbuild(t);
2958 vswap();
2959 } else {
2960 /* duplicate value */
2961 rc = RC_INT;
2962 sv.t = VT_INT;
2963 if (is_float(t)) {
2964 rc = RC_FLOAT;
2965 sv.t = t;
2967 r = gv(rc);
2968 r1 = get_reg(rc);
2969 sv.r = r;
2970 sv.c.ul = 0;
2971 load(r1, &sv); /* move r to r1 */
2972 vdup();
2973 /* duplicates value */
2974 vtop->r = r1;
2978 /* generate CPU independent (unsigned) long long operations */
2979 void gen_opl(int op)
2981 int t, a, b, op1, c, i;
2982 void *func;
2983 GFuncContext gf;
2984 SValue tmp;
2986 switch(op) {
2987 case '/':
2988 case TOK_PDIV:
2989 func = __divll;
2990 goto gen_func;
2991 case TOK_UDIV:
2992 func = __divull;
2993 goto gen_func;
2994 case '%':
2995 func = __modll;
2996 goto gen_func;
2997 case TOK_UMOD:
2998 func = __modull;
2999 gen_func:
3000 /* call generic long long function */
3001 gfunc_start(&gf, FUNC_CDECL);
3002 gfunc_param(&gf);
3003 gfunc_param(&gf);
3004 vpushi((int)func);
3005 gfunc_call(&gf);
3006 vpushi(0);
3007 vtop->r = REG_IRET;
3008 vtop->r2 = REG_LRET;
3009 break;
3010 case '^':
3011 case '&':
3012 case '|':
3013 case '*':
3014 case '+':
3015 case '-':
3016 t = vtop->t;
3017 vswap();
3018 lexpand();
3019 vrotb(3);
3020 lexpand();
3021 /* stack: L1 H1 L2 H2 */
3022 tmp = vtop[0];
3023 vtop[0] = vtop[-3];
3024 vtop[-3] = tmp;
3025 tmp = vtop[-2];
3026 vtop[-2] = vtop[-3];
3027 vtop[-3] = tmp;
3028 vswap();
3029 /* stack: H1 H2 L1 L2 */
3030 if (op == '*') {
3031 vpushv(vtop - 1);
3032 vpushv(vtop - 1);
3033 gen_op(TOK_UMULL);
3034 lexpand();
3035 /* stack: H1 H2 L1 L2 ML MH */
3036 for(i=0;i<4;i++)
3037 vrotb(6);
3038 /* stack: ML MH H1 H2 L1 L2 */
3039 tmp = vtop[0];
3040 vtop[0] = vtop[-2];
3041 vtop[-2] = tmp;
3042 /* stack: ML MH H1 L2 H2 L1 */
3043 gen_op('*');
3044 vrotb(3);
3045 vrotb(3);
3046 gen_op('*');
3047 /* stack: ML MH M1 M2 */
3048 gen_op('+');
3049 gen_op('+');
3050 } else if (op == '+' || op == '-') {
3051 /* XXX: add non carry method too (for MIPS or alpha) */
3052 if (op == '+')
3053 op1 = TOK_ADDC1;
3054 else
3055 op1 = TOK_SUBC1;
3056 gen_op(op1);
3057 /* stack: H1 H2 (L1 op L2) */
3058 vrotb(3);
3059 vrotb(3);
3060 gen_op(op1 + 1); /* TOK_xxxC2 */
3061 } else {
3062 gen_op(op);
3063 /* stack: H1 H2 (L1 op L2) */
3064 vrotb(3);
3065 vrotb(3);
3066 /* stack: (L1 op L2) H1 H2 */
3067 gen_op(op);
3068 /* stack: (L1 op L2) (H1 op H2) */
3070 /* stack: L H */
3071 lbuild(t);
3072 break;
3073 case TOK_SAR:
3074 case TOK_SHR:
3075 case TOK_SHL:
3076 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
3077 t = vtop[-1].t;
3078 vswap();
3079 lexpand();
3080 vrotb(3);
3081 /* stack: L H shift */
3082 c = (int)vtop->c.i;
3083 /* constant: simpler */
3084 /* NOTE: all comments are for SHL. the other cases are
3085 done by swaping words */
3086 vpop();
3087 if (op != TOK_SHL)
3088 vswap();
3089 if (c >= 32) {
3090 /* stack: L H */
3091 vpop();
3092 if (c > 32) {
3093 vpushi(c - 32);
3094 gen_op(op);
3096 if (op != TOK_SAR) {
3097 vpushi(0);
3098 } else {
3099 gv_dup();
3100 vpushi(31);
3101 gen_op(TOK_SAR);
3103 vswap();
3104 } else {
3105 vswap();
3106 gv_dup();
3107 /* stack: H L L */
3108 vpushi(c);
3109 gen_op(op);
3110 vswap();
3111 vpushi(32 - c);
3112 if (op == TOK_SHL)
3113 gen_op(TOK_SHR);
3114 else
3115 gen_op(TOK_SHL);
3116 vrotb(3);
3117 /* stack: L L H */
3118 vpushi(c);
3119 gen_op(op);
3120 gen_op('|');
3122 if (op != TOK_SHL)
3123 vswap();
3124 lbuild(t);
3125 } else {
3126 /* XXX: should provide a faster fallback on x86 ? */
3127 switch(op) {
3128 case TOK_SAR:
3129 func = __sardi3;
3130 goto gen_func;
3131 case TOK_SHR:
3132 func = __shrdi3;
3133 goto gen_func;
3134 case TOK_SHL:
3135 func = __shldi3;
3136 goto gen_func;
3139 break;
3140 default:
3141 /* compare operations */
3142 t = vtop->t;
3143 vswap();
3144 lexpand();
3145 vrotb(3);
3146 lexpand();
3147 /* stack: L1 H1 L2 H2 */
3148 tmp = vtop[-1];
3149 vtop[-1] = vtop[-2];
3150 vtop[-2] = tmp;
3151 /* stack: L1 L2 H1 H2 */
3152 /* compare high */
3153 op1 = op;
3154 /* when values are equal, we need to compare low words. since
3155 the jump is inverted, we invert the test too. */
3156 if (op1 == TOK_LT)
3157 op1 = TOK_LE;
3158 else if (op1 == TOK_GT)
3159 op1 = TOK_GE;
3160 else if (op1 == TOK_ULT)
3161 op1 = TOK_ULE;
3162 else if (op1 == TOK_UGT)
3163 op1 = TOK_UGE;
3164 a = 0;
3165 b = 0;
3166 gen_op(op1);
3167 if (op1 != TOK_NE) {
3168 a = gtst(1, 0);
3170 if (op != TOK_EQ) {
3171 /* generate non equal test */
3172 /* XXX: NOT PORTABLE yet */
3173 if (a == 0) {
3174 b = gtst(0, 0);
3175 } else {
3176 #ifdef TCC_TARGET_I386
3177 b = psym(0x850f, 0);
3178 #else
3179 error("not implemented");
3180 #endif
3183 /* compare low */
3184 gen_op(op);
3185 a = gtst(1, a);
3186 gsym(b);
3187 vset(VT_INT, VT_JMPI, a);
3188 break;
3192 /* handle integer constant optimizations and various machine
3193 independant opt */
3194 void gen_opic(int op)
3196 int fc, c1, c2, n;
3197 SValue *v1, *v2;
3199 v1 = vtop - 1;
3200 v2 = vtop;
3201 /* currently, we cannot do computations with forward symbols */
3202 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
3203 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
3204 if (c1 && c2) {
3205 fc = v2->c.i;
3206 switch(op) {
3207 case '+': v1->c.i += fc; break;
3208 case '-': v1->c.i -= fc; break;
3209 case '&': v1->c.i &= fc; break;
3210 case '^': v1->c.i ^= fc; break;
3211 case '|': v1->c.i |= fc; break;
3212 case '*': v1->c.i *= fc; break;
3214 case TOK_PDIV:
3215 case '/':
3216 case '%':
3217 case TOK_UDIV:
3218 case TOK_UMOD:
3219 /* if division by zero, generate explicit division */
3220 if (fc == 0) {
3221 if (const_wanted)
3222 error("division by zero in constant");
3223 goto general_case;
3225 switch(op) {
3226 default: v1->c.i /= fc; break;
3227 case '%': v1->c.i %= fc; break;
3228 case TOK_UDIV: v1->c.i = (unsigned)v1->c.i / fc; break;
3229 case TOK_UMOD: v1->c.i = (unsigned)v1->c.i % fc; break;
3231 break;
3232 case TOK_SHL: v1->c.i <<= fc; break;
3233 case TOK_SHR: v1->c.i = (unsigned)v1->c.i >> fc; break;
3234 case TOK_SAR: v1->c.i >>= fc; break;
3235 /* tests */
3236 case TOK_ULT: v1->c.i = (unsigned)v1->c.i < (unsigned)fc; break;
3237 case TOK_UGE: v1->c.i = (unsigned)v1->c.i >= (unsigned)fc; break;
3238 case TOK_EQ: v1->c.i = v1->c.i == fc; break;
3239 case TOK_NE: v1->c.i = v1->c.i != fc; break;
3240 case TOK_ULE: v1->c.i = (unsigned)v1->c.i <= (unsigned)fc; break;
3241 case TOK_UGT: v1->c.i = (unsigned)v1->c.i > (unsigned)fc; break;
3242 case TOK_LT: v1->c.i = v1->c.i < fc; break;
3243 case TOK_GE: v1->c.i = v1->c.i >= fc; break;
3244 case TOK_LE: v1->c.i = v1->c.i <= fc; break;
3245 case TOK_GT: v1->c.i = v1->c.i > fc; break;
3246 /* logical */
3247 case TOK_LAND: v1->c.i = v1->c.i && fc; break;
3248 case TOK_LOR: v1->c.i = v1->c.i || fc; break;
3249 default:
3250 goto general_case;
3252 vtop--;
3253 } else {
3254 /* if commutative ops, put c2 as constant */
3255 if (c1 && (op == '+' || op == '&' || op == '^' ||
3256 op == '|' || op == '*')) {
3257 vswap();
3258 swap(&c1, &c2);
3260 fc = vtop->c.i;
3261 if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
3262 op == TOK_PDIV) &&
3263 fc == 1) ||
3264 ((op == '+' || op == '-' || op == '|' || op == '^' ||
3265 op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
3266 fc == 0) ||
3267 (op == '&' &&
3268 fc == -1))) {
3269 /* nothing to do */
3270 vtop--;
3271 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
3272 /* try to use shifts instead of muls or divs */
3273 if (fc > 0 && (fc & (fc - 1)) == 0) {
3274 n = -1;
3275 while (fc) {
3276 fc >>= 1;
3277 n++;
3279 vtop->c.i = n;
3280 if (op == '*')
3281 op = TOK_SHL;
3282 else if (op == TOK_PDIV)
3283 op = TOK_SAR;
3284 else
3285 op = TOK_SHR;
3287 goto general_case;
3288 } else {
3289 general_case:
3290 /* call low level op generator */
3291 gen_opi(op);
3296 /* generate a floating point operation with constant propagation */
3297 void gen_opif(int op)
3299 int c1, c2;
3300 SValue *v1, *v2;
3301 long double f1, f2;
3303 v1 = vtop - 1;
3304 v2 = vtop;
3305 /* currently, we cannot do computations with forward symbols */
3306 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
3307 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
3308 if (c1 && c2) {
3309 if (v1->t == VT_FLOAT) {
3310 f1 = v1->c.f;
3311 f2 = v2->c.f;
3312 } else if (v1->t == VT_DOUBLE) {
3313 f1 = v1->c.d;
3314 f2 = v2->c.d;
3315 } else {
3316 f1 = v1->c.ld;
3317 f2 = v2->c.ld;
3320 /* NOTE: we only do constant propagation if finite number (not
3321 NaN or infinity) (ANSI spec) */
3322 if (!ieee_finite(f1) || !ieee_finite(f2))
3323 goto general_case;
3325 switch(op) {
3326 case '+': f1 += f2; break;
3327 case '-': f1 -= f2; break;
3328 case '*': f1 *= f2; break;
3329 case '/':
3330 if (f2 == 0.0) {
3331 if (const_wanted)
3332 error("division by zero in constant");
3333 goto general_case;
3335 f1 /= f2;
3336 break;
3337 /* XXX: also handles tests ? */
3338 default:
3339 goto general_case;
3341 /* XXX: overflow test ? */
3342 if (v1->t == VT_FLOAT) {
3343 v1->c.f = f1;
3344 } else if (v1->t == VT_DOUBLE) {
3345 v1->c.d = f1;
3346 } else {
3347 v1->c.ld = f1;
3349 vtop--;
3350 } else {
3351 general_case:
3352 gen_opf(op);
3357 int pointed_size(int t)
3359 return type_size(pointed_type(t), &t);
3362 #if 0
3363 void check_pointer_types(SValue *p1, SValue *p2)
3365 char buf1[256], buf2[256];
3366 int t1, t2;
3367 t1 = p1->t;
3368 t2 = p2->t;
3369 if (!is_compatible_types(t1, t2)) {
3370 type_to_str(buf1, sizeof(buf1), t1, NULL);
3371 type_to_str(buf2, sizeof(buf2), t2, NULL);
3372 error("incompatible pointers '%s' and '%s'", buf1, buf2);
3375 #endif
3377 /* generic gen_op: handles types problems */
3378 void gen_op(int op)
3380 int u, t1, t2, bt1, bt2, t;
3382 t1 = vtop[-1].t;
3383 t2 = vtop[0].t;
3384 bt1 = t1 & VT_BTYPE;
3385 bt2 = t2 & VT_BTYPE;
3387 if (bt1 == VT_PTR || bt2 == VT_PTR) {
3388 /* at least one operand is a pointer */
3389 /* relationnal op: must be both pointers */
3390 if (op >= TOK_ULT && op <= TOK_GT) {
3391 // check_pointer_types(vtop, vtop - 1);
3392 /* pointers are handled are unsigned */
3393 t = VT_INT | VT_UNSIGNED;
3394 goto std_op;
3396 /* if both pointers, then it must be the '-' op */
3397 if ((t1 & VT_BTYPE) == VT_PTR &&
3398 (t2 & VT_BTYPE) == VT_PTR) {
3399 if (op != '-')
3400 error("cannot use pointers here");
3401 // check_pointer_types(vtop - 1, vtop);
3402 /* XXX: check that types are compatible */
3403 u = pointed_size(t1);
3404 gen_opic(op);
3405 /* set to integer type */
3406 vtop->t = VT_INT;
3407 vpushi(u);
3408 gen_op(TOK_PDIV);
3409 } else {
3410 /* exactly one pointer : must be '+' or '-'. */
3411 if (op != '-' && op != '+')
3412 error("cannot use pointers here");
3413 /* Put pointer as first operand */
3414 if ((t2 & VT_BTYPE) == VT_PTR) {
3415 vswap();
3416 swap(&t1, &t2);
3418 /* XXX: cast to int ? (long long case) */
3419 vpushi(pointed_size(vtop[-1].t));
3420 gen_op('*');
3421 #ifdef CONFIG_TCC_BCHECK
3422 /* if evaluating constant expression, no code should be
3423 generated, so no bound check */
3424 if (do_bounds_check && !const_wanted) {
3425 /* if bounded pointers, we generate a special code to
3426 test bounds */
3427 if (op == '-') {
3428 vpushi(0);
3429 vswap();
3430 gen_op('-');
3432 gen_bounded_ptr_add();
3433 } else
3434 #endif
3436 gen_opic(op);
3438 /* put again type if gen_opic() swaped operands */
3439 vtop->t = t1;
3441 } else if (is_float(bt1) || is_float(bt2)) {
3442 /* compute bigger type and do implicit casts */
3443 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
3444 t = VT_LDOUBLE;
3445 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
3446 t = VT_DOUBLE;
3447 } else {
3448 t = VT_FLOAT;
3450 /* floats can only be used for a few operations */
3451 if (op != '+' && op != '-' && op != '*' && op != '/' &&
3452 (op < TOK_ULT || op > TOK_GT))
3453 error("invalid operands for binary operation");
3454 goto std_op;
3455 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
3456 /* cast to biggest op */
3457 t = VT_LLONG;
3458 /* convert to unsigned if it does not fit in a long long */
3459 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
3460 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
3461 t |= VT_UNSIGNED;
3462 goto std_op;
3463 } else {
3464 /* integer operations */
3465 t = VT_INT;
3466 /* convert to unsigned if it does not fit in an integer */
3467 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
3468 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
3469 t |= VT_UNSIGNED;
3470 std_op:
3471 /* XXX: currently, some unsigned operations are explicit, so
3472 we modify them here */
3473 if (t & VT_UNSIGNED) {
3474 if (op == TOK_SAR)
3475 op = TOK_SHR;
3476 else if (op == '/')
3477 op = TOK_UDIV;
3478 else if (op == '%')
3479 op = TOK_UMOD;
3480 else if (op == TOK_LT)
3481 op = TOK_ULT;
3482 else if (op == TOK_GT)
3483 op = TOK_UGT;
3484 else if (op == TOK_LE)
3485 op = TOK_ULE;
3486 else if (op == TOK_GE)
3487 op = TOK_UGE;
3489 vswap();
3490 gen_cast(t);
3491 vswap();
3492 /* special case for shifts and long long: we keep the shift as
3493 an integer */
3494 if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL)
3495 gen_cast(VT_INT);
3496 else
3497 gen_cast(t);
3498 if (is_float(t))
3499 gen_opif(op);
3500 else if ((t & VT_BTYPE) == VT_LLONG)
3501 gen_opl(op);
3502 else
3503 gen_opic(op);
3504 if (op >= TOK_ULT && op <= TOK_GT) {
3505 /* relationnal op: the result is an int */
3506 vtop->t = VT_INT;
3507 } else {
3508 vtop->t = t;
3513 /* generic itof for unsigned long long case */
3514 void gen_cvt_itof1(int t)
3516 GFuncContext gf;
3518 if ((vtop->t & (VT_BTYPE | VT_UNSIGNED)) ==
3519 (VT_LLONG | VT_UNSIGNED)) {
3521 gfunc_start(&gf, FUNC_CDECL);
3522 gfunc_param(&gf);
3523 if (t == VT_FLOAT)
3524 vpushi((int)&__ulltof);
3525 else if (t == VT_DOUBLE)
3526 vpushi((int)&__ulltod);
3527 else
3528 vpushi((int)&__ulltold);
3529 gfunc_call(&gf);
3530 vpushi(0);
3531 vtop->r = REG_FRET;
3532 } else {
3533 gen_cvt_itof(t);
3537 /* generic ftoi for unsigned long long case */
3538 void gen_cvt_ftoi1(int t)
3540 GFuncContext gf;
3541 int st;
3543 if (t == (VT_LLONG | VT_UNSIGNED)) {
3544 /* not handled natively */
3545 gfunc_start(&gf, FUNC_CDECL);
3546 st = vtop->t & VT_BTYPE;
3547 gfunc_param(&gf);
3548 if (st == VT_FLOAT)
3549 vpushi((int)&__ftoull);
3550 else if (st == VT_DOUBLE)
3551 vpushi((int)&__dtoull);
3552 else
3553 vpushi((int)&__ldtoull);
3554 gfunc_call(&gf);
3555 vpushi(0);
3556 vtop->r = REG_IRET;
3557 vtop->r2 = REG_LRET;
3558 } else {
3559 gen_cvt_ftoi(t);
3563 /* force char or short cast */
3564 void force_charshort_cast(int t)
3566 int bits, dbt;
3567 dbt = t & VT_BTYPE;
3568 /* XXX: add optimization if lvalue : just change type and offset */
3569 if (dbt == VT_BYTE)
3570 bits = 8;
3571 else
3572 bits = 16;
3573 if (t & VT_UNSIGNED) {
3574 vpushi((1 << bits) - 1);
3575 gen_op('&');
3576 } else {
3577 bits = 32 - bits;
3578 vpushi(bits);
3579 gen_op(TOK_SHL);
3580 vpushi(bits);
3581 gen_op(TOK_SAR);
3585 /* cast 'vtop' to 't' type */
3586 void gen_cast(int t)
3588 int sbt, dbt, sf, df, c;
3590 /* special delayed cast for char/short */
3591 /* XXX: in some cases (multiple cascaded casts), it may still
3592 be incorrect */
3593 if (vtop->r & VT_MUSTCAST) {
3594 vtop->r &= ~VT_MUSTCAST;
3595 force_charshort_cast(vtop->t);
3598 dbt = t & (VT_BTYPE | VT_UNSIGNED);
3599 sbt = vtop->t & (VT_BTYPE | VT_UNSIGNED);
3601 if (sbt != dbt) {
3602 sf = is_float(sbt);
3603 df = is_float(dbt);
3604 c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
3605 if (sf && df) {
3606 /* convert from fp to fp */
3607 if (c) {
3608 /* constant case: we can do it now */
3609 /* XXX: in ISOC, cannot do it if error in convert */
3610 if (dbt == VT_FLOAT && sbt == VT_DOUBLE)
3611 vtop->c.f = (float)vtop->c.d;
3612 else if (dbt == VT_FLOAT && sbt == VT_LDOUBLE)
3613 vtop->c.f = (float)vtop->c.ld;
3614 else if (dbt == VT_DOUBLE && sbt == VT_FLOAT)
3615 vtop->c.d = (double)vtop->c.f;
3616 else if (dbt == VT_DOUBLE && sbt == VT_LDOUBLE)
3617 vtop->c.d = (double)vtop->c.ld;
3618 else if (dbt == VT_LDOUBLE && sbt == VT_FLOAT)
3619 vtop->c.ld = (long double)vtop->c.f;
3620 else if (dbt == VT_LDOUBLE && sbt == VT_DOUBLE)
3621 vtop->c.ld = (long double)vtop->c.d;
3622 } else {
3623 /* non constant case: generate code */
3624 gen_cvt_ftof(dbt);
3626 } else if (df) {
3627 /* convert int to fp */
3628 if (c) {
3629 switch(sbt) {
3630 case VT_LLONG | VT_UNSIGNED:
3631 case VT_LLONG:
3632 /* XXX: add const cases for long long */
3633 goto do_itof;
3634 case VT_INT | VT_UNSIGNED:
3635 switch(dbt) {
3636 case VT_FLOAT: vtop->c.f = (float)vtop->c.ui; break;
3637 case VT_DOUBLE: vtop->c.d = (double)vtop->c.ui; break;
3638 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.ui; break;
3640 break;
3641 default:
3642 switch(dbt) {
3643 case VT_FLOAT: vtop->c.f = (float)vtop->c.i; break;
3644 case VT_DOUBLE: vtop->c.d = (double)vtop->c.i; break;
3645 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.i; break;
3647 break;
3649 } else {
3650 do_itof:
3651 gen_cvt_itof1(dbt);
3653 } else if (sf) {
3654 /* convert fp to int */
3655 /* we handle char/short/etc... with generic code */
3656 if (dbt != (VT_INT | VT_UNSIGNED) &&
3657 dbt != (VT_LLONG | VT_UNSIGNED) &&
3658 dbt != VT_LLONG)
3659 dbt = VT_INT;
3660 if (c) {
3661 switch(dbt) {
3662 case VT_LLONG | VT_UNSIGNED:
3663 case VT_LLONG:
3664 /* XXX: add const cases for long long */
3665 goto do_ftoi;
3666 case VT_INT | VT_UNSIGNED:
3667 switch(sbt) {
3668 case VT_FLOAT: vtop->c.ui = (unsigned int)vtop->c.d; break;
3669 case VT_DOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
3670 case VT_LDOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
3672 break;
3673 default:
3674 /* int case */
3675 switch(sbt) {
3676 case VT_FLOAT: vtop->c.i = (int)vtop->c.d; break;
3677 case VT_DOUBLE: vtop->c.i = (int)vtop->c.d; break;
3678 case VT_LDOUBLE: vtop->c.i = (int)vtop->c.d; break;
3680 break;
3682 } else {
3683 do_ftoi:
3684 gen_cvt_ftoi1(dbt);
3686 if (dbt == VT_INT && (t & (VT_BTYPE | VT_UNSIGNED)) != dbt) {
3687 /* additionnal cast for char/short/bool... */
3688 vtop->t = dbt;
3689 gen_cast(t);
3691 } else if ((dbt & VT_BTYPE) == VT_LLONG) {
3692 if ((sbt & VT_BTYPE) != VT_LLONG) {
3693 /* scalar to long long */
3694 if (c) {
3695 if (sbt == (VT_INT | VT_UNSIGNED))
3696 vtop->c.ll = vtop->c.ui;
3697 else
3698 vtop->c.ll = vtop->c.i;
3699 } else {
3700 /* machine independant conversion */
3701 gv(RC_INT);
3702 /* generate high word */
3703 if (sbt == (VT_INT | VT_UNSIGNED)) {
3704 vpushi(0);
3705 gv(RC_INT);
3706 } else {
3707 gv_dup();
3708 vpushi(31);
3709 gen_op(TOK_SAR);
3711 /* patch second register */
3712 vtop[-1].r2 = vtop->r;
3713 vpop();
3716 } else if (dbt == VT_BOOL) {
3717 /* scalar to bool */
3718 vpushi(0);
3719 gen_op(TOK_NE);
3720 } else if ((dbt & VT_BTYPE) == VT_BYTE ||
3721 (dbt & VT_BTYPE) == VT_SHORT) {
3722 force_charshort_cast(t);
3723 } else if ((dbt & VT_BTYPE) == VT_INT) {
3724 /* scalar to int */
3725 if (sbt == VT_LLONG) {
3726 /* from long long: just take low order word */
3727 lexpand();
3728 vpop();
3730 /* if lvalue and single word type, nothing to do because
3731 the lvalue already contains the real type size (see
3732 VT_LVAL_xxx constants) */
3735 vtop->t = t;
3738 /* return type size. Put alignment at 'a' */
3739 int type_size(int t, int *a)
3741 Sym *s;
3742 int bt;
3744 bt = t & VT_BTYPE;
3745 if (bt == VT_STRUCT) {
3746 /* struct/union */
3747 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
3748 *a = 4; /* XXX: cannot store it yet. Doing that is safe */
3749 return s->c;
3750 } else if (bt == VT_PTR) {
3751 if (t & VT_ARRAY) {
3752 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
3753 return type_size(s->t, a) * s->c;
3754 } else {
3755 *a = PTR_SIZE;
3756 return PTR_SIZE;
3758 } else if (bt == VT_LDOUBLE) {
3759 *a = LDOUBLE_ALIGN;
3760 return LDOUBLE_SIZE;
3761 } else if (bt == VT_DOUBLE || bt == VT_LLONG) {
3762 *a = 8;
3763 return 8;
3764 } else if (bt == VT_INT || bt == VT_ENUM || bt == VT_FLOAT) {
3765 *a = 4;
3766 return 4;
3767 } else if (bt == VT_SHORT) {
3768 *a = 2;
3769 return 2;
3770 } else {
3771 /* char, void, function, _Bool */
3772 *a = 1;
3773 return 1;
3777 /* return the pointed type of t */
3778 int pointed_type(int t)
3780 Sym *s;
3781 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
3782 return s->t | (t & ~VT_TYPE);
3785 int mk_pointer(int t)
3787 int p;
3788 p = anon_sym++;
3789 sym_push(p, t, 0, -1);
3790 return VT_PTR | (p << VT_STRUCT_SHIFT) | (t & ~VT_TYPE);
3793 int is_compatible_types(int t1, int t2)
3795 Sym *s1, *s2;
3796 int bt1, bt2;
3798 t1 &= VT_TYPE;
3799 t2 &= VT_TYPE;
3800 bt1 = t1 & VT_BTYPE;
3801 bt2 = t2 & VT_BTYPE;
3802 if (bt1 == VT_PTR) {
3803 t1 = pointed_type(t1);
3804 /* if function, then convert implicitely to function pointer */
3805 if (bt2 != VT_FUNC) {
3806 if (bt2 != VT_PTR)
3807 return 0;
3808 t2 = pointed_type(t2);
3810 /* void matches everything */
3811 t1 &= VT_TYPE;
3812 t2 &= VT_TYPE;
3813 if (t1 == VT_VOID || t2 == VT_VOID)
3814 return 1;
3815 return is_compatible_types(t1, t2);
3816 } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
3817 return (t2 == t1);
3818 } else if (bt1 == VT_FUNC) {
3819 if (bt2 != VT_FUNC)
3820 return 0;
3821 s1 = sym_find(((unsigned)t1 >> VT_STRUCT_SHIFT));
3822 s2 = sym_find(((unsigned)t2 >> VT_STRUCT_SHIFT));
3823 if (!is_compatible_types(s1->t, s2->t))
3824 return 0;
3825 /* XXX: not complete */
3826 if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
3827 return 1;
3828 if (s1->c != s2->c)
3829 return 0;
3830 while (s1 != NULL) {
3831 if (s2 == NULL)
3832 return 0;
3833 if (!is_compatible_types(s1->t, s2->t))
3834 return 0;
3835 s1 = s1->next;
3836 s2 = s2->next;
3838 if (s2)
3839 return 0;
3840 return 1;
3841 } else {
3842 /* XXX: not complete */
3843 return 1;
3847 /* print a type. If 'varstr' is not NULL, then the variable is also
3848 printed in the type */
3849 /* XXX: union */
3850 /* XXX: add array and function pointers */
3851 void type_to_str(char *buf, int buf_size,
3852 int t, const char *varstr)
3854 int bt, v;
3855 Sym *s, *sa;
3856 char buf1[256];
3857 const char *tstr;
3859 t = t & VT_TYPE;
3860 bt = t & VT_BTYPE;
3861 buf[0] = '\0';
3862 if (t & VT_UNSIGNED)
3863 pstrcat(buf, buf_size, "unsigned ");
3864 switch(bt) {
3865 case VT_VOID:
3866 tstr = "void";
3867 goto add_tstr;
3868 case VT_BOOL:
3869 tstr = "_Bool";
3870 goto add_tstr;
3871 case VT_BYTE:
3872 tstr = "char";
3873 goto add_tstr;
3874 case VT_SHORT:
3875 tstr = "short";
3876 goto add_tstr;
3877 case VT_INT:
3878 tstr = "int";
3879 goto add_tstr;
3880 case VT_LONG:
3881 tstr = "long";
3882 goto add_tstr;
3883 case VT_LLONG:
3884 tstr = "long long";
3885 goto add_tstr;
3886 case VT_FLOAT:
3887 tstr = "float";
3888 goto add_tstr;
3889 case VT_DOUBLE:
3890 tstr = "double";
3891 goto add_tstr;
3892 case VT_LDOUBLE:
3893 tstr = "long double";
3894 add_tstr:
3895 pstrcat(buf, buf_size, tstr);
3896 break;
3897 case VT_ENUM:
3898 case VT_STRUCT:
3899 if (bt == VT_STRUCT)
3900 tstr = "struct ";
3901 else
3902 tstr = "enum ";
3903 pstrcat(buf, buf_size, tstr);
3904 v = (unsigned)t >> VT_STRUCT_SHIFT;
3905 if (v >= SYM_FIRST_ANOM)
3906 pstrcat(buf, buf_size, "<anonymous>");
3907 else
3908 pstrcat(buf, buf_size, get_tok_str(v, NULL));
3909 break;
3910 case VT_FUNC:
3911 s = sym_find((unsigned)t >> VT_STRUCT_SHIFT);
3912 type_to_str(buf, buf_size, s->t, varstr);
3913 pstrcat(buf, buf_size, "(");
3914 sa = s->next;
3915 while (sa != NULL) {
3916 type_to_str(buf1, sizeof(buf1), sa->t, NULL);
3917 pstrcat(buf, buf_size, buf1);
3918 sa = sa->next;
3919 if (sa)
3920 pstrcat(buf, buf_size, ", ");
3922 pstrcat(buf, buf_size, ")");
3923 goto no_var;
3924 case VT_PTR:
3925 s = sym_find((unsigned)t >> VT_STRUCT_SHIFT);
3926 pstrcpy(buf1, sizeof(buf1), "*");
3927 if (varstr)
3928 pstrcat(buf1, sizeof(buf1), varstr);
3929 type_to_str(buf, buf_size, s->t, buf1);
3930 goto no_var;
3932 if (varstr) {
3933 pstrcat(buf, buf_size, " ");
3934 pstrcat(buf, buf_size, varstr);
3936 no_var: ;
3939 /* verify type compatibility to store vtop in 'dt' type, and generate
3940 casts if needed. */
3941 void gen_assign_cast(int dt)
3943 int st;
3944 char buf1[256], buf2[256];
3946 st = vtop->t; /* source type */
3947 if ((dt & VT_BTYPE) == VT_PTR) {
3948 /* special cases for pointers */
3949 /* a function is implicitely a function pointer */
3950 if ((st & VT_BTYPE) == VT_FUNC) {
3951 if (!is_compatible_types(pointed_type(dt), st))
3952 goto error;
3953 else
3954 goto type_ok;
3956 /* '0' can also be a pointer */
3957 if ((st & VT_BTYPE) == VT_INT &&
3958 ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) &&
3959 vtop->c.i == 0)
3960 goto type_ok;
3962 if (!is_compatible_types(dt, st)) {
3963 error:
3964 type_to_str(buf1, sizeof(buf1), st, NULL);
3965 type_to_str(buf2, sizeof(buf2), dt, NULL);
3966 error("cannot cast '%s' to '%s'", buf1, buf2);
3968 type_ok:
3969 gen_cast(dt);
3972 /* store vtop in lvalue pushed on stack */
3973 void vstore(void)
3975 int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
3976 GFuncContext gf;
3978 ft = vtop[-1].t;
3979 sbt = vtop->t & VT_BTYPE;
3980 dbt = ft & VT_BTYPE;
3981 if (((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
3982 (sbt == VT_INT && dbt == VT_SHORT)) {
3983 /* optimize char/short casts */
3984 delayed_cast = VT_MUSTCAST;
3985 vtop->t = ft & VT_TYPE;
3986 } else {
3987 delayed_cast = 0;
3988 gen_assign_cast(ft & VT_TYPE);
3991 if (sbt == VT_STRUCT) {
3992 /* if structure, only generate pointer */
3993 /* structure assignment : generate memcpy */
3994 /* XXX: optimize if small size */
3995 vdup();
3996 gfunc_start(&gf, FUNC_CDECL);
3997 /* type size */
3998 size = type_size(vtop->t, &align);
3999 vpushi(size);
4000 gfunc_param(&gf);
4001 /* source */
4002 vtop->t = VT_INT;
4003 gaddrof();
4004 gfunc_param(&gf);
4005 /* destination */
4006 vswap();
4007 vtop->t = VT_INT;
4008 gaddrof();
4009 gfunc_param(&gf);
4011 save_regs(0);
4012 vpushi((int)&memcpy);
4013 gfunc_call(&gf);
4014 /* leave source on stack */
4015 } else if (ft & VT_BITFIELD) {
4016 /* bitfield store handling */
4017 bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
4018 bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
4019 /* remove bit field info to avoid loops */
4020 vtop[-1].t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
4022 /* duplicate destination */
4023 vdup();
4024 vtop[-1] = vtop[-2];
4026 /* mask and shift source */
4027 vpushi((1 << bit_size) - 1);
4028 gen_op('&');
4029 vpushi(bit_pos);
4030 gen_op(TOK_SHL);
4031 /* load destination, mask and or with source */
4032 vswap();
4033 vpushi(~(((1 << bit_size) - 1) << bit_pos));
4034 gen_op('&');
4035 gen_op('|');
4036 /* store result */
4037 vstore();
4038 } else {
4039 #ifdef CONFIG_TCC_BCHECK
4040 /* bound check case */
4041 if (vtop[-1].r & VT_MUSTBOUND) {
4042 vswap();
4043 gbound();
4044 vswap();
4046 #endif
4047 rc = RC_INT;
4048 if (is_float(ft))
4049 rc = RC_FLOAT;
4050 r = gv(rc); /* generate value */
4051 /* if lvalue was saved on stack, must read it */
4052 if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
4053 SValue sv;
4054 t = get_reg(RC_INT);
4055 sv.t = VT_INT;
4056 sv.r = VT_LOCAL | VT_LVAL;
4057 sv.c.ul = vtop[-1].c.ul;
4058 load(t, &sv);
4059 vtop[-1].r = t | VT_LVAL;
4061 store(r, vtop - 1);
4062 /* two word case handling : store second register at word + 4 */
4063 if ((ft & VT_BTYPE) == VT_LLONG) {
4064 vswap();
4065 /* convert to int to increment easily */
4066 vtop->t = VT_INT;
4067 gaddrof();
4068 vpushi(4);
4069 gen_op('+');
4070 vtop->r |= VT_LVAL;
4071 vswap();
4072 /* XXX: it works because r2 is spilled last ! */
4073 store(vtop->r2, vtop - 1);
4075 vswap();
4076 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
4077 vtop->r |= delayed_cast;
4081 /* post defines POST/PRE add. c is the token ++ or -- */
4082 void inc(int post, int c)
4084 test_lvalue();
4085 vdup(); /* save lvalue */
4086 if (post) {
4087 gv_dup(); /* duplicate value */
4088 vrotb(3);
4089 vrotb(3);
4091 /* add constant */
4092 vpushi(c - TOK_MID);
4093 gen_op('+');
4094 vstore(); /* store value */
4095 if (post)
4096 vpop(); /* if post op, return saved value */
4099 /* Parse GNUC __attribute__ extension. Currently, the following
4100 extensions are recognized:
4101 - aligned(n) : set data/function alignment.
4102 - section(x) : generate data/code in this section.
4103 - unused : currently ignored, but may be used someday.
4105 void parse_attribute(AttributeDef *ad)
4107 int t, n;
4109 next();
4110 skip('(');
4111 skip('(');
4112 while (tok != ')') {
4113 if (tok < TOK_IDENT)
4114 expect("attribute name");
4115 t = tok;
4116 next();
4117 switch(t) {
4118 case TOK_SECTION:
4119 case TOK___SECTION__:
4120 skip('(');
4121 if (tok != TOK_STR)
4122 expect("section name");
4123 ad->section = find_section(tokc.ts->str);
4124 next();
4125 skip(')');
4126 break;
4127 case TOK_ALIGNED:
4128 case TOK___ALIGNED__:
4129 skip('(');
4130 n = expr_const();
4131 if (n <= 0 || (n & (n - 1)) != 0)
4132 error("alignment must be a positive power of two");
4133 ad->aligned = n;
4134 skip(')');
4135 break;
4136 case TOK_UNUSED:
4137 case TOK___UNUSED__:
4138 /* currently, no need to handle it because tcc does not
4139 track unused objects */
4140 break;
4141 case TOK_NORETURN:
4142 case TOK___NORETURN__:
4143 /* currently, no need to handle it because tcc does not
4144 track unused objects */
4145 break;
4146 case TOK_CDECL:
4147 case TOK___CDECL:
4148 case TOK___CDECL__:
4149 ad->func_call = FUNC_CDECL;
4150 break;
4151 case TOK_STDCALL:
4152 case TOK___STDCALL:
4153 case TOK___STDCALL__:
4154 ad->func_call = FUNC_STDCALL;
4155 break;
4156 default:
4157 warning("'%s' attribute ignored", get_tok_str(t, NULL));
4158 /* skip parameters */
4159 /* XXX: skip parenthesis too */
4160 if (tok == '(') {
4161 next();
4162 while (tok != ')' && tok != -1)
4163 next();
4164 next();
4166 break;
4168 if (tok != ',')
4169 break;
4170 next();
4172 skip(')');
4173 skip(')');
4176 /* enum/struct/union declaration */
4177 int struct_decl(int u)
4179 int a, t, b, v, size, align, maxalign, c, offset;
4180 int bit_size, bit_pos, bsize, bt, lbit_pos;
4181 Sym *s, *ss, **ps;
4182 AttributeDef ad;
4184 a = tok; /* save decl type */
4185 next();
4186 if (tok != '{') {
4187 v = tok;
4188 next();
4189 /* struct already defined ? return it */
4190 /* XXX: check consistency */
4191 s = sym_find(v | SYM_STRUCT);
4192 if (s) {
4193 if (s->t != a)
4194 error("invalid type");
4195 goto do_decl;
4197 } else {
4198 v = anon_sym++;
4200 s = sym_push(v | SYM_STRUCT, a, 0, 0);
4201 /* put struct/union/enum name in type */
4202 do_decl:
4203 u = u | (v << VT_STRUCT_SHIFT);
4205 if (tok == '{') {
4206 next();
4207 if (s->c)
4208 error("struct/union/enum already defined");
4209 /* cannot be empty */
4210 c = 0;
4211 maxalign = 0;
4212 ps = &s->next;
4213 bit_pos = 0;
4214 offset = 0;
4215 while (1) {
4216 if (a == TOK_ENUM) {
4217 v = tok;
4218 next();
4219 if (tok == '=') {
4220 next();
4221 c = expr_const();
4223 /* enum symbols have static storage */
4224 sym_push(v, VT_STATIC | VT_INT, VT_CONST, c);
4225 if (tok == ',')
4226 next();
4227 c++;
4228 } else {
4229 parse_btype(&b, &ad);
4230 while (1) {
4231 bit_size = -1;
4232 v = 0;
4233 if (tok != ':') {
4234 t = type_decl(&ad, &v, b, TYPE_DIRECT);
4235 if ((t & VT_BTYPE) == VT_FUNC ||
4236 (t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN)))
4237 error("invalid type for '%s'",
4238 get_tok_str(v, NULL));
4239 } else {
4240 t = b;
4242 if (tok == ':') {
4243 next();
4244 bit_size = expr_const();
4245 /* XXX: handle v = 0 case for messages */
4246 if (bit_size < 0)
4247 error("negative width in bit-field '%s'",
4248 get_tok_str(v, NULL));
4249 if (v && bit_size == 0)
4250 error("zero width for bit-field '%s'",
4251 get_tok_str(v, NULL));
4253 size = type_size(t, &align);
4254 lbit_pos = 0;
4255 if (bit_size >= 0) {
4256 bt = t & VT_BTYPE;
4257 if (bt != VT_INT &&
4258 bt != VT_BYTE &&
4259 bt != VT_SHORT)
4260 error("bitfields must have scalar type");
4261 bsize = size * 8;
4262 if (bit_size > bsize) {
4263 error("width of '%s' exceeds its type",
4264 get_tok_str(v, NULL));
4265 } else if (bit_size == bsize) {
4266 /* no need for bit fields */
4267 bit_pos = 0;
4268 } else if (bit_size == 0) {
4269 /* XXX: what to do if only padding in a
4270 structure ? */
4271 /* zero size: means to pad */
4272 if (bit_pos > 0)
4273 bit_pos = bsize;
4274 } else {
4275 /* we do not have enough room ? */
4276 if ((bit_pos + bit_size) > bsize)
4277 bit_pos = 0;
4278 lbit_pos = bit_pos;
4279 /* XXX: handle LSB first */
4280 t |= VT_BITFIELD |
4281 (bit_pos << VT_STRUCT_SHIFT) |
4282 (bit_size << (VT_STRUCT_SHIFT + 6));
4283 bit_pos += bit_size;
4285 } else {
4286 bit_pos = 0;
4288 if (v) {
4289 /* add new memory data only if starting
4290 bit field */
4291 if (lbit_pos == 0) {
4292 if (a == TOK_STRUCT) {
4293 c = (c + align - 1) & -align;
4294 offset = c;
4295 c += size;
4296 } else {
4297 offset = 0;
4298 if (size > c)
4299 c = size;
4301 if (align > maxalign)
4302 maxalign = align;
4304 #if 0
4305 printf("add field %s offset=%d",
4306 get_tok_str(v, NULL), offset);
4307 if (t & VT_BITFIELD) {
4308 printf(" pos=%d size=%d",
4309 (t >> VT_STRUCT_SHIFT) & 0x3f,
4310 (t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
4312 printf("\n");
4313 #endif
4314 ss = sym_push(v | SYM_FIELD, t, 0, offset);
4315 *ps = ss;
4316 ps = &ss->next;
4318 if (tok == ';' || tok == -1)
4319 break;
4320 skip(',');
4322 skip(';');
4324 if (tok == '}')
4325 break;
4327 skip('}');
4328 /* size for struct/union, dummy for enum */
4329 s->c = (c + maxalign - 1) & -maxalign;
4331 return u;
4334 /* return 0 if no type declaration. otherwise, return the basic type
4335 and skip it.
4337 int parse_btype(int *type_ptr, AttributeDef *ad)
4339 int t, u, type_found;
4340 Sym *s;
4342 memset(ad, 0, sizeof(AttributeDef));
4343 type_found = 0;
4344 t = 0;
4345 while(1) {
4346 switch(tok) {
4347 /* basic types */
4348 case TOK_CHAR:
4349 u = VT_BYTE;
4350 basic_type:
4351 next();
4352 basic_type1:
4353 if ((t & VT_BTYPE) != 0)
4354 error("too many basic types");
4355 t |= u;
4356 break;
4357 case TOK_VOID:
4358 u = VT_VOID;
4359 goto basic_type;
4360 case TOK_SHORT:
4361 u = VT_SHORT;
4362 goto basic_type;
4363 case TOK_INT:
4364 next();
4365 break;
4366 case TOK_LONG:
4367 next();
4368 if ((t & VT_BTYPE) == VT_DOUBLE) {
4369 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
4370 } else if ((t & VT_BTYPE) == VT_LONG) {
4371 t = (t & ~VT_BTYPE) | VT_LLONG;
4372 } else {
4373 u = VT_LONG;
4374 goto basic_type1;
4376 break;
4377 case TOK_BOOL:
4378 u = VT_BOOL;
4379 goto basic_type;
4380 case TOK_FLOAT:
4381 u = VT_FLOAT;
4382 goto basic_type;
4383 case TOK_DOUBLE:
4384 next();
4385 if ((t & VT_BTYPE) == VT_LONG) {
4386 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
4387 } else {
4388 u = VT_DOUBLE;
4389 goto basic_type1;
4391 break;
4392 case TOK_ENUM:
4393 u = struct_decl(VT_ENUM);
4394 goto basic_type1;
4395 case TOK_STRUCT:
4396 case TOK_UNION:
4397 u = struct_decl(VT_STRUCT);
4398 goto basic_type1;
4400 /* type modifiers */
4401 case TOK_CONST:
4402 case TOK_VOLATILE:
4403 case TOK_REGISTER:
4404 case TOK_SIGNED:
4405 case TOK___SIGNED__:
4406 case TOK_AUTO:
4407 case TOK_INLINE:
4408 case TOK___INLINE__:
4409 case TOK_RESTRICT:
4410 next();
4411 break;
4412 case TOK_UNSIGNED:
4413 t |= VT_UNSIGNED;
4414 next();
4415 break;
4417 /* storage */
4418 case TOK_EXTERN:
4419 t |= VT_EXTERN;
4420 next();
4421 break;
4422 case TOK_STATIC:
4423 t |= VT_STATIC;
4424 next();
4425 break;
4426 case TOK_TYPEDEF:
4427 t |= VT_TYPEDEF;
4428 next();
4429 break;
4430 /* GNUC attribute */
4431 case TOK___ATTRIBUTE__:
4432 parse_attribute(ad);
4433 break;
4434 default:
4435 s = sym_find(tok);
4436 if (!s || !(s->t & VT_TYPEDEF))
4437 goto the_end;
4438 t |= (s->t & ~VT_TYPEDEF);
4439 next();
4440 break;
4442 type_found = 1;
4444 the_end:
4445 /* long is never used as type */
4446 if ((t & VT_BTYPE) == VT_LONG)
4447 t = (t & ~VT_BTYPE) | VT_INT;
4448 *type_ptr = t;
4449 return type_found;
4452 int post_type(int t, AttributeDef *ad)
4454 int p, n, pt, l, t1;
4455 Sym **plast, *s, *first;
4456 AttributeDef ad1;
4458 if (tok == '(') {
4459 /* function declaration */
4460 next();
4461 l = 0;
4462 first = NULL;
4463 plast = &first;
4464 while (tok != ')') {
4465 /* read param name and compute offset */
4466 if (l != FUNC_OLD) {
4467 if (!parse_btype(&pt, &ad1)) {
4468 if (l) {
4469 error("invalid type");
4470 } else {
4471 l = FUNC_OLD;
4472 goto old_proto;
4475 l = FUNC_NEW;
4476 if ((pt & VT_BTYPE) == VT_VOID && tok == ')')
4477 break;
4478 pt = type_decl(&ad1, &n, pt, TYPE_DIRECT | TYPE_ABSTRACT);
4479 if ((pt & VT_BTYPE) == VT_VOID)
4480 error("parameter declared as void");
4481 } else {
4482 old_proto:
4483 n = tok;
4484 pt = VT_INT;
4485 next();
4487 /* array must be transformed to pointer according to ANSI C */
4488 pt &= ~VT_ARRAY;
4489 s = sym_push(n | SYM_FIELD, pt, 0, 0);
4490 *plast = s;
4491 plast = &s->next;
4492 if (tok == ',') {
4493 next();
4494 if (l == FUNC_NEW && tok == TOK_DOTS) {
4495 l = FUNC_ELLIPSIS;
4496 next();
4497 break;
4501 /* if no parameters, then old type prototype */
4502 if (l == 0)
4503 l = FUNC_OLD;
4504 skip(')');
4505 t1 = t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN);
4506 t = post_type(t & ~(VT_TYPEDEF | VT_STATIC | VT_EXTERN), ad);
4507 /* we push a anonymous symbol which will contain the function prototype */
4508 p = anon_sym++;
4509 s = sym_push(p, t, ad->func_call, l);
4510 s->next = first;
4511 t = t1 | VT_FUNC | (p << VT_STRUCT_SHIFT);
4512 } else if (tok == '[') {
4513 /* array definition */
4514 next();
4515 n = -1;
4516 if (tok != ']') {
4517 n = expr_const();
4518 if (n < 0)
4519 error("invalid array size");
4521 skip(']');
4522 /* parse next post type */
4523 t1 = t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN);
4524 t = post_type(t & ~(VT_TYPEDEF | VT_STATIC | VT_EXTERN), ad);
4526 /* we push a anonymous symbol which will contain the array
4527 element type */
4528 p = anon_sym++;
4529 sym_push(p, t, 0, n);
4530 t = t1 | VT_ARRAY | VT_PTR | (p << VT_STRUCT_SHIFT);
4532 return t;
4535 /* Read a type declaration (except basic type), and return the
4536 type. 'td' is a bitmask indicating which kind of type decl is
4537 expected. 't' should contain the basic type. 'ad' is the attribute
4538 definition of the basic type. It can be modified by type_decl(). */
4539 int type_decl(AttributeDef *ad, int *v, int t, int td)
4541 int u, p;
4542 Sym *s;
4544 while (tok == '*') {
4545 next();
4546 while (tok == TOK_CONST || tok == TOK_VOLATILE || tok == TOK_RESTRICT)
4547 next();
4548 t = mk_pointer(t);
4551 /* recursive type */
4552 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
4553 if (tok == '(') {
4554 next();
4555 /* XXX: this is not correct to modify 'ad' at this point, but
4556 the syntax is not clear */
4557 if (tok == TOK___ATTRIBUTE__)
4558 parse_attribute(ad);
4559 u = type_decl(ad, v, 0, td);
4560 skip(')');
4561 } else {
4562 u = 0;
4563 /* type identifier */
4564 if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
4565 *v = tok;
4566 next();
4567 } else {
4568 if (!(td & TYPE_ABSTRACT))
4569 expect("identifier");
4570 *v = 0;
4573 /* append t at the end of u */
4574 t = post_type(t, ad);
4575 if (tok == TOK___ATTRIBUTE__)
4576 parse_attribute(ad);
4577 if (!u)
4578 return t;
4579 p = u;
4580 while(1) {
4581 s = sym_find((unsigned)p >> VT_STRUCT_SHIFT);
4582 p = s->t;
4583 if (!p) {
4584 s->t = t;
4585 break;
4588 return u;
4591 /* define a new external reference to a symbol 'v' of type 'u' */
4592 Sym *external_sym(int v, int u, int r)
4594 Sym *s;
4596 s = sym_find(v);
4597 if (!s) {
4598 /* push forward reference */
4599 s = sym_push1(&global_stack,
4600 v, u | VT_EXTERN, 0);
4601 s->r = r | VT_CONST | VT_SYM;
4603 return s;
4606 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
4607 static int lvalue_type(int t)
4609 int bt, r;
4610 r = VT_LVAL;
4611 bt = t & VT_BTYPE;
4612 if (bt == VT_BYTE)
4613 r |= VT_LVAL_BYTE;
4614 else if (bt == VT_SHORT)
4615 r |= VT_LVAL_SHORT;
4616 else
4617 return r;
4618 if (t & VT_UNSIGNED)
4619 r |= VT_LVAL_UNSIGNED;
4620 return r;
4623 /* indirection with full error checking and bound check */
4624 static void indir(void)
4626 if ((vtop->t & VT_BTYPE) != VT_PTR)
4627 expect("pointer");
4628 if (vtop->r & VT_LVAL)
4629 gv(RC_INT);
4630 vtop->t = pointed_type(vtop->t);
4631 /* an array is never an lvalue */
4632 if (!(vtop->t & VT_ARRAY)) {
4633 vtop->r |= lvalue_type(vtop->t);
4634 /* if bound checking, the referenced pointer must be checked */
4635 if (do_bounds_check)
4636 vtop->r |= VT_MUSTBOUND;
4640 /* pass a parameter to a function and do type checking and casting */
4641 void gfunc_param_typed(GFuncContext *gf, Sym *func, Sym *arg)
4643 int func_type;
4644 func_type = func->c;
4645 if (func_type == FUNC_OLD ||
4646 (func_type == FUNC_ELLIPSIS && arg == NULL)) {
4647 /* default casting : only need to convert float to double */
4648 if ((vtop->t & VT_BTYPE) == VT_FLOAT)
4649 gen_cast(VT_DOUBLE);
4650 } else if (arg == NULL) {
4651 error("too many arguments to function");
4652 } else {
4653 gen_assign_cast(arg->t);
4655 gfunc_param(gf);
4658 void unary(void)
4660 int n, t, ft, fc, p, align, size, r, data_offset;
4661 Sym *s;
4662 GFuncContext gf;
4663 AttributeDef ad;
4665 if (tok == TOK_CINT || tok == TOK_CCHAR || tok == TOK_LCHAR) {
4666 vpushi(tokc.i);
4667 next();
4668 } else if (tok == TOK_CUINT) {
4669 vsetc(VT_INT | VT_UNSIGNED, VT_CONST, &tokc);
4670 next();
4671 } else if (tok == TOK_CLLONG) {
4672 vsetc(VT_LLONG, VT_CONST, &tokc);
4673 next();
4674 } else if (tok == TOK_CULLONG) {
4675 vsetc(VT_LLONG | VT_UNSIGNED, VT_CONST, &tokc);
4676 next();
4677 } else if (tok == TOK_CFLOAT) {
4678 vsetc(VT_FLOAT, VT_CONST, &tokc);
4679 next();
4680 } else if (tok == TOK_CDOUBLE) {
4681 vsetc(VT_DOUBLE, VT_CONST, &tokc);
4682 next();
4683 } else if (tok == TOK_CLDOUBLE) {
4684 vsetc(VT_LDOUBLE, VT_CONST, &tokc);
4685 next();
4686 } else if (tok == TOK___FUNC__) {
4687 /* special function name identifier */
4688 /* generate (char *) type */
4689 data_offset = data_section->data_ptr - data_section->data;
4690 vpush_ref(mk_pointer(VT_BYTE), data_section, data_offset);
4691 strcpy(data_section->data + data_offset, funcname);
4692 data_offset += strlen(funcname) + 1;
4693 data_section->data_ptr = data_section->data + data_offset;
4694 next();
4695 } else if (tok == TOK_LSTR) {
4696 t = VT_INT;
4697 goto str_init;
4698 } else if (tok == TOK_STR) {
4699 /* string parsing */
4700 t = VT_BYTE;
4701 str_init:
4702 type_size(t, &align);
4703 data_offset = data_section->data_ptr - data_section->data;
4704 data_offset = (data_offset + align - 1) & -align;
4705 fc = data_offset;
4706 /* we must declare it as an array first to use initializer parser */
4707 t = VT_ARRAY | mk_pointer(t);
4708 decl_initializer(t, data_section, data_offset, 1, 0);
4709 data_offset += type_size(t, &align);
4710 /* put it as pointer */
4711 vpush_ref(t & ~VT_ARRAY, data_section, fc);
4712 data_section->data_ptr = data_section->data + data_offset;
4713 } else {
4714 t = tok;
4715 next();
4716 if (t == '(') {
4717 /* cast ? */
4718 if (parse_btype(&t, &ad)) {
4719 ft = type_decl(&ad, &n, t, TYPE_ABSTRACT);
4720 skip(')');
4721 /* check ISOC99 compound literal */
4722 if (tok == '{') {
4723 /* data is allocated locally by default */
4724 if (global_expr)
4725 r = VT_CONST;
4726 else
4727 r = VT_LOCAL;
4728 /* all except arrays are lvalues */
4729 if (!(ft & VT_ARRAY))
4730 r |= lvalue_type(ft);
4731 memset(&ad, 0, sizeof(AttributeDef));
4732 decl_initializer_alloc(ft, &ad, r, 1, 0, 0);
4733 } else {
4734 unary();
4735 gen_cast(ft);
4737 } else {
4738 gexpr();
4739 skip(')');
4741 } else if (t == '*') {
4742 unary();
4743 indir();
4744 } else if (t == '&') {
4745 unary();
4746 /* functions names must be treated as function pointers,
4747 except for unary '&' and sizeof. Since we consider that
4748 functions are not lvalues, we only have to handle it
4749 there and in function calls. */
4750 /* arrays can also be used although they are not lvalues */
4751 if ((vtop->t & VT_BTYPE) != VT_FUNC &&
4752 !(vtop->t & VT_ARRAY))
4753 test_lvalue();
4754 vtop->t = mk_pointer(vtop->t);
4755 gaddrof();
4756 } else
4757 if (t == '!') {
4758 unary();
4759 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST)
4760 vtop->c.i = !vtop->c.i;
4761 else if ((vtop->r & VT_VALMASK) == VT_CMP)
4762 vtop->c.i = vtop->c.i ^ 1;
4763 else
4764 vset(VT_INT, VT_JMP, gtst(1, 0));
4765 } else
4766 if (t == '~') {
4767 unary();
4768 vpushi(-1);
4769 gen_op('^');
4770 } else
4771 if (t == '+') {
4772 unary();
4773 } else
4774 if (t == TOK_SIZEOF) {
4775 if (tok == '(') {
4776 next();
4777 if (parse_btype(&t, &ad)) {
4778 t = type_decl(&ad, &n, t, TYPE_ABSTRACT);
4779 } else {
4780 /* XXX: some code could be generated: add eval
4781 flag */
4782 gexpr();
4783 t = vtop->t;
4784 vpop();
4786 skip(')');
4787 } else {
4788 unary();
4789 t = vtop->t;
4790 vpop();
4792 vpushi(type_size(t, &t));
4793 } else
4794 if (t == TOK_INC || t == TOK_DEC) {
4795 unary();
4796 inc(0, t);
4797 } else if (t == '-') {
4798 vpushi(0);
4799 unary();
4800 gen_op('-');
4801 } else
4803 if (t < TOK_UIDENT)
4804 expect("identifier");
4805 s = sym_find(t);
4806 if (!s) {
4807 if (tok != '(')
4808 error("'%s' undeclared", get_tok_str(t, NULL));
4809 /* for simple function calls, we tolerate undeclared
4810 external reference */
4811 p = anon_sym++;
4812 sym_push1(&global_stack, p, 0, FUNC_OLD);
4813 /* int() function */
4814 s = external_sym(t, VT_FUNC | (p << VT_STRUCT_SHIFT), 0);
4816 vset(s->t, s->r, s->c);
4817 /* if forward reference, we must point to s */
4818 if (vtop->r & VT_SYM)
4819 vtop->c.sym = s;
4823 /* post operations */
4824 while (1) {
4825 if (tok == TOK_INC || tok == TOK_DEC) {
4826 inc(1, tok);
4827 next();
4828 } else if (tok == '.' || tok == TOK_ARROW) {
4829 /* field */
4830 if (tok == TOK_ARROW)
4831 indir();
4832 test_lvalue();
4833 gaddrof();
4834 next();
4835 /* expect pointer on structure */
4836 if ((vtop->t & VT_BTYPE) != VT_STRUCT)
4837 expect("struct or union");
4838 s = sym_find(((unsigned)vtop->t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
4839 /* find field */
4840 tok |= SYM_FIELD;
4841 while ((s = s->next) != NULL) {
4842 if (s->v == tok)
4843 break;
4845 if (!s)
4846 error("field not found");
4847 /* add field offset to pointer */
4848 vtop->t = char_pointer_type; /* change type to 'char *' */
4849 vpushi(s->c);
4850 gen_op('+');
4851 /* change type to field type, and set to lvalue */
4852 vtop->t = s->t;
4853 /* an array is never an lvalue */
4854 if (!(vtop->t & VT_ARRAY))
4855 vtop->r |= lvalue_type(vtop->t);
4856 next();
4857 } else if (tok == '[') {
4858 next();
4859 gexpr();
4860 gen_op('+');
4861 indir();
4862 skip(']');
4863 } else if (tok == '(') {
4864 SValue ret;
4865 Sym *sa;
4867 /* function call */
4868 if ((vtop->t & VT_BTYPE) != VT_FUNC) {
4869 /* pointer test (no array accepted) */
4870 if ((vtop->t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
4871 vtop->t = pointed_type(vtop->t);
4872 if ((vtop->t & VT_BTYPE) != VT_FUNC)
4873 goto error_func;
4874 } else {
4875 error_func:
4876 expect("function pointer");
4878 } else {
4879 vtop->r &= ~VT_LVAL; /* no lvalue */
4881 /* get return type */
4882 s = sym_find((unsigned)vtop->t >> VT_STRUCT_SHIFT);
4883 save_regs(0); /* save used temporary registers */
4884 gfunc_start(&gf, s->r);
4885 next();
4886 sa = s->next; /* first parameter */
4887 #ifdef INVERT_FUNC_PARAMS
4889 int parlevel;
4890 Sym *args, *s1;
4891 ParseState saved_parse_state;
4892 TokenString str;
4894 /* read each argument and store it on a stack */
4895 /* XXX: merge it with macro args ? */
4896 args = NULL;
4897 if (tok != ')') {
4898 for(;;) {
4899 tok_str_new(&str);
4900 parlevel = 0;
4901 while ((parlevel > 0 || (tok != ')' && tok != ',')) &&
4902 tok != -1) {
4903 if (tok == '(')
4904 parlevel++;
4905 else if (tok == ')')
4906 parlevel--;
4907 tok_str_add_tok(&str);
4908 next();
4910 tok_str_add(&str, -1); /* end of file added */
4911 tok_str_add(&str, 0);
4912 s1 = sym_push2(&args, 0, 0, (int)str.str);
4913 s1->next = sa; /* add reference to argument */
4914 if (sa)
4915 sa = sa->next;
4916 if (tok == ')')
4917 break;
4918 skip(',');
4922 /* now generate code in reverse order by reading the stack */
4923 save_parse_state(&saved_parse_state);
4924 while (args) {
4925 macro_ptr = (int *)args->c;
4926 next();
4927 expr_eq();
4928 if (tok != -1)
4929 expect("',' or ')'");
4930 gfunc_param_typed(&gf, s, args->next);
4931 s1 = args->prev;
4932 free((int *)args->c);
4933 free(args);
4934 args = s1;
4936 restore_parse_state(&saved_parse_state);
4938 #endif
4939 /* compute first implicit argument if a structure is returned */
4940 if ((s->t & VT_BTYPE) == VT_STRUCT) {
4941 /* get some space for the returned structure */
4942 size = type_size(s->t, &align);
4943 loc = (loc - size) & -align;
4944 ret.t = s->t;
4945 ret.r = VT_LOCAL | VT_LVAL;
4946 /* pass it as 'int' to avoid structure arg passing
4947 problems */
4948 vset(VT_INT, VT_LOCAL, loc);
4949 ret.c = vtop->c;
4950 gfunc_param(&gf);
4951 } else {
4952 ret.t = s->t;
4953 ret.r2 = VT_CONST;
4954 /* return in register */
4955 if (is_float(ret.t)) {
4956 ret.r = REG_FRET;
4957 } else {
4958 if ((ret.t & VT_BTYPE) == VT_LLONG)
4959 ret.r2 = REG_LRET;
4960 ret.r = REG_IRET;
4962 ret.c.i = 0;
4964 #ifndef INVERT_FUNC_PARAMS
4965 if (tok != ')') {
4966 for(;;) {
4967 expr_eq();
4968 gfunc_param_typed(&gf, s, sa);
4969 if (sa)
4970 sa = sa->next;
4971 if (tok == ')')
4972 break;
4973 skip(',');
4976 #endif
4977 if (sa)
4978 error("too few arguments to function");
4979 skip(')');
4980 gfunc_call(&gf);
4981 /* return value */
4982 vsetc(ret.t, ret.r, &ret.c);
4983 vtop->r2 = ret.r2;
4984 } else {
4985 break;
4990 void uneq(void)
4992 int t;
4994 unary();
4995 if (tok == '=' ||
4996 (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
4997 tok == TOK_A_XOR || tok == TOK_A_OR ||
4998 tok == TOK_A_SHL || tok == TOK_A_SAR) {
4999 test_lvalue();
5000 t = tok;
5001 next();
5002 if (t == '=') {
5003 expr_eq();
5004 } else {
5005 vdup();
5006 expr_eq();
5007 gen_op(t & 0x7f);
5009 vstore();
5013 void sum(int l)
5015 int t;
5017 if (l == 0)
5018 uneq();
5019 else {
5020 sum(--l);
5021 while ((l == 0 && (tok == '*' || tok == '/' || tok == '%')) ||
5022 (l == 1 && (tok == '+' || tok == '-')) ||
5023 (l == 2 && (tok == TOK_SHL || tok == TOK_SAR)) ||
5024 (l == 3 && ((tok >= TOK_ULE && tok <= TOK_GT) ||
5025 tok == TOK_ULT || tok == TOK_UGE)) ||
5026 (l == 4 && (tok == TOK_EQ || tok == TOK_NE)) ||
5027 (l == 5 && tok == '&') ||
5028 (l == 6 && tok == '^') ||
5029 (l == 7 && tok == '|') ||
5030 (l == 8 && tok == TOK_LAND) ||
5031 (l == 9 && tok == TOK_LOR)) {
5032 t = tok;
5033 next();
5034 sum(l);
5035 gen_op(t);
5040 /* only used if non constant */
5041 void eand(void)
5043 int t;
5045 sum(8);
5046 t = 0;
5047 while (1) {
5048 if (tok != TOK_LAND) {
5049 if (t) {
5050 t = gtst(1, t);
5051 vset(VT_INT, VT_JMPI, t);
5053 break;
5055 t = gtst(1, t);
5056 next();
5057 sum(8);
5061 void eor(void)
5063 int t;
5065 eand();
5066 t = 0;
5067 while (1) {
5068 if (tok != TOK_LOR) {
5069 if (t) {
5070 t = gtst(0, t);
5071 vset(VT_INT, VT_JMP, t);
5073 break;
5075 t = gtst(0, t);
5076 next();
5077 eand();
5081 /* XXX: better constant handling */
5082 void expr_eq(void)
5084 int t, u, c, r1, r2, rc;
5086 if (const_wanted) {
5087 sum(10);
5088 if (tok == '?') {
5089 c = vtop->c.i;
5090 vpop();
5091 next();
5092 gexpr();
5093 t = vtop->c.i;
5094 vpop();
5095 skip(':');
5096 expr_eq();
5097 if (c)
5098 vtop->c.i = t;
5100 } else {
5101 eor();
5102 if (tok == '?') {
5103 next();
5104 save_regs(1); /* we need to save all registers here except
5105 at the top because it is a branch point */
5106 t = gtst(1, 0);
5107 gexpr();
5108 /* XXX: long long handling ? */
5109 rc = RC_INT;
5110 if (is_float(vtop->t))
5111 rc = RC_FLOAT;
5112 r1 = gv(rc);
5113 vtop--; /* no vpop so that FP stack is not flushed */
5114 skip(':');
5115 u = gjmp(0);
5117 gsym(t);
5118 expr_eq();
5119 r2 = gv(rc);
5120 move_reg(r1, r2);
5121 vtop->r = r1;
5122 gsym(u);
5127 void gexpr(void)
5129 while (1) {
5130 expr_eq();
5131 if (tok != ',')
5132 break;
5133 vpop();
5134 next();
5138 /* parse a constant expression and return value in vtop */
5139 void expr_const1(void)
5141 int a;
5142 a = const_wanted;
5143 const_wanted = 1;
5144 expr_eq();
5145 if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST)
5146 expect("constant");
5147 const_wanted = a;
5150 /* parse an integer constant and return its value */
5151 int expr_const(void)
5153 int c;
5154 expr_const1();
5155 c = vtop->c.i;
5156 vpop();
5157 return c;
5160 /* return the label token if current token is a label, otherwise
5161 return zero */
5162 int is_label(void)
5164 int t;
5165 CValue c;
5167 /* fast test first */
5168 if (tok < TOK_UIDENT)
5169 return 0;
5170 /* no need to save tokc since we expect an identifier */
5171 t = tok;
5172 c = tokc;
5173 next();
5174 if (tok == ':') {
5175 next();
5176 return t;
5177 } else {
5178 /* XXX: may not work in all cases (macros ?) */
5179 tok1 = tok;
5180 tok1c = tokc;
5181 tok = t;
5182 tokc = c;
5183 return 0;
5187 void block(int *bsym, int *csym, int *case_sym, int *def_sym, int case_reg)
5189 int a, b, c, d;
5190 Sym *s;
5192 /* generate line number info */
5193 if (do_debug &&
5194 (last_line_num != file->line_num || last_ind != ind)) {
5195 put_stabn(N_SLINE, 0, file->line_num, ind - func_ind);
5196 last_ind = ind;
5197 last_line_num = file->line_num;
5200 if (tok == TOK_IF) {
5201 /* if test */
5202 next();
5203 skip('(');
5204 gexpr();
5205 skip(')');
5206 a = gtst(1, 0);
5207 block(bsym, csym, case_sym, def_sym, case_reg);
5208 c = tok;
5209 if (c == TOK_ELSE) {
5210 next();
5211 d = gjmp(0);
5212 gsym(a);
5213 block(bsym, csym, case_sym, def_sym, case_reg);
5214 gsym(d); /* patch else jmp */
5215 } else
5216 gsym(a);
5217 } else if (tok == TOK_WHILE) {
5218 next();
5219 d = ind;
5220 skip('(');
5221 gexpr();
5222 skip(')');
5223 a = gtst(1, 0);
5224 b = 0;
5225 block(&a, &b, case_sym, def_sym, case_reg);
5226 gjmp_addr(d);
5227 gsym(a);
5228 gsym_addr(b, d);
5229 } else if (tok == '{') {
5230 next();
5231 /* declarations */
5232 s = local_stack.top;
5233 while (tok != '}') {
5234 decl(VT_LOCAL);
5235 if (tok != '}')
5236 block(bsym, csym, case_sym, def_sym, case_reg);
5238 /* pop locally defined symbols */
5239 sym_pop(&local_stack, s);
5240 next();
5241 } else if (tok == TOK_RETURN) {
5242 next();
5243 if (tok != ';') {
5244 gexpr();
5245 gen_assign_cast(func_vt);
5246 if ((func_vt & VT_BTYPE) == VT_STRUCT) {
5247 /* if returning structure, must copy it to implicit
5248 first pointer arg location */
5249 vset(mk_pointer(func_vt), VT_LOCAL | VT_LVAL, func_vc);
5250 indir();
5251 vswap();
5252 /* copy structure value to pointer */
5253 vstore();
5254 } else if (is_float(func_vt)) {
5255 gv(RC_FRET);
5256 } else {
5257 gv(RC_IRET);
5259 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
5261 skip(';');
5262 rsym = gjmp(rsym); /* jmp */
5263 } else if (tok == TOK_BREAK) {
5264 /* compute jump */
5265 if (!bsym)
5266 error("cannot break");
5267 *bsym = gjmp(*bsym);
5268 next();
5269 skip(';');
5270 } else if (tok == TOK_CONTINUE) {
5271 /* compute jump */
5272 if (!csym)
5273 error("cannot continue");
5274 *csym = gjmp(*csym);
5275 next();
5276 skip(';');
5277 } else if (tok == TOK_FOR) {
5278 int e;
5279 next();
5280 skip('(');
5281 if (tok != ';') {
5282 gexpr();
5283 vpop();
5285 skip(';');
5286 d = ind;
5287 c = ind;
5288 a = 0;
5289 b = 0;
5290 if (tok != ';') {
5291 gexpr();
5292 a = gtst(1, 0);
5294 skip(';');
5295 if (tok != ')') {
5296 e = gjmp(0);
5297 c = ind;
5298 gexpr();
5299 vpop();
5300 gjmp_addr(d);
5301 gsym(e);
5303 skip(')');
5304 block(&a, &b, case_sym, def_sym, case_reg);
5305 gjmp_addr(c);
5306 gsym(a);
5307 gsym_addr(b, c);
5308 } else
5309 if (tok == TOK_DO) {
5310 next();
5311 a = 0;
5312 b = 0;
5313 d = ind;
5314 block(&a, &b, case_sym, def_sym, case_reg);
5315 skip(TOK_WHILE);
5316 skip('(');
5317 gsym(b);
5318 gexpr();
5319 c = gtst(0, 0);
5320 gsym_addr(c, d);
5321 skip(')');
5322 gsym(a);
5323 skip(';');
5324 } else
5325 if (tok == TOK_SWITCH) {
5326 next();
5327 skip('(');
5328 gexpr();
5329 /* XXX: other types than integer */
5330 case_reg = gv(RC_INT);
5331 vpop();
5332 skip(')');
5333 a = 0;
5334 b = gjmp(0); /* jump to first case */
5335 c = 0;
5336 block(&a, csym, &b, &c, case_reg);
5337 /* if no default, jmp after switch */
5338 if (c == 0)
5339 c = ind;
5340 /* default label */
5341 gsym_addr(b, c);
5342 /* break label */
5343 gsym(a);
5344 } else
5345 if (tok == TOK_CASE) {
5346 int v1, v2;
5347 if (!case_sym)
5348 expect("switch");
5349 next();
5350 v1 = expr_const();
5351 v2 = v1;
5352 if (gnu_ext && tok == TOK_DOTS) {
5353 next();
5354 v2 = expr_const();
5355 if (v2 < v1)
5356 warning("empty case range");
5358 /* since a case is like a label, we must skip it with a jmp */
5359 b = gjmp(0);
5360 gsym(*case_sym);
5361 vset(VT_INT, case_reg, 0);
5362 vpushi(v1);
5363 if (v1 == v2) {
5364 gen_op(TOK_EQ);
5365 *case_sym = gtst(1, 0);
5366 } else {
5367 gen_op(TOK_GE);
5368 *case_sym = gtst(1, 0);
5369 vset(VT_INT, case_reg, 0);
5370 vpushi(v2);
5371 gen_op(TOK_LE);
5372 *case_sym = gtst(1, *case_sym);
5374 gsym(b);
5375 skip(':');
5376 block(bsym, csym, case_sym, def_sym, case_reg);
5377 } else
5378 if (tok == TOK_DEFAULT) {
5379 next();
5380 skip(':');
5381 if (!def_sym)
5382 expect("switch");
5383 if (*def_sym)
5384 error("too many 'default'");
5385 *def_sym = ind;
5386 block(bsym, csym, case_sym, def_sym, case_reg);
5387 } else
5388 if (tok == TOK_GOTO) {
5389 next();
5390 s = sym_find1(&label_stack, tok);
5391 /* put forward definition if needed */
5392 if (!s)
5393 s = sym_push1(&label_stack, tok, LABEL_FORWARD, 0);
5394 /* label already defined */
5395 if (s->t & LABEL_FORWARD)
5396 s->c = gjmp(s->c);
5397 else
5398 gjmp_addr(s->c);
5399 next();
5400 skip(';');
5401 } else {
5402 b = is_label();
5403 if (b) {
5404 /* label case */
5405 s = sym_find1(&label_stack, b);
5406 if (s) {
5407 if (!(s->t & LABEL_FORWARD))
5408 error("multiple defined label");
5409 gsym(s->c);
5410 s->c = ind;
5411 s->t = 0;
5412 } else {
5413 sym_push1(&label_stack, b, 0, ind);
5415 /* we accept this, but it is a mistake */
5416 if (tok == '}')
5417 warning("deprecated use of label at end of compound statement");
5418 else
5419 block(bsym, csym, case_sym, def_sym, case_reg);
5420 } else {
5421 /* expression case */
5422 if (tok != ';') {
5423 gexpr();
5424 vpop();
5426 skip(';');
5431 /* t is the array or struct type. c is the array or struct
5432 address. cur_index/cur_field is the pointer to the current
5433 value. 'size_only' is true if only size info is needed (only used
5434 in arrays) */
5435 void decl_designator(int t, Section *sec, unsigned long c,
5436 int *cur_index, Sym **cur_field,
5437 int size_only)
5439 Sym *s, *f;
5440 int notfirst, index, align, l;
5442 notfirst = 0;
5443 if (gnu_ext && (l = is_label()) != 0)
5444 goto struct_field;
5446 while (tok == '[' || tok == '.') {
5447 if (tok == '[') {
5448 if (!(t & VT_ARRAY))
5449 expect("array type");
5450 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
5451 next();
5452 index = expr_const();
5453 if (index < 0 || (s->c >= 0 && index >= s->c))
5454 expect("invalid index");
5455 skip(']');
5456 if (!notfirst)
5457 *cur_index = index;
5458 t = pointed_type(t);
5459 c += index * type_size(t, &align);
5460 } else {
5461 next();
5462 l = tok;
5463 next();
5464 struct_field:
5465 if ((t & VT_BTYPE) != VT_STRUCT)
5466 expect("struct/union type");
5467 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
5468 l |= SYM_FIELD;
5469 f = s->next;
5470 while (f) {
5471 if (f->v == l)
5472 break;
5473 f = f->next;
5475 if (!f)
5476 expect("field");
5477 if (!notfirst)
5478 *cur_field = f;
5479 t = f->t | (t & ~VT_TYPE);
5480 c += f->c;
5482 notfirst = 1;
5484 if (notfirst) {
5485 if (tok == '=') {
5486 next();
5487 } else {
5488 if (!gnu_ext)
5489 expect("=");
5491 } else {
5492 if (t & VT_ARRAY) {
5493 index = *cur_index;
5494 t = pointed_type(t);
5495 c += index * type_size(t, &align);
5496 } else {
5497 f = *cur_field;
5498 if (!f)
5499 error("too many field init");
5500 t = f->t | (t & ~VT_TYPE);
5501 c += f->c;
5504 decl_initializer(t, sec, c, 0, size_only);
5507 #define EXPR_VAL 0
5508 #define EXPR_CONST 1
5509 #define EXPR_ANY 2
5511 /* store a value or an expression directly in global data or in local array */
5512 void init_putv(int t, Section *sec, unsigned long c,
5513 int v, int expr_type)
5515 int saved_global_expr, bt;
5516 void *ptr;
5518 switch(expr_type) {
5519 case EXPR_VAL:
5520 vpushi(v);
5521 break;
5522 case EXPR_CONST:
5523 /* compound literals must be allocated globally in this case */
5524 saved_global_expr = global_expr;
5525 global_expr = 1;
5526 expr_const1();
5527 global_expr = saved_global_expr;
5528 break;
5529 case EXPR_ANY:
5530 expr_eq();
5531 break;
5534 if (sec) {
5535 /* XXX: not portable */
5536 /* XXX: generate error if incorrect relocation */
5537 gen_assign_cast(t);
5538 bt = t & VT_BTYPE;
5539 ptr = sec->data + c;
5540 if ((vtop->r & VT_SYM) &&
5541 (bt == VT_BYTE ||
5542 bt == VT_SHORT ||
5543 bt == VT_DOUBLE ||
5544 bt == VT_LDOUBLE ||
5545 bt == VT_LLONG))
5546 error("initializer element is not computable at load time");
5547 switch(bt) {
5548 case VT_BYTE:
5549 *(char *)ptr = vtop->c.i;
5550 break;
5551 case VT_SHORT:
5552 *(short *)ptr = vtop->c.i;
5553 break;
5554 case VT_DOUBLE:
5555 *(double *)ptr = vtop->c.d;
5556 break;
5557 case VT_LDOUBLE:
5558 *(long double *)ptr = vtop->c.ld;
5559 break;
5560 case VT_LLONG:
5561 *(long long *)ptr = vtop->c.ll;
5562 break;
5563 default:
5564 if (vtop->r & VT_SYM) {
5565 greloc(sec, vtop->c.sym, c, R_DATA_32);
5566 *(int *)ptr = 0;
5567 } else {
5568 *(int *)ptr = vtop->c.i;
5570 break;
5572 vtop--;
5573 } else {
5574 vset(t, VT_LOCAL, c);
5575 vswap();
5576 vstore();
5577 vpop();
5581 /* put zeros for variable based init */
5582 void init_putz(int t, Section *sec, unsigned long c, int size)
5584 GFuncContext gf;
5586 if (sec) {
5587 /* nothing to do because globals are already set to zero */
5588 } else {
5589 gfunc_start(&gf, FUNC_CDECL);
5590 vpushi(size);
5591 gfunc_param(&gf);
5592 vpushi(0);
5593 gfunc_param(&gf);
5594 vset(VT_INT, VT_LOCAL, c);
5595 gfunc_param(&gf);
5596 vpushi((int)&memset);
5597 gfunc_call(&gf);
5601 /* 't' contains the type and storage info. 'c' is the offset of the
5602 object in section 'sec'. If 'sec' is NULL, it means stack based
5603 allocation. 'first' is true if array '{' must be read (multi
5604 dimension implicit array init handling). 'size_only' is true if
5605 size only evaluation is wanted (only for arrays). */
5606 void decl_initializer(int t, Section *sec, unsigned long c, int first, int size_only)
5608 int index, array_length, n, no_oblock, nb, parlevel, i;
5609 int t1, size1, align1, expr_type;
5610 Sym *s, *f;
5611 TokenSym *ts;
5613 if (t & VT_ARRAY) {
5614 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
5615 n = s->c;
5616 array_length = 0;
5617 t1 = pointed_type(t);
5618 size1 = type_size(t1, &align1);
5620 no_oblock = 1;
5621 if ((first && tok != TOK_LSTR && tok != TOK_STR) ||
5622 tok == '{') {
5623 skip('{');
5624 no_oblock = 0;
5627 /* only parse strings here if correct type (otherwise: handle
5628 them as ((w)char *) expressions */
5629 if ((tok == TOK_LSTR &&
5630 (t1 & VT_BTYPE) == VT_INT) ||
5631 (tok == TOK_STR &&
5632 (t1 & VT_BTYPE) == VT_BYTE)) {
5633 /* XXX: move multiple string parsing in parser ? */
5634 while (tok == TOK_STR || tok == TOK_LSTR) {
5635 ts = tokc.ts;
5636 /* compute maximum number of chars wanted */
5637 nb = ts->len;
5638 if (n >= 0 && nb > (n - array_length))
5639 nb = n - array_length;
5640 if (!size_only) {
5641 if (ts->len > nb)
5642 warning("initializer-string for array is too long");
5643 for(i=0;i<nb;i++) {
5644 init_putv(t1, sec, c + (array_length + i) * size1,
5645 ts->str[i], EXPR_VAL);
5648 array_length += nb;
5649 next();
5651 /* only add trailing zero if enough storage (no
5652 warning in this case since it is standard) */
5653 if (n < 0 || array_length < n) {
5654 if (!size_only) {
5655 init_putv(t1, sec, c + (array_length * size1), 0, EXPR_VAL);
5657 array_length++;
5659 } else {
5660 index = 0;
5661 while (tok != '}') {
5662 decl_designator(t, sec, c, &index, NULL, size_only);
5663 if (n >= 0 && index >= n)
5664 error("index too large");
5665 /* must put zero in holes (note that doing it that way
5666 ensures that it even works with designators) */
5667 if (!size_only && array_length < index) {
5668 init_putz(t1, sec, c + array_length * size1,
5669 (index - array_length) * size1);
5671 index++;
5672 if (index > array_length)
5673 array_length = index;
5674 /* special test for multi dimensional arrays (may not
5675 be strictly correct if designators are used at the
5676 same time) */
5677 if (index >= n && no_oblock)
5678 break;
5679 if (tok == '}')
5680 break;
5681 skip(',');
5684 if (!no_oblock)
5685 skip('}');
5686 /* put zeros at the end */
5687 if (!size_only && n >= 0 && array_length < n) {
5688 init_putz(t1, sec, c + array_length * size1,
5689 (n - array_length) * size1);
5691 /* patch type size if needed */
5692 if (n < 0)
5693 s->c = array_length;
5694 } else if ((t & VT_BTYPE) == VT_STRUCT && tok == '{') {
5695 /* XXX: union needs only one init */
5696 next();
5697 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
5698 f = s->next;
5699 array_length = 0;
5700 index = 0;
5701 n = s->c;
5702 while (tok != '}') {
5703 decl_designator(t, sec, c, NULL, &f, size_only);
5704 /* fill with zero between fields */
5705 index = f->c;
5706 if (!size_only && array_length < index) {
5707 init_putz(t, sec, c + array_length,
5708 index - array_length);
5710 index = index + type_size(f->t, &align1);
5711 if (index > array_length)
5712 array_length = index;
5713 if (tok == '}')
5714 break;
5715 skip(',');
5716 f = f->next;
5718 /* put zeros at the end */
5719 if (!size_only && array_length < n) {
5720 init_putz(t, sec, c + array_length,
5721 n - array_length);
5723 skip('}');
5724 } else if (tok == '{') {
5725 next();
5726 decl_initializer(t, sec, c, first, size_only);
5727 skip('}');
5728 } else if (size_only) {
5729 /* just skip expression */
5730 parlevel = 0;
5731 while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
5732 tok != -1) {
5733 if (tok == '(')
5734 parlevel++;
5735 else if (tok == ')')
5736 parlevel--;
5737 next();
5739 } else {
5740 /* currently, we always use constant expression for globals
5741 (may change for scripting case) */
5742 expr_type = EXPR_CONST;
5743 if (!sec)
5744 expr_type = EXPR_ANY;
5745 init_putv(t, sec, c, 0, expr_type);
5749 /* parse an initializer for type 't' if 'has_init' is true, and
5750 allocate space in local or global data space ('r' is either
5751 VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
5752 variable 'v' of scope 'scope' is declared before initializers are
5753 parsed. If 'v' is zero, then a reference to the new object is put
5754 in the value stack. */
5755 void decl_initializer_alloc(int t, AttributeDef *ad, int r, int has_init,
5756 int v, int scope)
5758 int size, align, addr, data_offset;
5759 int level;
5760 ParseState saved_parse_state;
5761 TokenString init_str;
5762 Section *sec;
5764 size = type_size(t, &align);
5765 /* If unknown size, we must evaluate it before
5766 evaluating initializers because
5767 initializers can generate global data too
5768 (e.g. string pointers or ISOC99 compound
5769 literals). It also simplifies local
5770 initializers handling */
5771 tok_str_new(&init_str);
5772 if (size < 0) {
5773 if (!has_init)
5774 error("unknown type size");
5775 /* get all init string */
5776 level = 0;
5777 while (level > 0 || (tok != ',' && tok != ';')) {
5778 if (tok < 0)
5779 error("unexpected end of file in initializer");
5780 tok_str_add_tok(&init_str);
5781 if (tok == '{')
5782 level++;
5783 else if (tok == '}') {
5784 if (level == 0)
5785 break;
5786 level--;
5788 next();
5790 tok_str_add(&init_str, -1);
5791 tok_str_add(&init_str, 0);
5793 /* compute size */
5794 save_parse_state(&saved_parse_state);
5796 macro_ptr = init_str.str;
5797 next();
5798 decl_initializer(t, NULL, 0, 1, 1);
5799 /* prepare second initializer parsing */
5800 macro_ptr = init_str.str;
5801 next();
5803 /* if still unknown size, error */
5804 size = type_size(t, &align);
5805 if (size < 0)
5806 error("unknown type size");
5808 /* take into account specified alignment if bigger */
5809 if (ad->aligned > align)
5810 align = ad->aligned;
5811 if ((r & VT_VALMASK) == VT_LOCAL) {
5812 sec = NULL;
5813 if (do_bounds_check && (t & VT_ARRAY))
5814 loc--;
5815 #ifdef TCC_TARGET_IL
5816 /* XXX: ugly patch to allocate local variables for IL, just
5817 for testing */
5818 addr = loc;
5819 loc++;
5820 #else
5821 loc = (loc - size) & -align;
5822 addr = loc;
5823 #endif
5824 /* handles bounds */
5825 /* XXX: currently, since we do only one pass, we cannot track
5826 '&' operators, so we add only arrays */
5827 if (do_bounds_check && (t & VT_ARRAY)) {
5828 int *bounds_ptr;
5829 /* add padding between regions */
5830 loc--;
5831 /* then add local bound info */
5832 bounds_ptr = (int *)lbounds_section->data_ptr;
5833 *bounds_ptr++ = addr;
5834 *bounds_ptr++ = size;
5835 lbounds_section->data_ptr = (unsigned char *)bounds_ptr;
5837 } else {
5838 /* compute section */
5839 sec = ad->section;
5840 if (!sec) {
5841 if (has_init)
5842 sec = data_section;
5843 else
5844 sec = bss_section;
5846 data_offset = sec->data_ptr - sec->data;
5847 data_offset = (data_offset + align - 1) & -align;
5848 addr = data_offset;
5849 /* very important to increment global pointer at this time
5850 because initializers themselves can create new initializers */
5851 data_offset += size;
5852 /* handles bounds */
5853 if (do_bounds_check) {
5854 int *bounds_ptr;
5855 /* first, we need to add at least one byte between each region */
5856 data_offset++;
5857 /* then add global bound info */
5858 bounds_ptr = (int *)bounds_section->data_ptr;
5859 /* XXX: add relocation */
5860 *bounds_ptr++ = addr + (unsigned long)sec->data;
5861 *bounds_ptr++ = size;
5862 bounds_section->data_ptr = (unsigned char *)bounds_ptr;
5864 sec->data_ptr = sec->data + data_offset;
5866 if (v) {
5867 Sym *sym;
5869 if (!sec) {
5870 /* local variable */
5871 sym_push(v, t, r, addr);
5872 } else {
5873 if (scope == VT_CONST) {
5874 /* global scope: see if already defined */
5875 sym = sym_find(v);
5876 if (!sym)
5877 goto do_def;
5878 if (!is_compatible_types(sym->t, t))
5879 error("incompatible types for redefinition of '%s'",
5880 get_tok_str(v, NULL));
5881 if (!(sym->t & VT_EXTERN))
5882 error("redefinition of '%s'", get_tok_str(v, NULL));
5883 sym->t &= ~VT_EXTERN;
5884 } else {
5885 do_def:
5886 sym = sym_push(v, t, r | VT_SYM, 0);
5888 put_extern_sym(sym, sec, addr);
5890 } else {
5891 if (!sec) {
5892 /* push local reference */
5893 vset(t, r, addr);
5894 } else {
5895 /* push global reference */
5896 vpush_ref(t, sec, addr);
5899 if (has_init) {
5900 decl_initializer(t, sec, addr, 1, 0);
5901 /* restore parse state if needed */
5902 if (init_str.str) {
5903 free(init_str.str);
5904 restore_parse_state(&saved_parse_state);
5909 void put_func_debug(int t)
5911 char buf[512];
5913 /* stabs info */
5914 /* XXX: we put here a dummy type */
5915 snprintf(buf, sizeof(buf), "%s:%c1",
5916 funcname, t & VT_STATIC ? 'f' : 'F');
5917 put_stabs(buf, N_FUN, 0, file->line_num, ind);
5918 func_ind = ind;
5919 last_ind = 0;
5920 last_line_num = 0;
5923 /* not finished : try to put some local vars in registers */
5924 //#define CONFIG_REG_VARS
5926 #ifdef CONFIG_REG_VARS
5927 void add_var_ref(int t)
5929 printf("%s:%d: &%s\n",
5930 file->filename, file->line_num,
5931 get_tok_str(t, NULL));
5934 /* first pass on a function with heuristic to extract variable usage
5935 and pointer references to local variables for register allocation */
5936 void analyse_function(void)
5938 int level, t;
5940 for(;;) {
5941 if (tok == -1)
5942 break;
5943 /* any symbol coming after '&' is considered as being a
5944 variable whose reference is taken. It is highly unaccurate
5945 but it is difficult to do better without a complete parse */
5946 if (tok == '&') {
5947 next();
5948 /* if '& number', then no need to examine next tokens */
5949 if (tok == TOK_CINT ||
5950 tok == TOK_CUINT ||
5951 tok == TOK_CLLONG ||
5952 tok == TOK_CULLONG) {
5953 continue;
5954 } else if (tok >= TOK_UIDENT) {
5955 /* if '& ident [' or '& ident ->', then ident address
5956 is not needed */
5957 t = tok;
5958 next();
5959 if (tok != '[' && tok != TOK_ARROW)
5960 add_var_ref(t);
5961 } else {
5962 level = 0;
5963 while (tok != '}' && tok != ';' &&
5964 !((tok == ',' || tok == ')') && level == 0)) {
5965 if (tok >= TOK_UIDENT) {
5966 add_var_ref(tok);
5967 } else if (tok == '(') {
5968 level++;
5969 } else if (tok == ')') {
5970 level--;
5972 next();
5975 } else {
5976 next();
5980 #endif
5982 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
5983 void decl(int l)
5985 int t, b, v, has_init, r;
5986 Sym *sym;
5987 AttributeDef ad;
5989 while (1) {
5990 if (!parse_btype(&b, &ad)) {
5991 /* skip redundant ';' */
5992 /* XXX: find more elegant solution */
5993 if (tok == ';') {
5994 next();
5995 continue;
5997 /* special test for old K&R protos without explicit int
5998 type. Only accepted when defining global data */
5999 if (l == VT_LOCAL || tok < TOK_DEFINE)
6000 break;
6001 b = VT_INT;
6003 if (((b & VT_BTYPE) == VT_ENUM ||
6004 (b & VT_BTYPE) == VT_STRUCT) &&
6005 tok == ';') {
6006 /* we accept no variable after */
6007 next();
6008 continue;
6010 while (1) { /* iterate thru each declaration */
6011 t = type_decl(&ad, &v, b, TYPE_DIRECT);
6012 #if 0
6014 char buf[500];
6015 type_to_str(buf, sizeof(buf), t, get_tok_str(v, NULL));
6016 printf("type = '%s'\n", buf);
6018 #endif
6019 if (tok == '{') {
6020 #ifdef CONFIG_REG_VARS
6021 TokenString func_str;
6022 ParseState saved_parse_state;
6023 int block_level;
6024 #endif
6026 if (l == VT_LOCAL)
6027 error("cannot use local functions");
6028 if (!(t & VT_FUNC))
6029 expect("function definition");
6031 #ifdef CONFIG_REG_VARS
6032 /* parse all function code and record it */
6034 tok_str_new(&func_str);
6036 block_level = 0;
6037 for(;;) {
6038 int t;
6039 if (tok == -1)
6040 error("unexpected end of file");
6041 tok_str_add_tok(&func_str);
6042 t = tok;
6043 next();
6044 if (t == '{') {
6045 block_level++;
6046 } else if (t == '}') {
6047 block_level--;
6048 if (block_level == 0)
6049 break;
6052 tok_str_add(&func_str, -1);
6053 tok_str_add(&func_str, 0);
6055 save_parse_state(&saved_parse_state);
6057 macro_ptr = func_str.str;
6058 next();
6059 analyse_function();
6060 #endif
6062 /* compute text section */
6063 cur_text_section = ad.section;
6064 if (!cur_text_section)
6065 cur_text_section = text_section;
6066 ind = (int)cur_text_section->data_ptr;
6067 funcname = get_tok_str(v, NULL);
6068 sym = sym_find(v);
6069 if (sym) {
6070 /* if symbol is already defined, then put complete type */
6071 sym->t = t;
6072 } else {
6073 /* put function symbol */
6074 sym = sym_push1(&global_stack, v, t, 0);
6076 put_extern_sym(sym, cur_text_section,
6077 ind - (int)cur_text_section->data);
6078 sym->r = VT_SYM | VT_CONST;
6079 /* put debug symbol */
6080 if (do_debug)
6081 put_func_debug(t);
6082 /* push a dummy symbol to enable local sym storage */
6083 sym_push1(&local_stack, 0, 0, 0);
6084 gfunc_prolog(t);
6085 loc = 0;
6086 rsym = 0;
6087 #ifdef CONFIG_REG_VARS
6088 macro_ptr = func_str.str;
6089 next();
6090 #endif
6091 block(NULL, NULL, NULL, NULL, 0);
6092 gsym(rsym);
6093 gfunc_epilog();
6094 cur_text_section->data_ptr = (unsigned char *)ind;
6095 sym_pop(&label_stack, NULL); /* reset label stack */
6096 sym_pop(&local_stack, NULL); /* reset local stack */
6097 /* end of function */
6098 if (do_debug) {
6099 put_stabn(N_FUN, 0, 0, ind - func_ind);
6101 funcname = ""; /* for safety */
6102 func_vt = VT_VOID; /* for safety */
6103 ind = 0; /* for safety */
6105 #ifdef CONFIG_REG_VARS
6106 free(func_str.str);
6107 restore_parse_state(&saved_parse_state);
6108 #endif
6109 break;
6110 } else {
6111 if (b & VT_TYPEDEF) {
6112 /* save typedefed type */
6113 /* XXX: test storage specifiers ? */
6114 sym_push(v, t | VT_TYPEDEF, 0, 0);
6115 } else if ((t & VT_BTYPE) == VT_FUNC) {
6116 /* external function definition */
6117 external_sym(v, t, 0);
6118 } else {
6119 /* not lvalue if array */
6120 r = 0;
6121 if (!(t & VT_ARRAY))
6122 r |= lvalue_type(t);
6123 if (b & VT_EXTERN) {
6124 /* external variable */
6125 external_sym(v, t, r);
6126 } else {
6127 if (t & VT_STATIC)
6128 r |= VT_CONST;
6129 else
6130 r |= l;
6131 has_init = (tok == '=');
6132 if (has_init)
6133 next();
6134 decl_initializer_alloc(t, &ad, r,
6135 has_init, v, l);
6138 if (tok != ',') {
6139 skip(';');
6140 break;
6142 next();
6148 /* compile the C file opened in 'file'. Return non zero if errors. */
6149 int tcc_compile(TCCState *s)
6151 Sym *define_start;
6152 char buf[512];
6154 funcname = "";
6155 include_stack_ptr = include_stack;
6156 ifdef_stack_ptr = ifdef_stack;
6158 vtop = vstack - 1;
6159 anon_sym = SYM_FIRST_ANOM;
6161 /* file info: full path + filename */
6162 if (do_debug) {
6163 getcwd(buf, sizeof(buf));
6164 pstrcat(buf, sizeof(buf), "/");
6165 put_stabs(buf, N_SO, 0, 0, (unsigned long)text_section->data_ptr);
6166 put_stabs(file->filename, N_SO, 0, 0,
6167 (unsigned long)text_section->data_ptr);
6169 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
6170 symbols can be safely used */
6171 put_elf_sym(symtab_section, 0, 0,
6172 ELF32_ST_INFO(STB_LOCAL, STT_FILE), 0,
6173 SHN_ABS, file->filename);
6175 /* define common 'char *' type because it is often used internally
6176 for arrays and struct dereference */
6177 char_pointer_type = mk_pointer(VT_BYTE);
6179 define_start = define_stack.top;
6180 inp();
6181 ch = '\n'; /* needed to parse correctly first preprocessor command */
6182 next();
6183 decl(VT_CONST);
6184 if (tok != -1)
6185 expect("declaration");
6187 /* end of translation unit info */
6188 if (do_debug) {
6189 put_stabn(N_SO, 0, 0, (unsigned long)text_section->data_ptr);
6192 /* reset define stack, but leave -Dsymbols (may be incorrect if
6193 they are undefined) */
6194 sym_pop(&define_stack, define_start);
6196 sym_pop(&global_stack, NULL);
6198 return 0;
6201 int tcc_compile_file(TCCState *s, const char *filename1)
6203 int ret;
6204 file = tcc_open(filename1);
6205 if (!file)
6206 error("file '%s' not found", filename1);
6207 ret = tcc_compile(s);
6208 tcc_close(file);
6209 return ret;
6212 int tcc_compile_string(TCCState *s, const char *str)
6214 BufferedFile bf1, *bf = &bf1;
6215 int ret;
6217 /* init file structure */
6218 bf->fd = -1;
6219 bf->buf_ptr = (char *)str;
6220 bf->buf_end = (char *)str + strlen(bf->buffer);
6221 pstrcpy(bf->filename, sizeof(bf->filename), "<string>");
6222 bf->line_num = 1;
6223 file = bf;
6225 ret = tcc_compile(s);
6227 /* currently, no need to close */
6228 return ret;
6231 /* define a symbol. A value can also be provided with the '=' operator */
6232 void tcc_define_symbol(TCCState *s, const char *sym, const char *value)
6234 BufferedFile bf1, *bf = &bf1;
6236 pstrcpy(bf->buffer, IO_BUF_SIZE, sym);
6237 pstrcat(bf->buffer, IO_BUF_SIZE, " ");
6238 /* default value */
6239 if (!value)
6240 value = "1";
6241 pstrcat(bf->buffer, IO_BUF_SIZE, value);
6243 /* init file structure */
6244 bf->fd = -1;
6245 bf->buf_ptr = bf->buffer;
6246 bf->buf_end = bf->buffer + strlen(bf->buffer);
6247 bf->filename[0] = '\0';
6248 bf->line_num = 1;
6249 file = bf;
6251 include_stack_ptr = include_stack;
6253 /* parse with define parser */
6254 inp();
6255 ch = '\n'; /* needed to parse correctly first preprocessor command */
6256 next_nomacro();
6257 parse_define();
6258 file = NULL;
6261 void tcc_undefine_symbol(TCCState *s1, const char *sym)
6263 TokenSym *ts;
6264 Sym *s;
6265 ts = tok_alloc(sym, 0);
6266 s = sym_find1(&define_stack, tok);
6267 /* undefine symbol by putting an invalid name */
6268 if (s)
6269 sym_undef(&define_stack, s);
6272 /* open a dynamic library so that its symbol are available for
6273 compiled programs */
6274 /* XXX: open the lib only to actually run the program */
6275 int tcc_add_dll(TCCState *s, const char *library_name)
6277 void *h;
6279 h = dlopen(library_name, RTLD_GLOBAL | RTLD_LAZY);
6280 if (!h)
6281 error((char *)dlerror());
6282 return 0;
6285 static int put_elf_str(Section *s, const char *sym)
6287 int c, offset;
6288 offset = s->data_ptr - s->data;
6289 for(;;) {
6290 c = *sym++;
6291 *s->data_ptr++ = c;
6292 if (c == '\0')
6293 break;
6295 return offset;
6298 /* elf symbol hashing function */
6299 static unsigned long elf_hash(const unsigned char *name)
6301 unsigned long h = 0, g;
6303 while (*name) {
6304 h = (h << 4) + *name++;
6305 g = h & 0xf0000000;
6306 if (g)
6307 h ^= g >> 24;
6308 h &= ~g;
6310 return h;
6313 /* add one symbol in hash table if it is global */
6314 /* WARNING: must be called each time a symbol is added otherwise the
6315 hash table is not synchronized with the symbol table */
6316 static void update_hash_elf_sym(Section *hs,
6317 int sym_index, int info, const char *name)
6319 int nbuckets, h;
6321 /* only add global symbols */
6322 if (ELF32_ST_BIND(info) == STB_GLOBAL) {
6323 /* add another hashing entry */
6324 nbuckets = ((int *)hs->data)[0];
6325 h = elf_hash(name) % nbuckets;
6326 ((int *)hs->data)[2 + nbuckets + sym_index] = ((int *)hs->data)[2 + h];
6327 ((int *)hs->data)[2 + h] = sym_index;
6329 /* but still add room for all symbols */
6330 ((int *)hs->data)[1]++;
6331 hs->data_ptr += sizeof(int);
6334 /* return the symbol number */
6335 static int put_elf_sym(Section *s,
6336 unsigned long value, unsigned long size,
6337 int info, int other, int shndx, const char *name)
6339 int name_offset, sym_index;
6340 Elf32_Sym *sym;
6341 Section *hs;
6343 sym = (Elf32_Sym *)s->data_ptr;
6344 if (name)
6345 name_offset = put_elf_str(s->link, name);
6346 else
6347 name_offset = 0;
6348 /* XXX: endianness */
6349 sym->st_name = name_offset;
6350 sym->st_value = value;
6351 sym->st_size = size;
6352 sym->st_info = info;
6353 sym->st_other = other;
6354 sym->st_shndx = shndx;
6355 sym_index = sym - (Elf32_Sym *)s->data;
6356 hs = s->hash;
6357 if (hs) {
6358 update_hash_elf_sym(hs, sym_index, info, name);
6360 s->data_ptr += sizeof(Elf32_Sym);
6361 return sym_index;
6364 /* find global ELF symbol 'name' and return its index. Return 0 if not
6365 found. */
6366 static int find_elf_sym(Section *s, const char *name)
6368 Elf32_Sym *sym;
6369 Section *hs;
6370 int nbuckets, sym_index, h;
6371 const char *name1;
6373 hs = s->hash;
6374 if (!hs)
6375 return 0;
6376 nbuckets = ((int *)hs->data)[0];
6377 h = elf_hash(name) % nbuckets;
6378 sym_index = ((int *)hs->data)[2 + h];
6379 while (sym_index != 0) {
6380 sym = &((Elf32_Sym *)s->data)[sym_index];
6381 name1 = s->link->data + sym->st_name;
6382 if (!strcmp(name, name1))
6383 return sym_index;
6384 sym_index = ((int *)hs->data)[2 + nbuckets + sym_index];
6386 return 0;
6389 /* update sym->c so that it points to an external symbol in section
6390 'section' with value 'value' */
6391 /* XXX: get rid of put_elf_sym */
6392 void put_extern_sym(Sym *sym, Section *section, unsigned long value)
6394 int sym_type, sym_bind, sh_num;
6395 Elf32_Sym *esym;
6396 const char *name;
6398 if (section)
6399 sh_num = section->sh_num;
6400 else
6401 sh_num = SHN_UNDEF;
6402 if (!sym->c) {
6403 if ((sym->t & VT_BTYPE) == VT_FUNC)
6404 sym_type = STT_FUNC;
6405 else
6406 sym_type = STT_OBJECT;
6407 if (sym->t & VT_STATIC)
6408 sym_bind = STB_LOCAL;
6409 else
6410 sym_bind = STB_GLOBAL;
6411 /* if the symbol is global, then we look if it is already
6412 defined */
6413 name = get_tok_str(sym->v, NULL);
6414 if (sym_bind == STB_GLOBAL) {
6415 sym->c = find_elf_sym(symtab_section, name);
6416 if (!sym->c)
6417 goto do_def;
6418 /* check if not defined */
6419 if (section) {
6420 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
6421 if (esym->st_shndx != SHN_UNDEF)
6422 error("'%s' defined twice", name);
6423 esym->st_shndx = sh_num;
6424 esym->st_value = value;
6426 } else {
6427 do_def:
6428 sym->c = put_elf_sym(symtab_section, value, 0,
6429 ELF32_ST_INFO(sym_bind, sym_type), 0,
6430 sh_num, name);
6432 } else {
6433 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
6434 esym->st_value = value;
6435 esym->st_shndx = sh_num;
6439 /* put relocation */
6440 static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
6441 int type, int symbol)
6443 char buf[256];
6444 Section *sr;
6445 Elf32_Rel *rel;
6447 sr = s->reloc;
6448 if (!sr) {
6449 /* if no relocation section, create it */
6450 snprintf(buf, sizeof(buf), ".rel%s", s->name);
6451 /* if the symtab is allocated, then we consider the relocation
6452 are also */
6453 sr = new_section(buf, SHT_REL, symtab->sh_flags);
6454 sr->sh_entsize = sizeof(Elf32_Rel);
6455 sr->link = symtab;
6456 sr->sh_info = s->sh_num;
6457 s->reloc = sr;
6459 rel = (Elf32_Rel *)sr->data_ptr;
6460 /* XXX: endianness */
6461 rel->r_offset = offset;
6462 rel->r_info = ELF32_R_INFO(symbol, type);
6463 sr->data_ptr += sizeof(Elf32_Rel);
6466 /* put stab debug information */
6468 typedef struct {
6469 unsigned long n_strx; /* index into string table of name */
6470 unsigned char n_type; /* type of symbol */
6471 unsigned char n_other; /* misc info (usually empty) */
6472 unsigned short n_desc; /* description field */
6473 unsigned long n_value; /* value of symbol */
6474 } Stab_Sym;
6476 static void put_stabs(const char *str, int type, int other, int desc, int value)
6478 Stab_Sym *sym;
6480 sym = (Stab_Sym *)stab_section->data_ptr;
6481 if (str) {
6482 sym->n_strx = put_elf_str(stabstr_section, str);
6483 } else {
6484 sym->n_strx = 0;
6486 sym->n_type = type;
6487 sym->n_other = other;
6488 sym->n_desc = desc;
6489 sym->n_value = value;
6491 stab_section->data_ptr += sizeof(Stab_Sym);
6494 static void put_stabn(int type, int other, int desc, int value)
6496 put_stabs(NULL, type, other, desc, value);
6499 static void put_stabd(int type, int other, int desc)
6501 put_stabs(NULL, type, other, desc, 0);
6504 /* In an ELF file symbol table, the local symbols must appear below
6505 the global and weak ones. Since TCC cannot sort it while generating
6506 the code, we must do it after. All the relocation tables are also
6507 modified to take into account the symbol table sorting */
6508 static void sort_symbols(Section *s)
6510 int *old_to_new_syms;
6511 Elf32_Sym *new_syms;
6512 int nb_syms, i;
6513 Elf32_Sym *p, *q;
6514 Elf32_Rel *rel;
6515 Section *sr;
6516 int type, sym_index;
6518 nb_syms = (s->data_ptr - s->data) / sizeof(Elf32_Sym);
6519 new_syms = malloc(nb_syms * sizeof(Elf32_Sym));
6520 if (!new_syms)
6521 error("memory full");
6522 old_to_new_syms = malloc(nb_syms * sizeof(int));
6523 if (!old_to_new_syms)
6524 error("memory full");
6525 /* first pass for local symbols */
6526 p = (Elf32_Sym *)s->data;
6527 q = new_syms;
6528 for(i = 0; i < nb_syms; i++) {
6529 if (ELF32_ST_BIND(p->st_info) == STB_LOCAL) {
6530 old_to_new_syms[i] = q - new_syms;
6531 *q++ = *p;
6533 p++;
6535 /* save the number of local symbols in section header */
6536 s->sh_info = q - new_syms;
6538 /* then second pass for non local symbols */
6539 p = (Elf32_Sym *)s->data;
6540 for(i = 0; i < nb_syms; i++) {
6541 if (ELF32_ST_BIND(p->st_info) != STB_LOCAL) {
6542 old_to_new_syms[i] = q - new_syms;
6543 *q++ = *p;
6545 p++;
6548 /* we copy the new symbols to the old */
6549 memcpy(s->data, new_syms, nb_syms * sizeof(Elf32_Sym));
6550 free(new_syms);
6552 /* now we modify all the relocations */
6553 for(sr = first_section; sr != NULL; sr = sr->next) {
6554 if (sr->sh_type == SHT_REL && sr->link == s) {
6555 for(rel = (Elf32_Rel *)sr->data;
6556 rel < (Elf32_Rel *)sr->data_ptr;
6557 rel++) {
6558 sym_index = ELF32_R_SYM(rel->r_info);
6559 type = ELF32_R_TYPE(rel->r_info);
6560 sym_index = old_to_new_syms[sym_index];
6561 rel->r_info = ELF32_R_INFO(sym_index, type);
6566 free(old_to_new_syms);
6569 static unsigned long get_sym_val(int sym_index)
6571 unsigned long val;
6572 Elf32_Sym *sym;
6574 sym = &((Elf32_Sym *)symtab_section->data)[sym_index];
6575 val = sym->st_value;
6576 if (sym->st_shndx != SHN_UNDEF && sym->st_shndx < SHN_LORESERVE)
6577 val += sections[sym->st_shndx]->sh_addr;
6578 return val;
6581 /* relocate a given section */
6582 static void relocate_section(Section *s)
6584 Section *sr;
6585 Elf32_Rel *rel;
6586 int type;
6587 unsigned char *ptr;
6588 unsigned long val;
6590 sr = s->reloc;
6591 for(rel = (Elf32_Rel *)sr->data;
6592 rel < (Elf32_Rel *)sr->data_ptr;
6593 rel++) {
6594 ptr = s->data + rel->r_offset;
6595 val = get_sym_val(ELF32_R_SYM(rel->r_info));
6596 type = ELF32_R_TYPE(rel->r_info);
6597 greloc_patch(ptr, s->sh_addr + rel->r_offset, val, type);
6601 static Section *new_section_hash(const char *name, int sh_flags,
6602 int nb_buckets, Section *symtab)
6604 Section *hash;
6605 hash = new_section(name, SHT_HASH, sh_flags);
6606 ((int *)hash->data)[0] = nb_buckets;
6607 ((int *)hash->data)[1] = 1;
6608 hash->sh_entsize = sizeof(int);
6609 hash->data_ptr += (2 + nb_buckets + 1) * sizeof(int);
6610 symtab->hash = hash;
6611 hash->link = symtab;
6612 return hash;
6615 /* put dynamic tag */
6616 static void put_dt(Section *dynamic, int dt, unsigned long val)
6618 Elf32_Dyn *dyn;
6619 dyn = (Elf32_Dyn *)dynamic->data_ptr;
6620 dyn->d_tag = dt;
6621 dyn->d_un.d_val = val;
6622 dynamic->data_ptr += sizeof(Elf32_Dyn);
6625 /* add dynamic sections so that the executable is dynamically linked */
6626 static char elf_interp[] = "/lib/ld-linux.so.2";
6628 #define ELF_START_ADDR 0x08048000
6629 #define ELF_PAGE_SIZE 0x1000
6631 /* XXX: suppress that */
6632 static void put32(unsigned char *p, unsigned int val)
6634 p[0] = val;
6635 p[1] = val >> 8;
6636 p[2] = val >> 16;
6637 p[3] = val >> 24;
6640 /* output an ELF file (currently, only for testing) */
6641 /* XXX: handle realloc'ed sections (instead of mmaping them) */
6642 /* XXX: suppress unneeded sections */
6643 int tcc_output_file(TCCState *s1, const char *filename, int file_type)
6645 Elf32_Ehdr ehdr;
6646 FILE *f;
6647 int fd, mode;
6648 int *section_order;
6649 int shnum, i, phnum, file_offset, offset, size, j, tmp, sh_order_index;
6650 unsigned long addr;
6651 Section *strsec, *s;
6652 Elf32_Shdr shdr, *sh;
6653 Elf32_Phdr *phdr, *ph;
6654 Section *interp, *plt, *got, *dynamic, *dynsym, *dynstr, *hash;
6655 unsigned char *saved_dynamic_data_ptr;
6656 Elf32_Sym *sym;
6657 int type;
6659 interp = NULL;
6660 dynamic = NULL;
6661 plt = NULL; /* avoid warning */
6662 got = NULL; /* avoid warning */
6663 dynsym = NULL; /* avoid warning */
6664 hash = NULL; /* avoid warning */
6665 dynstr = NULL; /* avoid warning */
6666 saved_dynamic_data_ptr = NULL; /* avoid warning */
6668 if (file_type != TCC_FILE_OBJ && !static_link) {
6669 const char *name;
6670 int nb_plt_entries;
6672 if (file_type == TCC_FILE_EXE) {
6673 /* add interpreter section only if executable */
6674 interp = new_section(".interp", SHT_PROGBITS, SHF_ALLOC);
6675 interp->sh_addralign = 1;
6676 strcpy(interp->data_ptr, elf_interp);
6677 interp->data_ptr += sizeof(elf_interp);
6680 /* add dynamic symbol table */
6681 dynsym = new_section(".dynsym", SHT_DYNSYM, SHF_ALLOC);
6682 dynsym->sh_entsize = sizeof(Elf32_Sym);
6683 dynstr = new_section(".dynstr", SHT_STRTAB, SHF_ALLOC);
6684 put_elf_str(dynstr, "");
6685 dynsym->link = dynstr;
6686 put_elf_sym(dynsym, 0, 0, 0, 0, 0, NULL);
6688 /* hash table */
6689 hash = new_section_hash(".hash", SHF_ALLOC,
6690 ELF_DYNSYM_HASH_SIZE, dynsym);
6692 /* add dynamic section */
6693 dynamic = new_section(".dynamic", SHT_DYNAMIC,
6694 SHF_ALLOC | SHF_WRITE);
6695 dynamic->link = dynstr;
6696 dynamic->sh_entsize = sizeof(Elf32_Dyn);
6698 /* add PLT and GOT */
6699 plt = new_section(".plt", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
6700 plt->sh_entsize = 4;
6701 got = new_section(".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
6702 got->sh_entsize = 4;
6704 /* add undefined symbols in dynamic symbol table */
6705 nb_plt_entries = 0;
6706 for(sym = (Elf32_Sym *)symtab_section->data + 1;
6707 sym < (Elf32_Sym *)symtab_section->data_ptr;
6708 sym++) {
6709 if (sym->st_shndx == SHN_UNDEF) {
6710 name = symtab_section->link->data + sym->st_name;
6711 type = ELF32_ST_TYPE(sym->st_info);
6712 put_elf_sym(dynsym, 0, 0,
6713 sym->st_info, 0, SHN_UNDEF, name);
6714 if (type == STT_FUNC) {
6715 nb_plt_entries++;
6716 /* prepare space for relocation */
6717 put_elf_reloc(dynsym, got, 0, 0, 0);
6722 /* update PLT/GOT sizes so that we can allocate their space */
6723 plt->data_ptr += 16 * (nb_plt_entries + 1);
6724 got->data_ptr += 4 * (nb_plt_entries + 3);
6726 put_dt(dynamic, DT_NEEDED, put_elf_str(dynstr, "libc.so.6"));
6727 /* XXX: add other libs */
6729 /* add necessary space for other entries */
6730 saved_dynamic_data_ptr = dynamic->data_ptr;
6731 dynamic->data_ptr += 8 * 9;
6734 sort_symbols(symtab_section);
6736 memset(&ehdr, 0, sizeof(ehdr));
6738 /* we add a section for symbols */
6739 strsec = new_section(".shstrtab", SHT_STRTAB, 0);
6740 put_elf_str(strsec, "");
6742 /* compute number of sections */
6743 shnum = nb_sections;
6745 /* this array is used to reorder sections in the output file */
6746 section_order = malloc(sizeof(int) * shnum);
6747 if (!section_order)
6748 error("memory full");
6749 section_order[0] = 0;
6750 sh_order_index = 1;
6752 /* compute number of program headers */
6753 switch(file_type) {
6754 default:
6755 case TCC_FILE_OBJ:
6756 phnum = 0;
6757 break;
6758 case TCC_FILE_EXE:
6759 if (!static_link)
6760 phnum = 4;
6761 else
6762 phnum = 2;
6763 break;
6764 case TCC_FILE_DLL:
6765 phnum = 3;
6766 break;
6769 /* allocate strings for section names */
6770 for(i = 1; i < nb_sections; i++) {
6771 s = sections[i];
6772 s->sh_name = put_elf_str(strsec, s->name);
6773 s->sh_size = s->data_ptr - s->data;
6776 /* allocate program segment headers */
6777 phdr = malloc(phnum * sizeof(Elf32_Phdr));
6778 if (!phdr)
6779 error("memory full");
6780 memset(phdr, 0, phnum * sizeof(Elf32_Phdr));
6782 file_offset = sizeof(Elf32_Ehdr) + phnum * sizeof(Elf32_Phdr);
6783 if (phnum > 0) {
6784 /* compute section to program header mapping */
6785 if (file_type == TCC_FILE_DLL)
6786 addr = 0;
6787 else
6788 addr = ELF_START_ADDR;
6790 /* compute address after headers */
6791 addr += (file_offset & (ELF_PAGE_SIZE - 1));
6793 /* leave one program header for the program interpreter */
6794 ph = &phdr[0];
6795 if (interp)
6796 ph++;
6798 for(j = 0; j < 2; j++) {
6799 ph->p_type = PT_LOAD;
6800 if (j == 0)
6801 ph->p_flags = PF_R | PF_X;
6802 else
6803 ph->p_flags = PF_R | PF_W;
6804 ph->p_align = ELF_PAGE_SIZE;
6806 for(i = 1; i < nb_sections; i++) {
6807 s = sections[i];
6808 /* compute if section should be included */
6809 if (j == 0) {
6810 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
6811 SHF_ALLOC)
6812 continue;
6813 } else {
6814 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
6815 (SHF_ALLOC | SHF_WRITE))
6816 continue;
6818 section_order[sh_order_index++] = i;
6820 /* section matches: we align it and add its size */
6821 tmp = file_offset;
6822 file_offset = (file_offset + s->sh_addralign - 1) &
6823 ~(s->sh_addralign - 1);
6824 s->sh_offset = file_offset;
6825 addr += file_offset - tmp;
6826 s->sh_addr = addr;
6828 if (ph->p_offset == 0) {
6829 ph->p_offset = file_offset;
6830 ph->p_vaddr = addr;
6831 ph->p_paddr = ph->p_vaddr;
6833 addr += s->sh_size;
6834 if (s->sh_type != SHT_NOBITS)
6835 file_offset += s->sh_size;
6837 ph->p_filesz = file_offset - ph->p_offset;
6838 ph->p_memsz = addr - ph->p_vaddr;
6839 ph++;
6842 /* if interpreter, then add corresponing program header */
6843 if (interp) {
6844 ph = &phdr[0];
6846 ph->p_type = PT_INTERP;
6847 ph->p_offset = interp->sh_offset;
6848 ph->p_vaddr = interp->sh_addr;
6849 ph->p_paddr = ph->p_vaddr;
6850 ph->p_filesz = interp->sh_size;
6851 ph->p_memsz = interp->sh_size;
6852 ph->p_flags = PF_R;
6853 ph->p_align = interp->sh_addralign;
6856 /* if dynamic section, then add corresponing program header */
6857 if (dynamic) {
6858 int sym_index, plt_offset;
6859 unsigned char *p;
6861 ph = &phdr[phnum - 1];
6863 ph->p_type = PT_DYNAMIC;
6864 ph->p_offset = dynamic->sh_offset;
6865 ph->p_vaddr = dynamic->sh_addr;
6866 ph->p_paddr = ph->p_vaddr;
6867 ph->p_filesz = dynamic->sh_size;
6868 ph->p_memsz = dynamic->sh_size;
6869 ph->p_flags = PF_R | PF_W;
6870 ph->p_align = dynamic->sh_addralign;
6872 /* now all the sections are mapped, so we can compute all
6873 PLT/GOT stuff */
6875 /* first three got entries */
6876 got->data_ptr = got->data;
6877 plt->data_ptr = plt->data;
6878 if (got->reloc)
6879 got->reloc->data_ptr = got->reloc->data;
6881 put32(got->data_ptr, dynamic->sh_addr);
6882 got->data_ptr += 4;
6883 put32(got->data_ptr, 0);
6884 got->data_ptr += 4;
6885 put32(got->data_ptr, 0);
6886 got->data_ptr += 4;
6888 /* first plt entry */
6889 p = plt->data_ptr;
6890 p[0] = 0xff; /* pushl got + 4 */
6891 p[1] = 0x35;
6892 put32(p + 2, got->sh_addr + 4);
6893 p[6] = 0xff; /* jmp *(got + 8) */
6894 p[7] = 0x25;
6895 put32(p + 8, got->sh_addr + 8);
6896 plt->data_ptr += 16;
6898 /* add undefined symbols in dynamic symbol table. also update
6899 PLT and GOT if needed */
6900 plt_offset = 0;
6901 sym_index = 1;
6902 for(sym = (Elf32_Sym *)dynsym->data + 1;
6903 sym < (Elf32_Sym *)dynsym->data_ptr;
6904 sym++) {
6905 type = ELF32_ST_TYPE(sym->st_info);
6906 if (type == STT_FUNC) {
6907 /* one more entry in PLT */
6908 p = plt->data_ptr;
6909 p[0] = 0xff; /* jmp *(got + x) */
6910 p[1] = 0x25;
6911 put32(p + 2, got->sh_addr + got->data_ptr - got->data);
6912 p[6] = 0x68; /* push $xxx */
6913 put32(p + 7, plt_offset);
6914 p[11] = 0xe9; /* jmp plt_start */
6915 put32(p + 12, -(plt->data_ptr + 16 - plt->data));
6917 /* patch symbol value to point to plt */
6918 sym->st_value = plt->sh_addr + p - plt->data;
6920 plt_offset += 8;
6921 plt->data_ptr += 16;
6923 /* corresponding got entry */
6924 put_elf_reloc(dynsym, got,
6925 got->sh_addr + got->data_ptr - got->data,
6926 R_386_JMP_SLOT,
6927 sym_index);
6928 put32(got->data_ptr, 0);
6929 got->data_ptr += 4;
6931 sym_index++;
6933 /* put dynamic section entries */
6935 dynamic->data_ptr = saved_dynamic_data_ptr;
6936 put_dt(dynamic, DT_HASH, hash->sh_addr);
6937 put_dt(dynamic, DT_STRTAB, dynstr->sh_addr);
6938 put_dt(dynamic, DT_SYMTAB, dynsym->sh_addr);
6939 put_dt(dynamic, DT_STRSZ, dynstr->data_ptr - dynstr->data);
6940 put_dt(dynamic, DT_SYMENT, sizeof(Elf32_Sym));
6941 put_dt(dynamic, DT_REL, got->reloc->sh_addr);
6942 put_dt(dynamic, DT_RELSZ, got->reloc->data_ptr - got->reloc->data);
6943 put_dt(dynamic, DT_RELENT, sizeof(Elf32_Rel));
6944 put_dt(dynamic, DT_NULL, 0);
6947 ehdr.e_phentsize = sizeof(Elf32_Phdr);
6948 ehdr.e_phnum = phnum;
6949 ehdr.e_phoff = sizeof(Elf32_Ehdr);
6952 /* all other sections come after */
6953 for(i = 1; i < nb_sections; i++) {
6954 s = sections[i];
6955 if (phnum > 0 && (s->sh_flags & SHF_ALLOC))
6956 continue;
6957 section_order[sh_order_index++] = i;
6959 file_offset = (file_offset + s->sh_addralign - 1) &
6960 ~(s->sh_addralign - 1);
6961 s->sh_offset = file_offset;
6962 if (s->sh_type != SHT_NOBITS)
6963 file_offset += s->sh_size;
6966 #if 1
6967 /* if building executable, then relocate each section except the GOT
6968 which is already relocated */
6969 if (file_type == TCC_FILE_EXE) {
6970 for(i = 1; i < nb_sections; i++) {
6971 s = sections[i];
6972 if (s->reloc && s != got)
6973 relocate_section(s);
6976 #endif
6978 /* align to 4 */
6979 file_offset = (file_offset + 3) & -4;
6981 /* fill header */
6982 ehdr.e_ident[0] = ELFMAG0;
6983 ehdr.e_ident[1] = ELFMAG1;
6984 ehdr.e_ident[2] = ELFMAG2;
6985 ehdr.e_ident[3] = ELFMAG3;
6986 ehdr.e_ident[4] = ELFCLASS32;
6987 ehdr.e_ident[5] = ELFDATA2LSB;
6988 ehdr.e_ident[6] = EV_CURRENT;
6989 switch(file_type) {
6990 default:
6991 case TCC_FILE_EXE:
6992 ehdr.e_type = ET_EXEC;
6993 break;
6994 case TCC_FILE_DLL:
6995 ehdr.e_type = ET_DYN;
6996 break;
6997 case TCC_FILE_OBJ:
6998 ehdr.e_type = ET_REL;
6999 break;
7001 ehdr.e_machine = EM_386;
7002 ehdr.e_version = EV_CURRENT;
7003 ehdr.e_entry = 0; /* XXX: patch it */
7004 ehdr.e_shoff = file_offset;
7005 ehdr.e_ehsize = sizeof(Elf32_Ehdr);
7006 ehdr.e_shentsize = sizeof(Elf32_Shdr);
7007 ehdr.e_shnum = shnum;
7008 ehdr.e_shstrndx = shnum - 1;
7010 /* write elf file */
7011 if (file_type == TCC_FILE_OBJ)
7012 mode = 0666;
7013 else
7014 mode = 0777;
7015 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, mode);
7016 if (fd < 0)
7017 error("could not write '%s'", filename);
7019 f = fdopen(fd, "w");
7020 fwrite(&ehdr, 1, sizeof(Elf32_Ehdr), f);
7021 fwrite(phdr, 1, phnum * sizeof(Elf32_Phdr), f);
7022 offset = sizeof(Elf32_Ehdr) + phnum * sizeof(Elf32_Phdr);
7023 for(i=1;i<nb_sections;i++) {
7024 s = sections[section_order[i]];
7025 if (s->sh_type != SHT_NOBITS) {
7026 while (offset < s->sh_offset) {
7027 fputc(0, f);
7028 offset++;
7030 size = s->data_ptr - s->data;
7031 fwrite(s->data, 1, size, f);
7032 offset += size;
7035 while (offset < ehdr.e_shoff) {
7036 fputc(0, f);
7037 offset++;
7040 /* output section headers */
7041 for(i=0;i<nb_sections;i++) {
7042 sh = &shdr;
7043 memset(sh, 0, sizeof(Elf32_Shdr));
7044 s = sections[i];
7045 if (s) {
7046 sh->sh_name = s->sh_name;
7047 sh->sh_type = s->sh_type;
7048 sh->sh_flags = s->sh_flags;
7049 sh->sh_entsize = s->sh_entsize;
7050 sh->sh_info = s->sh_info;
7051 if (s->link)
7052 sh->sh_link = s->link->sh_num;
7053 sh->sh_addralign = s->sh_addralign;
7054 sh->sh_addr = s->sh_addr;
7055 sh->sh_offset = s->sh_offset;
7056 sh->sh_size = s->sh_size;
7058 fwrite(sh, 1, sizeof(Elf32_Shdr), f);
7060 fclose(f);
7062 free(section_order);
7063 free(phdr);
7064 return 0;
7067 typedef struct SectionMergeInfo {
7068 Section *s; /* corresponding existing section */
7069 unsigned long offset; /* offset of the new section in the existing section */
7070 int new_section; /* true if section 's' was added */
7071 } SectionMergeInfo;
7073 /* load an object file and merge it with current files */
7074 /* XXX: handle correctly stab (debug) info */
7075 int tcc_load_object(TCCState *s1, const char *filename)
7077 Elf32_Ehdr ehdr;
7078 FILE *f;
7079 Elf32_Shdr *shdr, *sh;
7080 int size, i, j, offset, offsetl, offseti;
7081 unsigned char *strsec;
7082 char *sh_name;
7083 SectionMergeInfo *sm_table, *sm;
7084 Elf32_Sym *sym;
7085 Elf32_Rel *rel;
7086 Section *s, *sl;
7088 f = fopen(filename, "r");
7089 if (!f)
7090 error("could not open '%s'", filename);
7091 if (fread(&ehdr, 1, sizeof(ehdr), f) != sizeof(ehdr))
7092 goto fail;
7093 if (ehdr.e_ident[0] != ELFMAG0 ||
7094 ehdr.e_ident[1] != ELFMAG1 ||
7095 ehdr.e_ident[2] != ELFMAG2 ||
7096 ehdr.e_ident[3] != ELFMAG3)
7097 goto fail;
7098 /* test if object file */
7099 if (ehdr.e_type != ET_REL)
7100 goto fail;
7101 /* test CPU specific stuff */
7102 if (ehdr.e_ident[5] != ELFDATA2LSB ||
7103 ehdr.e_machine != EM_386) {
7104 fail:
7105 error("invalid object file '%s'", filename);
7107 /* read sections */
7108 size = sizeof(Elf32_Shdr) * ehdr.e_shnum;
7109 shdr = malloc(size);
7110 if (!shdr)
7111 error("memory full");
7112 fseek(f, ehdr.e_shoff, SEEK_SET);
7113 if (fread(shdr, 1, size, f) != size)
7114 goto fail;
7116 sm_table = malloc(sizeof(SectionMergeInfo) * ehdr.e_shnum);
7117 if (!sm_table)
7118 error("memory full");
7119 memset(sm_table, 0, sizeof(SectionMergeInfo) * ehdr.e_shnum);
7121 /* load section names */
7122 sh = &shdr[ehdr.e_shstrndx];
7123 strsec = malloc(sh->sh_size);
7124 if (!strsec)
7125 error("memory full");
7126 fseek(f, sh->sh_offset, SEEK_SET);
7127 fread(strsec, 1, sh->sh_size, f);
7129 /* now examine each section and try to merge its content with the
7130 ones in memory */
7131 for(i = 1; i < ehdr.e_shnum; i++) {
7132 /* no need to examine section name strtab */
7133 if (i == ehdr.e_shstrndx)
7134 continue;
7135 sh = &shdr[i];
7136 sh_name = strsec + sh->sh_name;
7137 printf("%d: sh_name=%s\n", i, sh_name);
7138 /* ignore sections types we do not handle */
7139 if (sh->sh_type != SHT_PROGBITS &&
7140 sh->sh_type != SHT_SYMTAB &&
7141 sh->sh_type != SHT_STRTAB &&
7142 sh->sh_type != SHT_REL &&
7143 sh->sh_type != SHT_NOBITS)
7144 continue;
7145 if (sh->sh_addralign < 1)
7146 sh->sh_addralign = 1;
7147 /* find corresponding section, if any */
7148 for(j = 1; j < nb_sections;j++) {
7149 s = sections[j];
7150 if (!strcmp(s->name, sh_name))
7151 goto found;
7153 /* not found: create new section */
7154 s = new_section(sh_name, sh->sh_type, sh->sh_flags);
7155 /* take as much info as possible from the section. sh_link and
7156 sh_info will be updated later */
7157 s->sh_addralign = sh->sh_addralign;
7158 s->sh_entsize = sh->sh_entsize;
7159 sm_table[i].new_section = 1;
7160 found:
7161 if (sh->sh_type != s->sh_type)
7162 goto fail;
7163 if (sh->sh_type == SHT_SYMTAB) {
7164 /* if symbol, suppress first dummy entry */
7165 sh->sh_size -= sizeof(Elf32_Sym);
7166 sh->sh_offset += sizeof(Elf32_Sym);
7169 /* align start of section */
7170 offset = s->data_ptr - s->data;
7171 size = sh->sh_addralign - 1;
7172 offset = (offset + size) & ~size;
7173 if (sh->sh_addralign > s->sh_addralign)
7174 s->sh_addralign = sh->sh_addralign;
7175 s->data_ptr = s->data + offset;
7176 sm_table[i].offset = offset;
7177 sm_table[i].s = s;
7178 /* concatenate sections */
7179 size = sh->sh_size;
7180 if (sh->sh_type != SHT_NOBITS) {
7181 fseek(f, sh->sh_offset, SEEK_SET);
7182 fread(s->data_ptr, 1, size, f);
7184 s->data_ptr += size;
7187 /* second short pass to update sh_link and sh_info fields of new
7188 sections */
7189 sm = sm_table;
7190 for(i = 1; i < ehdr.e_shnum; i++) {
7191 s = sm_table[i].s;
7192 if (!s || !sm_table[i].new_section)
7193 continue;
7194 sh = &shdr[i];
7195 if (sh->sh_link > 0)
7196 s->link = sm_table[sh->sh_link].s;
7197 if (sh->sh_type == SHT_REL) {
7198 s->sh_info = sm_table[sh->sh_info].s->sh_num;
7199 /* update backward link */
7200 sections[s->sh_info]->reloc = s;
7204 /* third pass to patch symbol and relocation entries */
7205 for(i = 1; i < ehdr.e_shnum; i++) {
7206 s = sm_table[i].s;
7207 if (!s)
7208 continue;
7209 sh = &shdr[i];
7210 offset = sm_table[i].offset;
7211 switch(s->sh_type) {
7212 case SHT_SYMTAB:
7213 /* take strtab offset information */
7214 sl = sm_table[sh->sh_link].s;
7215 offsetl = sm_table[sh->sh_link].offset;
7217 for(sym = (Elf32_Sym *)(s->data + offset);
7218 sym < (Elf32_Sym *)s->data_ptr;
7219 sym++) {
7220 /* offset name */
7221 if (sym->st_name != 0)
7222 sym->st_name += offsetl;
7223 /* add to internal hash table */
7224 if (s->hash) {
7225 update_hash_elf_sym(s->hash, sym - (Elf32_Sym *)s->data,
7226 sym->st_info, sl->data + sym->st_name);
7228 /* no need to patch */
7229 if (sym->st_shndx == SHN_UNDEF ||
7230 sym->st_shndx >= SHN_LORESERVE)
7231 continue;
7232 /* transform section number */
7233 sm = &sm_table[sym->st_shndx];
7234 if (sm->s) {
7235 sym->st_shndx = sm->s->sh_num;
7236 /* offset value */
7237 sym->st_value += sm->offset;
7238 } else {
7239 /* if the section was suppressed, we put a dummy symbol */
7240 /* XXX: suppress it ? */
7241 sym->st_value = 0;
7242 sym->st_shndx = SHN_ABS;
7243 sym->st_info = 0;
7244 sym->st_name = 0;
7245 printf("warning: invalid symbol %d\n",
7246 sym - (Elf32_Sym *)(s->data + offset) + 1);
7249 break;
7250 case SHT_REL:
7251 /* take symbol offset information */
7252 /* minus one because we deleted the first symbol */
7253 offsetl = (sm_table[sh->sh_link].offset / sizeof(Elf32_Sym)) - 1;
7254 /* take relocation offset information */
7255 offseti = sm_table[sh->sh_info].offset;
7257 for(rel = (Elf32_Rel *)(s->data + offset);
7258 rel < (Elf32_Rel *)s->data_ptr;
7259 rel++) {
7260 int type, sym_index;
7261 /* offset symbol index */
7262 type = ELF32_R_TYPE(rel->r_info);
7263 sym_index = ELF32_R_SYM(rel->r_info);
7264 sym_index += offsetl;
7265 rel->r_info = ELF32_R_INFO(sym_index, type);
7266 /* offset the relocation offset */
7267 rel->r_offset += offseti;
7269 break;
7270 default:
7271 break;
7274 free(sm_table);
7275 free(shdr);
7276 fclose(f);
7277 return 0;
7280 /* print the position in the source file of PC value 'pc' by reading
7281 the stabs debug information */
7282 static void rt_printline(unsigned long wanted_pc)
7284 Stab_Sym *sym, *sym_end;
7285 char func_name[128];
7286 unsigned long func_addr, last_pc, pc;
7287 const char *incl_files[INCLUDE_STACK_SIZE];
7288 int incl_index, len, last_line_num, i;
7289 const char *str, *p;
7291 func_name[0] = '\0';
7292 func_addr = 0;
7293 incl_index = 0;
7294 last_pc = 0xffffffff;
7295 last_line_num = 1;
7296 sym = (Stab_Sym *)stab_section->data + 1;
7297 sym_end = (Stab_Sym *)stab_section->data_ptr;
7298 while (sym < sym_end) {
7299 switch(sym->n_type) {
7300 /* function start or end */
7301 case N_FUN:
7302 if (sym->n_strx == 0) {
7303 func_name[0] = '\0';
7304 func_addr = 0;
7305 } else {
7306 str = stabstr_section->data + sym->n_strx;
7307 p = strchr(str, ':');
7308 if (!p) {
7309 pstrcpy(func_name, sizeof(func_name), str);
7310 } else {
7311 len = p - str;
7312 if (len > sizeof(func_name) - 1)
7313 len = sizeof(func_name) - 1;
7314 memcpy(func_name, str, len);
7315 func_name[len] = '\0';
7317 func_addr = sym->n_value;
7319 break;
7320 /* line number info */
7321 case N_SLINE:
7322 pc = sym->n_value + func_addr;
7323 if (wanted_pc >= last_pc && wanted_pc < pc)
7324 goto found;
7325 last_pc = pc;
7326 last_line_num = sym->n_desc;
7327 break;
7328 /* include files */
7329 case N_BINCL:
7330 str = stabstr_section->data + sym->n_strx;
7331 add_incl:
7332 if (incl_index < INCLUDE_STACK_SIZE) {
7333 incl_files[incl_index++] = str;
7335 break;
7336 case N_EINCL:
7337 if (incl_index > 1)
7338 incl_index--;
7339 break;
7340 case N_SO:
7341 if (sym->n_strx == 0) {
7342 incl_index = 0; /* end of translation unit */
7343 } else {
7344 str = stabstr_section->data + sym->n_strx;
7345 /* do not add path */
7346 len = strlen(str);
7347 if (len > 0 && str[len - 1] != '/')
7348 goto add_incl;
7350 break;
7352 sym++;
7354 /* did not find line number info: */
7355 fprintf(stderr, "(no debug info, pc=0x%08lx): ", wanted_pc);
7356 return;
7357 found:
7358 for(i = 0; i < incl_index - 1; i++)
7359 fprintf(stderr, "In file included from %s\n",
7360 incl_files[i]);
7361 if (incl_index > 0) {
7362 fprintf(stderr, "%s:%d: ",
7363 incl_files[incl_index - 1], last_line_num);
7365 if (func_name[0] != '\0') {
7366 fprintf(stderr, "in function '%s()': ", func_name);
7370 /* emit a run time error at position 'pc' */
7371 void rt_error(unsigned long pc, const char *fmt, ...)
7373 va_list ap;
7374 va_start(ap, fmt);
7376 rt_printline(pc);
7377 vfprintf(stderr, fmt, ap);
7378 fprintf(stderr, "\n");
7379 exit(255);
7380 va_end(ap);
7383 #ifndef WIN32
7384 /* signal handler for fatal errors */
7385 static void sig_error(int signum, siginfo_t *siginf, void *puc)
7387 struct ucontext *uc = puc;
7388 unsigned long pc;
7390 #ifdef __i386__
7391 pc = uc->uc_mcontext.gregs[14];
7392 #else
7393 #error please put the right sigcontext field
7394 #endif
7396 switch(signum) {
7397 case SIGFPE:
7398 switch(siginf->si_code) {
7399 case FPE_INTDIV:
7400 case FPE_FLTDIV:
7401 rt_error(pc, "division by zero");
7402 break;
7403 default:
7404 rt_error(pc, "floating point exception");
7405 break;
7407 break;
7408 case SIGBUS:
7409 case SIGSEGV:
7410 rt_error(pc, "dereferencing invalid pointer");
7411 break;
7412 case SIGILL:
7413 rt_error(pc, "illegal instruction");
7414 break;
7415 case SIGABRT:
7416 rt_error(pc, "abort() called");
7417 break;
7418 default:
7419 rt_error(pc, "caught signal %d", signum);
7420 break;
7422 exit(255);
7424 #endif
7426 static void *resolve_sym(const char *sym)
7428 #ifdef CONFIG_TCC_BCHECK
7429 if (do_bounds_check) {
7430 void *ptr;
7431 ptr = bound_resolve_sym(sym);
7432 if (ptr)
7433 return ptr;
7435 #endif
7436 return dlsym(NULL, sym);
7439 static void resolve_extern_syms(void)
7441 unsigned long addr;
7442 Elf32_Sym *sym;
7443 const char *name;
7445 for(sym = (Elf32_Sym *)symtab_section->data + 1;
7446 sym < (Elf32_Sym *)symtab_section->data_ptr;
7447 sym++) {
7448 if (sym->st_shndx == SHN_UNDEF) {
7449 name = symtab_section->link->data + sym->st_name;
7450 addr = (unsigned long)resolve_sym(name);
7451 if (!addr)
7452 error("unresolved external reference '%s'", name);
7453 sym->st_value = addr;
7454 sym->st_shndx = SHN_ABS;
7459 /* relocate all the code and data */
7460 static void relocate_program(void)
7462 Section *s;
7464 /* compute relocation address : section are relocated in place */
7465 for(s = first_section; s != NULL; s = s->next) {
7466 if (s->sh_flags & SHF_ALLOC)
7467 s->sh_addr = (unsigned long)s->data;
7470 /* relocate each section */
7471 for(s = first_section; s != NULL; s = s->next) {
7472 if ((s->sh_flags & SHF_ALLOC) && s->reloc)
7473 relocate_section(s);
7477 /* launch the compiled program with the given arguments */
7478 int tcc_run(TCCState *s1, int argc, char **argv)
7480 int (*prog_main)(int, char **);
7481 int sym_index;
7483 resolve_extern_syms();
7485 relocate_program();
7487 sym_index = find_elf_sym(symtab_section, "main");
7488 if (!sym_index)
7489 error("main() not defined");
7490 prog_main = (void *)get_sym_val(sym_index);
7492 if (do_debug) {
7493 #ifdef WIN32
7494 error("debug mode currently not available for Windows");
7495 #else
7496 struct sigaction sigact;
7497 /* install TCC signal handlers to print debug info on fatal
7498 runtime errors */
7499 sigact.sa_flags = SA_SIGINFO | SA_ONESHOT;
7500 sigact.sa_sigaction = sig_error;
7501 sigemptyset(&sigact.sa_mask);
7502 sigaction(SIGFPE, &sigact, NULL);
7503 sigaction(SIGILL, &sigact, NULL);
7504 sigaction(SIGSEGV, &sigact, NULL);
7505 sigaction(SIGBUS, &sigact, NULL);
7506 sigaction(SIGABRT, &sigact, NULL);
7507 #endif
7510 #ifdef CONFIG_TCC_BCHECK
7511 if (do_bounds_check) {
7512 int *p, *p_end;
7513 __bound_init();
7514 /* add all known static regions */
7515 p = (int *)bounds_section->data;
7516 p_end = (int *)bounds_section->data_ptr;
7517 while (p < p_end) {
7518 __bound_new_region((void *)p[0], p[1]);
7519 p += 2;
7522 #endif
7524 return (*prog_main)(argc, argv);
7527 TCCState *tcc_new(void)
7529 char *p, *r;
7530 TCCState *s;
7532 s = malloc(sizeof(TCCState));
7533 if (!s)
7534 return NULL;
7536 /* default include paths */
7537 nb_include_paths = 0;
7538 tcc_add_include_path(s, "/usr/include");
7539 tcc_add_include_path(s, CONFIG_TCC_PREFIX "/lib/tcc/include");
7541 /* add all tokens */
7542 tok_ident = TOK_IDENT;
7543 p = tcc_keywords;
7544 while (*p) {
7545 r = p;
7546 while (*r++);
7547 tok_alloc(p, r - p - 1);
7548 p = r;
7551 /* standard defines */
7552 tcc_define_symbol(s, "__STDC__", NULL);
7553 #ifdef __i386__
7554 tcc_define_symbol(s, "__i386__", NULL);
7555 #endif
7556 /* tiny C specific defines */
7557 tcc_define_symbol(s, "__TINYC__", NULL);
7559 /* create standard sections */
7560 nb_sections = 1;
7561 text_section = new_section(".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
7562 data_section = new_section(".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
7563 bss_section = new_section(".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
7565 /* symbols are always generated for linking stage */
7566 symtab_section = new_section(".symtab", SHT_SYMTAB, 0);
7567 symtab_section->sh_entsize = sizeof(Elf32_Sym);
7568 strtab_section = new_section(".strtab", SHT_STRTAB, 0);
7569 put_elf_str(strtab_section, "");
7570 symtab_section->link = strtab_section;
7571 put_elf_sym(symtab_section, 0, 0, 0, 0, 0, NULL);
7573 /* private hash table for extern symbols */
7574 new_section_hash(".hashtab", SHF_PRIVATE,
7575 ELF_SYM_HASH_SIZE, symtab_section);
7576 return s;
7579 void tcc_delete(TCCState *s)
7581 free(s);
7584 int tcc_add_include_path(TCCState *s, const char *pathname)
7586 char *pathname1;
7588 if (nb_include_paths >= INCLUDE_PATHS_MAX)
7589 return -1;
7590 pathname1 = strdup(pathname);
7591 if (!pathname1)
7592 return -1;
7593 include_paths[nb_include_paths++] = pathname1;
7594 return 0;
7597 #if !defined(LIBTCC)
7599 void tcc_add_file(TCCState *s, const char *filename)
7601 const char *p;
7602 int ext;
7604 /* find file type with extension */
7605 p = strrchr(filename, '.');
7606 if (!p)
7607 ext = '\0';
7608 else
7609 ext = p[1];
7610 if (ext == 'o') {
7611 tcc_load_object(s, filename);
7612 } else {
7613 tcc_compile_file(s, filename);
7617 void help(void)
7619 printf("tcc version 0.9.8 - Tiny C Compiler - Copyright (C) 2001, 2002 Fabrice Bellard\n"
7620 "usage: tcc [-Idir] [-Dsym[=val]] [-Usym] [-llib] [-g] [-b]\n"
7621 " [-i infile] [-bench] infile [infile_args...]\n"
7622 "\n"
7623 "-Idir : add include path 'dir'\n"
7624 "-Dsym[=val] : define 'sym' with value 'val'\n"
7625 "-Usym : undefine 'sym'\n"
7626 "-llib : link with dynamic library 'lib'\n"
7627 "-g : generate runtime debug info\n"
7628 #ifdef CONFIG_TCC_BCHECK
7629 "-b : compile with built-in memory and bounds checker (implies -g)\n"
7630 #endif
7631 "-i infile : compile infile\n"
7632 "-bench : output compilation statistics\n"
7636 int main(int argc, char **argv)
7638 char *r, *outfile;
7639 int optind, file_type;
7640 TCCState *s;
7642 s = tcc_new();
7643 file_type = TCC_FILE_EXE;
7645 optind = 1;
7646 outfile = NULL;
7647 while (1) {
7648 if (optind >= argc) {
7649 show_help:
7650 help();
7651 return 1;
7653 r = argv[optind];
7654 if (r[0] != '-')
7655 break;
7656 optind++;
7657 if (r[1] == 'I') {
7658 if (tcc_add_include_path(s, r + 2) < 0)
7659 error("too many include paths");
7660 } else if (r[1] == 'D') {
7661 char *sym, *value;
7662 sym = r + 2;
7663 value = strchr(sym, '=');
7664 if (value) {
7665 *value = '\0';
7666 value++;
7668 tcc_define_symbol(s, sym, value);
7669 } else if (r[1] == 'U') {
7670 tcc_undefine_symbol(s, r + 2);
7671 } else if (r[1] == 'l') {
7672 char buf[1024];
7673 snprintf(buf, sizeof(buf), "lib%s.so", r + 2);
7674 tcc_add_dll(s, buf);
7675 } else if (r[1] == 'i') {
7676 if (optind >= argc)
7677 goto show_help;
7678 tcc_add_file(s, argv[optind++]);
7679 } else if (!strcmp(r + 1, "bench")) {
7680 do_bench = 1;
7681 #ifdef CONFIG_TCC_BCHECK
7682 } else if (r[1] == 'b') {
7683 if (!do_bounds_check) {
7684 do_bounds_check = 1;
7685 /* define symbol */
7686 tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL);
7687 /* create bounds sections */
7688 bounds_section = new_section(".bounds",
7689 SHT_PROGBITS, SHF_ALLOC);
7690 lbounds_section = new_section(".lbounds",
7691 SHT_PROGBITS, SHF_ALLOC);
7692 /* debug is implied */
7693 goto debug_opt;
7695 #endif
7696 } else if (r[1] == 'g') {
7697 #ifdef CONFIG_TCC_BCHECK
7698 debug_opt:
7699 #endif
7700 if (!do_debug) {
7701 do_debug = 1;
7703 /* stab symbols */
7704 stab_section = new_section(".stab", SHT_PROGBITS, 0);
7705 stab_section->sh_entsize = sizeof(Stab_Sym);
7706 stabstr_section = new_section(".stabstr", SHT_STRTAB, 0);
7707 put_elf_str(stabstr_section, "");
7708 stab_section->link = stabstr_section;
7709 /* put first entry */
7710 put_stabs("", 0, 0, 0, 0);
7712 } else
7713 /* the following options are only for testing, so not
7714 documented */
7715 if (r[1] == 'c') {
7716 file_type = TCC_FILE_OBJ;
7717 } else if (!strcmp(r + 1, "static")) {
7718 static_link = 1;
7719 } else if (!strcmp(r + 1, "shared")) {
7720 file_type = TCC_FILE_DLL;
7721 } else if (r[1] == 'o') {
7722 if (optind >= argc)
7723 goto show_help;
7724 outfile = argv[optind++];
7725 } else {
7726 error("invalid option -- '%s'", r);
7730 tcc_add_file(s, argv[optind]);
7732 if (do_bench) {
7733 printf("total: %d idents, %d lines, %d bytes\n",
7734 tok_ident - TOK_IDENT, total_lines, total_bytes);
7737 if (outfile) {
7738 tcc_output_file(s, outfile, file_type);
7739 return 0;
7740 } else {
7741 return tcc_run(s, argc - optind, argv + optind);
7745 #endif