added FPU control word
[tinycc.git] / tcc.c
blobf37b6877cb9e427777987523b61c62f0c57a82a4
1 /*
2 * TCC - Tiny C Compiler
3 *
4 * Copyright (c) 2001, 2002 Fabrice Bellard
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <stdarg.h>
23 #include <string.h>
24 #include <errno.h>
25 #include <math.h>
26 #include <unistd.h>
27 #include <signal.h>
28 #include <unistd.h>
29 #include <fcntl.h>
30 #ifndef WIN32
31 #include <sys/ucontext.h>
32 #include <sys/mman.h>
33 #endif
34 #include "elf.h"
35 #include "stab.h"
36 #ifndef CONFIG_TCC_STATIC
37 #include <dlfcn.h>
38 #endif
40 #include "libtcc.h"
42 //#define DEBUG
43 /* preprocessor debug */
44 //#define PP_DEBUG
46 /* target selection */
47 //#define TCC_TARGET_I386 /* i386 code generator */
48 //#define TCC_TARGET_IL /* .NET CLI generator */
50 /* default target is I386 */
51 #if !defined(TCC_TARGET_I386) && !defined(TCC_TARGET_IL)
52 #define TCC_TARGET_I386
53 #endif
55 #if !defined(WIN32) && !defined(TCC_UCLIBC) && !defined(TCC_TARGET_IL)
56 #define CONFIG_TCC_BCHECK /* enable bound checking code */
57 #endif
59 #ifndef CONFIG_TCC_PREFIX
60 #define CONFIG_TCC_PREFIX "/usr/local"
61 #endif
63 /* path to find crt1.o, crti.o and crtn.o. Only needed when generating
64 executables or dlls */
65 #define CONFIG_TCC_CRT_PREFIX "/usr/lib"
67 /* amount of virtual memory associated to a section (currently, we do
68 not realloc them) */
69 #define SECTION_VSIZE (1024 * 1024)
71 #define INCLUDE_STACK_SIZE 32
72 #define IFDEF_STACK_SIZE 64
73 #define VSTACK_SIZE 64
74 #define STRING_MAX_SIZE 1024
76 #define TOK_HASH_SIZE 2048 /* must be a power of two */
77 #define TOK_ALLOC_INCR 512 /* must be a power of two */
78 #define SYM_HASH_SIZE 1031
79 #define ELF_SYM_HASH_SIZE 2048
80 #define ELF_DYNSYM_HASH_SIZE 32
82 /* token symbol management */
83 typedef struct TokenSym {
84 struct TokenSym *hash_next;
85 int tok; /* token number */
86 int len;
87 char str[1];
88 } TokenSym;
90 /* constant value */
91 typedef union CValue {
92 long double ld;
93 double d;
94 float f;
95 int i;
96 unsigned int ui;
97 unsigned int ul; /* address (should be unsigned long on 64 bit cpu) */
98 long long ll;
99 unsigned long long ull;
100 struct TokenSym *ts;
101 struct Sym *sym;
102 void *ptr;
103 int tab[1];
104 } CValue;
106 /* value on stack */
107 typedef struct SValue {
108 int t; /* type */
109 unsigned short r; /* register + flags */
110 unsigned short r2; /* second register, used for 'long long'
111 type. If not used, set to VT_CONST */
112 CValue c; /* constant, if VT_CONST */
113 } SValue;
115 /* symbol management */
116 typedef struct Sym {
117 int v; /* symbol token */
118 int t; /* associated type */
119 int r; /* associated register */
120 int c; /* associated number */
121 struct Sym *next; /* next related symbol */
122 struct Sym *prev; /* prev symbol in stack */
123 struct Sym *hash_next; /* next symbol in hash table */
124 } Sym;
126 typedef struct SymStack {
127 struct Sym *top;
128 struct Sym *hash[SYM_HASH_SIZE];
129 } SymStack;
131 /* section definition */
132 /* XXX: use directly ELF structure for parameters ? */
133 /* special flag to indicate that the section should not be linked to
134 the other ones */
135 #define SHF_PRIVATE 0x80000000
137 typedef struct Section {
138 unsigned char *data; /* section data */
139 unsigned char *data_ptr; /* current data pointer */
140 int sh_name; /* elf section name (only used during output) */
141 int sh_num; /* elf section number */
142 int sh_type; /* elf section type */
143 int sh_flags; /* elf section flags */
144 int sh_info; /* elf section info */
145 int sh_addralign; /* elf section alignment */
146 int sh_entsize; /* elf entry size */
147 unsigned long sh_size; /* section size (only used during output) */
148 unsigned long sh_addr; /* address at which the section is relocated */
149 unsigned long sh_offset; /* address at which the section is relocated */
150 struct Section *link; /* link to another section */
151 struct Section *reloc; /* corresponding section for relocation, if any */
152 struct Section *hash; /* hash table for symbols */
153 struct Section *next;
154 char name[64]; /* section name */
155 } Section;
157 typedef struct DLLReference {
158 int level;
159 char name[1];
160 } DLLReference;
162 /* GNUC attribute definition */
163 typedef struct AttributeDef {
164 int aligned;
165 Section *section;
166 unsigned char func_call; /* FUNC_CDECL or FUNC_STDCALL */
167 } AttributeDef;
169 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
170 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
171 #define SYM_FIRST_ANOM (1 << (31 - VT_STRUCT_SHIFT)) /* first anonymous sym */
173 /* stored in 'Sym.c' field */
174 #define FUNC_NEW 1 /* ansi function prototype */
175 #define FUNC_OLD 2 /* old function prototype */
176 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
178 /* stored in 'Sym.r' field */
179 #define FUNC_CDECL 0 /* standard c call */
180 #define FUNC_STDCALL 1 /* pascal c call */
182 /* field 'Sym.t' for macros */
183 #define MACRO_OBJ 0 /* object like macro */
184 #define MACRO_FUNC 1 /* function like macro */
186 /* field 'Sym.t' for labels */
187 #define LABEL_FORWARD 1 /* label is forward defined */
189 /* type_decl() types */
190 #define TYPE_ABSTRACT 1 /* type without variable */
191 #define TYPE_DIRECT 2 /* type with variable */
193 #define IO_BUF_SIZE 8192
195 typedef struct BufferedFile {
196 unsigned char *buf_ptr;
197 unsigned char *buf_end;
198 int fd;
199 int line_num; /* current line number - here to simply code */
200 char filename[1024]; /* current filename - here to simply code */
201 unsigned char buffer[IO_BUF_SIZE + 1]; /* extra size for CH_EOB char */
202 } BufferedFile;
204 #define CH_EOB 0 /* end of buffer or '\0' char in file */
205 #define CH_EOF (-1) /* end of file */
207 /* parsing state (used to save parser state to reparse part of the
208 source several times) */
209 typedef struct ParseState {
210 int *macro_ptr;
211 int line_num;
212 int tok;
213 CValue tokc;
214 } ParseState;
216 /* used to record tokens */
217 typedef struct TokenString {
218 int *str;
219 int len;
220 int last_line_num;
221 } TokenString;
223 /* parser */
224 struct BufferedFile *file;
225 int ch, ch1, tok, tok1;
226 CValue tokc, tok1c;
228 /* sections */
229 Section **sections;
230 int nb_sections; /* number of sections, including first dummy section */
231 Section *text_section, *data_section, *bss_section; /* predefined sections */
232 Section *cur_text_section; /* current section where function code is
233 generated */
234 /* bound check related sections */
235 Section *bounds_section; /* contains global data bound description */
236 Section *lbounds_section; /* contains local data bound description */
237 /* symbol sections */
238 Section *symtab_section, *strtab_section;
239 /* temporary dynamic symbol sections (for dll loading) */
240 Section *dynsymtab_section, *dynstrtab_section;
241 /* exported dynamic symbol section */
242 Section *dynsym;
243 /* got handling */
244 Section *got;
245 unsigned long *got_offsets;
246 int nb_got_offsets;
247 int nb_plt_entries;
250 /* array of all loaded dlls (including those referenced by loaded
251 dlls) */
252 DLLReference **loaded_dlls;
253 int nb_loaded_dlls;
255 /* debug sections */
256 Section *stab_section, *stabstr_section;
258 char **library_paths;
259 int nb_library_paths;
261 /* loc : local variable index
262 ind : output code index
263 rsym: return symbol
264 anon_sym: anonymous symbol index
266 int rsym, anon_sym,
267 prog, ind, loc, const_wanted;
268 int global_expr; /* true if compound literals must be allocated
269 globally (used during initializers parsing */
270 int func_vt, func_vc; /* current function return type (used by
271 return instruction) */
272 int last_line_num, last_ind, func_ind; /* debug last line number and pc */
273 int tok_ident;
274 TokenSym **table_ident;
275 TokenSym *hash_ident[TOK_HASH_SIZE];
276 char token_buf[STRING_MAX_SIZE + 1];
277 char *funcname;
278 SymStack define_stack, global_stack, local_stack, label_stack;
280 SValue vstack[VSTACK_SIZE], *vtop;
281 int *macro_ptr, *macro_ptr_allocated;
282 BufferedFile *include_stack[INCLUDE_STACK_SIZE], **include_stack_ptr;
283 int ifdef_stack[IFDEF_STACK_SIZE], *ifdef_stack_ptr;
284 char **include_paths;
285 int nb_include_paths;
286 int char_pointer_type;
287 int func_old_type;
289 /* compile with debug symbol (and use them if error during execution) */
290 int do_debug = 0;
292 /* compile with built-in memory and bounds checker */
293 int do_bounds_check = 0;
295 /* display benchmark infos */
296 int do_bench = 0;
297 int total_lines;
298 int total_bytes;
300 /* use GNU C extensions */
301 int gnu_ext = 1;
303 /* use Tiny C extensions */
304 int tcc_ext = 1;
306 /* if true, static linking is performed */
307 int static_link = 0;
309 /* give the path of the tcc libraries */
310 static const char *tcc_lib_path = CONFIG_TCC_PREFIX "/lib/tcc";
312 struct TCCState {
313 int output_type;
316 /* The current value can be: */
317 #define VT_VALMASK 0x00ff
318 #define VT_CONST 0x00f0 /* constant in vc
319 (must be first non register value) */
320 #define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */
321 #define VT_LOCAL 0x00f2 /* offset on stack */
322 #define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */
323 #define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */
324 #define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */
325 #define VT_LVAL 0x0100 /* var is an lvalue */
326 #define VT_SYM 0x0200 /* a symbol value is added */
327 #define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for
328 char/short stored in integer registers) */
329 #define VT_MUSTBOUND 0x0800 /* bound checking must be done before
330 dereferencing value */
331 #define VT_BOUNDED 0x8000 /* value is bounded. The address of the
332 bounding function call point is in vc */
333 #define VT_LVAL_BYTE 0x1000 /* lvalue is a byte */
334 #define VT_LVAL_SHORT 0x2000 /* lvalue is a short */
335 #define VT_LVAL_UNSIGNED 0x4000 /* lvalue is unsigned */
336 #define VT_LVAL_TYPE (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)
338 /* types */
339 #define VT_STRUCT_SHIFT 16 /* structure/enum name shift (16 bits left) */
341 #define VT_INT 0 /* integer type */
342 #define VT_BYTE 1 /* signed byte type */
343 #define VT_SHORT 2 /* short type */
344 #define VT_VOID 3 /* void type */
345 #define VT_PTR 4 /* pointer */
346 #define VT_ENUM 5 /* enum definition */
347 #define VT_FUNC 6 /* function type */
348 #define VT_STRUCT 7 /* struct/union definition */
349 #define VT_FLOAT 8 /* IEEE float */
350 #define VT_DOUBLE 9 /* IEEE double */
351 #define VT_LDOUBLE 10 /* IEEE long double */
352 #define VT_BOOL 11 /* ISOC99 boolean type */
353 #define VT_LLONG 12 /* 64 bit integer */
354 #define VT_LONG 13 /* long integer (NEVER USED as type, only
355 during parsing) */
356 #define VT_BTYPE 0x000f /* mask for basic type */
357 #define VT_UNSIGNED 0x0010 /* unsigned type */
358 #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
359 #define VT_BITFIELD 0x0040 /* bitfield modifier */
361 /* storage */
362 #define VT_EXTERN 0x00000080 /* extern definition */
363 #define VT_STATIC 0x00000100 /* static variable */
364 #define VT_TYPEDEF 0x00000200 /* typedef definition */
366 /* type mask (except storage) */
367 #define VT_TYPE (~(VT_EXTERN | VT_STATIC | VT_TYPEDEF))
369 /* token values */
371 /* warning: the following compare tokens depend on i386 asm code */
372 #define TOK_ULT 0x92
373 #define TOK_UGE 0x93
374 #define TOK_EQ 0x94
375 #define TOK_NE 0x95
376 #define TOK_ULE 0x96
377 #define TOK_UGT 0x97
378 #define TOK_LT 0x9c
379 #define TOK_GE 0x9d
380 #define TOK_LE 0x9e
381 #define TOK_GT 0x9f
383 #define TOK_LAND 0xa0
384 #define TOK_LOR 0xa1
386 #define TOK_DEC 0xa2
387 #define TOK_MID 0xa3 /* inc/dec, to void constant */
388 #define TOK_INC 0xa4
389 #define TOK_UDIV 0xb0 /* unsigned division */
390 #define TOK_UMOD 0xb1 /* unsigned modulo */
391 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
392 #define TOK_CINT 0xb3 /* number in tokc */
393 #define TOK_CCHAR 0xb4 /* char constant in tokc */
394 #define TOK_STR 0xb5 /* pointer to string in tokc */
395 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
396 #define TOK_LCHAR 0xb7
397 #define TOK_LSTR 0xb8
398 #define TOK_CFLOAT 0xb9 /* float constant */
399 #define TOK_LINENUM 0xba /* line number info */
400 #define TOK_CDOUBLE 0xc0 /* double constant */
401 #define TOK_CLDOUBLE 0xc1 /* long double constant */
402 #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
403 #define TOK_ADDC1 0xc3 /* add with carry generation */
404 #define TOK_ADDC2 0xc4 /* add with carry use */
405 #define TOK_SUBC1 0xc5 /* add with carry generation */
406 #define TOK_SUBC2 0xc6 /* add with carry use */
407 #define TOK_CUINT 0xc8 /* unsigned int constant */
408 #define TOK_CLLONG 0xc9 /* long long constant */
409 #define TOK_CULLONG 0xca /* unsigned long long constant */
410 #define TOK_ARROW 0xcb
411 #define TOK_DOTS 0xcc /* three dots */
412 #define TOK_SHR 0xcd /* unsigned shift right */
414 #define TOK_SHL 0x01 /* shift left */
415 #define TOK_SAR 0x02 /* signed shift right */
417 /* assignement operators : normal operator or 0x80 */
418 #define TOK_A_MOD 0xa5
419 #define TOK_A_AND 0xa6
420 #define TOK_A_MUL 0xaa
421 #define TOK_A_ADD 0xab
422 #define TOK_A_SUB 0xad
423 #define TOK_A_DIV 0xaf
424 #define TOK_A_XOR 0xde
425 #define TOK_A_OR 0xfc
426 #define TOK_A_SHL 0x81
427 #define TOK_A_SAR 0x82
429 #define TOK_EOF (-1) /* end of file */
431 /* all identificators and strings have token above that */
432 #define TOK_IDENT 256
434 enum {
435 TOK_INT = TOK_IDENT,
436 TOK_VOID,
437 TOK_CHAR,
438 TOK_IF,
439 TOK_ELSE,
440 TOK_WHILE,
441 TOK_BREAK,
442 TOK_RETURN,
443 TOK_FOR,
444 TOK_EXTERN,
445 TOK_STATIC,
446 TOK_UNSIGNED,
447 TOK_GOTO,
448 TOK_DO,
449 TOK_CONTINUE,
450 TOK_SWITCH,
451 TOK_CASE,
453 /* ignored types Must have contiguous values */
454 TOK_CONST,
455 TOK_VOLATILE,
456 TOK_LONG,
457 TOK_REGISTER,
458 TOK_SIGNED,
459 TOK___SIGNED__, /* gcc keyword */
460 TOK_AUTO,
461 TOK_INLINE,
462 TOK___INLINE__, /* gcc keyword */
463 TOK_RESTRICT,
465 /* unsupported type */
466 TOK_FLOAT,
467 TOK_DOUBLE,
468 TOK_BOOL,
470 TOK_SHORT,
471 TOK_STRUCT,
472 TOK_UNION,
473 TOK_TYPEDEF,
474 TOK_DEFAULT,
475 TOK_ENUM,
476 TOK_SIZEOF,
477 TOK___ATTRIBUTE__,
479 /* preprocessor only */
480 TOK_UIDENT, /* first "user" ident (not keyword) */
481 TOK_DEFINE = TOK_UIDENT,
482 TOK_INCLUDE,
483 TOK_IFDEF,
484 TOK_IFNDEF,
485 TOK_ELIF,
486 TOK_ENDIF,
487 TOK_DEFINED,
488 TOK_UNDEF,
489 TOK_ERROR,
490 TOK_LINE,
491 TOK___LINE__,
492 TOK___FILE__,
493 TOK___DATE__,
494 TOK___TIME__,
495 TOK___VA_ARGS__,
497 /* special identifiers */
498 TOK___FUNC__,
499 TOK_MAIN,
500 #define DEF(id, str) id,
501 #include "tcctok.h"
502 #undef DEF
505 char *tcc_keywords =
506 "int\0void\0char\0if\0else\0while\0break\0return\0for\0extern\0static\0"
507 "unsigned\0goto\0do\0continue\0switch\0case\0const\0volatile\0long\0"
508 "register\0signed\0__signed__\0auto\0inline\0__inline__\0restrict\0"
509 "float\0double\0_Bool\0short\0struct\0union\0typedef\0default\0enum\0"
510 "sizeof\0__attribute__\0"
511 /* the following are not keywords. They are included to ease parsing */
512 "define\0include\0ifdef\0ifndef\0elif\0endif\0"
513 "defined\0undef\0error\0line\0"
514 "__LINE__\0__FILE__\0__DATE__\0__TIME__\0__VA_ARGS__\0"
515 "__func__\0main\0"
516 /* builtin functions */
517 #define DEF(id, str) str "\0"
518 #include "tcctok.h"
519 #undef DEF
522 #ifdef WIN32
523 #define snprintf _snprintf
524 #endif
526 #if defined(WIN32) || defined(TCC_UCLIBC)
527 /* currently incorrect */
528 long double strtold(const char *nptr, char **endptr)
530 return (long double)strtod(nptr, endptr);
532 float strtof(const char *nptr, char **endptr)
534 return (float)strtod(nptr, endptr);
536 #else
537 /* XXX: need to define this to use them in non ISOC99 context */
538 extern float strtof (const char *__nptr, char **__endptr);
539 extern long double strtold (const char *__nptr, char **__endptr);
540 #endif
542 static char *pstrcpy(char *buf, int buf_size, const char *s);
543 static char *pstrcat(char *buf, int buf_size, const char *s);
545 void sum(int l);
546 void next(void);
547 void next_nomacro(void);
548 int expr_const(void);
549 void expr_eq(void);
550 void gexpr(void);
551 void decl(int l);
552 void decl_initializer(int t, Section *sec, unsigned long c, int first, int size_only);
553 void decl_initializer_alloc(int t, AttributeDef *ad, int r, int has_init,
554 int v, int scope);
555 int gv(int rc);
556 void gv2(int rc1, int rc2);
557 void move_reg(int r, int s);
558 void save_regs(int n);
559 void save_reg(int r);
560 void vpop(void);
561 void vswap(void);
562 void vdup(void);
563 int get_reg(int rc);
565 void macro_subst(TokenString *tok_str,
566 Sym **nested_list, int *macro_str);
567 int save_reg_forced(int r);
568 void gen_op(int op);
569 void force_charshort_cast(int t);
570 void gen_cast(int t);
571 void vstore(void);
572 Sym *sym_find(int v);
573 Sym *sym_push(int v, int t, int r, int c);
575 /* type handling */
576 int type_size(int t, int *a);
577 int pointed_type(int t);
578 int pointed_size(int t);
579 int is_compatible_types(int t1, int t2);
580 int parse_btype(int *type_ptr, AttributeDef *ad);
581 int type_decl(AttributeDef *ad, int *v, int t, int td);
583 void error(const char *fmt, ...);
584 void rt_error(unsigned long pc, const char *fmt, ...);
585 void vpushi(int v);
586 void vset(int t, int r, int v);
587 void type_to_str(char *buf, int buf_size,
588 int t, const char *varstr);
589 char *get_tok_str(int v, CValue *cv);
590 Sym *external_sym(int v, int u, int r);
591 static Sym *get_sym_ref(int t, Section *sec,
592 unsigned long offset, unsigned long size);
594 /* section generation */
595 void put_extern_sym(Sym *sym, Section *section, unsigned long value);
596 void greloc(Section *s, Sym *sym, unsigned long addr, int type);
597 static int put_elf_str(Section *s, const char *sym);
598 static int put_elf_sym(Section *s,
599 unsigned long value, unsigned long size,
600 int info, int other, int shndx, const char *name);
601 static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
602 int type, int symbol);
603 static void put_stabs(const char *str, int type, int other, int desc, int value);
604 static void put_stabn(int type, int other, int desc, int value);
605 static void put_stabd(int type, int other, int desc);
606 static int tcc_add_dll(TCCState *s, const char *filename, int flags);
608 #define AFF_PRINT_ERROR 0x0001 /* print error if file not found */
609 #define AFF_REFERENCED_DLL 0x0002 /* load a referenced dll from another dll */
610 static int tcc_add_file_internal(TCCState *s, const char *filename, int flags);
612 /* true if float/double/long double type */
613 static inline int is_float(int t)
615 int bt;
616 bt = t & VT_BTYPE;
617 return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT;
620 #ifdef TCC_TARGET_I386
621 #include "i386-gen.c"
622 #endif
623 #ifdef TCC_TARGET_IL
624 #include "il-gen.c"
625 #endif
627 #ifdef CONFIG_TCC_STATIC
629 #define RTLD_LAZY 0x001
630 #define RTLD_NOW 0x002
631 #define RTLD_GLOBAL 0x100
633 /* dummy function for profiling */
634 void *dlopen(const char *filename, int flag)
636 return NULL;
639 const char *dlerror(void)
641 return "error";
644 typedef struct TCCSyms {
645 char *str;
646 void *ptr;
647 } TCCSyms;
649 #define TCCSYM(a) { #a, &a, },
651 /* add the symbol you want here if no dynamic linking is done */
652 static TCCSyms tcc_syms[] = {
653 TCCSYM(printf)
654 TCCSYM(fprintf)
655 TCCSYM(fopen)
656 TCCSYM(fclose)
657 { NULL, NULL },
660 void *dlsym(void *handle, const char *symbol)
662 TCCSyms *p;
663 p = tcc_syms;
664 while (p->str != NULL) {
665 if (!strcmp(p->str, symbol))
666 return p->ptr;
667 p++;
669 return NULL;
672 #endif
674 /********************************************************/
676 /* we use our own 'finite' function to avoid potential problems with
677 non standard math libs */
678 /* XXX: endianness dependant */
679 int ieee_finite(double d)
681 int *p = (int *)&d;
682 return ((unsigned)((p[1] | 0x800fffff) + 1)) >> 31;
685 /* copy a string and truncate it. */
686 static char *pstrcpy(char *buf, int buf_size, const char *s)
688 char *q, *q_end;
689 int c;
691 if (buf_size > 0) {
692 q = buf;
693 q_end = buf + buf_size - 1;
694 while (q < q_end) {
695 c = *s++;
696 if (c == '\0')
697 break;
698 *q++ = c;
700 *q = '\0';
702 return buf;
705 /* strcat and truncate. */
706 static char *pstrcat(char *buf, int buf_size, const char *s)
708 int len;
709 len = strlen(buf);
710 if (len < buf_size)
711 pstrcpy(buf + len, buf_size - len, s);
712 return buf;
715 static void dynarray_add(void ***ptab, int *nb_ptr, void *data)
717 int nb, nb_alloc;
718 void **pp;
720 nb = *nb_ptr;
721 pp = *ptab;
722 /* every power of two we double array size */
723 if ((nb & (nb - 1)) == 0) {
724 if (!nb)
725 nb_alloc = 1;
726 else
727 nb_alloc = nb * 2;
728 pp = realloc(pp, nb_alloc * sizeof(void *));
729 if (!pp)
730 error("memory full");
731 *ptab = pp;
733 pp[nb++] = data;
734 *nb_ptr = nb;
737 Section *new_section(const char *name, int sh_type, int sh_flags)
739 Section *sec;
740 void *data;
742 sec = malloc(sizeof(Section));
743 if (!sec)
744 error("memory full");
745 memset(sec, 0, sizeof(Section));
746 pstrcpy(sec->name, sizeof(sec->name), name);
747 sec->sh_type = sh_type;
748 sec->sh_flags = sh_flags;
749 switch(sh_type) {
750 case SHT_HASH:
751 case SHT_REL:
752 case SHT_DYNSYM:
753 case SHT_SYMTAB:
754 case SHT_DYNAMIC:
755 sec->sh_addralign = 4;
756 break;
757 case SHT_STRTAB:
758 sec->sh_addralign = 1;
759 break;
760 default:
761 sec->sh_addralign = 32; /* default conservative alignment */
762 break;
764 #ifdef WIN32
765 /* XXX: currently, a single malloc */
766 data = malloc(SECTION_VSIZE);
767 if (data == NULL)
768 error("could not alloc section '%s'", name);
769 #else
770 data = mmap(NULL, SECTION_VSIZE,
771 PROT_EXEC | PROT_READ | PROT_WRITE,
772 MAP_PRIVATE | MAP_ANONYMOUS,
773 -1, 0);
774 if (data == (void *)(-1))
775 error("could not mmap section '%s'", name);
776 #endif
777 sec->data = data;
778 sec->data_ptr = data;
780 /* only add section if not private */
781 if (!(sh_flags & SHF_PRIVATE)) {
782 sec->sh_num = nb_sections;
783 dynarray_add((void ***)&sections, &nb_sections, sec);
785 return sec;
788 /* return a reference to a section, and create it if it does not
789 exists */
790 Section *find_section(const char *name)
792 Section *sec;
793 int i;
794 for(i = 1; i < nb_sections; i++) {
795 sec = sections[i];
796 if (!strcmp(name, sec->name))
797 return sec;
799 /* sections are created as PROGBITS */
800 return new_section(name, SHT_PROGBITS, SHF_ALLOC);
803 /* add a new relocation entry to symbol 'sym' in section 's' */
804 void greloc(Section *s, Sym *sym, unsigned long offset, int type)
806 if (!sym->c)
807 put_extern_sym(sym, NULL, 0);
808 /* now we can add ELF relocation info */
809 put_elf_reloc(symtab_section, s, offset, type, sym->c);
812 static inline int isid(int c)
814 return (c >= 'a' && c <= 'z') ||
815 (c >= 'A' && c <= 'Z') ||
816 c == '_';
819 static inline int isnum(int c)
821 return c >= '0' && c <= '9';
824 static inline int toup(int c)
826 if (ch >= 'a' && ch <= 'z')
827 return ch - 'a' + 'A';
828 else
829 return ch;
832 void printline(void)
834 BufferedFile **f;
836 if (file) {
837 for(f = include_stack; f < include_stack_ptr; f++)
838 fprintf(stderr, "In file included from %s:%d:\n",
839 (*f)->filename, (*f)->line_num);
840 if (file->line_num > 0) {
841 fprintf(stderr, "%s:%d: ", file->filename, file->line_num);
842 } else {
843 fprintf(stderr, "%s: ", file->filename);
845 } else {
846 fprintf(stderr, "tcc: ");
850 void error(const char *fmt, ...)
852 va_list ap;
853 va_start(ap, fmt);
854 printline();
855 vfprintf(stderr, fmt, ap);
856 fprintf(stderr, "\n");
857 exit(1);
858 va_end(ap);
861 void expect(const char *msg)
863 error("%s expected", msg);
866 void warning(const char *fmt, ...)
868 va_list ap;
870 va_start(ap, fmt);
871 printline();
872 fprintf(stderr, "warning: ");
873 vfprintf(stderr, fmt, ap);
874 fprintf(stderr, "\n");
875 va_end(ap);
878 void skip(int c)
880 if (tok != c)
881 error("'%c' expected", c);
882 next();
885 void test_lvalue(void)
887 if (!(vtop->r & VT_LVAL))
888 expect("lvalue");
891 TokenSym *tok_alloc(const char *str, int len)
893 TokenSym *ts, **pts, **ptable;
894 int h, i;
896 if (len <= 0)
897 len = strlen(str);
898 h = 1;
899 for(i=0;i<len;i++)
900 h = (h * 263 + ((unsigned char *)str)[i]) & (TOK_HASH_SIZE - 1);
902 pts = &hash_ident[h];
903 while (1) {
904 ts = *pts;
905 if (!ts)
906 break;
907 if (ts->len == len && !memcmp(ts->str, str, len))
908 return ts;
909 pts = &(ts->hash_next);
912 if (tok_ident >= SYM_FIRST_ANOM)
913 error("memory full");
915 /* expand token table if needed */
916 i = tok_ident - TOK_IDENT;
917 if ((i % TOK_ALLOC_INCR) == 0) {
918 ptable = realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *));
919 if (!ptable)
920 error("memory full");
921 table_ident = ptable;
924 ts = malloc(sizeof(TokenSym) + len);
925 if (!ts)
926 error("memory full");
927 table_ident[i] = ts;
928 ts->tok = tok_ident++;
929 ts->len = len;
930 ts->hash_next = NULL;
931 memcpy(ts->str, str, len + 1);
932 *pts = ts;
933 return ts;
936 void add_char(char **pp, int c)
938 char *p;
939 p = *pp;
940 if (c == '\'' || c == '\"' || c == '\\') {
941 /* XXX: could be more precise if char or string */
942 *p++ = '\\';
944 if (c >= 32 && c <= 126) {
945 *p++ = c;
946 } else {
947 *p++ = '\\';
948 if (c == '\n') {
949 *p++ = 'n';
950 } else {
951 *p++ = '0' + ((c >> 6) & 7);
952 *p++ = '0' + ((c >> 3) & 7);
953 *p++ = '0' + (c & 7);
956 *pp = p;
959 /* XXX: buffer overflow */
960 char *get_tok_str(int v, CValue *cv)
962 static char buf[STRING_MAX_SIZE + 1];
963 TokenSym *ts;
964 char *p;
965 int i;
967 if (v == TOK_CINT || v == TOK_CUINT) {
968 sprintf(buf, "%u", cv->ui);
969 return buf;
970 } else if (v == TOK_CCHAR || v == TOK_LCHAR) {
971 p = buf;
972 *p++ = '\'';
973 add_char(&p, cv->i);
974 *p++ = '\'';
975 *p = '\0';
976 return buf;
977 } else if (v == TOK_STR || v == TOK_LSTR) {
978 ts = cv->ts;
979 p = buf;
980 *p++ = '\"';
981 for(i=0;i<ts->len;i++)
982 add_char(&p, ts->str[i]);
983 *p++ = '\"';
984 *p = '\0';
985 return buf;
986 } else if (v < TOK_IDENT) {
987 p = buf;
988 *p++ = v;
989 *p = '\0';
990 return buf;
991 } else if (v < tok_ident) {
992 return table_ident[v - TOK_IDENT]->str;
993 } else if (v >= SYM_FIRST_ANOM) {
994 /* special name for anonymous symbol */
995 sprintf(buf, "L.%u", v - SYM_FIRST_ANOM);
996 return buf;
997 } else {
998 /* should never happen */
999 return NULL;
1003 /* push, without hashing */
1004 Sym *sym_push2(Sym **ps, int v, int t, int c)
1006 Sym *s;
1007 s = malloc(sizeof(Sym));
1008 if (!s)
1009 error("memory full");
1010 s->v = v;
1011 s->t = t;
1012 s->c = c;
1013 s->next = NULL;
1014 /* add in stack */
1015 s->prev = *ps;
1016 *ps = s;
1017 return s;
1020 /* find a symbol and return its associated structure. 's' is the top
1021 of the symbol stack */
1022 Sym *sym_find2(Sym *s, int v)
1024 while (s) {
1025 if (s->v == v)
1026 return s;
1027 s = s->prev;
1029 return NULL;
1032 #define HASH_SYM(v) ((unsigned)(v) % SYM_HASH_SIZE)
1034 /* find a symbol and return its associated structure. 'st' is the
1035 symbol stack */
1036 Sym *sym_find1(SymStack *st, int v)
1038 Sym *s;
1040 s = st->hash[HASH_SYM(v)];
1041 while (s) {
1042 if (s->v == v)
1043 return s;
1044 s = s->hash_next;
1046 return NULL;
1049 Sym *sym_push1(SymStack *st, int v, int t, int c)
1051 Sym *s, **ps;
1052 s = sym_push2(&st->top, v, t, c);
1053 /* add in hash table */
1054 if (v) {
1055 ps = &st->hash[HASH_SYM(v)];
1056 s->hash_next = *ps;
1057 *ps = s;
1059 return s;
1062 /* find a symbol in the right symbol space */
1063 Sym *sym_find(int v)
1065 Sym *s;
1066 s = sym_find1(&local_stack, v);
1067 if (!s)
1068 s = sym_find1(&global_stack, v);
1069 return s;
1072 /* push a given symbol on the symbol stack */
1073 Sym *sym_push(int v, int t, int r, int c)
1075 Sym *s;
1076 if (local_stack.top)
1077 s = sym_push1(&local_stack, v, t, c);
1078 else
1079 s = sym_push1(&global_stack, v, t, c);
1080 s->r = r;
1081 return s;
1084 /* pop symbols until top reaches 'b' */
1085 void sym_pop(SymStack *st, Sym *b)
1087 Sym *s, *ss;
1089 s = st->top;
1090 while(s != b) {
1091 ss = s->prev;
1092 /* free hash table entry, except if symbol was freed (only
1093 used for #undef symbols) */
1094 if (s->v)
1095 st->hash[HASH_SYM(s->v)] = s->hash_next;
1096 free(s);
1097 s = ss;
1099 st->top = b;
1102 /* undefined a hashed symbol (used for #undef). Its name is set to
1103 zero */
1104 void sym_undef(SymStack *st, Sym *s)
1106 Sym **ss;
1107 ss = &st->hash[HASH_SYM(s->v)];
1108 while (*ss != NULL) {
1109 if (*ss == s)
1110 break;
1111 ss = &(*ss)->hash_next;
1113 *ss = s->hash_next;
1114 s->v = 0;
1117 /* I/O layer */
1119 BufferedFile *tcc_open(const char *filename)
1121 int fd;
1122 BufferedFile *bf;
1124 fd = open(filename, O_RDONLY);
1125 if (fd < 0)
1126 return NULL;
1127 bf = malloc(sizeof(BufferedFile));
1128 if (!bf) {
1129 close(fd);
1130 return NULL;
1132 bf->fd = fd;
1133 bf->buf_ptr = bf->buffer;
1134 bf->buf_end = bf->buffer;
1135 bf->buffer[0] = CH_EOB; /* put eob symbol */
1136 pstrcpy(bf->filename, sizeof(bf->filename), filename);
1137 bf->line_num = 1;
1138 // printf("opening '%s'\n", filename);
1139 return bf;
1142 void tcc_close(BufferedFile *bf)
1144 total_lines += bf->line_num;
1145 close(bf->fd);
1146 free(bf);
1149 /* read one char. MUST call tcc_fillbuf if CH_EOB is read */
1150 #define TCC_GETC(bf) (*(bf)->buf_ptr++)
1152 /* fill input buffer and return next char */
1153 int tcc_getc_slow(BufferedFile *bf)
1155 int len;
1156 /* only tries to read if really end of buffer */
1157 if (bf->buf_ptr >= bf->buf_end) {
1158 if (bf->fd != -1) {
1159 len = read(bf->fd, bf->buffer, IO_BUF_SIZE);
1160 if (len < 0)
1161 len = 0;
1162 } else {
1163 len = 0;
1165 total_bytes += len;
1166 bf->buf_ptr = bf->buffer;
1167 bf->buf_end = bf->buffer + len;
1168 *bf->buf_end = CH_EOB;
1170 if (bf->buf_ptr < bf->buf_end) {
1171 return *bf->buf_ptr++;
1172 } else {
1173 bf->buf_ptr = bf->buf_end;
1174 return CH_EOF;
1178 /* no need to put that inline */
1179 void handle_eob(void)
1181 for(;;) {
1182 ch1 = tcc_getc_slow(file);
1183 if (ch1 != CH_EOF)
1184 return;
1186 if (include_stack_ptr == include_stack)
1187 return;
1188 /* add end of include file debug info */
1189 if (do_debug) {
1190 put_stabd(N_EINCL, 0, 0);
1192 /* pop include stack */
1193 tcc_close(file);
1194 include_stack_ptr--;
1195 file = *include_stack_ptr;
1199 /* read next char from current input file */
1200 static inline void inp(void)
1202 ch1 = TCC_GETC(file);
1203 /* end of buffer/file handling */
1204 if (ch1 == CH_EOB)
1205 handle_eob();
1206 if (ch1 == '\n')
1207 file->line_num++;
1208 // printf("ch1=%c 0x%x\n", ch1, ch1);
1211 /* input with '\\n' handling */
1212 static inline void minp(void)
1214 redo:
1215 ch = ch1;
1216 inp();
1217 if (ch == '\\' && ch1 == '\n') {
1218 inp();
1219 goto redo;
1221 //printf("ch=%c 0x%x\n", ch, ch);
1225 /* same as minp, but also skip comments */
1226 void cinp(void)
1228 int c;
1230 if (ch1 == '/') {
1231 inp();
1232 if (ch1 == '/') {
1233 /* single line C++ comments */
1234 inp();
1235 while (ch1 != '\n' && ch1 != -1)
1236 inp();
1237 inp();
1238 ch = ' '; /* return space */
1239 } else if (ch1 == '*') {
1240 /* C comments */
1241 inp();
1242 while (ch1 != -1) {
1243 c = ch1;
1244 inp();
1245 if (c == '*' && ch1 == '/') {
1246 inp();
1247 ch = ' '; /* return space */
1248 break;
1251 } else {
1252 ch = '/';
1254 } else {
1255 minp();
1259 void skip_spaces(void)
1261 while (ch == ' ' || ch == '\t')
1262 cinp();
1265 /* skip block of text until #else, #elif or #endif. skip also pairs of
1266 #if/#endif */
1267 void preprocess_skip(void)
1269 int a;
1270 a = 0;
1271 while (1) {
1272 while (ch != '\n') {
1273 if (ch == -1)
1274 expect("#endif");
1275 cinp();
1277 cinp();
1278 skip_spaces();
1279 if (ch == '#') {
1280 cinp();
1281 next_nomacro();
1282 if (a == 0 &&
1283 (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
1284 break;
1285 if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
1286 a++;
1287 else if (tok == TOK_ENDIF)
1288 a--;
1293 /* ParseState handling */
1295 /* XXX: currently, no include file info is stored. Thus, we cannot display
1296 accurate messages if the function or data definition spans multiple
1297 files */
1299 /* save current parse state in 's' */
1300 void save_parse_state(ParseState *s)
1302 s->line_num = file->line_num;
1303 s->macro_ptr = macro_ptr;
1304 s->tok = tok;
1305 s->tokc = tokc;
1308 /* restore parse state from 's' */
1309 void restore_parse_state(ParseState *s)
1311 file->line_num = s->line_num;
1312 macro_ptr = s->macro_ptr;
1313 tok = s->tok;
1314 tokc = s->tokc;
1317 /* return the number of additionnal 'ints' necessary to store the
1318 token */
1319 static inline int tok_ext_size(int t)
1321 switch(t) {
1322 /* 4 bytes */
1323 case TOK_CINT:
1324 case TOK_CUINT:
1325 case TOK_CCHAR:
1326 case TOK_LCHAR:
1327 case TOK_STR:
1328 case TOK_LSTR:
1329 case TOK_CFLOAT:
1330 case TOK_LINENUM:
1331 return 1;
1332 case TOK_CDOUBLE:
1333 case TOK_CLLONG:
1334 case TOK_CULLONG:
1335 return 2;
1336 case TOK_CLDOUBLE:
1337 return LDOUBLE_SIZE / 4;
1338 default:
1339 return 0;
1343 /* token string handling */
1345 static inline void tok_str_new(TokenString *s)
1347 s->str = NULL;
1348 s->len = 0;
1349 s->last_line_num = -1;
1352 static void tok_str_add(TokenString *s, int t)
1354 int len, *str;
1356 len = s->len;
1357 str = s->str;
1358 if ((len & 63) == 0) {
1359 str = realloc(str, (len + 64) * sizeof(int));
1360 if (!str)
1361 return;
1362 s->str = str;
1364 str[len++] = t;
1365 s->len = len;
1368 static void tok_str_add2(TokenString *s, int t, CValue *cv)
1370 int n, i;
1371 tok_str_add(s, t);
1372 n = tok_ext_size(t);
1373 for(i=0;i<n;i++)
1374 tok_str_add(s, cv->tab[i]);
1377 /* add the current parse token in token string 's' */
1378 static void tok_str_add_tok(TokenString *s)
1380 CValue cval;
1382 /* save line number info */
1383 if (file->line_num != s->last_line_num) {
1384 s->last_line_num = file->line_num;
1385 cval.i = s->last_line_num;
1386 tok_str_add2(s, TOK_LINENUM, &cval);
1388 tok_str_add2(s, tok, &tokc);
1391 /* get a token from an integer array and increment pointer accordingly */
1392 static int tok_get(int **tok_str, CValue *cv)
1394 int *p, t, n, i;
1396 p = *tok_str;
1397 t = *p++;
1398 n = tok_ext_size(t);
1399 for(i=0;i<n;i++)
1400 cv->tab[i] = *p++;
1401 *tok_str = p;
1402 return t;
1405 /* eval an expression for #if/#elif */
1406 int expr_preprocess(void)
1408 int c, t;
1409 TokenString str;
1411 tok_str_new(&str);
1412 while (1) {
1413 skip_spaces();
1414 if (ch == '\n')
1415 break;
1416 next(); /* do macro subst */
1417 if (tok == TOK_DEFINED) {
1418 next_nomacro();
1419 t = tok;
1420 if (t == '(')
1421 next_nomacro();
1422 c = sym_find1(&define_stack, tok) != 0;
1423 if (t == '(')
1424 next_nomacro();
1425 tok = TOK_CINT;
1426 tokc.i = c;
1427 } else if (tok >= TOK_IDENT) {
1428 /* if undefined macro */
1429 tok = TOK_CINT;
1430 tokc.i = 0;
1432 tok_str_add_tok(&str);
1434 tok_str_add(&str, -1); /* simulate end of file */
1435 tok_str_add(&str, 0);
1436 /* now evaluate C constant expression */
1437 macro_ptr = str.str;
1438 next();
1439 c = expr_const();
1440 macro_ptr = NULL;
1441 free(str.str);
1442 return c != 0;
1445 #if defined(DEBUG) || defined(PP_DEBUG)
1446 void tok_print(int *str)
1448 int t;
1449 CValue cval;
1451 while (1) {
1452 t = tok_get(&str, &cval);
1453 if (!t)
1454 break;
1455 printf(" %s", get_tok_str(t, &cval));
1457 printf("\n");
1459 #endif
1461 /* parse after #define */
1462 void parse_define(void)
1464 Sym *s, *first, **ps;
1465 int v, t, varg, is_vaargs;
1466 TokenString str;
1468 v = tok;
1469 /* XXX: should check if same macro (ANSI) */
1470 first = NULL;
1471 t = MACRO_OBJ;
1472 /* '(' must be just after macro definition for MACRO_FUNC */
1473 if (ch == '(') {
1474 next_nomacro();
1475 next_nomacro();
1476 ps = &first;
1477 while (tok != ')') {
1478 varg = tok;
1479 next_nomacro();
1480 is_vaargs = 0;
1481 if (varg == TOK_DOTS) {
1482 varg = TOK___VA_ARGS__;
1483 is_vaargs = 1;
1484 } else if (tok == TOK_DOTS && gnu_ext) {
1485 is_vaargs = 1;
1486 next_nomacro();
1488 if (varg < TOK_IDENT)
1489 error("badly punctuated parameter list");
1490 s = sym_push1(&define_stack, varg | SYM_FIELD, is_vaargs, 0);
1491 *ps = s;
1492 ps = &s->next;
1493 if (tok != ',')
1494 break;
1495 next_nomacro();
1497 t = MACRO_FUNC;
1499 tok_str_new(&str);
1500 while (1) {
1501 skip_spaces();
1502 if (ch == '\n' || ch == -1)
1503 break;
1504 next_nomacro();
1505 tok_str_add2(&str, tok, &tokc);
1507 tok_str_add(&str, 0);
1508 #ifdef PP_DEBUG
1509 printf("define %s %d: ", get_tok_str(v, NULL), t);
1510 tok_print(str);
1511 #endif
1512 s = sym_push1(&define_stack, v, t, (int)str.str);
1513 s->next = first;
1516 void preprocess(void)
1518 int size, i, c;
1519 char buf[1024], *q, *p;
1520 char buf1[1024];
1521 BufferedFile *f;
1522 Sym *s;
1524 cinp();
1525 next_nomacro();
1526 redo:
1527 if (tok == TOK_DEFINE) {
1528 next_nomacro();
1529 parse_define();
1530 } else if (tok == TOK_UNDEF) {
1531 next_nomacro();
1532 s = sym_find1(&define_stack, tok);
1533 /* undefine symbol by putting an invalid name */
1534 if (s)
1535 sym_undef(&define_stack, s);
1536 } else if (tok == TOK_INCLUDE) {
1537 skip_spaces();
1538 if (ch == '<') {
1539 c = '>';
1540 goto read_name;
1541 } else if (ch == '\"') {
1542 c = ch;
1543 read_name:
1544 minp();
1545 q = buf;
1546 while (ch != c && ch != '\n' && ch != -1) {
1547 if ((q - buf) < sizeof(buf) - 1)
1548 *q++ = ch;
1549 minp();
1551 *q = '\0';
1552 } else {
1553 next();
1554 if (tok != TOK_STR)
1555 error("#include syntax error");
1556 pstrcpy(buf, sizeof(buf), get_tok_str(tok, &tokc));
1557 c = '\"';
1559 /* eat all spaces and comments after include */
1560 /* XXX: slightly incorrect */
1561 while (ch1 != '\n' && ch1 != -1)
1562 inp();
1564 if (include_stack_ptr >= include_stack + INCLUDE_STACK_SIZE)
1565 error("memory full");
1566 if (c == '\"') {
1567 /* first search in current dir if "header.h" */
1568 size = 0;
1569 p = strrchr(file->filename, '/');
1570 if (p)
1571 size = p + 1 - file->filename;
1572 if (size > sizeof(buf1) - 1)
1573 size = sizeof(buf1) - 1;
1574 memcpy(buf1, file->filename, size);
1575 buf1[size] = '\0';
1576 pstrcat(buf1, sizeof(buf1), buf);
1577 f = tcc_open(buf1);
1578 if (f)
1579 goto found;
1581 /* now search in standard include path */
1582 for(i=nb_include_paths - 1;i>=0;i--) {
1583 strcpy(buf1, include_paths[i]);
1584 strcat(buf1, "/");
1585 strcat(buf1, buf);
1586 f = tcc_open(buf1);
1587 if (f)
1588 goto found;
1590 error("include file '%s' not found", buf);
1591 f = NULL;
1592 found:
1593 /* push current file in stack */
1594 /* XXX: fix current line init */
1595 *include_stack_ptr++ = file;
1596 file = f;
1597 /* add include file debug info */
1598 if (do_debug) {
1599 put_stabs(file->filename, N_BINCL, 0, 0, 0);
1601 } else if (tok == TOK_IFNDEF) {
1602 c = 1;
1603 goto do_ifdef;
1604 } else if (tok == TOK_IF) {
1605 c = expr_preprocess();
1606 goto do_if;
1607 } else if (tok == TOK_IFDEF) {
1608 c = 0;
1609 do_ifdef:
1610 next_nomacro();
1611 c = (sym_find1(&define_stack, tok) != 0) ^ c;
1612 do_if:
1613 if (ifdef_stack_ptr >= ifdef_stack + IFDEF_STACK_SIZE)
1614 error("memory full");
1615 *ifdef_stack_ptr++ = c;
1616 goto test_skip;
1617 } else if (tok == TOK_ELSE) {
1618 if (ifdef_stack_ptr == ifdef_stack)
1619 error("#else without matching #if");
1620 if (ifdef_stack_ptr[-1] & 2)
1621 error("#else after #else");
1622 c = (ifdef_stack_ptr[-1] ^= 3);
1623 goto test_skip;
1624 } else if (tok == TOK_ELIF) {
1625 if (ifdef_stack_ptr == ifdef_stack)
1626 error("#elif without matching #if");
1627 c = ifdef_stack_ptr[-1];
1628 if (c > 1)
1629 error("#elif after #else");
1630 /* last #if/#elif expression was true: we skip */
1631 if (c == 1)
1632 goto skip;
1633 c = expr_preprocess();
1634 ifdef_stack_ptr[-1] = c;
1635 test_skip:
1636 if (!(c & 1)) {
1637 skip:
1638 preprocess_skip();
1639 goto redo;
1641 } else if (tok == TOK_ENDIF) {
1642 if (ifdef_stack_ptr == ifdef_stack)
1643 error("#endif without matching #if");
1644 ifdef_stack_ptr--;
1645 } else if (tok == TOK_LINE) {
1646 next();
1647 if (tok != TOK_CINT)
1648 error("#line");
1649 file->line_num = tokc.i;
1650 skip_spaces();
1651 if (ch != '\n') {
1652 next();
1653 if (tok != TOK_STR)
1654 error("#line");
1655 pstrcpy(file->filename, sizeof(file->filename),
1656 get_tok_str(tok, &tokc));
1658 } else if (tok == TOK_ERROR) {
1659 error("#error");
1661 /* ignore other preprocess commands or #! for C scripts */
1662 while (ch != '\n' && ch != -1)
1663 cinp();
1666 /* read a number in base b */
1667 int getn(b)
1669 int n, t;
1670 n = 0;
1671 while (1) {
1672 if (ch >= 'a' && ch <= 'f')
1673 t = ch - 'a' + 10;
1674 else if (ch >= 'A' && ch <= 'F')
1675 t = ch - 'A' + 10;
1676 else if (isnum(ch))
1677 t = ch - '0';
1678 else
1679 break;
1680 if (t < 0 || t >= b)
1681 break;
1682 n = n * b + t;
1683 cinp();
1685 return n;
1688 /* read a character for string or char constant and eval escape codes */
1689 int getq()
1691 int c;
1693 c = ch;
1694 minp();
1695 if (c == '\\') {
1696 if (isnum(ch)) {
1697 /* at most three octal digits */
1698 c = ch - '0';
1699 minp();
1700 if (isnum(ch)) {
1701 c = c * 8 + ch - '0';
1702 minp();
1703 if (isnum(ch)) {
1704 c = c * 8 + ch - '0';
1705 minp();
1708 return c;
1709 } else if (ch == 'x') {
1710 minp();
1711 return getn(16);
1712 } else {
1713 if (ch == 'a')
1714 c = '\a';
1715 else if (ch == 'b')
1716 c = '\b';
1717 else if (ch == 'f')
1718 c = '\f';
1719 else if (ch == 'n')
1720 c = '\n';
1721 else if (ch == 'r')
1722 c = '\r';
1723 else if (ch == 't')
1724 c = '\t';
1725 else if (ch == 'v')
1726 c = '\v';
1727 else if (ch == 'e' && gnu_ext)
1728 c = 27;
1729 else if (ch == '\'' || ch == '\"' || ch == '\\' || ch == '?')
1730 c = ch;
1731 else
1732 error("invalid escaped char");
1733 minp();
1736 return c;
1739 /* we use 64 bit numbers */
1740 #define BN_SIZE 2
1742 /* bn = (bn << shift) | or_val */
1743 void bn_lshift(unsigned int *bn, int shift, int or_val)
1745 int i;
1746 unsigned int v;
1747 for(i=0;i<BN_SIZE;i++) {
1748 v = bn[i];
1749 bn[i] = (v << shift) | or_val;
1750 or_val = v >> (32 - shift);
1754 void bn_zero(unsigned int *bn)
1756 int i;
1757 for(i=0;i<BN_SIZE;i++) {
1758 bn[i] = 0;
1762 void parse_number(void)
1764 int b, t, shift, frac_bits, s, exp_val;
1765 char *q;
1766 unsigned int bn[BN_SIZE];
1767 double d;
1769 /* number */
1770 q = token_buf;
1771 t = ch;
1772 cinp();
1773 *q++ = t;
1774 b = 10;
1775 if (t == '.') {
1776 /* special dot handling */
1777 if (ch >= '0' && ch <= '9') {
1778 goto float_frac_parse;
1779 } else if (ch == '.') {
1780 cinp();
1781 if (ch != '.')
1782 expect("'.'");
1783 cinp();
1784 tok = TOK_DOTS;
1785 } else {
1786 /* dots */
1787 tok = t;
1789 return;
1790 } else if (t == '0') {
1791 if (ch == 'x' || ch == 'X') {
1792 q--;
1793 cinp();
1794 b = 16;
1795 } else if (tcc_ext && (ch == 'b' || ch == 'B')) {
1796 q--;
1797 cinp();
1798 b = 2;
1801 /* parse all digits. cannot check octal numbers at this stage
1802 because of floating point constants */
1803 while (1) {
1804 if (ch >= 'a' && ch <= 'f')
1805 t = ch - 'a' + 10;
1806 else if (ch >= 'A' && ch <= 'F')
1807 t = ch - 'A' + 10;
1808 else if (isnum(ch))
1809 t = ch - '0';
1810 else
1811 break;
1812 if (t >= b)
1813 break;
1814 if (q >= token_buf + STRING_MAX_SIZE) {
1815 num_too_long:
1816 error("number too long");
1818 *q++ = ch;
1819 cinp();
1821 if (ch == '.' ||
1822 ((ch == 'e' || ch == 'E') && b == 10) ||
1823 ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
1824 if (b != 10) {
1825 /* NOTE: strtox should support that for hexa numbers, but
1826 non ISOC99 libcs do not support it, so we prefer to do
1827 it by hand */
1828 /* hexadecimal or binary floats */
1829 /* XXX: handle overflows */
1830 *q = '\0';
1831 if (b == 16)
1832 shift = 4;
1833 else
1834 shift = 2;
1835 bn_zero(bn);
1836 q = token_buf;
1837 while (1) {
1838 t = *q++;
1839 if (t == '\0') {
1840 break;
1841 } else if (t >= 'a') {
1842 t = t - 'a' + 10;
1843 } else if (t >= 'A') {
1844 t = t - 'A' + 10;
1845 } else {
1846 t = t - '0';
1848 bn_lshift(bn, shift, t);
1850 frac_bits = 0;
1851 if (ch == '.') {
1852 cinp();
1853 while (1) {
1854 t = ch;
1855 if (t >= 'a' && t <= 'f') {
1856 t = t - 'a' + 10;
1857 } else if (t >= 'A' && t <= 'F') {
1858 t = t - 'A' + 10;
1859 } else if (t >= '0' && t <= '9') {
1860 t = t - '0';
1861 } else {
1862 break;
1864 if (t >= b)
1865 error("invalid digit");
1866 bn_lshift(bn, shift, t);
1867 frac_bits += shift;
1868 cinp();
1871 if (ch != 'p' && ch != 'P')
1872 error("exponent expected");
1873 cinp();
1874 s = 1;
1875 exp_val = 0;
1876 if (ch == '+') {
1877 cinp();
1878 } else if (ch == '-') {
1879 s = -1;
1880 cinp();
1882 if (ch < '0' || ch > '9')
1883 error("exponent digits expected");
1884 while (ch >= '0' && ch <= '9') {
1885 exp_val = exp_val * 10 + ch - '0';
1886 cinp();
1888 exp_val = exp_val * s;
1890 /* now we can generate the number */
1891 /* XXX: should patch directly float number */
1892 d = (double)bn[1] * 4294967296.0 + (double)bn[0];
1893 d = ldexp(d, exp_val - frac_bits);
1894 t = toup(ch);
1895 if (t == 'F') {
1896 cinp();
1897 tok = TOK_CFLOAT;
1898 /* float : should handle overflow */
1899 tokc.f = (float)d;
1900 } else if (t == 'L') {
1901 cinp();
1902 tok = TOK_CLDOUBLE;
1903 /* XXX: not large enough */
1904 tokc.ld = (long double)d;
1905 } else {
1906 tok = TOK_CDOUBLE;
1907 tokc.d = d;
1909 } else {
1910 /* decimal floats */
1911 if (ch == '.') {
1912 if (q >= token_buf + STRING_MAX_SIZE)
1913 goto num_too_long;
1914 *q++ = ch;
1915 cinp();
1916 float_frac_parse:
1917 while (ch >= '0' && ch <= '9') {
1918 if (q >= token_buf + STRING_MAX_SIZE)
1919 goto num_too_long;
1920 *q++ = ch;
1921 cinp();
1924 if (ch == 'e' || ch == 'E') {
1925 if (q >= token_buf + STRING_MAX_SIZE)
1926 goto num_too_long;
1927 *q++ = ch;
1928 cinp();
1929 if (ch == '-' || ch == '+') {
1930 if (q >= token_buf + STRING_MAX_SIZE)
1931 goto num_too_long;
1932 *q++ = ch;
1933 cinp();
1935 if (ch < '0' || ch > '9')
1936 error("exponent digits expected");
1937 while (ch >= '0' && ch <= '9') {
1938 if (q >= token_buf + STRING_MAX_SIZE)
1939 goto num_too_long;
1940 *q++ = ch;
1941 cinp();
1944 *q = '\0';
1945 t = toup(ch);
1946 errno = 0;
1947 if (t == 'F') {
1948 cinp();
1949 tok = TOK_CFLOAT;
1950 tokc.f = strtof(token_buf, NULL);
1951 } else if (t == 'L') {
1952 cinp();
1953 tok = TOK_CLDOUBLE;
1954 tokc.ld = strtold(token_buf, NULL);
1955 } else {
1956 tok = TOK_CDOUBLE;
1957 tokc.d = strtod(token_buf, NULL);
1960 } else {
1961 unsigned long long n, n1;
1962 int lcount;
1964 /* integer number */
1965 *q = '\0';
1966 q = token_buf;
1967 if (b == 10 && *q == '0') {
1968 b = 8;
1969 q++;
1971 n = 0;
1972 while(1) {
1973 t = *q++;
1974 /* no need for checks except for base 10 / 8 errors */
1975 if (t == '\0') {
1976 break;
1977 } else if (t >= 'a') {
1978 t = t - 'a' + 10;
1979 } else if (t >= 'A') {
1980 t = t - 'A' + 10;
1981 } else {
1982 t = t - '0';
1983 if (t >= b)
1984 error("invalid digit");
1986 n1 = n;
1987 n = n * b + t;
1988 /* detect overflow */
1989 if (n < n1)
1990 error("integer constant overflow");
1993 /* XXX: not exactly ANSI compliant */
1994 if ((n & 0xffffffff00000000LL) != 0) {
1995 if ((n >> 63) != 0)
1996 tok = TOK_CULLONG;
1997 else
1998 tok = TOK_CLLONG;
1999 } else if (n > 0x7fffffff) {
2000 tok = TOK_CUINT;
2001 } else {
2002 tok = TOK_CINT;
2004 lcount = 0;
2005 for(;;) {
2006 t = toup(ch);
2007 if (t == 'L') {
2008 if (lcount >= 2)
2009 error("three 'l' in integer constant");
2010 lcount++;
2011 if (lcount == 2) {
2012 if (tok == TOK_CINT)
2013 tok = TOK_CLLONG;
2014 else if (tok == TOK_CUINT)
2015 tok = TOK_CULLONG;
2017 cinp();
2018 } else if (t == 'U') {
2019 if (tok == TOK_CINT)
2020 tok = TOK_CUINT;
2021 else if (tok == TOK_CLLONG)
2022 tok = TOK_CULLONG;
2023 cinp();
2024 } else {
2025 break;
2028 if (tok == TOK_CINT || tok == TOK_CUINT)
2029 tokc.ui = n;
2030 else
2031 tokc.ull = n;
2036 /* return next token without macro substitution */
2037 void next_nomacro1(void)
2039 int b;
2040 char *q;
2041 TokenSym *ts;
2043 /* skip spaces */
2044 while(1) {
2045 while (ch == '\n') {
2046 cinp();
2047 while (ch == ' ' || ch == '\t')
2048 cinp();
2049 if (ch == '#') {
2050 /* preprocessor command if # at start of line after
2051 spaces */
2052 preprocess();
2055 if (ch != ' ' && ch != '\t' && ch != '\f')
2056 break;
2057 cinp();
2059 if (isid(ch)) {
2060 q = token_buf;
2061 *q++ = ch;
2062 cinp();
2063 if (q[-1] == 'L') {
2064 if (ch == '\'') {
2065 tok = TOK_LCHAR;
2066 goto char_const;
2068 if (ch == '\"') {
2069 tok = TOK_LSTR;
2070 goto str_const;
2073 while (isid(ch) || isnum(ch)) {
2074 if (q >= token_buf + STRING_MAX_SIZE)
2075 error("ident too long");
2076 *q++ = ch;
2077 cinp();
2079 *q = '\0';
2080 ts = tok_alloc(token_buf, q - token_buf);
2081 tok = ts->tok;
2082 } else if (isnum(ch) || ch == '.') {
2083 parse_number();
2084 } else if (ch == '\'') {
2085 tok = TOK_CCHAR;
2086 char_const:
2087 minp();
2088 tokc.i = getq();
2089 if (ch != '\'')
2090 expect("\'");
2091 minp();
2092 } else if (ch == '\"') {
2093 tok = TOK_STR;
2094 str_const:
2095 minp();
2096 q = token_buf;
2097 while (ch != '\"') {
2098 b = getq();
2099 if (ch == -1)
2100 error("unterminated string");
2101 if (q >= token_buf + STRING_MAX_SIZE)
2102 error("string too long");
2103 *q++ = b;
2105 *q = '\0';
2106 tokc.ts = tok_alloc(token_buf, q - token_buf);
2107 minp();
2108 } else {
2109 q = "<=\236>=\235!=\225&&\240||\241++\244--\242==\224<<\1>>\2+=\253-=\255*=\252/=\257%=\245&=\246^=\336|=\374->\313..\250##\266";
2110 /* two chars */
2111 tok = ch;
2112 cinp();
2113 while (*q) {
2114 if (*q == tok && q[1] == ch) {
2115 cinp();
2116 tok = q[2] & 0xff;
2117 /* three chars tests */
2118 if (tok == TOK_SHL || tok == TOK_SAR) {
2119 if (ch == '=') {
2120 tok = tok | 0x80;
2121 cinp();
2123 } else if (tok == TOK_DOTS) {
2124 if (ch != '.')
2125 error("parse error");
2126 cinp();
2128 return;
2130 q = q + 3;
2132 /* single char substitutions */
2133 if (tok == '<')
2134 tok = TOK_LT;
2135 else if (tok == '>')
2136 tok = TOK_GT;
2140 /* return next token without macro substitution. Can read input from
2141 macro_ptr buffer */
2142 void next_nomacro()
2144 if (macro_ptr) {
2145 redo:
2146 tok = *macro_ptr;
2147 if (tok) {
2148 tok = tok_get(&macro_ptr, &tokc);
2149 if (tok == TOK_LINENUM) {
2150 file->line_num = tokc.i;
2151 goto redo;
2154 } else {
2155 next_nomacro1();
2159 /* substitute args in macro_str and return allocated string */
2160 int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
2162 int *st, last_tok, t, notfirst;
2163 Sym *s;
2164 TokenSym *ts;
2165 CValue cval;
2166 TokenString str;
2168 tok_str_new(&str);
2169 last_tok = 0;
2170 while(1) {
2171 t = tok_get(&macro_str, &cval);
2172 if (!t)
2173 break;
2174 if (t == '#') {
2175 /* stringize */
2176 t = tok_get(&macro_str, &cval);
2177 if (!t)
2178 break;
2179 s = sym_find2(args, t);
2180 if (s) {
2181 token_buf[0] = '\0';
2182 st = (int *)s->c;
2183 notfirst = 0;
2184 while (*st) {
2185 if (notfirst)
2186 pstrcat(token_buf, sizeof(token_buf), " ");
2187 t = tok_get(&st, &cval);
2188 pstrcat(token_buf, sizeof(token_buf), get_tok_str(t, &cval));
2189 notfirst = 1;
2191 #ifdef PP_DEBUG
2192 printf("stringize: %s\n", token_buf);
2193 #endif
2194 /* add string */
2195 ts = tok_alloc(token_buf, 0);
2196 cval.ts = ts;
2197 tok_str_add2(&str, TOK_STR, &cval);
2198 } else {
2199 tok_str_add2(&str, t, &cval);
2201 } else if (t >= TOK_IDENT) {
2202 s = sym_find2(args, t);
2203 if (s) {
2204 st = (int *)s->c;
2205 /* if '##' is present before or after, no arg substitution */
2206 if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) {
2207 /* special case for var arg macros : ## eats the
2208 ',' if empty VA_ARGS riable. */
2209 /* XXX: test of the ',' is not 100%
2210 reliable. should fix it to avoid security
2211 problems */
2212 if (gnu_ext && s->t && *st == 0 &&
2213 last_tok == TOK_TWOSHARPS &&
2214 str.len >= 2&& str.str[str.len - 2] == ',') {
2215 /* suppress ',' '##' */
2216 str.len -= 2;
2217 } else {
2218 while (*st)
2219 tok_str_add(&str, *st++);
2221 } else {
2222 macro_subst(&str, nested_list, st);
2224 } else {
2225 tok_str_add(&str, t);
2227 } else {
2228 tok_str_add2(&str, t, &cval);
2230 last_tok = t;
2232 tok_str_add(&str, 0);
2233 return str.str;
2236 /* handle the '##' operator */
2237 int *macro_twosharps(int *macro_str)
2239 TokenSym *ts;
2240 int *macro_ptr1;
2241 int t;
2242 char *p;
2243 CValue cval;
2244 TokenString macro_str1;
2246 tok_str_new(&macro_str1);
2247 tok = 0;
2248 while (1) {
2249 next_nomacro();
2250 if (tok == 0)
2251 break;
2252 while (*macro_ptr == TOK_TWOSHARPS) {
2253 macro_ptr++;
2254 macro_ptr1 = macro_ptr;
2255 t = *macro_ptr;
2256 if (t) {
2257 t = tok_get(&macro_ptr, &cval);
2258 /* XXX: we handle only most common cases:
2259 ident + ident or ident + number */
2260 if (tok >= TOK_IDENT &&
2261 (t >= TOK_IDENT || t == TOK_CINT)) {
2262 p = get_tok_str(tok, &tokc);
2263 pstrcpy(token_buf, sizeof(token_buf), p);
2264 p = get_tok_str(t, &cval);
2265 pstrcat(token_buf, sizeof(token_buf), p);
2266 ts = tok_alloc(token_buf, 0);
2267 tok = ts->tok; /* modify current token */
2268 } else {
2269 /* cannot merge tokens: skip '##' */
2270 macro_ptr = macro_ptr1;
2271 break;
2275 tok_str_add2(&macro_str1, tok, &tokc);
2277 tok_str_add(&macro_str1, 0);
2278 return macro_str1.str;
2281 /* do macro substitution of macro_str and add result to
2282 (tok_str,tok_len). If macro_str is NULL, then input stream token is
2283 substituted. 'nested_list' is the list of all macros we got inside
2284 to avoid recursing. */
2285 void macro_subst(TokenString *tok_str,
2286 Sym **nested_list, int *macro_str)
2288 Sym *s, *args, *sa, *sa1;
2289 int parlevel, *mstr, t, *saved_macro_ptr;
2290 int mstr_allocated, *macro_str1;
2291 CValue cval;
2292 TokenString str;
2294 saved_macro_ptr = macro_ptr;
2295 macro_ptr = macro_str;
2296 macro_str1 = NULL;
2297 if (macro_str) {
2298 /* first scan for '##' operator handling */
2299 macro_str1 = macro_twosharps(macro_str);
2300 macro_ptr = macro_str1;
2303 while (1) {
2304 next_nomacro();
2305 if (tok == 0)
2306 break;
2307 /* special macros */
2308 if (tok == TOK___LINE__) {
2309 cval.i = file->line_num;
2310 tok_str_add2(tok_str, TOK_CINT, &cval);
2311 } else if (tok == TOK___FILE__) {
2312 cval.ts = tok_alloc(file->filename, 0);
2313 tok_str_add2(tok_str, TOK_STR, &cval);
2314 } else if (tok == TOK___DATE__) {
2315 cval.ts = tok_alloc("Jan 1 1970", 0);
2316 tok_str_add2(tok_str, TOK_STR, &cval);
2317 } else if (tok == TOK___TIME__) {
2318 cval.ts = tok_alloc("00:00:00", 0);
2319 tok_str_add2(tok_str, TOK_STR, &cval);
2320 } else if ((s = sym_find1(&define_stack, tok)) != NULL) {
2321 /* if symbol is a macro, prepare substitution */
2322 /* if nested substitution, do nothing */
2323 if (sym_find2(*nested_list, tok))
2324 goto no_subst;
2325 mstr = (int *)s->c;
2326 mstr_allocated = 0;
2327 if (s->t == MACRO_FUNC) {
2328 /* NOTE: we do not use next_nomacro to avoid eating the
2329 next token. XXX: find better solution */
2330 if (macro_ptr) {
2331 t = *macro_ptr;
2332 } else {
2333 while (ch == ' ' || ch == '\t' || ch == '\n')
2334 cinp();
2335 t = ch;
2337 if (t != '(') /* no macro subst */
2338 goto no_subst;
2340 /* argument macro */
2341 next_nomacro();
2342 next_nomacro();
2343 args = NULL;
2344 sa = s->next;
2345 /* NOTE: empty args are allowed, except if no args */
2346 for(;;) {
2347 /* handle '()' case */
2348 if (!args && tok == ')')
2349 break;
2350 if (!sa)
2351 error("macro '%s' used with too many args",
2352 get_tok_str(s->v, 0));
2353 tok_str_new(&str);
2354 parlevel = 0;
2355 /* NOTE: non zero sa->t indicates VA_ARGS */
2356 while ((parlevel > 0 ||
2357 (tok != ')' &&
2358 (tok != ',' || sa->t))) &&
2359 tok != -1) {
2360 if (tok == '(')
2361 parlevel++;
2362 else if (tok == ')')
2363 parlevel--;
2364 tok_str_add2(&str, tok, &tokc);
2365 next_nomacro();
2367 tok_str_add(&str, 0);
2368 sym_push2(&args, sa->v & ~SYM_FIELD, sa->t, (int)str.str);
2369 sa = sa->next;
2370 if (tok == ')') {
2371 /* special case for gcc var args: add an empty
2372 var arg argument if it is omitted */
2373 if (sa && sa->t && gnu_ext)
2374 continue;
2375 else
2376 break;
2378 if (tok != ',')
2379 expect(",");
2380 next_nomacro();
2382 if (sa) {
2383 error("macro '%s' used with too few args",
2384 get_tok_str(s->v, 0));
2387 /* now subst each arg */
2388 mstr = macro_arg_subst(nested_list, mstr, args);
2389 /* free memory */
2390 sa = args;
2391 while (sa) {
2392 sa1 = sa->prev;
2393 free((int *)sa->c);
2394 free(sa);
2395 sa = sa1;
2397 mstr_allocated = 1;
2399 sym_push2(nested_list, s->v, 0, 0);
2400 macro_subst(tok_str, nested_list, mstr);
2401 /* pop nested defined symbol */
2402 sa1 = *nested_list;
2403 *nested_list = sa1->prev;
2404 free(sa1);
2405 if (mstr_allocated)
2406 free(mstr);
2407 } else {
2408 no_subst:
2409 /* no need to add if reading input stream */
2410 if (!macro_str)
2411 return;
2412 tok_str_add2(tok_str, tok, &tokc);
2414 /* only replace one macro while parsing input stream */
2415 if (!macro_str)
2416 return;
2418 macro_ptr = saved_macro_ptr;
2419 if (macro_str1)
2420 free(macro_str1);
2423 /* return next token with macro substitution */
2424 void next(void)
2426 Sym *nested_list;
2427 TokenString str;
2429 /* special 'ungettok' case for label parsing */
2430 if (tok1) {
2431 tok = tok1;
2432 tokc = tok1c;
2433 tok1 = 0;
2434 } else {
2435 redo:
2436 if (!macro_ptr) {
2437 /* if not reading from macro substituted string, then try
2438 to substitute */
2439 /* XXX: optimize non macro case */
2440 tok_str_new(&str);
2441 nested_list = NULL;
2442 macro_subst(&str, &nested_list, NULL);
2443 if (str.str) {
2444 tok_str_add(&str, 0);
2445 macro_ptr = str.str;
2446 macro_ptr_allocated = str.str;
2447 goto redo;
2449 if (tok == 0)
2450 goto redo;
2451 } else {
2452 next_nomacro();
2453 if (tok == 0) {
2454 /* end of macro string: free it */
2455 free(macro_ptr_allocated);
2456 macro_ptr = NULL;
2457 goto redo;
2461 #if defined(DEBUG)
2462 printf("token = %s\n", get_tok_str(tok, tokc));
2463 #endif
2466 void swap(int *p, int *q)
2468 int t;
2469 t = *p;
2470 *p = *q;
2471 *q = t;
2474 void vsetc(int t, int r, CValue *vc)
2476 if (vtop >= vstack + VSTACK_SIZE)
2477 error("memory full");
2478 /* cannot let cpu flags if other instruction are generated */
2479 /* XXX: VT_JMP test too ? */
2480 if ((vtop->r & VT_VALMASK) == VT_CMP)
2481 gv(RC_INT);
2482 vtop++;
2483 vtop->t = t;
2484 vtop->r = r;
2485 vtop->r2 = VT_CONST;
2486 vtop->c = *vc;
2489 /* push integer constant */
2490 void vpushi(int v)
2492 CValue cval;
2493 cval.i = v;
2494 vsetc(VT_INT, VT_CONST, &cval);
2497 /* Return a static symbol pointing to a section */
2498 static Sym *get_sym_ref(int t, Section *sec,
2499 unsigned long offset, unsigned long size)
2501 int v;
2502 Sym *sym;
2504 v = anon_sym++;
2505 sym = sym_push1(&global_stack, v, t | VT_STATIC, 0);
2506 sym->r = VT_CONST | VT_SYM;
2507 put_extern_sym(sym, sec, offset);
2508 return sym;
2511 /* push a reference to a section offset by adding a dummy symbol */
2512 /* XXX: add size */
2513 void vpush_ref(int t, Section *sec, unsigned long offset)
2515 CValue cval;
2517 cval.sym = get_sym_ref(t, sec, offset, 0);
2518 vsetc(t, VT_CONST | VT_SYM, &cval);
2521 /* push a reference to symbol v */
2522 void vpush_sym(int t, int v)
2524 Sym *sym;
2525 CValue cval;
2527 sym = external_sym(v, t, 0);
2528 cval.sym = sym;
2529 vsetc(t, VT_CONST | VT_SYM, &cval);
2532 void vset(int t, int r, int v)
2534 CValue cval;
2536 cval.i = v;
2537 vsetc(t, r, &cval);
2540 void vswap(void)
2542 SValue tmp;
2544 tmp = vtop[0];
2545 vtop[0] = vtop[-1];
2546 vtop[-1] = tmp;
2549 void vpushv(SValue *v)
2551 if (vtop >= vstack + VSTACK_SIZE)
2552 error("memory full");
2553 vtop++;
2554 *vtop = *v;
2557 void vdup(void)
2559 vpushv(vtop);
2562 /* save r to the memory stack, and mark it as being free */
2563 void save_reg(int r)
2565 int l, i, saved, t, size, align;
2566 SValue *p, sv;
2568 /* modify all stack values */
2569 saved = 0;
2570 l = 0;
2571 for(p=vstack;p<=vtop;p++) {
2572 i = p->r & VT_VALMASK;
2573 if ((p->r & VT_VALMASK) == r ||
2574 (p->r2 & VT_VALMASK) == r) {
2575 /* must save value on stack if not already done */
2576 if (!saved) {
2577 /* store register in the stack */
2578 t = p->t;
2579 if ((p->r & VT_LVAL) ||
2580 (!is_float(t) && (t & VT_BTYPE) != VT_LLONG))
2581 t = VT_INT;
2582 size = type_size(t, &align);
2583 loc = (loc - size) & -align;
2584 sv.t = t;
2585 sv.r = VT_LOCAL | VT_LVAL;
2586 sv.c.ul = loc;
2587 store(r, &sv);
2588 #ifdef TCC_TARGET_I386
2589 /* x86 specific: need to pop fp register ST0 if saved */
2590 if (r == REG_ST0) {
2591 o(0xd9dd); /* fstp %st(1) */
2593 #endif
2594 /* special long long case */
2595 if ((t & VT_BTYPE) == VT_LLONG) {
2596 sv.c.ul += 4;
2597 store(p->r2, &sv);
2599 l = loc;
2600 saved = 1;
2602 /* mark that stack entry as being saved on the stack */
2603 if (p->r & VT_LVAL)
2604 t = VT_LLOCAL;
2605 else
2606 t = VT_LOCAL;
2607 p->r = VT_LVAL | t;
2608 p->r2 = VT_CONST;
2609 p->c.ul = l;
2614 /* find a free register of class 'rc'. If none, save one register */
2615 int get_reg(int rc)
2617 int r;
2618 SValue *p;
2620 /* find a free register */
2621 for(r=0;r<NB_REGS;r++) {
2622 if (reg_classes[r] & rc) {
2623 for(p=vstack;p<=vtop;p++) {
2624 if ((p->r & VT_VALMASK) == r ||
2625 (p->r2 & VT_VALMASK) == r)
2626 goto notfound;
2628 return r;
2630 notfound: ;
2633 /* no register left : free the first one on the stack (VERY
2634 IMPORTANT to start from the bottom to ensure that we don't
2635 spill registers used in gen_opi()) */
2636 for(p=vstack;p<=vtop;p++) {
2637 r = p->r & VT_VALMASK;
2638 if (r < VT_CONST && (reg_classes[r] & rc)) {
2639 save_reg(r);
2640 break;
2643 return r;
2646 /* save registers up to (vtop - n) stack entry */
2647 void save_regs(int n)
2649 int r;
2650 SValue *p, *p1;
2651 p1 = vtop - n;
2652 for(p = vstack;p <= p1; p++) {
2653 r = p->r & VT_VALMASK;
2654 if (r < VT_CONST) {
2655 save_reg(r);
2660 /* move register 's' to 'r', and flush previous value of r to memory
2661 if needed */
2662 void move_reg(int r, int s)
2664 SValue sv;
2666 if (r != s) {
2667 save_reg(r);
2668 sv.t = VT_INT;
2669 sv.r = s;
2670 sv.c.ul = 0;
2671 load(r, &sv);
2675 /* get address of vtop (vtop MUST BE an lvalue) */
2676 void gaddrof(void)
2678 vtop->r &= ~VT_LVAL;
2679 /* tricky: if saved lvalue, then we can go back to lvalue */
2680 if ((vtop->r & VT_VALMASK) == VT_LLOCAL)
2681 vtop->r = (vtop->r & ~VT_VALMASK) | VT_LOCAL | VT_LVAL;
2684 #ifdef CONFIG_TCC_BCHECK
2685 /* generate lvalue bound code */
2686 void gbound(void)
2688 int lval_type;
2690 vtop->r &= ~VT_MUSTBOUND;
2691 /* if lvalue, then use checking code before dereferencing */
2692 if (vtop->r & VT_LVAL) {
2693 /* if not VT_BOUNDED value, then make one */
2694 if (!(vtop->r & VT_BOUNDED)) {
2695 lval_type = vtop->r & (VT_LVAL_TYPE | VT_LVAL);
2696 gaddrof();
2697 vpushi(0);
2698 gen_bounded_ptr_add();
2699 vtop->r |= lval_type;
2701 /* then check for dereferencing */
2702 gen_bounded_ptr_deref();
2705 #endif
2707 /* store vtop a register belonging to class 'rc'. lvalues are
2708 converted to values. Cannot be used if cannot be converted to
2709 register value (such as structures). */
2710 int gv(int rc)
2712 int r, r2, rc2, bit_pos, bit_size, size, align, i, data_offset;
2713 unsigned long long ll;
2715 /* NOTE: get_reg can modify vstack[] */
2716 if (vtop->t & VT_BITFIELD) {
2717 bit_pos = (vtop->t >> VT_STRUCT_SHIFT) & 0x3f;
2718 bit_size = (vtop->t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
2719 /* remove bit field info to avoid loops */
2720 vtop->t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
2721 /* generate shifts */
2722 vpushi(32 - (bit_pos + bit_size));
2723 gen_op(TOK_SHL);
2724 vpushi(32 - bit_size);
2725 /* NOTE: transformed to SHR if unsigned */
2726 gen_op(TOK_SAR);
2727 r = gv(rc);
2728 } else {
2729 if (is_float(vtop->t) &&
2730 (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
2731 int v;
2732 Sym *sym;
2734 /* XXX: unify with initializers handling ? */
2735 /* CPUs usually cannot use float constants, so we store them
2736 generically in data segment */
2737 size = type_size(vtop->t, &align);
2738 data_offset = data_section->data_ptr - data_section->data;
2739 data_offset = (data_offset + align - 1) & -align;
2740 /* XXX: not portable yet */
2741 size = size >> 2;
2742 for(i=0;i<size;i++)
2743 ((int *)(data_section->data + data_offset))[i] = vtop->c.tab[i];
2745 v = anon_sym++;
2746 sym = sym_push1(&global_stack, v, vtop->t | VT_STATIC, 0);
2747 sym->r = VT_CONST | VT_SYM;
2748 put_extern_sym(sym, data_section, data_offset);
2750 vtop->r |= VT_LVAL | VT_SYM;
2751 vtop->c.sym = sym;
2752 data_offset += size << 2;
2753 data_section->data_ptr = data_section->data + data_offset;
2755 #ifdef CONFIG_TCC_BCHECK
2756 if (vtop->r & VT_MUSTBOUND)
2757 gbound();
2758 #endif
2760 r = vtop->r & VT_VALMASK;
2761 /* need to reload if:
2762 - constant
2763 - lvalue (need to dereference pointer)
2764 - already a register, but not in the right class */
2765 if (r >= VT_CONST ||
2766 (vtop->r & VT_LVAL) ||
2767 !(reg_classes[r] & rc) ||
2768 ((vtop->t & VT_BTYPE) == VT_LLONG &&
2769 !(reg_classes[vtop->r2] & rc))) {
2770 r = get_reg(rc);
2771 if ((vtop->t & VT_BTYPE) == VT_LLONG) {
2772 /* two register type load : expand to two words
2773 temporarily */
2774 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
2775 /* load constant */
2776 ll = vtop->c.ull;
2777 vtop->c.ui = ll; /* first word */
2778 load(r, vtop);
2779 vtop->r = r; /* save register value */
2780 vpushi(ll >> 32); /* second word */
2781 } else if (r >= VT_CONST ||
2782 (vtop->r & VT_LVAL)) {
2783 /* load from memory */
2784 load(r, vtop);
2785 vdup();
2786 vtop[-1].r = r; /* save register value */
2787 /* increment pointer to get second word */
2788 vtop->t = VT_INT;
2789 gaddrof();
2790 vpushi(4);
2791 gen_op('+');
2792 vtop->r |= VT_LVAL;
2793 } else {
2794 /* move registers */
2795 load(r, vtop);
2796 vdup();
2797 vtop[-1].r = r; /* save register value */
2798 vtop->r = vtop[-1].r2;
2800 /* allocate second register */
2801 rc2 = RC_INT;
2802 if (rc == RC_IRET)
2803 rc2 = RC_LRET;
2804 r2 = get_reg(rc2);
2805 load(r2, vtop);
2806 vpop();
2807 /* write second register */
2808 vtop->r2 = r2;
2809 } else if ((vtop->r & VT_LVAL) && !is_float(vtop->t)) {
2810 int t1, t;
2811 /* lvalue of scalar type : need to use lvalue type
2812 because of possible cast */
2813 t = vtop->t;
2814 t1 = t;
2815 /* compute memory access type */
2816 if (vtop->r & VT_LVAL_BYTE)
2817 t = VT_BYTE;
2818 else if (vtop->r & VT_LVAL_SHORT)
2819 t = VT_SHORT;
2820 if (vtop->r & VT_LVAL_UNSIGNED)
2821 t |= VT_UNSIGNED;
2822 vtop->t = t;
2823 load(r, vtop);
2824 /* restore wanted type */
2825 vtop->t = t1;
2826 } else {
2827 /* one register type load */
2828 load(r, vtop);
2831 vtop->r = r;
2833 return r;
2836 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
2837 void gv2(int rc1, int rc2)
2839 /* generate more generic register first */
2840 if (rc1 <= rc2) {
2841 vswap();
2842 gv(rc1);
2843 vswap();
2844 gv(rc2);
2845 /* test if reload is needed for first register */
2846 if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
2847 vswap();
2848 gv(rc1);
2849 vswap();
2851 } else {
2852 gv(rc2);
2853 vswap();
2854 gv(rc1);
2855 vswap();
2856 /* test if reload is needed for first register */
2857 if ((vtop[0].r & VT_VALMASK) >= VT_CONST) {
2858 gv(rc2);
2863 /* expand long long on stack in two int registers */
2864 void lexpand(void)
2866 int u;
2868 u = vtop->t & VT_UNSIGNED;
2869 gv(RC_INT);
2870 vdup();
2871 vtop[0].r = vtop[-1].r2;
2872 vtop[0].r2 = VT_CONST;
2873 vtop[-1].r2 = VT_CONST;
2874 vtop[0].t = VT_INT | u;
2875 vtop[-1].t = VT_INT | u;
2878 /* build a long long from two ints */
2879 void lbuild(int t)
2881 gv2(RC_INT, RC_INT);
2882 vtop[-1].r2 = vtop[0].r;
2883 vtop[-1].t = t;
2884 vpop();
2887 /* rotate n first stack elements to the bottom */
2888 void vrotb(int n)
2890 int i;
2891 SValue tmp;
2893 tmp = vtop[-n + 1];
2894 for(i=-n+1;i!=0;i++)
2895 vtop[i] = vtop[i+1];
2896 vtop[0] = tmp;
2899 /* pop stack value */
2900 void vpop(void)
2902 int v;
2903 v = vtop->r & VT_VALMASK;
2904 #ifdef TCC_TARGET_I386
2905 /* for x86, we need to pop the FP stack */
2906 if (v == REG_ST0) {
2907 o(0xd9dd); /* fstp %st(1) */
2908 } else
2909 #endif
2910 if (v == VT_JMP || v == VT_JMPI) {
2911 /* need to put correct jump if && or || without test */
2912 gsym(vtop->c.ul);
2914 vtop--;
2917 /* convert stack entry to register and duplicate its value in another
2918 register */
2919 void gv_dup(void)
2921 int rc, t, r, r1;
2922 SValue sv;
2924 t = vtop->t;
2925 if ((t & VT_BTYPE) == VT_LLONG) {
2926 lexpand();
2927 gv_dup();
2928 vswap();
2929 vrotb(3);
2930 gv_dup();
2931 vrotb(4);
2932 /* stack: H L L1 H1 */
2933 lbuild(t);
2934 vrotb(3);
2935 vrotb(3);
2936 vswap();
2937 lbuild(t);
2938 vswap();
2939 } else {
2940 /* duplicate value */
2941 rc = RC_INT;
2942 sv.t = VT_INT;
2943 if (is_float(t)) {
2944 rc = RC_FLOAT;
2945 sv.t = t;
2947 r = gv(rc);
2948 r1 = get_reg(rc);
2949 sv.r = r;
2950 sv.c.ul = 0;
2951 load(r1, &sv); /* move r to r1 */
2952 vdup();
2953 /* duplicates value */
2954 vtop->r = r1;
2958 /* generate CPU independent (unsigned) long long operations */
2959 void gen_opl(int op)
2961 int t, a, b, op1, c, i;
2962 int func;
2963 GFuncContext gf;
2964 SValue tmp;
2966 switch(op) {
2967 case '/':
2968 case TOK_PDIV:
2969 func = TOK___divdi3;
2970 goto gen_func;
2971 case TOK_UDIV:
2972 func = TOK___udivdi3;
2973 goto gen_func;
2974 case '%':
2975 func = TOK___moddi3;
2976 goto gen_func;
2977 case TOK_UMOD:
2978 func = TOK___umoddi3;
2979 gen_func:
2980 /* call generic long long function */
2981 gfunc_start(&gf, FUNC_CDECL);
2982 gfunc_param(&gf);
2983 gfunc_param(&gf);
2984 vpush_sym(func_old_type, func);
2985 gfunc_call(&gf);
2986 vpushi(0);
2987 vtop->r = REG_IRET;
2988 vtop->r2 = REG_LRET;
2989 break;
2990 case '^':
2991 case '&':
2992 case '|':
2993 case '*':
2994 case '+':
2995 case '-':
2996 t = vtop->t;
2997 vswap();
2998 lexpand();
2999 vrotb(3);
3000 lexpand();
3001 /* stack: L1 H1 L2 H2 */
3002 tmp = vtop[0];
3003 vtop[0] = vtop[-3];
3004 vtop[-3] = tmp;
3005 tmp = vtop[-2];
3006 vtop[-2] = vtop[-3];
3007 vtop[-3] = tmp;
3008 vswap();
3009 /* stack: H1 H2 L1 L2 */
3010 if (op == '*') {
3011 vpushv(vtop - 1);
3012 vpushv(vtop - 1);
3013 gen_op(TOK_UMULL);
3014 lexpand();
3015 /* stack: H1 H2 L1 L2 ML MH */
3016 for(i=0;i<4;i++)
3017 vrotb(6);
3018 /* stack: ML MH H1 H2 L1 L2 */
3019 tmp = vtop[0];
3020 vtop[0] = vtop[-2];
3021 vtop[-2] = tmp;
3022 /* stack: ML MH H1 L2 H2 L1 */
3023 gen_op('*');
3024 vrotb(3);
3025 vrotb(3);
3026 gen_op('*');
3027 /* stack: ML MH M1 M2 */
3028 gen_op('+');
3029 gen_op('+');
3030 } else if (op == '+' || op == '-') {
3031 /* XXX: add non carry method too (for MIPS or alpha) */
3032 if (op == '+')
3033 op1 = TOK_ADDC1;
3034 else
3035 op1 = TOK_SUBC1;
3036 gen_op(op1);
3037 /* stack: H1 H2 (L1 op L2) */
3038 vrotb(3);
3039 vrotb(3);
3040 gen_op(op1 + 1); /* TOK_xxxC2 */
3041 } else {
3042 gen_op(op);
3043 /* stack: H1 H2 (L1 op L2) */
3044 vrotb(3);
3045 vrotb(3);
3046 /* stack: (L1 op L2) H1 H2 */
3047 gen_op(op);
3048 /* stack: (L1 op L2) (H1 op H2) */
3050 /* stack: L H */
3051 lbuild(t);
3052 break;
3053 case TOK_SAR:
3054 case TOK_SHR:
3055 case TOK_SHL:
3056 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
3057 t = vtop[-1].t;
3058 vswap();
3059 lexpand();
3060 vrotb(3);
3061 /* stack: L H shift */
3062 c = (int)vtop->c.i;
3063 /* constant: simpler */
3064 /* NOTE: all comments are for SHL. the other cases are
3065 done by swaping words */
3066 vpop();
3067 if (op != TOK_SHL)
3068 vswap();
3069 if (c >= 32) {
3070 /* stack: L H */
3071 vpop();
3072 if (c > 32) {
3073 vpushi(c - 32);
3074 gen_op(op);
3076 if (op != TOK_SAR) {
3077 vpushi(0);
3078 } else {
3079 gv_dup();
3080 vpushi(31);
3081 gen_op(TOK_SAR);
3083 vswap();
3084 } else {
3085 vswap();
3086 gv_dup();
3087 /* stack: H L L */
3088 vpushi(c);
3089 gen_op(op);
3090 vswap();
3091 vpushi(32 - c);
3092 if (op == TOK_SHL)
3093 gen_op(TOK_SHR);
3094 else
3095 gen_op(TOK_SHL);
3096 vrotb(3);
3097 /* stack: L L H */
3098 vpushi(c);
3099 gen_op(op);
3100 gen_op('|');
3102 if (op != TOK_SHL)
3103 vswap();
3104 lbuild(t);
3105 } else {
3106 /* XXX: should provide a faster fallback on x86 ? */
3107 switch(op) {
3108 case TOK_SAR:
3109 func = TOK___sardi3;
3110 goto gen_func;
3111 case TOK_SHR:
3112 func = TOK___shrdi3;
3113 goto gen_func;
3114 case TOK_SHL:
3115 func = TOK___shldi3;
3116 goto gen_func;
3119 break;
3120 default:
3121 /* compare operations */
3122 t = vtop->t;
3123 vswap();
3124 lexpand();
3125 vrotb(3);
3126 lexpand();
3127 /* stack: L1 H1 L2 H2 */
3128 tmp = vtop[-1];
3129 vtop[-1] = vtop[-2];
3130 vtop[-2] = tmp;
3131 /* stack: L1 L2 H1 H2 */
3132 /* compare high */
3133 op1 = op;
3134 /* when values are equal, we need to compare low words. since
3135 the jump is inverted, we invert the test too. */
3136 if (op1 == TOK_LT)
3137 op1 = TOK_LE;
3138 else if (op1 == TOK_GT)
3139 op1 = TOK_GE;
3140 else if (op1 == TOK_ULT)
3141 op1 = TOK_ULE;
3142 else if (op1 == TOK_UGT)
3143 op1 = TOK_UGE;
3144 a = 0;
3145 b = 0;
3146 gen_op(op1);
3147 if (op1 != TOK_NE) {
3148 a = gtst(1, 0);
3150 if (op != TOK_EQ) {
3151 /* generate non equal test */
3152 /* XXX: NOT PORTABLE yet */
3153 if (a == 0) {
3154 b = gtst(0, 0);
3155 } else {
3156 #ifdef TCC_TARGET_I386
3157 b = psym(0x850f, 0);
3158 #else
3159 error("not implemented");
3160 #endif
3163 /* compare low */
3164 gen_op(op);
3165 a = gtst(1, a);
3166 gsym(b);
3167 vset(VT_INT, VT_JMPI, a);
3168 break;
3172 /* handle integer constant optimizations and various machine
3173 independant opt */
3174 void gen_opic(int op)
3176 int fc, c1, c2, n;
3177 SValue *v1, *v2;
3179 v1 = vtop - 1;
3180 v2 = vtop;
3181 /* currently, we cannot do computations with forward symbols */
3182 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
3183 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
3184 if (c1 && c2) {
3185 fc = v2->c.i;
3186 switch(op) {
3187 case '+': v1->c.i += fc; break;
3188 case '-': v1->c.i -= fc; break;
3189 case '&': v1->c.i &= fc; break;
3190 case '^': v1->c.i ^= fc; break;
3191 case '|': v1->c.i |= fc; break;
3192 case '*': v1->c.i *= fc; break;
3194 case TOK_PDIV:
3195 case '/':
3196 case '%':
3197 case TOK_UDIV:
3198 case TOK_UMOD:
3199 /* if division by zero, generate explicit division */
3200 if (fc == 0) {
3201 if (const_wanted)
3202 error("division by zero in constant");
3203 goto general_case;
3205 switch(op) {
3206 default: v1->c.i /= fc; break;
3207 case '%': v1->c.i %= fc; break;
3208 case TOK_UDIV: v1->c.i = (unsigned)v1->c.i / fc; break;
3209 case TOK_UMOD: v1->c.i = (unsigned)v1->c.i % fc; break;
3211 break;
3212 case TOK_SHL: v1->c.i <<= fc; break;
3213 case TOK_SHR: v1->c.i = (unsigned)v1->c.i >> fc; break;
3214 case TOK_SAR: v1->c.i >>= fc; break;
3215 /* tests */
3216 case TOK_ULT: v1->c.i = (unsigned)v1->c.i < (unsigned)fc; break;
3217 case TOK_UGE: v1->c.i = (unsigned)v1->c.i >= (unsigned)fc; break;
3218 case TOK_EQ: v1->c.i = v1->c.i == fc; break;
3219 case TOK_NE: v1->c.i = v1->c.i != fc; break;
3220 case TOK_ULE: v1->c.i = (unsigned)v1->c.i <= (unsigned)fc; break;
3221 case TOK_UGT: v1->c.i = (unsigned)v1->c.i > (unsigned)fc; break;
3222 case TOK_LT: v1->c.i = v1->c.i < fc; break;
3223 case TOK_GE: v1->c.i = v1->c.i >= fc; break;
3224 case TOK_LE: v1->c.i = v1->c.i <= fc; break;
3225 case TOK_GT: v1->c.i = v1->c.i > fc; break;
3226 /* logical */
3227 case TOK_LAND: v1->c.i = v1->c.i && fc; break;
3228 case TOK_LOR: v1->c.i = v1->c.i || fc; break;
3229 default:
3230 goto general_case;
3232 vtop--;
3233 } else {
3234 /* if commutative ops, put c2 as constant */
3235 if (c1 && (op == '+' || op == '&' || op == '^' ||
3236 op == '|' || op == '*')) {
3237 vswap();
3238 swap(&c1, &c2);
3240 fc = vtop->c.i;
3241 if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
3242 op == TOK_PDIV) &&
3243 fc == 1) ||
3244 ((op == '+' || op == '-' || op == '|' || op == '^' ||
3245 op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
3246 fc == 0) ||
3247 (op == '&' &&
3248 fc == -1))) {
3249 /* nothing to do */
3250 vtop--;
3251 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
3252 /* try to use shifts instead of muls or divs */
3253 if (fc > 0 && (fc & (fc - 1)) == 0) {
3254 n = -1;
3255 while (fc) {
3256 fc >>= 1;
3257 n++;
3259 vtop->c.i = n;
3260 if (op == '*')
3261 op = TOK_SHL;
3262 else if (op == TOK_PDIV)
3263 op = TOK_SAR;
3264 else
3265 op = TOK_SHR;
3267 goto general_case;
3268 } else {
3269 general_case:
3270 /* call low level op generator */
3271 gen_opi(op);
3276 /* generate a floating point operation with constant propagation */
3277 void gen_opif(int op)
3279 int c1, c2;
3280 SValue *v1, *v2;
3281 long double f1, f2;
3283 v1 = vtop - 1;
3284 v2 = vtop;
3285 /* currently, we cannot do computations with forward symbols */
3286 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
3287 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
3288 if (c1 && c2) {
3289 if (v1->t == VT_FLOAT) {
3290 f1 = v1->c.f;
3291 f2 = v2->c.f;
3292 } else if (v1->t == VT_DOUBLE) {
3293 f1 = v1->c.d;
3294 f2 = v2->c.d;
3295 } else {
3296 f1 = v1->c.ld;
3297 f2 = v2->c.ld;
3300 /* NOTE: we only do constant propagation if finite number (not
3301 NaN or infinity) (ANSI spec) */
3302 if (!ieee_finite(f1) || !ieee_finite(f2))
3303 goto general_case;
3305 switch(op) {
3306 case '+': f1 += f2; break;
3307 case '-': f1 -= f2; break;
3308 case '*': f1 *= f2; break;
3309 case '/':
3310 if (f2 == 0.0) {
3311 if (const_wanted)
3312 error("division by zero in constant");
3313 goto general_case;
3315 f1 /= f2;
3316 break;
3317 /* XXX: also handles tests ? */
3318 default:
3319 goto general_case;
3321 /* XXX: overflow test ? */
3322 if (v1->t == VT_FLOAT) {
3323 v1->c.f = f1;
3324 } else if (v1->t == VT_DOUBLE) {
3325 v1->c.d = f1;
3326 } else {
3327 v1->c.ld = f1;
3329 vtop--;
3330 } else {
3331 general_case:
3332 gen_opf(op);
3337 int pointed_size(int t)
3339 return type_size(pointed_type(t), &t);
3342 #if 0
3343 void check_pointer_types(SValue *p1, SValue *p2)
3345 char buf1[256], buf2[256];
3346 int t1, t2;
3347 t1 = p1->t;
3348 t2 = p2->t;
3349 if (!is_compatible_types(t1, t2)) {
3350 type_to_str(buf1, sizeof(buf1), t1, NULL);
3351 type_to_str(buf2, sizeof(buf2), t2, NULL);
3352 error("incompatible pointers '%s' and '%s'", buf1, buf2);
3355 #endif
3357 /* generic gen_op: handles types problems */
3358 void gen_op(int op)
3360 int u, t1, t2, bt1, bt2, t;
3362 t1 = vtop[-1].t;
3363 t2 = vtop[0].t;
3364 bt1 = t1 & VT_BTYPE;
3365 bt2 = t2 & VT_BTYPE;
3367 if (bt1 == VT_PTR || bt2 == VT_PTR) {
3368 /* at least one operand is a pointer */
3369 /* relationnal op: must be both pointers */
3370 if (op >= TOK_ULT && op <= TOK_GT) {
3371 // check_pointer_types(vtop, vtop - 1);
3372 /* pointers are handled are unsigned */
3373 t = VT_INT | VT_UNSIGNED;
3374 goto std_op;
3376 /* if both pointers, then it must be the '-' op */
3377 if ((t1 & VT_BTYPE) == VT_PTR &&
3378 (t2 & VT_BTYPE) == VT_PTR) {
3379 if (op != '-')
3380 error("cannot use pointers here");
3381 // check_pointer_types(vtop - 1, vtop);
3382 /* XXX: check that types are compatible */
3383 u = pointed_size(t1);
3384 gen_opic(op);
3385 /* set to integer type */
3386 vtop->t = VT_INT;
3387 vpushi(u);
3388 gen_op(TOK_PDIV);
3389 } else {
3390 /* exactly one pointer : must be '+' or '-'. */
3391 if (op != '-' && op != '+')
3392 error("cannot use pointers here");
3393 /* Put pointer as first operand */
3394 if ((t2 & VT_BTYPE) == VT_PTR) {
3395 vswap();
3396 swap(&t1, &t2);
3398 /* XXX: cast to int ? (long long case) */
3399 vpushi(pointed_size(vtop[-1].t));
3400 gen_op('*');
3401 #ifdef CONFIG_TCC_BCHECK
3402 /* if evaluating constant expression, no code should be
3403 generated, so no bound check */
3404 if (do_bounds_check && !const_wanted) {
3405 /* if bounded pointers, we generate a special code to
3406 test bounds */
3407 if (op == '-') {
3408 vpushi(0);
3409 vswap();
3410 gen_op('-');
3412 gen_bounded_ptr_add();
3413 } else
3414 #endif
3416 gen_opic(op);
3418 /* put again type if gen_opic() swaped operands */
3419 vtop->t = t1;
3421 } else if (is_float(bt1) || is_float(bt2)) {
3422 /* compute bigger type and do implicit casts */
3423 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
3424 t = VT_LDOUBLE;
3425 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
3426 t = VT_DOUBLE;
3427 } else {
3428 t = VT_FLOAT;
3430 /* floats can only be used for a few operations */
3431 if (op != '+' && op != '-' && op != '*' && op != '/' &&
3432 (op < TOK_ULT || op > TOK_GT))
3433 error("invalid operands for binary operation");
3434 goto std_op;
3435 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
3436 /* cast to biggest op */
3437 t = VT_LLONG;
3438 /* convert to unsigned if it does not fit in a long long */
3439 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
3440 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
3441 t |= VT_UNSIGNED;
3442 goto std_op;
3443 } else {
3444 /* integer operations */
3445 t = VT_INT;
3446 /* convert to unsigned if it does not fit in an integer */
3447 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
3448 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
3449 t |= VT_UNSIGNED;
3450 std_op:
3451 /* XXX: currently, some unsigned operations are explicit, so
3452 we modify them here */
3453 if (t & VT_UNSIGNED) {
3454 if (op == TOK_SAR)
3455 op = TOK_SHR;
3456 else if (op == '/')
3457 op = TOK_UDIV;
3458 else if (op == '%')
3459 op = TOK_UMOD;
3460 else if (op == TOK_LT)
3461 op = TOK_ULT;
3462 else if (op == TOK_GT)
3463 op = TOK_UGT;
3464 else if (op == TOK_LE)
3465 op = TOK_ULE;
3466 else if (op == TOK_GE)
3467 op = TOK_UGE;
3469 vswap();
3470 gen_cast(t);
3471 vswap();
3472 /* special case for shifts and long long: we keep the shift as
3473 an integer */
3474 if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL)
3475 gen_cast(VT_INT);
3476 else
3477 gen_cast(t);
3478 if (is_float(t))
3479 gen_opif(op);
3480 else if ((t & VT_BTYPE) == VT_LLONG)
3481 gen_opl(op);
3482 else
3483 gen_opic(op);
3484 if (op >= TOK_ULT && op <= TOK_GT) {
3485 /* relationnal op: the result is an int */
3486 vtop->t = VT_INT;
3487 } else {
3488 vtop->t = t;
3493 /* generic itof for unsigned long long case */
3494 void gen_cvt_itof1(int t)
3496 GFuncContext gf;
3498 if ((vtop->t & (VT_BTYPE | VT_UNSIGNED)) ==
3499 (VT_LLONG | VT_UNSIGNED)) {
3501 gfunc_start(&gf, FUNC_CDECL);
3502 gfunc_param(&gf);
3503 if (t == VT_FLOAT)
3504 vpush_sym(func_old_type, TOK___ulltof);
3505 else if (t == VT_DOUBLE)
3506 vpush_sym(func_old_type, TOK___ulltod);
3507 else
3508 vpush_sym(func_old_type, TOK___ulltold);
3509 gfunc_call(&gf);
3510 vpushi(0);
3511 vtop->r = REG_FRET;
3512 } else {
3513 gen_cvt_itof(t);
3517 /* generic ftoi for unsigned long long case */
3518 void gen_cvt_ftoi1(int t)
3520 GFuncContext gf;
3521 int st;
3523 if (t == (VT_LLONG | VT_UNSIGNED)) {
3524 /* not handled natively */
3525 gfunc_start(&gf, FUNC_CDECL);
3526 st = vtop->t & VT_BTYPE;
3527 gfunc_param(&gf);
3528 if (st == VT_FLOAT)
3529 vpush_sym(func_old_type, TOK___fixunssfdi);
3530 else if (st == VT_DOUBLE)
3531 vpush_sym(func_old_type, TOK___fixunsdfdi);
3532 else
3533 vpush_sym(func_old_type, TOK___fixunsxfdi);
3534 gfunc_call(&gf);
3535 vpushi(0);
3536 vtop->r = REG_IRET;
3537 vtop->r2 = REG_LRET;
3538 } else {
3539 gen_cvt_ftoi(t);
3543 /* force char or short cast */
3544 void force_charshort_cast(int t)
3546 int bits, dbt;
3547 dbt = t & VT_BTYPE;
3548 /* XXX: add optimization if lvalue : just change type and offset */
3549 if (dbt == VT_BYTE)
3550 bits = 8;
3551 else
3552 bits = 16;
3553 if (t & VT_UNSIGNED) {
3554 vpushi((1 << bits) - 1);
3555 gen_op('&');
3556 } else {
3557 bits = 32 - bits;
3558 vpushi(bits);
3559 gen_op(TOK_SHL);
3560 vpushi(bits);
3561 gen_op(TOK_SAR);
3565 /* cast 'vtop' to 't' type */
3566 void gen_cast(int t)
3568 int sbt, dbt, sf, df, c;
3570 /* special delayed cast for char/short */
3571 /* XXX: in some cases (multiple cascaded casts), it may still
3572 be incorrect */
3573 if (vtop->r & VT_MUSTCAST) {
3574 vtop->r &= ~VT_MUSTCAST;
3575 force_charshort_cast(vtop->t);
3578 dbt = t & (VT_BTYPE | VT_UNSIGNED);
3579 sbt = vtop->t & (VT_BTYPE | VT_UNSIGNED);
3581 if (sbt != dbt) {
3582 sf = is_float(sbt);
3583 df = is_float(dbt);
3584 c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
3585 if (sf && df) {
3586 /* convert from fp to fp */
3587 if (c) {
3588 /* constant case: we can do it now */
3589 /* XXX: in ISOC, cannot do it if error in convert */
3590 if (dbt == VT_FLOAT && sbt == VT_DOUBLE)
3591 vtop->c.f = (float)vtop->c.d;
3592 else if (dbt == VT_FLOAT && sbt == VT_LDOUBLE)
3593 vtop->c.f = (float)vtop->c.ld;
3594 else if (dbt == VT_DOUBLE && sbt == VT_FLOAT)
3595 vtop->c.d = (double)vtop->c.f;
3596 else if (dbt == VT_DOUBLE && sbt == VT_LDOUBLE)
3597 vtop->c.d = (double)vtop->c.ld;
3598 else if (dbt == VT_LDOUBLE && sbt == VT_FLOAT)
3599 vtop->c.ld = (long double)vtop->c.f;
3600 else if (dbt == VT_LDOUBLE && sbt == VT_DOUBLE)
3601 vtop->c.ld = (long double)vtop->c.d;
3602 } else {
3603 /* non constant case: generate code */
3604 gen_cvt_ftof(dbt);
3606 } else if (df) {
3607 /* convert int to fp */
3608 if (c) {
3609 switch(sbt) {
3610 case VT_LLONG | VT_UNSIGNED:
3611 case VT_LLONG:
3612 /* XXX: add const cases for long long */
3613 goto do_itof;
3614 case VT_INT | VT_UNSIGNED:
3615 switch(dbt) {
3616 case VT_FLOAT: vtop->c.f = (float)vtop->c.ui; break;
3617 case VT_DOUBLE: vtop->c.d = (double)vtop->c.ui; break;
3618 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.ui; break;
3620 break;
3621 default:
3622 switch(dbt) {
3623 case VT_FLOAT: vtop->c.f = (float)vtop->c.i; break;
3624 case VT_DOUBLE: vtop->c.d = (double)vtop->c.i; break;
3625 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.i; break;
3627 break;
3629 } else {
3630 do_itof:
3631 gen_cvt_itof1(dbt);
3633 } else if (sf) {
3634 /* convert fp to int */
3635 /* we handle char/short/etc... with generic code */
3636 if (dbt != (VT_INT | VT_UNSIGNED) &&
3637 dbt != (VT_LLONG | VT_UNSIGNED) &&
3638 dbt != VT_LLONG)
3639 dbt = VT_INT;
3640 if (c) {
3641 switch(dbt) {
3642 case VT_LLONG | VT_UNSIGNED:
3643 case VT_LLONG:
3644 /* XXX: add const cases for long long */
3645 goto do_ftoi;
3646 case VT_INT | VT_UNSIGNED:
3647 switch(sbt) {
3648 case VT_FLOAT: vtop->c.ui = (unsigned int)vtop->c.d; break;
3649 case VT_DOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
3650 case VT_LDOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
3652 break;
3653 default:
3654 /* int case */
3655 switch(sbt) {
3656 case VT_FLOAT: vtop->c.i = (int)vtop->c.d; break;
3657 case VT_DOUBLE: vtop->c.i = (int)vtop->c.d; break;
3658 case VT_LDOUBLE: vtop->c.i = (int)vtop->c.d; break;
3660 break;
3662 } else {
3663 do_ftoi:
3664 gen_cvt_ftoi1(dbt);
3666 if (dbt == VT_INT && (t & (VT_BTYPE | VT_UNSIGNED)) != dbt) {
3667 /* additionnal cast for char/short/bool... */
3668 vtop->t = dbt;
3669 gen_cast(t);
3671 } else if ((dbt & VT_BTYPE) == VT_LLONG) {
3672 if ((sbt & VT_BTYPE) != VT_LLONG) {
3673 /* scalar to long long */
3674 if (c) {
3675 if (sbt == (VT_INT | VT_UNSIGNED))
3676 vtop->c.ll = vtop->c.ui;
3677 else
3678 vtop->c.ll = vtop->c.i;
3679 } else {
3680 /* machine independant conversion */
3681 gv(RC_INT);
3682 /* generate high word */
3683 if (sbt == (VT_INT | VT_UNSIGNED)) {
3684 vpushi(0);
3685 gv(RC_INT);
3686 } else {
3687 gv_dup();
3688 vpushi(31);
3689 gen_op(TOK_SAR);
3691 /* patch second register */
3692 vtop[-1].r2 = vtop->r;
3693 vpop();
3696 } else if (dbt == VT_BOOL) {
3697 /* scalar to bool */
3698 vpushi(0);
3699 gen_op(TOK_NE);
3700 } else if ((dbt & VT_BTYPE) == VT_BYTE ||
3701 (dbt & VT_BTYPE) == VT_SHORT) {
3702 force_charshort_cast(t);
3703 } else if ((dbt & VT_BTYPE) == VT_INT) {
3704 /* scalar to int */
3705 if (sbt == VT_LLONG) {
3706 /* from long long: just take low order word */
3707 lexpand();
3708 vpop();
3710 /* if lvalue and single word type, nothing to do because
3711 the lvalue already contains the real type size (see
3712 VT_LVAL_xxx constants) */
3715 vtop->t = t;
3718 /* return type size. Put alignment at 'a' */
3719 int type_size(int t, int *a)
3721 Sym *s;
3722 int bt;
3724 bt = t & VT_BTYPE;
3725 if (bt == VT_STRUCT) {
3726 /* struct/union */
3727 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
3728 *a = 4; /* XXX: cannot store it yet. Doing that is safe */
3729 return s->c;
3730 } else if (bt == VT_PTR) {
3731 if (t & VT_ARRAY) {
3732 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
3733 return type_size(s->t, a) * s->c;
3734 } else {
3735 *a = PTR_SIZE;
3736 return PTR_SIZE;
3738 } else if (bt == VT_LDOUBLE) {
3739 *a = LDOUBLE_ALIGN;
3740 return LDOUBLE_SIZE;
3741 } else if (bt == VT_DOUBLE || bt == VT_LLONG) {
3742 *a = 8;
3743 return 8;
3744 } else if (bt == VT_INT || bt == VT_ENUM || bt == VT_FLOAT) {
3745 *a = 4;
3746 return 4;
3747 } else if (bt == VT_SHORT) {
3748 *a = 2;
3749 return 2;
3750 } else {
3751 /* char, void, function, _Bool */
3752 *a = 1;
3753 return 1;
3757 /* return the pointed type of t */
3758 int pointed_type(int t)
3760 Sym *s;
3761 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
3762 return s->t | (t & ~VT_TYPE);
3765 int mk_pointer(int t)
3767 int p;
3768 p = anon_sym++;
3769 sym_push(p, t, 0, -1);
3770 return VT_PTR | (p << VT_STRUCT_SHIFT) | (t & ~VT_TYPE);
3773 int is_compatible_types(int t1, int t2)
3775 Sym *s1, *s2;
3776 int bt1, bt2;
3778 t1 &= VT_TYPE;
3779 t2 &= VT_TYPE;
3780 bt1 = t1 & VT_BTYPE;
3781 bt2 = t2 & VT_BTYPE;
3782 if (bt1 == VT_PTR) {
3783 t1 = pointed_type(t1);
3784 /* if function, then convert implicitely to function pointer */
3785 if (bt2 != VT_FUNC) {
3786 if (bt2 != VT_PTR)
3787 return 0;
3788 t2 = pointed_type(t2);
3790 /* void matches everything */
3791 t1 &= VT_TYPE;
3792 t2 &= VT_TYPE;
3793 if (t1 == VT_VOID || t2 == VT_VOID)
3794 return 1;
3795 return is_compatible_types(t1, t2);
3796 } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
3797 return (t2 == t1);
3798 } else if (bt1 == VT_FUNC) {
3799 if (bt2 != VT_FUNC)
3800 return 0;
3801 s1 = sym_find(((unsigned)t1 >> VT_STRUCT_SHIFT));
3802 s2 = sym_find(((unsigned)t2 >> VT_STRUCT_SHIFT));
3803 if (!is_compatible_types(s1->t, s2->t))
3804 return 0;
3805 /* XXX: not complete */
3806 if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
3807 return 1;
3808 if (s1->c != s2->c)
3809 return 0;
3810 while (s1 != NULL) {
3811 if (s2 == NULL)
3812 return 0;
3813 if (!is_compatible_types(s1->t, s2->t))
3814 return 0;
3815 s1 = s1->next;
3816 s2 = s2->next;
3818 if (s2)
3819 return 0;
3820 return 1;
3821 } else {
3822 /* XXX: not complete */
3823 return 1;
3827 /* print a type. If 'varstr' is not NULL, then the variable is also
3828 printed in the type */
3829 /* XXX: union */
3830 /* XXX: add array and function pointers */
3831 void type_to_str(char *buf, int buf_size,
3832 int t, const char *varstr)
3834 int bt, v;
3835 Sym *s, *sa;
3836 char buf1[256];
3837 const char *tstr;
3839 t = t & VT_TYPE;
3840 bt = t & VT_BTYPE;
3841 buf[0] = '\0';
3842 if (t & VT_UNSIGNED)
3843 pstrcat(buf, buf_size, "unsigned ");
3844 switch(bt) {
3845 case VT_VOID:
3846 tstr = "void";
3847 goto add_tstr;
3848 case VT_BOOL:
3849 tstr = "_Bool";
3850 goto add_tstr;
3851 case VT_BYTE:
3852 tstr = "char";
3853 goto add_tstr;
3854 case VT_SHORT:
3855 tstr = "short";
3856 goto add_tstr;
3857 case VT_INT:
3858 tstr = "int";
3859 goto add_tstr;
3860 case VT_LONG:
3861 tstr = "long";
3862 goto add_tstr;
3863 case VT_LLONG:
3864 tstr = "long long";
3865 goto add_tstr;
3866 case VT_FLOAT:
3867 tstr = "float";
3868 goto add_tstr;
3869 case VT_DOUBLE:
3870 tstr = "double";
3871 goto add_tstr;
3872 case VT_LDOUBLE:
3873 tstr = "long double";
3874 add_tstr:
3875 pstrcat(buf, buf_size, tstr);
3876 break;
3877 case VT_ENUM:
3878 case VT_STRUCT:
3879 if (bt == VT_STRUCT)
3880 tstr = "struct ";
3881 else
3882 tstr = "enum ";
3883 pstrcat(buf, buf_size, tstr);
3884 v = (unsigned)t >> VT_STRUCT_SHIFT;
3885 if (v >= SYM_FIRST_ANOM)
3886 pstrcat(buf, buf_size, "<anonymous>");
3887 else
3888 pstrcat(buf, buf_size, get_tok_str(v, NULL));
3889 break;
3890 case VT_FUNC:
3891 s = sym_find((unsigned)t >> VT_STRUCT_SHIFT);
3892 type_to_str(buf, buf_size, s->t, varstr);
3893 pstrcat(buf, buf_size, "(");
3894 sa = s->next;
3895 while (sa != NULL) {
3896 type_to_str(buf1, sizeof(buf1), sa->t, NULL);
3897 pstrcat(buf, buf_size, buf1);
3898 sa = sa->next;
3899 if (sa)
3900 pstrcat(buf, buf_size, ", ");
3902 pstrcat(buf, buf_size, ")");
3903 goto no_var;
3904 case VT_PTR:
3905 s = sym_find((unsigned)t >> VT_STRUCT_SHIFT);
3906 pstrcpy(buf1, sizeof(buf1), "*");
3907 if (varstr)
3908 pstrcat(buf1, sizeof(buf1), varstr);
3909 type_to_str(buf, buf_size, s->t, buf1);
3910 goto no_var;
3912 if (varstr) {
3913 pstrcat(buf, buf_size, " ");
3914 pstrcat(buf, buf_size, varstr);
3916 no_var: ;
3919 /* verify type compatibility to store vtop in 'dt' type, and generate
3920 casts if needed. */
3921 void gen_assign_cast(int dt)
3923 int st;
3924 char buf1[256], buf2[256];
3926 st = vtop->t; /* source type */
3927 if ((dt & VT_BTYPE) == VT_PTR) {
3928 /* special cases for pointers */
3929 /* a function is implicitely a function pointer */
3930 if ((st & VT_BTYPE) == VT_FUNC) {
3931 if (!is_compatible_types(pointed_type(dt), st))
3932 goto error;
3933 else
3934 goto type_ok;
3936 /* '0' can also be a pointer */
3937 if ((st & VT_BTYPE) == VT_INT &&
3938 ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) &&
3939 vtop->c.i == 0)
3940 goto type_ok;
3942 if (!is_compatible_types(dt, st)) {
3943 error:
3944 type_to_str(buf1, sizeof(buf1), st, NULL);
3945 type_to_str(buf2, sizeof(buf2), dt, NULL);
3946 error("cannot cast '%s' to '%s'", buf1, buf2);
3948 type_ok:
3949 gen_cast(dt);
3952 /* store vtop in lvalue pushed on stack */
3953 void vstore(void)
3955 int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
3956 GFuncContext gf;
3958 ft = vtop[-1].t;
3959 sbt = vtop->t & VT_BTYPE;
3960 dbt = ft & VT_BTYPE;
3961 if (((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
3962 (sbt == VT_INT && dbt == VT_SHORT)) {
3963 /* optimize char/short casts */
3964 delayed_cast = VT_MUSTCAST;
3965 vtop->t = ft & VT_TYPE;
3966 } else {
3967 delayed_cast = 0;
3968 gen_assign_cast(ft & VT_TYPE);
3971 if (sbt == VT_STRUCT) {
3972 /* if structure, only generate pointer */
3973 /* structure assignment : generate memcpy */
3974 /* XXX: optimize if small size */
3975 vdup();
3976 gfunc_start(&gf, FUNC_CDECL);
3977 /* type size */
3978 size = type_size(vtop->t, &align);
3979 vpushi(size);
3980 gfunc_param(&gf);
3981 /* source */
3982 vtop->t = VT_INT;
3983 gaddrof();
3984 gfunc_param(&gf);
3985 /* destination */
3986 vswap();
3987 vtop->t = VT_INT;
3988 gaddrof();
3989 gfunc_param(&gf);
3991 save_regs(0);
3992 vpush_sym(func_old_type, TOK_memcpy);
3993 gfunc_call(&gf);
3994 /* leave source on stack */
3995 } else if (ft & VT_BITFIELD) {
3996 /* bitfield store handling */
3997 bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
3998 bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
3999 /* remove bit field info to avoid loops */
4000 vtop[-1].t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
4002 /* duplicate destination */
4003 vdup();
4004 vtop[-1] = vtop[-2];
4006 /* mask and shift source */
4007 vpushi((1 << bit_size) - 1);
4008 gen_op('&');
4009 vpushi(bit_pos);
4010 gen_op(TOK_SHL);
4011 /* load destination, mask and or with source */
4012 vswap();
4013 vpushi(~(((1 << bit_size) - 1) << bit_pos));
4014 gen_op('&');
4015 gen_op('|');
4016 /* store result */
4017 vstore();
4018 } else {
4019 #ifdef CONFIG_TCC_BCHECK
4020 /* bound check case */
4021 if (vtop[-1].r & VT_MUSTBOUND) {
4022 vswap();
4023 gbound();
4024 vswap();
4026 #endif
4027 rc = RC_INT;
4028 if (is_float(ft))
4029 rc = RC_FLOAT;
4030 r = gv(rc); /* generate value */
4031 /* if lvalue was saved on stack, must read it */
4032 if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
4033 SValue sv;
4034 t = get_reg(RC_INT);
4035 sv.t = VT_INT;
4036 sv.r = VT_LOCAL | VT_LVAL;
4037 sv.c.ul = vtop[-1].c.ul;
4038 load(t, &sv);
4039 vtop[-1].r = t | VT_LVAL;
4041 store(r, vtop - 1);
4042 /* two word case handling : store second register at word + 4 */
4043 if ((ft & VT_BTYPE) == VT_LLONG) {
4044 vswap();
4045 /* convert to int to increment easily */
4046 vtop->t = VT_INT;
4047 gaddrof();
4048 vpushi(4);
4049 gen_op('+');
4050 vtop->r |= VT_LVAL;
4051 vswap();
4052 /* XXX: it works because r2 is spilled last ! */
4053 store(vtop->r2, vtop - 1);
4055 vswap();
4056 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
4057 vtop->r |= delayed_cast;
4061 /* post defines POST/PRE add. c is the token ++ or -- */
4062 void inc(int post, int c)
4064 test_lvalue();
4065 vdup(); /* save lvalue */
4066 if (post) {
4067 gv_dup(); /* duplicate value */
4068 vrotb(3);
4069 vrotb(3);
4071 /* add constant */
4072 vpushi(c - TOK_MID);
4073 gen_op('+');
4074 vstore(); /* store value */
4075 if (post)
4076 vpop(); /* if post op, return saved value */
4079 /* Parse GNUC __attribute__ extension. Currently, the following
4080 extensions are recognized:
4081 - aligned(n) : set data/function alignment.
4082 - section(x) : generate data/code in this section.
4083 - unused : currently ignored, but may be used someday.
4085 void parse_attribute(AttributeDef *ad)
4087 int t, n;
4089 next();
4090 skip('(');
4091 skip('(');
4092 while (tok != ')') {
4093 if (tok < TOK_IDENT)
4094 expect("attribute name");
4095 t = tok;
4096 next();
4097 switch(t) {
4098 case TOK_SECTION:
4099 case TOK___SECTION__:
4100 skip('(');
4101 if (tok != TOK_STR)
4102 expect("section name");
4103 ad->section = find_section(tokc.ts->str);
4104 next();
4105 skip(')');
4106 break;
4107 case TOK_ALIGNED:
4108 case TOK___ALIGNED__:
4109 skip('(');
4110 n = expr_const();
4111 if (n <= 0 || (n & (n - 1)) != 0)
4112 error("alignment must be a positive power of two");
4113 ad->aligned = n;
4114 skip(')');
4115 break;
4116 case TOK_UNUSED:
4117 case TOK___UNUSED__:
4118 /* currently, no need to handle it because tcc does not
4119 track unused objects */
4120 break;
4121 case TOK_NORETURN:
4122 case TOK___NORETURN__:
4123 /* currently, no need to handle it because tcc does not
4124 track unused objects */
4125 break;
4126 case TOK_CDECL:
4127 case TOK___CDECL:
4128 case TOK___CDECL__:
4129 ad->func_call = FUNC_CDECL;
4130 break;
4131 case TOK_STDCALL:
4132 case TOK___STDCALL:
4133 case TOK___STDCALL__:
4134 ad->func_call = FUNC_STDCALL;
4135 break;
4136 default:
4137 warning("'%s' attribute ignored", get_tok_str(t, NULL));
4138 /* skip parameters */
4139 /* XXX: skip parenthesis too */
4140 if (tok == '(') {
4141 next();
4142 while (tok != ')' && tok != -1)
4143 next();
4144 next();
4146 break;
4148 if (tok != ',')
4149 break;
4150 next();
4152 skip(')');
4153 skip(')');
4156 /* enum/struct/union declaration */
4157 int struct_decl(int u)
4159 int a, t, b, v, size, align, maxalign, c, offset;
4160 int bit_size, bit_pos, bsize, bt, lbit_pos;
4161 Sym *s, *ss, **ps;
4162 AttributeDef ad;
4164 a = tok; /* save decl type */
4165 next();
4166 if (tok != '{') {
4167 v = tok;
4168 next();
4169 /* struct already defined ? return it */
4170 /* XXX: check consistency */
4171 s = sym_find(v | SYM_STRUCT);
4172 if (s) {
4173 if (s->t != a)
4174 error("invalid type");
4175 goto do_decl;
4177 } else {
4178 v = anon_sym++;
4180 s = sym_push(v | SYM_STRUCT, a, 0, 0);
4181 /* put struct/union/enum name in type */
4182 do_decl:
4183 u = u | (v << VT_STRUCT_SHIFT);
4185 if (tok == '{') {
4186 next();
4187 if (s->c)
4188 error("struct/union/enum already defined");
4189 /* cannot be empty */
4190 c = 0;
4191 maxalign = 0;
4192 ps = &s->next;
4193 bit_pos = 0;
4194 offset = 0;
4195 while (1) {
4196 if (a == TOK_ENUM) {
4197 v = tok;
4198 next();
4199 if (tok == '=') {
4200 next();
4201 c = expr_const();
4203 /* enum symbols have static storage */
4204 sym_push(v, VT_STATIC | VT_INT, VT_CONST, c);
4205 if (tok == ',')
4206 next();
4207 c++;
4208 } else {
4209 parse_btype(&b, &ad);
4210 while (1) {
4211 bit_size = -1;
4212 v = 0;
4213 if (tok != ':') {
4214 t = type_decl(&ad, &v, b, TYPE_DIRECT);
4215 if ((t & VT_BTYPE) == VT_FUNC ||
4216 (t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN)))
4217 error("invalid type for '%s'",
4218 get_tok_str(v, NULL));
4219 } else {
4220 t = b;
4222 if (tok == ':') {
4223 next();
4224 bit_size = expr_const();
4225 /* XXX: handle v = 0 case for messages */
4226 if (bit_size < 0)
4227 error("negative width in bit-field '%s'",
4228 get_tok_str(v, NULL));
4229 if (v && bit_size == 0)
4230 error("zero width for bit-field '%s'",
4231 get_tok_str(v, NULL));
4233 size = type_size(t, &align);
4234 lbit_pos = 0;
4235 if (bit_size >= 0) {
4236 bt = t & VT_BTYPE;
4237 if (bt != VT_INT &&
4238 bt != VT_BYTE &&
4239 bt != VT_SHORT)
4240 error("bitfields must have scalar type");
4241 bsize = size * 8;
4242 if (bit_size > bsize) {
4243 error("width of '%s' exceeds its type",
4244 get_tok_str(v, NULL));
4245 } else if (bit_size == bsize) {
4246 /* no need for bit fields */
4247 bit_pos = 0;
4248 } else if (bit_size == 0) {
4249 /* XXX: what to do if only padding in a
4250 structure ? */
4251 /* zero size: means to pad */
4252 if (bit_pos > 0)
4253 bit_pos = bsize;
4254 } else {
4255 /* we do not have enough room ? */
4256 if ((bit_pos + bit_size) > bsize)
4257 bit_pos = 0;
4258 lbit_pos = bit_pos;
4259 /* XXX: handle LSB first */
4260 t |= VT_BITFIELD |
4261 (bit_pos << VT_STRUCT_SHIFT) |
4262 (bit_size << (VT_STRUCT_SHIFT + 6));
4263 bit_pos += bit_size;
4265 } else {
4266 bit_pos = 0;
4268 if (v) {
4269 /* add new memory data only if starting
4270 bit field */
4271 if (lbit_pos == 0) {
4272 if (a == TOK_STRUCT) {
4273 c = (c + align - 1) & -align;
4274 offset = c;
4275 c += size;
4276 } else {
4277 offset = 0;
4278 if (size > c)
4279 c = size;
4281 if (align > maxalign)
4282 maxalign = align;
4284 #if 0
4285 printf("add field %s offset=%d",
4286 get_tok_str(v, NULL), offset);
4287 if (t & VT_BITFIELD) {
4288 printf(" pos=%d size=%d",
4289 (t >> VT_STRUCT_SHIFT) & 0x3f,
4290 (t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
4292 printf("\n");
4293 #endif
4294 ss = sym_push(v | SYM_FIELD, t, 0, offset);
4295 *ps = ss;
4296 ps = &ss->next;
4298 if (tok == ';' || tok == -1)
4299 break;
4300 skip(',');
4302 skip(';');
4304 if (tok == '}')
4305 break;
4307 skip('}');
4308 /* size for struct/union, dummy for enum */
4309 s->c = (c + maxalign - 1) & -maxalign;
4311 return u;
4314 /* return 0 if no type declaration. otherwise, return the basic type
4315 and skip it.
4317 int parse_btype(int *type_ptr, AttributeDef *ad)
4319 int t, u, type_found;
4320 Sym *s;
4322 memset(ad, 0, sizeof(AttributeDef));
4323 type_found = 0;
4324 t = 0;
4325 while(1) {
4326 switch(tok) {
4327 /* basic types */
4328 case TOK_CHAR:
4329 u = VT_BYTE;
4330 basic_type:
4331 next();
4332 basic_type1:
4333 if ((t & VT_BTYPE) != 0)
4334 error("too many basic types");
4335 t |= u;
4336 break;
4337 case TOK_VOID:
4338 u = VT_VOID;
4339 goto basic_type;
4340 case TOK_SHORT:
4341 u = VT_SHORT;
4342 goto basic_type;
4343 case TOK_INT:
4344 next();
4345 break;
4346 case TOK_LONG:
4347 next();
4348 if ((t & VT_BTYPE) == VT_DOUBLE) {
4349 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
4350 } else if ((t & VT_BTYPE) == VT_LONG) {
4351 t = (t & ~VT_BTYPE) | VT_LLONG;
4352 } else {
4353 u = VT_LONG;
4354 goto basic_type1;
4356 break;
4357 case TOK_BOOL:
4358 u = VT_BOOL;
4359 goto basic_type;
4360 case TOK_FLOAT:
4361 u = VT_FLOAT;
4362 goto basic_type;
4363 case TOK_DOUBLE:
4364 next();
4365 if ((t & VT_BTYPE) == VT_LONG) {
4366 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
4367 } else {
4368 u = VT_DOUBLE;
4369 goto basic_type1;
4371 break;
4372 case TOK_ENUM:
4373 u = struct_decl(VT_ENUM);
4374 goto basic_type1;
4375 case TOK_STRUCT:
4376 case TOK_UNION:
4377 u = struct_decl(VT_STRUCT);
4378 goto basic_type1;
4380 /* type modifiers */
4381 case TOK_CONST:
4382 case TOK_VOLATILE:
4383 case TOK_REGISTER:
4384 case TOK_SIGNED:
4385 case TOK___SIGNED__:
4386 case TOK_AUTO:
4387 case TOK_INLINE:
4388 case TOK___INLINE__:
4389 case TOK_RESTRICT:
4390 next();
4391 break;
4392 case TOK_UNSIGNED:
4393 t |= VT_UNSIGNED;
4394 next();
4395 break;
4397 /* storage */
4398 case TOK_EXTERN:
4399 t |= VT_EXTERN;
4400 next();
4401 break;
4402 case TOK_STATIC:
4403 t |= VT_STATIC;
4404 next();
4405 break;
4406 case TOK_TYPEDEF:
4407 t |= VT_TYPEDEF;
4408 next();
4409 break;
4410 /* GNUC attribute */
4411 case TOK___ATTRIBUTE__:
4412 parse_attribute(ad);
4413 break;
4414 default:
4415 s = sym_find(tok);
4416 if (!s || !(s->t & VT_TYPEDEF))
4417 goto the_end;
4418 t |= (s->t & ~VT_TYPEDEF);
4419 next();
4420 break;
4422 type_found = 1;
4424 the_end:
4425 /* long is never used as type */
4426 if ((t & VT_BTYPE) == VT_LONG)
4427 t = (t & ~VT_BTYPE) | VT_INT;
4428 *type_ptr = t;
4429 return type_found;
4432 int post_type(int t, AttributeDef *ad)
4434 int p, n, pt, l, t1;
4435 Sym **plast, *s, *first;
4436 AttributeDef ad1;
4438 if (tok == '(') {
4439 /* function declaration */
4440 next();
4441 l = 0;
4442 first = NULL;
4443 plast = &first;
4444 while (tok != ')') {
4445 /* read param name and compute offset */
4446 if (l != FUNC_OLD) {
4447 if (!parse_btype(&pt, &ad1)) {
4448 if (l) {
4449 error("invalid type");
4450 } else {
4451 l = FUNC_OLD;
4452 goto old_proto;
4455 l = FUNC_NEW;
4456 if ((pt & VT_BTYPE) == VT_VOID && tok == ')')
4457 break;
4458 pt = type_decl(&ad1, &n, pt, TYPE_DIRECT | TYPE_ABSTRACT);
4459 if ((pt & VT_BTYPE) == VT_VOID)
4460 error("parameter declared as void");
4461 } else {
4462 old_proto:
4463 n = tok;
4464 pt = VT_INT;
4465 next();
4467 /* array must be transformed to pointer according to ANSI C */
4468 pt &= ~VT_ARRAY;
4469 s = sym_push(n | SYM_FIELD, pt, 0, 0);
4470 *plast = s;
4471 plast = &s->next;
4472 if (tok == ',') {
4473 next();
4474 if (l == FUNC_NEW && tok == TOK_DOTS) {
4475 l = FUNC_ELLIPSIS;
4476 next();
4477 break;
4481 /* if no parameters, then old type prototype */
4482 if (l == 0)
4483 l = FUNC_OLD;
4484 skip(')');
4485 t1 = t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN);
4486 t = post_type(t & ~(VT_TYPEDEF | VT_STATIC | VT_EXTERN), ad);
4487 /* we push a anonymous symbol which will contain the function prototype */
4488 p = anon_sym++;
4489 s = sym_push(p, t, ad->func_call, l);
4490 s->next = first;
4491 t = t1 | VT_FUNC | (p << VT_STRUCT_SHIFT);
4492 } else if (tok == '[') {
4493 /* array definition */
4494 next();
4495 n = -1;
4496 if (tok != ']') {
4497 n = expr_const();
4498 if (n < 0)
4499 error("invalid array size");
4501 skip(']');
4502 /* parse next post type */
4503 t1 = t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN);
4504 t = post_type(t & ~(VT_TYPEDEF | VT_STATIC | VT_EXTERN), ad);
4506 /* we push a anonymous symbol which will contain the array
4507 element type */
4508 p = anon_sym++;
4509 sym_push(p, t, 0, n);
4510 t = t1 | VT_ARRAY | VT_PTR | (p << VT_STRUCT_SHIFT);
4512 return t;
4515 /* Read a type declaration (except basic type), and return the
4516 type. 'td' is a bitmask indicating which kind of type decl is
4517 expected. 't' should contain the basic type. 'ad' is the attribute
4518 definition of the basic type. It can be modified by type_decl(). */
4519 int type_decl(AttributeDef *ad, int *v, int t, int td)
4521 int u, p;
4522 Sym *s;
4524 while (tok == '*') {
4525 next();
4526 while (tok == TOK_CONST || tok == TOK_VOLATILE || tok == TOK_RESTRICT)
4527 next();
4528 t = mk_pointer(t);
4531 /* recursive type */
4532 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
4533 if (tok == '(') {
4534 next();
4535 /* XXX: this is not correct to modify 'ad' at this point, but
4536 the syntax is not clear */
4537 if (tok == TOK___ATTRIBUTE__)
4538 parse_attribute(ad);
4539 u = type_decl(ad, v, 0, td);
4540 skip(')');
4541 } else {
4542 u = 0;
4543 /* type identifier */
4544 if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
4545 *v = tok;
4546 next();
4547 } else {
4548 if (!(td & TYPE_ABSTRACT))
4549 expect("identifier");
4550 *v = 0;
4553 /* append t at the end of u */
4554 t = post_type(t, ad);
4555 if (tok == TOK___ATTRIBUTE__)
4556 parse_attribute(ad);
4557 if (!u)
4558 return t;
4559 p = u;
4560 while(1) {
4561 s = sym_find((unsigned)p >> VT_STRUCT_SHIFT);
4562 p = s->t;
4563 if (!p) {
4564 s->t = t;
4565 break;
4568 return u;
4571 /* define a new external reference to a symbol 'v' of type 'u' */
4572 Sym *external_sym(int v, int u, int r)
4574 Sym *s;
4576 s = sym_find(v);
4577 if (!s) {
4578 /* push forward reference */
4579 s = sym_push1(&global_stack,
4580 v, u | VT_EXTERN, 0);
4581 s->r = r | VT_CONST | VT_SYM;
4583 return s;
4586 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
4587 static int lvalue_type(int t)
4589 int bt, r;
4590 r = VT_LVAL;
4591 bt = t & VT_BTYPE;
4592 if (bt == VT_BYTE)
4593 r |= VT_LVAL_BYTE;
4594 else if (bt == VT_SHORT)
4595 r |= VT_LVAL_SHORT;
4596 else
4597 return r;
4598 if (t & VT_UNSIGNED)
4599 r |= VT_LVAL_UNSIGNED;
4600 return r;
4603 /* indirection with full error checking and bound check */
4604 static void indir(void)
4606 if ((vtop->t & VT_BTYPE) != VT_PTR)
4607 expect("pointer");
4608 if (vtop->r & VT_LVAL)
4609 gv(RC_INT);
4610 vtop->t = pointed_type(vtop->t);
4611 /* an array is never an lvalue */
4612 if (!(vtop->t & VT_ARRAY)) {
4613 vtop->r |= lvalue_type(vtop->t);
4614 /* if bound checking, the referenced pointer must be checked */
4615 if (do_bounds_check)
4616 vtop->r |= VT_MUSTBOUND;
4620 /* pass a parameter to a function and do type checking and casting */
4621 void gfunc_param_typed(GFuncContext *gf, Sym *func, Sym *arg)
4623 int func_type;
4624 func_type = func->c;
4625 if (func_type == FUNC_OLD ||
4626 (func_type == FUNC_ELLIPSIS && arg == NULL)) {
4627 /* default casting : only need to convert float to double */
4628 if ((vtop->t & VT_BTYPE) == VT_FLOAT)
4629 gen_cast(VT_DOUBLE);
4630 } else if (arg == NULL) {
4631 error("too many arguments to function");
4632 } else {
4633 gen_assign_cast(arg->t);
4635 gfunc_param(gf);
4638 void unary(void)
4640 int n, t, ft, fc, align, size, r, data_offset;
4641 Sym *s;
4642 GFuncContext gf;
4643 AttributeDef ad;
4645 if (tok == TOK_CINT || tok == TOK_CCHAR || tok == TOK_LCHAR) {
4646 vpushi(tokc.i);
4647 next();
4648 } else if (tok == TOK_CUINT) {
4649 vsetc(VT_INT | VT_UNSIGNED, VT_CONST, &tokc);
4650 next();
4651 } else if (tok == TOK_CLLONG) {
4652 vsetc(VT_LLONG, VT_CONST, &tokc);
4653 next();
4654 } else if (tok == TOK_CULLONG) {
4655 vsetc(VT_LLONG | VT_UNSIGNED, VT_CONST, &tokc);
4656 next();
4657 } else if (tok == TOK_CFLOAT) {
4658 vsetc(VT_FLOAT, VT_CONST, &tokc);
4659 next();
4660 } else if (tok == TOK_CDOUBLE) {
4661 vsetc(VT_DOUBLE, VT_CONST, &tokc);
4662 next();
4663 } else if (tok == TOK_CLDOUBLE) {
4664 vsetc(VT_LDOUBLE, VT_CONST, &tokc);
4665 next();
4666 } else if (tok == TOK___FUNC__) {
4667 /* special function name identifier */
4668 /* generate (char *) type */
4669 data_offset = data_section->data_ptr - data_section->data;
4670 vpush_ref(mk_pointer(VT_BYTE), data_section, data_offset);
4671 strcpy(data_section->data + data_offset, funcname);
4672 data_offset += strlen(funcname) + 1;
4673 data_section->data_ptr = data_section->data + data_offset;
4674 next();
4675 } else if (tok == TOK_LSTR) {
4676 t = VT_INT;
4677 goto str_init;
4678 } else if (tok == TOK_STR) {
4679 /* string parsing */
4680 t = VT_BYTE;
4681 str_init:
4682 type_size(t, &align);
4683 data_offset = data_section->data_ptr - data_section->data;
4684 data_offset = (data_offset + align - 1) & -align;
4685 fc = data_offset;
4686 /* we must declare it as an array first to use initializer parser */
4687 t = VT_ARRAY | mk_pointer(t);
4688 decl_initializer(t, data_section, data_offset, 1, 0);
4689 data_offset += type_size(t, &align);
4690 /* put it as pointer */
4691 vpush_ref(t & ~VT_ARRAY, data_section, fc);
4692 data_section->data_ptr = data_section->data + data_offset;
4693 } else {
4694 t = tok;
4695 next();
4696 if (t == '(') {
4697 /* cast ? */
4698 if (parse_btype(&t, &ad)) {
4699 ft = type_decl(&ad, &n, t, TYPE_ABSTRACT);
4700 skip(')');
4701 /* check ISOC99 compound literal */
4702 if (tok == '{') {
4703 /* data is allocated locally by default */
4704 if (global_expr)
4705 r = VT_CONST;
4706 else
4707 r = VT_LOCAL;
4708 /* all except arrays are lvalues */
4709 if (!(ft & VT_ARRAY))
4710 r |= lvalue_type(ft);
4711 memset(&ad, 0, sizeof(AttributeDef));
4712 decl_initializer_alloc(ft, &ad, r, 1, 0, 0);
4713 } else {
4714 unary();
4715 gen_cast(ft);
4717 } else {
4718 gexpr();
4719 skip(')');
4721 } else if (t == '*') {
4722 unary();
4723 indir();
4724 } else if (t == '&') {
4725 unary();
4726 /* functions names must be treated as function pointers,
4727 except for unary '&' and sizeof. Since we consider that
4728 functions are not lvalues, we only have to handle it
4729 there and in function calls. */
4730 /* arrays can also be used although they are not lvalues */
4731 if ((vtop->t & VT_BTYPE) != VT_FUNC &&
4732 !(vtop->t & VT_ARRAY))
4733 test_lvalue();
4734 vtop->t = mk_pointer(vtop->t);
4735 gaddrof();
4736 } else
4737 if (t == '!') {
4738 unary();
4739 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST)
4740 vtop->c.i = !vtop->c.i;
4741 else if ((vtop->r & VT_VALMASK) == VT_CMP)
4742 vtop->c.i = vtop->c.i ^ 1;
4743 else
4744 vset(VT_INT, VT_JMP, gtst(1, 0));
4745 } else
4746 if (t == '~') {
4747 unary();
4748 vpushi(-1);
4749 gen_op('^');
4750 } else
4751 if (t == '+') {
4752 unary();
4753 } else
4754 if (t == TOK_SIZEOF) {
4755 if (tok == '(') {
4756 next();
4757 if (parse_btype(&t, &ad)) {
4758 t = type_decl(&ad, &n, t, TYPE_ABSTRACT);
4759 } else {
4760 /* XXX: some code could be generated: add eval
4761 flag */
4762 gexpr();
4763 t = vtop->t;
4764 vpop();
4766 skip(')');
4767 } else {
4768 unary();
4769 t = vtop->t;
4770 vpop();
4772 vpushi(type_size(t, &t));
4773 } else
4774 if (t == TOK_INC || t == TOK_DEC) {
4775 unary();
4776 inc(0, t);
4777 } else if (t == '-') {
4778 vpushi(0);
4779 unary();
4780 gen_op('-');
4781 } else
4783 if (t < TOK_UIDENT)
4784 expect("identifier");
4785 s = sym_find(t);
4786 if (!s) {
4787 if (tok != '(')
4788 error("'%s' undeclared", get_tok_str(t, NULL));
4789 /* for simple function calls, we tolerate undeclared
4790 external reference to int() function */
4791 s = external_sym(t, func_old_type, 0);
4793 vset(s->t, s->r, s->c);
4794 /* if forward reference, we must point to s */
4795 if (vtop->r & VT_SYM)
4796 vtop->c.sym = s;
4800 /* post operations */
4801 while (1) {
4802 if (tok == TOK_INC || tok == TOK_DEC) {
4803 inc(1, tok);
4804 next();
4805 } else if (tok == '.' || tok == TOK_ARROW) {
4806 /* field */
4807 if (tok == TOK_ARROW)
4808 indir();
4809 test_lvalue();
4810 gaddrof();
4811 next();
4812 /* expect pointer on structure */
4813 if ((vtop->t & VT_BTYPE) != VT_STRUCT)
4814 expect("struct or union");
4815 s = sym_find(((unsigned)vtop->t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
4816 /* find field */
4817 tok |= SYM_FIELD;
4818 while ((s = s->next) != NULL) {
4819 if (s->v == tok)
4820 break;
4822 if (!s)
4823 error("field not found");
4824 /* add field offset to pointer */
4825 vtop->t = char_pointer_type; /* change type to 'char *' */
4826 vpushi(s->c);
4827 gen_op('+');
4828 /* change type to field type, and set to lvalue */
4829 vtop->t = s->t;
4830 /* an array is never an lvalue */
4831 if (!(vtop->t & VT_ARRAY))
4832 vtop->r |= lvalue_type(vtop->t);
4833 next();
4834 } else if (tok == '[') {
4835 next();
4836 gexpr();
4837 gen_op('+');
4838 indir();
4839 skip(']');
4840 } else if (tok == '(') {
4841 SValue ret;
4842 Sym *sa;
4844 /* function call */
4845 if ((vtop->t & VT_BTYPE) != VT_FUNC) {
4846 /* pointer test (no array accepted) */
4847 if ((vtop->t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
4848 vtop->t = pointed_type(vtop->t);
4849 if ((vtop->t & VT_BTYPE) != VT_FUNC)
4850 goto error_func;
4851 } else {
4852 error_func:
4853 expect("function pointer");
4855 } else {
4856 vtop->r &= ~VT_LVAL; /* no lvalue */
4858 /* get return type */
4859 s = sym_find((unsigned)vtop->t >> VT_STRUCT_SHIFT);
4860 save_regs(0); /* save used temporary registers */
4861 gfunc_start(&gf, s->r);
4862 next();
4863 sa = s->next; /* first parameter */
4864 #ifdef INVERT_FUNC_PARAMS
4866 int parlevel;
4867 Sym *args, *s1;
4868 ParseState saved_parse_state;
4869 TokenString str;
4871 /* read each argument and store it on a stack */
4872 /* XXX: merge it with macro args ? */
4873 args = NULL;
4874 if (tok != ')') {
4875 for(;;) {
4876 tok_str_new(&str);
4877 parlevel = 0;
4878 while ((parlevel > 0 || (tok != ')' && tok != ',')) &&
4879 tok != -1) {
4880 if (tok == '(')
4881 parlevel++;
4882 else if (tok == ')')
4883 parlevel--;
4884 tok_str_add_tok(&str);
4885 next();
4887 tok_str_add(&str, -1); /* end of file added */
4888 tok_str_add(&str, 0);
4889 s1 = sym_push2(&args, 0, 0, (int)str.str);
4890 s1->next = sa; /* add reference to argument */
4891 if (sa)
4892 sa = sa->next;
4893 if (tok == ')')
4894 break;
4895 skip(',');
4899 /* now generate code in reverse order by reading the stack */
4900 save_parse_state(&saved_parse_state);
4901 while (args) {
4902 macro_ptr = (int *)args->c;
4903 next();
4904 expr_eq();
4905 if (tok != -1)
4906 expect("',' or ')'");
4907 gfunc_param_typed(&gf, s, args->next);
4908 s1 = args->prev;
4909 free((int *)args->c);
4910 free(args);
4911 args = s1;
4913 restore_parse_state(&saved_parse_state);
4915 #endif
4916 /* compute first implicit argument if a structure is returned */
4917 if ((s->t & VT_BTYPE) == VT_STRUCT) {
4918 /* get some space for the returned structure */
4919 size = type_size(s->t, &align);
4920 loc = (loc - size) & -align;
4921 ret.t = s->t;
4922 ret.r = VT_LOCAL | VT_LVAL;
4923 /* pass it as 'int' to avoid structure arg passing
4924 problems */
4925 vset(VT_INT, VT_LOCAL, loc);
4926 ret.c = vtop->c;
4927 gfunc_param(&gf);
4928 } else {
4929 ret.t = s->t;
4930 ret.r2 = VT_CONST;
4931 /* return in register */
4932 if (is_float(ret.t)) {
4933 ret.r = REG_FRET;
4934 } else {
4935 if ((ret.t & VT_BTYPE) == VT_LLONG)
4936 ret.r2 = REG_LRET;
4937 ret.r = REG_IRET;
4939 ret.c.i = 0;
4941 #ifndef INVERT_FUNC_PARAMS
4942 if (tok != ')') {
4943 for(;;) {
4944 expr_eq();
4945 gfunc_param_typed(&gf, s, sa);
4946 if (sa)
4947 sa = sa->next;
4948 if (tok == ')')
4949 break;
4950 skip(',');
4953 #endif
4954 if (sa)
4955 error("too few arguments to function");
4956 skip(')');
4957 gfunc_call(&gf);
4958 /* return value */
4959 vsetc(ret.t, ret.r, &ret.c);
4960 vtop->r2 = ret.r2;
4961 } else {
4962 break;
4967 void uneq(void)
4969 int t;
4971 unary();
4972 if (tok == '=' ||
4973 (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
4974 tok == TOK_A_XOR || tok == TOK_A_OR ||
4975 tok == TOK_A_SHL || tok == TOK_A_SAR) {
4976 test_lvalue();
4977 t = tok;
4978 next();
4979 if (t == '=') {
4980 expr_eq();
4981 } else {
4982 vdup();
4983 expr_eq();
4984 gen_op(t & 0x7f);
4986 vstore();
4990 void sum(int l)
4992 int t;
4994 if (l == 0)
4995 uneq();
4996 else {
4997 sum(--l);
4998 while ((l == 0 && (tok == '*' || tok == '/' || tok == '%')) ||
4999 (l == 1 && (tok == '+' || tok == '-')) ||
5000 (l == 2 && (tok == TOK_SHL || tok == TOK_SAR)) ||
5001 (l == 3 && ((tok >= TOK_ULE && tok <= TOK_GT) ||
5002 tok == TOK_ULT || tok == TOK_UGE)) ||
5003 (l == 4 && (tok == TOK_EQ || tok == TOK_NE)) ||
5004 (l == 5 && tok == '&') ||
5005 (l == 6 && tok == '^') ||
5006 (l == 7 && tok == '|') ||
5007 (l == 8 && tok == TOK_LAND) ||
5008 (l == 9 && tok == TOK_LOR)) {
5009 t = tok;
5010 next();
5011 sum(l);
5012 gen_op(t);
5017 /* only used if non constant */
5018 void eand(void)
5020 int t;
5022 sum(8);
5023 t = 0;
5024 while (1) {
5025 if (tok != TOK_LAND) {
5026 if (t) {
5027 t = gtst(1, t);
5028 vset(VT_INT, VT_JMPI, t);
5030 break;
5032 t = gtst(1, t);
5033 next();
5034 sum(8);
5038 void eor(void)
5040 int t;
5042 eand();
5043 t = 0;
5044 while (1) {
5045 if (tok != TOK_LOR) {
5046 if (t) {
5047 t = gtst(0, t);
5048 vset(VT_INT, VT_JMP, t);
5050 break;
5052 t = gtst(0, t);
5053 next();
5054 eand();
5058 /* XXX: better constant handling */
5059 void expr_eq(void)
5061 int t, u, c, r1, r2, rc;
5063 if (const_wanted) {
5064 sum(10);
5065 if (tok == '?') {
5066 c = vtop->c.i;
5067 vpop();
5068 next();
5069 gexpr();
5070 t = vtop->c.i;
5071 vpop();
5072 skip(':');
5073 expr_eq();
5074 if (c)
5075 vtop->c.i = t;
5077 } else {
5078 eor();
5079 if (tok == '?') {
5080 next();
5081 save_regs(1); /* we need to save all registers here except
5082 at the top because it is a branch point */
5083 t = gtst(1, 0);
5084 gexpr();
5085 /* XXX: long long handling ? */
5086 rc = RC_INT;
5087 if (is_float(vtop->t))
5088 rc = RC_FLOAT;
5089 r1 = gv(rc);
5090 vtop--; /* no vpop so that FP stack is not flushed */
5091 skip(':');
5092 u = gjmp(0);
5094 gsym(t);
5095 expr_eq();
5096 r2 = gv(rc);
5097 move_reg(r1, r2);
5098 vtop->r = r1;
5099 gsym(u);
5104 void gexpr(void)
5106 while (1) {
5107 expr_eq();
5108 if (tok != ',')
5109 break;
5110 vpop();
5111 next();
5115 /* parse a constant expression and return value in vtop */
5116 void expr_const1(void)
5118 int a;
5119 a = const_wanted;
5120 const_wanted = 1;
5121 expr_eq();
5122 if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST)
5123 expect("constant");
5124 const_wanted = a;
5127 /* parse an integer constant and return its value */
5128 int expr_const(void)
5130 int c;
5131 expr_const1();
5132 c = vtop->c.i;
5133 vpop();
5134 return c;
5137 /* return the label token if current token is a label, otherwise
5138 return zero */
5139 int is_label(void)
5141 int t;
5142 CValue c;
5144 /* fast test first */
5145 if (tok < TOK_UIDENT)
5146 return 0;
5147 /* no need to save tokc since we expect an identifier */
5148 t = tok;
5149 c = tokc;
5150 next();
5151 if (tok == ':') {
5152 next();
5153 return t;
5154 } else {
5155 /* XXX: may not work in all cases (macros ?) */
5156 tok1 = tok;
5157 tok1c = tokc;
5158 tok = t;
5159 tokc = c;
5160 return 0;
5164 void block(int *bsym, int *csym, int *case_sym, int *def_sym, int case_reg)
5166 int a, b, c, d;
5167 Sym *s;
5169 /* generate line number info */
5170 if (do_debug &&
5171 (last_line_num != file->line_num || last_ind != ind)) {
5172 put_stabn(N_SLINE, 0, file->line_num, ind - func_ind);
5173 last_ind = ind;
5174 last_line_num = file->line_num;
5177 if (tok == TOK_IF) {
5178 /* if test */
5179 next();
5180 skip('(');
5181 gexpr();
5182 skip(')');
5183 a = gtst(1, 0);
5184 block(bsym, csym, case_sym, def_sym, case_reg);
5185 c = tok;
5186 if (c == TOK_ELSE) {
5187 next();
5188 d = gjmp(0);
5189 gsym(a);
5190 block(bsym, csym, case_sym, def_sym, case_reg);
5191 gsym(d); /* patch else jmp */
5192 } else
5193 gsym(a);
5194 } else if (tok == TOK_WHILE) {
5195 next();
5196 d = ind;
5197 skip('(');
5198 gexpr();
5199 skip(')');
5200 a = gtst(1, 0);
5201 b = 0;
5202 block(&a, &b, case_sym, def_sym, case_reg);
5203 gjmp_addr(d);
5204 gsym(a);
5205 gsym_addr(b, d);
5206 } else if (tok == '{') {
5207 next();
5208 /* declarations */
5209 s = local_stack.top;
5210 while (tok != '}') {
5211 decl(VT_LOCAL);
5212 if (tok != '}')
5213 block(bsym, csym, case_sym, def_sym, case_reg);
5215 /* pop locally defined symbols */
5216 sym_pop(&local_stack, s);
5217 next();
5218 } else if (tok == TOK_RETURN) {
5219 next();
5220 if (tok != ';') {
5221 gexpr();
5222 gen_assign_cast(func_vt);
5223 if ((func_vt & VT_BTYPE) == VT_STRUCT) {
5224 /* if returning structure, must copy it to implicit
5225 first pointer arg location */
5226 vset(mk_pointer(func_vt), VT_LOCAL | VT_LVAL, func_vc);
5227 indir();
5228 vswap();
5229 /* copy structure value to pointer */
5230 vstore();
5231 } else if (is_float(func_vt)) {
5232 gv(RC_FRET);
5233 } else {
5234 gv(RC_IRET);
5236 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
5238 skip(';');
5239 rsym = gjmp(rsym); /* jmp */
5240 } else if (tok == TOK_BREAK) {
5241 /* compute jump */
5242 if (!bsym)
5243 error("cannot break");
5244 *bsym = gjmp(*bsym);
5245 next();
5246 skip(';');
5247 } else if (tok == TOK_CONTINUE) {
5248 /* compute jump */
5249 if (!csym)
5250 error("cannot continue");
5251 *csym = gjmp(*csym);
5252 next();
5253 skip(';');
5254 } else if (tok == TOK_FOR) {
5255 int e;
5256 next();
5257 skip('(');
5258 if (tok != ';') {
5259 gexpr();
5260 vpop();
5262 skip(';');
5263 d = ind;
5264 c = ind;
5265 a = 0;
5266 b = 0;
5267 if (tok != ';') {
5268 gexpr();
5269 a = gtst(1, 0);
5271 skip(';');
5272 if (tok != ')') {
5273 e = gjmp(0);
5274 c = ind;
5275 gexpr();
5276 vpop();
5277 gjmp_addr(d);
5278 gsym(e);
5280 skip(')');
5281 block(&a, &b, case_sym, def_sym, case_reg);
5282 gjmp_addr(c);
5283 gsym(a);
5284 gsym_addr(b, c);
5285 } else
5286 if (tok == TOK_DO) {
5287 next();
5288 a = 0;
5289 b = 0;
5290 d = ind;
5291 block(&a, &b, case_sym, def_sym, case_reg);
5292 skip(TOK_WHILE);
5293 skip('(');
5294 gsym(b);
5295 gexpr();
5296 c = gtst(0, 0);
5297 gsym_addr(c, d);
5298 skip(')');
5299 gsym(a);
5300 skip(';');
5301 } else
5302 if (tok == TOK_SWITCH) {
5303 next();
5304 skip('(');
5305 gexpr();
5306 /* XXX: other types than integer */
5307 case_reg = gv(RC_INT);
5308 vpop();
5309 skip(')');
5310 a = 0;
5311 b = gjmp(0); /* jump to first case */
5312 c = 0;
5313 block(&a, csym, &b, &c, case_reg);
5314 /* if no default, jmp after switch */
5315 if (c == 0)
5316 c = ind;
5317 /* default label */
5318 gsym_addr(b, c);
5319 /* break label */
5320 gsym(a);
5321 } else
5322 if (tok == TOK_CASE) {
5323 int v1, v2;
5324 if (!case_sym)
5325 expect("switch");
5326 next();
5327 v1 = expr_const();
5328 v2 = v1;
5329 if (gnu_ext && tok == TOK_DOTS) {
5330 next();
5331 v2 = expr_const();
5332 if (v2 < v1)
5333 warning("empty case range");
5335 /* since a case is like a label, we must skip it with a jmp */
5336 b = gjmp(0);
5337 gsym(*case_sym);
5338 vset(VT_INT, case_reg, 0);
5339 vpushi(v1);
5340 if (v1 == v2) {
5341 gen_op(TOK_EQ);
5342 *case_sym = gtst(1, 0);
5343 } else {
5344 gen_op(TOK_GE);
5345 *case_sym = gtst(1, 0);
5346 vset(VT_INT, case_reg, 0);
5347 vpushi(v2);
5348 gen_op(TOK_LE);
5349 *case_sym = gtst(1, *case_sym);
5351 gsym(b);
5352 skip(':');
5353 block(bsym, csym, case_sym, def_sym, case_reg);
5354 } else
5355 if (tok == TOK_DEFAULT) {
5356 next();
5357 skip(':');
5358 if (!def_sym)
5359 expect("switch");
5360 if (*def_sym)
5361 error("too many 'default'");
5362 *def_sym = ind;
5363 block(bsym, csym, case_sym, def_sym, case_reg);
5364 } else
5365 if (tok == TOK_GOTO) {
5366 next();
5367 s = sym_find1(&label_stack, tok);
5368 /* put forward definition if needed */
5369 if (!s)
5370 s = sym_push1(&label_stack, tok, LABEL_FORWARD, 0);
5371 /* label already defined */
5372 if (s->t & LABEL_FORWARD)
5373 s->c = gjmp(s->c);
5374 else
5375 gjmp_addr(s->c);
5376 next();
5377 skip(';');
5378 } else {
5379 b = is_label();
5380 if (b) {
5381 /* label case */
5382 s = sym_find1(&label_stack, b);
5383 if (s) {
5384 if (!(s->t & LABEL_FORWARD))
5385 error("multiple defined label");
5386 gsym(s->c);
5387 s->c = ind;
5388 s->t = 0;
5389 } else {
5390 sym_push1(&label_stack, b, 0, ind);
5392 /* we accept this, but it is a mistake */
5393 if (tok == '}')
5394 warning("deprecated use of label at end of compound statement");
5395 else
5396 block(bsym, csym, case_sym, def_sym, case_reg);
5397 } else {
5398 /* expression case */
5399 if (tok != ';') {
5400 gexpr();
5401 vpop();
5403 skip(';');
5408 /* t is the array or struct type. c is the array or struct
5409 address. cur_index/cur_field is the pointer to the current
5410 value. 'size_only' is true if only size info is needed (only used
5411 in arrays) */
5412 void decl_designator(int t, Section *sec, unsigned long c,
5413 int *cur_index, Sym **cur_field,
5414 int size_only)
5416 Sym *s, *f;
5417 int notfirst, index, align, l;
5419 notfirst = 0;
5420 if (gnu_ext && (l = is_label()) != 0)
5421 goto struct_field;
5423 while (tok == '[' || tok == '.') {
5424 if (tok == '[') {
5425 if (!(t & VT_ARRAY))
5426 expect("array type");
5427 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
5428 next();
5429 index = expr_const();
5430 if (index < 0 || (s->c >= 0 && index >= s->c))
5431 expect("invalid index");
5432 skip(']');
5433 if (!notfirst)
5434 *cur_index = index;
5435 t = pointed_type(t);
5436 c += index * type_size(t, &align);
5437 } else {
5438 next();
5439 l = tok;
5440 next();
5441 struct_field:
5442 if ((t & VT_BTYPE) != VT_STRUCT)
5443 expect("struct/union type");
5444 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
5445 l |= SYM_FIELD;
5446 f = s->next;
5447 while (f) {
5448 if (f->v == l)
5449 break;
5450 f = f->next;
5452 if (!f)
5453 expect("field");
5454 if (!notfirst)
5455 *cur_field = f;
5456 t = f->t | (t & ~VT_TYPE);
5457 c += f->c;
5459 notfirst = 1;
5461 if (notfirst) {
5462 if (tok == '=') {
5463 next();
5464 } else {
5465 if (!gnu_ext)
5466 expect("=");
5468 } else {
5469 if (t & VT_ARRAY) {
5470 index = *cur_index;
5471 t = pointed_type(t);
5472 c += index * type_size(t, &align);
5473 } else {
5474 f = *cur_field;
5475 if (!f)
5476 error("too many field init");
5477 t = f->t | (t & ~VT_TYPE);
5478 c += f->c;
5481 decl_initializer(t, sec, c, 0, size_only);
5484 #define EXPR_VAL 0
5485 #define EXPR_CONST 1
5486 #define EXPR_ANY 2
5488 /* store a value or an expression directly in global data or in local array */
5489 void init_putv(int t, Section *sec, unsigned long c,
5490 int v, int expr_type)
5492 int saved_global_expr, bt;
5493 void *ptr;
5495 switch(expr_type) {
5496 case EXPR_VAL:
5497 vpushi(v);
5498 break;
5499 case EXPR_CONST:
5500 /* compound literals must be allocated globally in this case */
5501 saved_global_expr = global_expr;
5502 global_expr = 1;
5503 expr_const1();
5504 global_expr = saved_global_expr;
5505 break;
5506 case EXPR_ANY:
5507 expr_eq();
5508 break;
5511 if (sec) {
5512 /* XXX: not portable */
5513 /* XXX: generate error if incorrect relocation */
5514 gen_assign_cast(t);
5515 bt = t & VT_BTYPE;
5516 ptr = sec->data + c;
5517 if ((vtop->r & VT_SYM) &&
5518 (bt == VT_BYTE ||
5519 bt == VT_SHORT ||
5520 bt == VT_DOUBLE ||
5521 bt == VT_LDOUBLE ||
5522 bt == VT_LLONG))
5523 error("initializer element is not computable at load time");
5524 switch(bt) {
5525 case VT_BYTE:
5526 *(char *)ptr = vtop->c.i;
5527 break;
5528 case VT_SHORT:
5529 *(short *)ptr = vtop->c.i;
5530 break;
5531 case VT_DOUBLE:
5532 *(double *)ptr = vtop->c.d;
5533 break;
5534 case VT_LDOUBLE:
5535 *(long double *)ptr = vtop->c.ld;
5536 break;
5537 case VT_LLONG:
5538 *(long long *)ptr = vtop->c.ll;
5539 break;
5540 default:
5541 if (vtop->r & VT_SYM) {
5542 greloc(sec, vtop->c.sym, c, R_DATA_32);
5543 *(int *)ptr = 0;
5544 } else {
5545 *(int *)ptr = vtop->c.i;
5547 break;
5549 vtop--;
5550 } else {
5551 vset(t, VT_LOCAL, c);
5552 vswap();
5553 vstore();
5554 vpop();
5558 /* put zeros for variable based init */
5559 void init_putz(int t, Section *sec, unsigned long c, int size)
5561 GFuncContext gf;
5563 if (sec) {
5564 /* nothing to do because globals are already set to zero */
5565 } else {
5566 gfunc_start(&gf, FUNC_CDECL);
5567 vpushi(size);
5568 gfunc_param(&gf);
5569 vpushi(0);
5570 gfunc_param(&gf);
5571 vset(VT_INT, VT_LOCAL, c);
5572 gfunc_param(&gf);
5573 vpush_sym(func_old_type, TOK_memset);
5574 gfunc_call(&gf);
5578 /* 't' contains the type and storage info. 'c' is the offset of the
5579 object in section 'sec'. If 'sec' is NULL, it means stack based
5580 allocation. 'first' is true if array '{' must be read (multi
5581 dimension implicit array init handling). 'size_only' is true if
5582 size only evaluation is wanted (only for arrays). */
5583 void decl_initializer(int t, Section *sec, unsigned long c, int first, int size_only)
5585 int index, array_length, n, no_oblock, nb, parlevel, i;
5586 int t1, size1, align1, expr_type;
5587 Sym *s, *f;
5588 TokenSym *ts;
5590 if (t & VT_ARRAY) {
5591 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
5592 n = s->c;
5593 array_length = 0;
5594 t1 = pointed_type(t);
5595 size1 = type_size(t1, &align1);
5597 no_oblock = 1;
5598 if ((first && tok != TOK_LSTR && tok != TOK_STR) ||
5599 tok == '{') {
5600 skip('{');
5601 no_oblock = 0;
5604 /* only parse strings here if correct type (otherwise: handle
5605 them as ((w)char *) expressions */
5606 if ((tok == TOK_LSTR &&
5607 (t1 & VT_BTYPE) == VT_INT) ||
5608 (tok == TOK_STR &&
5609 (t1 & VT_BTYPE) == VT_BYTE)) {
5610 /* XXX: move multiple string parsing in parser ? */
5611 while (tok == TOK_STR || tok == TOK_LSTR) {
5612 ts = tokc.ts;
5613 /* compute maximum number of chars wanted */
5614 nb = ts->len;
5615 if (n >= 0 && nb > (n - array_length))
5616 nb = n - array_length;
5617 if (!size_only) {
5618 if (ts->len > nb)
5619 warning("initializer-string for array is too long");
5620 for(i=0;i<nb;i++) {
5621 init_putv(t1, sec, c + (array_length + i) * size1,
5622 ts->str[i], EXPR_VAL);
5625 array_length += nb;
5626 next();
5628 /* only add trailing zero if enough storage (no
5629 warning in this case since it is standard) */
5630 if (n < 0 || array_length < n) {
5631 if (!size_only) {
5632 init_putv(t1, sec, c + (array_length * size1), 0, EXPR_VAL);
5634 array_length++;
5636 } else {
5637 index = 0;
5638 while (tok != '}') {
5639 decl_designator(t, sec, c, &index, NULL, size_only);
5640 if (n >= 0 && index >= n)
5641 error("index too large");
5642 /* must put zero in holes (note that doing it that way
5643 ensures that it even works with designators) */
5644 if (!size_only && array_length < index) {
5645 init_putz(t1, sec, c + array_length * size1,
5646 (index - array_length) * size1);
5648 index++;
5649 if (index > array_length)
5650 array_length = index;
5651 /* special test for multi dimensional arrays (may not
5652 be strictly correct if designators are used at the
5653 same time) */
5654 if (index >= n && no_oblock)
5655 break;
5656 if (tok == '}')
5657 break;
5658 skip(',');
5661 if (!no_oblock)
5662 skip('}');
5663 /* put zeros at the end */
5664 if (!size_only && n >= 0 && array_length < n) {
5665 init_putz(t1, sec, c + array_length * size1,
5666 (n - array_length) * size1);
5668 /* patch type size if needed */
5669 if (n < 0)
5670 s->c = array_length;
5671 } else if ((t & VT_BTYPE) == VT_STRUCT && tok == '{') {
5672 /* XXX: union needs only one init */
5673 next();
5674 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
5675 f = s->next;
5676 array_length = 0;
5677 index = 0;
5678 n = s->c;
5679 while (tok != '}') {
5680 decl_designator(t, sec, c, NULL, &f, size_only);
5681 /* fill with zero between fields */
5682 index = f->c;
5683 if (!size_only && array_length < index) {
5684 init_putz(t, sec, c + array_length,
5685 index - array_length);
5687 index = index + type_size(f->t, &align1);
5688 if (index > array_length)
5689 array_length = index;
5690 if (tok == '}')
5691 break;
5692 skip(',');
5693 f = f->next;
5695 /* put zeros at the end */
5696 if (!size_only && array_length < n) {
5697 init_putz(t, sec, c + array_length,
5698 n - array_length);
5700 skip('}');
5701 } else if (tok == '{') {
5702 next();
5703 decl_initializer(t, sec, c, first, size_only);
5704 skip('}');
5705 } else if (size_only) {
5706 /* just skip expression */
5707 parlevel = 0;
5708 while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
5709 tok != -1) {
5710 if (tok == '(')
5711 parlevel++;
5712 else if (tok == ')')
5713 parlevel--;
5714 next();
5716 } else {
5717 /* currently, we always use constant expression for globals
5718 (may change for scripting case) */
5719 expr_type = EXPR_CONST;
5720 if (!sec)
5721 expr_type = EXPR_ANY;
5722 init_putv(t, sec, c, 0, expr_type);
5726 /* parse an initializer for type 't' if 'has_init' is true, and
5727 allocate space in local or global data space ('r' is either
5728 VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
5729 variable 'v' of scope 'scope' is declared before initializers are
5730 parsed. If 'v' is zero, then a reference to the new object is put
5731 in the value stack. */
5732 void decl_initializer_alloc(int t, AttributeDef *ad, int r, int has_init,
5733 int v, int scope)
5735 int size, align, addr, data_offset;
5736 int level;
5737 ParseState saved_parse_state;
5738 TokenString init_str;
5739 Section *sec;
5741 size = type_size(t, &align);
5742 /* If unknown size, we must evaluate it before
5743 evaluating initializers because
5744 initializers can generate global data too
5745 (e.g. string pointers or ISOC99 compound
5746 literals). It also simplifies local
5747 initializers handling */
5748 tok_str_new(&init_str);
5749 if (size < 0) {
5750 if (!has_init)
5751 error("unknown type size");
5752 /* get all init string */
5753 level = 0;
5754 while (level > 0 || (tok != ',' && tok != ';')) {
5755 if (tok < 0)
5756 error("unexpected end of file in initializer");
5757 tok_str_add_tok(&init_str);
5758 if (tok == '{')
5759 level++;
5760 else if (tok == '}') {
5761 if (level == 0)
5762 break;
5763 level--;
5765 next();
5767 tok_str_add(&init_str, -1);
5768 tok_str_add(&init_str, 0);
5770 /* compute size */
5771 save_parse_state(&saved_parse_state);
5773 macro_ptr = init_str.str;
5774 next();
5775 decl_initializer(t, NULL, 0, 1, 1);
5776 /* prepare second initializer parsing */
5777 macro_ptr = init_str.str;
5778 next();
5780 /* if still unknown size, error */
5781 size = type_size(t, &align);
5782 if (size < 0)
5783 error("unknown type size");
5785 /* take into account specified alignment if bigger */
5786 if (ad->aligned > align)
5787 align = ad->aligned;
5788 if ((r & VT_VALMASK) == VT_LOCAL) {
5789 sec = NULL;
5790 if (do_bounds_check && (t & VT_ARRAY))
5791 loc--;
5792 #ifdef TCC_TARGET_IL
5793 /* XXX: ugly patch to allocate local variables for IL, just
5794 for testing */
5795 addr = loc;
5796 loc++;
5797 #else
5798 loc = (loc - size) & -align;
5799 addr = loc;
5800 #endif
5801 /* handles bounds */
5802 /* XXX: currently, since we do only one pass, we cannot track
5803 '&' operators, so we add only arrays */
5804 if (do_bounds_check && (t & VT_ARRAY)) {
5805 int *bounds_ptr;
5806 /* add padding between regions */
5807 loc--;
5808 /* then add local bound info */
5809 bounds_ptr = (int *)lbounds_section->data_ptr;
5810 *bounds_ptr++ = addr;
5811 *bounds_ptr++ = size;
5812 lbounds_section->data_ptr = (unsigned char *)bounds_ptr;
5814 } else {
5815 /* compute section */
5816 sec = ad->section;
5817 if (!sec) {
5818 if (has_init)
5819 sec = data_section;
5820 else
5821 sec = bss_section;
5823 data_offset = sec->data_ptr - sec->data;
5824 data_offset = (data_offset + align - 1) & -align;
5825 addr = data_offset;
5826 /* very important to increment global pointer at this time
5827 because initializers themselves can create new initializers */
5828 data_offset += size;
5829 /* handles bounds */
5830 if (do_bounds_check) {
5831 int *bounds_ptr;
5832 /* first, we need to add at least one byte between each region */
5833 data_offset++;
5834 /* then add global bound info */
5835 bounds_ptr = (int *)bounds_section->data_ptr;
5836 /* XXX: add relocation */
5837 *bounds_ptr++ = addr + (unsigned long)sec->data;
5838 *bounds_ptr++ = size;
5839 bounds_section->data_ptr = (unsigned char *)bounds_ptr;
5841 sec->data_ptr = sec->data + data_offset;
5843 if (v) {
5844 Sym *sym;
5846 if (!sec) {
5847 /* local variable */
5848 sym_push(v, t, r, addr);
5849 } else {
5850 if (scope == VT_CONST) {
5851 /* global scope: see if already defined */
5852 sym = sym_find(v);
5853 if (!sym)
5854 goto do_def;
5855 if (!is_compatible_types(sym->t, t))
5856 error("incompatible types for redefinition of '%s'",
5857 get_tok_str(v, NULL));
5858 if (!(sym->t & VT_EXTERN))
5859 error("redefinition of '%s'", get_tok_str(v, NULL));
5860 sym->t &= ~VT_EXTERN;
5861 } else {
5862 do_def:
5863 sym = sym_push(v, t, r | VT_SYM, 0);
5865 put_extern_sym(sym, sec, addr);
5867 } else {
5868 if (!sec) {
5869 /* push local reference */
5870 vset(t, r, addr);
5871 } else {
5872 /* push global reference */
5873 vpush_ref(t, sec, addr);
5876 if (has_init) {
5877 decl_initializer(t, sec, addr, 1, 0);
5878 /* restore parse state if needed */
5879 if (init_str.str) {
5880 free(init_str.str);
5881 restore_parse_state(&saved_parse_state);
5886 void put_func_debug(int t)
5888 char buf[512];
5890 /* stabs info */
5891 /* XXX: we put here a dummy type */
5892 snprintf(buf, sizeof(buf), "%s:%c1",
5893 funcname, t & VT_STATIC ? 'f' : 'F');
5894 put_stabs(buf, N_FUN, 0, file->line_num, ind);
5895 func_ind = ind;
5896 last_ind = 0;
5897 last_line_num = 0;
5900 /* not finished : try to put some local vars in registers */
5901 //#define CONFIG_REG_VARS
5903 #ifdef CONFIG_REG_VARS
5904 void add_var_ref(int t)
5906 printf("%s:%d: &%s\n",
5907 file->filename, file->line_num,
5908 get_tok_str(t, NULL));
5911 /* first pass on a function with heuristic to extract variable usage
5912 and pointer references to local variables for register allocation */
5913 void analyse_function(void)
5915 int level, t;
5917 for(;;) {
5918 if (tok == -1)
5919 break;
5920 /* any symbol coming after '&' is considered as being a
5921 variable whose reference is taken. It is highly unaccurate
5922 but it is difficult to do better without a complete parse */
5923 if (tok == '&') {
5924 next();
5925 /* if '& number', then no need to examine next tokens */
5926 if (tok == TOK_CINT ||
5927 tok == TOK_CUINT ||
5928 tok == TOK_CLLONG ||
5929 tok == TOK_CULLONG) {
5930 continue;
5931 } else if (tok >= TOK_UIDENT) {
5932 /* if '& ident [' or '& ident ->', then ident address
5933 is not needed */
5934 t = tok;
5935 next();
5936 if (tok != '[' && tok != TOK_ARROW)
5937 add_var_ref(t);
5938 } else {
5939 level = 0;
5940 while (tok != '}' && tok != ';' &&
5941 !((tok == ',' || tok == ')') && level == 0)) {
5942 if (tok >= TOK_UIDENT) {
5943 add_var_ref(tok);
5944 } else if (tok == '(') {
5945 level++;
5946 } else if (tok == ')') {
5947 level--;
5949 next();
5952 } else {
5953 next();
5957 #endif
5959 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
5960 void decl(int l)
5962 int t, b, v, has_init, r;
5963 Sym *sym;
5964 AttributeDef ad;
5966 while (1) {
5967 if (!parse_btype(&b, &ad)) {
5968 /* skip redundant ';' */
5969 /* XXX: find more elegant solution */
5970 if (tok == ';') {
5971 next();
5972 continue;
5974 /* special test for old K&R protos without explicit int
5975 type. Only accepted when defining global data */
5976 if (l == VT_LOCAL || tok < TOK_DEFINE)
5977 break;
5978 b = VT_INT;
5980 if (((b & VT_BTYPE) == VT_ENUM ||
5981 (b & VT_BTYPE) == VT_STRUCT) &&
5982 tok == ';') {
5983 /* we accept no variable after */
5984 next();
5985 continue;
5987 while (1) { /* iterate thru each declaration */
5988 t = type_decl(&ad, &v, b, TYPE_DIRECT);
5989 #if 0
5991 char buf[500];
5992 type_to_str(buf, sizeof(buf), t, get_tok_str(v, NULL));
5993 printf("type = '%s'\n", buf);
5995 #endif
5996 if (tok == '{') {
5997 #ifdef CONFIG_REG_VARS
5998 TokenString func_str;
5999 ParseState saved_parse_state;
6000 int block_level;
6001 #endif
6003 if (l == VT_LOCAL)
6004 error("cannot use local functions");
6005 if (!(t & VT_FUNC))
6006 expect("function definition");
6008 #ifdef CONFIG_REG_VARS
6009 /* parse all function code and record it */
6011 tok_str_new(&func_str);
6013 block_level = 0;
6014 for(;;) {
6015 int t;
6016 if (tok == -1)
6017 error("unexpected end of file");
6018 tok_str_add_tok(&func_str);
6019 t = tok;
6020 next();
6021 if (t == '{') {
6022 block_level++;
6023 } else if (t == '}') {
6024 block_level--;
6025 if (block_level == 0)
6026 break;
6029 tok_str_add(&func_str, -1);
6030 tok_str_add(&func_str, 0);
6032 save_parse_state(&saved_parse_state);
6034 macro_ptr = func_str.str;
6035 next();
6036 analyse_function();
6037 #endif
6039 /* compute text section */
6040 cur_text_section = ad.section;
6041 if (!cur_text_section)
6042 cur_text_section = text_section;
6043 ind = (int)cur_text_section->data_ptr;
6044 funcname = get_tok_str(v, NULL);
6045 sym = sym_find(v);
6046 if (sym) {
6047 /* if symbol is already defined, then put complete type */
6048 sym->t = t;
6049 } else {
6050 /* put function symbol */
6051 sym = sym_push1(&global_stack, v, t, 0);
6053 put_extern_sym(sym, cur_text_section,
6054 ind - (int)cur_text_section->data);
6055 sym->r = VT_SYM | VT_CONST;
6056 /* put debug symbol */
6057 if (do_debug)
6058 put_func_debug(t);
6059 /* push a dummy symbol to enable local sym storage */
6060 sym_push1(&local_stack, 0, 0, 0);
6061 gfunc_prolog(t);
6062 loc = 0;
6063 rsym = 0;
6064 #ifdef CONFIG_REG_VARS
6065 macro_ptr = func_str.str;
6066 next();
6067 #endif
6068 block(NULL, NULL, NULL, NULL, 0);
6069 gsym(rsym);
6070 gfunc_epilog();
6071 cur_text_section->data_ptr = (unsigned char *)ind;
6072 sym_pop(&label_stack, NULL); /* reset label stack */
6073 sym_pop(&local_stack, NULL); /* reset local stack */
6074 /* end of function */
6075 if (do_debug) {
6076 put_stabn(N_FUN, 0, 0, ind - func_ind);
6078 funcname = ""; /* for safety */
6079 func_vt = VT_VOID; /* for safety */
6080 ind = 0; /* for safety */
6082 #ifdef CONFIG_REG_VARS
6083 free(func_str.str);
6084 restore_parse_state(&saved_parse_state);
6085 #endif
6086 break;
6087 } else {
6088 if (b & VT_TYPEDEF) {
6089 /* save typedefed type */
6090 /* XXX: test storage specifiers ? */
6091 sym_push(v, t | VT_TYPEDEF, 0, 0);
6092 } else if ((t & VT_BTYPE) == VT_FUNC) {
6093 /* external function definition */
6094 external_sym(v, t, 0);
6095 } else {
6096 /* not lvalue if array */
6097 r = 0;
6098 if (!(t & VT_ARRAY))
6099 r |= lvalue_type(t);
6100 if (b & VT_EXTERN) {
6101 /* external variable */
6102 external_sym(v, t, r);
6103 } else {
6104 if (t & VT_STATIC)
6105 r |= VT_CONST;
6106 else
6107 r |= l;
6108 has_init = (tok == '=');
6109 if (has_init)
6110 next();
6111 decl_initializer_alloc(t, &ad, r,
6112 has_init, v, l);
6115 if (tok != ',') {
6116 skip(';');
6117 break;
6119 next();
6125 /* compile the C file opened in 'file'. Return non zero if errors. */
6126 static int tcc_compile(TCCState *s)
6128 Sym *define_start;
6129 char buf[512];
6130 int p;
6132 funcname = "";
6133 include_stack_ptr = include_stack;
6134 ifdef_stack_ptr = ifdef_stack;
6136 vtop = vstack - 1;
6137 anon_sym = SYM_FIRST_ANOM;
6139 /* file info: full path + filename */
6140 if (do_debug) {
6141 getcwd(buf, sizeof(buf));
6142 pstrcat(buf, sizeof(buf), "/");
6143 put_stabs(buf, N_SO, 0, 0, (unsigned long)text_section->data_ptr);
6144 put_stabs(file->filename, N_SO, 0, 0,
6145 (unsigned long)text_section->data_ptr);
6147 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
6148 symbols can be safely used */
6149 put_elf_sym(symtab_section, 0, 0,
6150 ELF32_ST_INFO(STB_LOCAL, STT_FILE), 0,
6151 SHN_ABS, file->filename);
6153 /* define common 'char *' type because it is often used internally
6154 for arrays and struct dereference */
6155 char_pointer_type = mk_pointer(VT_BYTE);
6156 /* define an old type function 'int func()' */
6157 p = anon_sym++;
6158 sym_push1(&global_stack, p, 0, FUNC_OLD);
6159 func_old_type = VT_FUNC | (p << VT_STRUCT_SHIFT);
6161 define_start = define_stack.top;
6162 inp();
6163 ch = '\n'; /* needed to parse correctly first preprocessor command */
6164 next();
6165 decl(VT_CONST);
6166 if (tok != -1)
6167 expect("declaration");
6169 /* end of translation unit info */
6170 if (do_debug) {
6171 put_stabn(N_SO, 0, 0, (unsigned long)text_section->data_ptr);
6174 /* reset define stack, but leave -Dsymbols (may be incorrect if
6175 they are undefined) */
6176 sym_pop(&define_stack, define_start);
6178 sym_pop(&global_stack, NULL);
6180 return 0;
6183 int tcc_compile_string(TCCState *s, const char *str)
6185 BufferedFile bf1, *bf = &bf1;
6186 int ret;
6188 /* init file structure */
6189 bf->fd = -1;
6190 bf->buf_ptr = (char *)str;
6191 bf->buf_end = (char *)str + strlen(bf->buffer);
6192 pstrcpy(bf->filename, sizeof(bf->filename), "<string>");
6193 bf->line_num = 1;
6194 file = bf;
6196 ret = tcc_compile(s);
6198 /* currently, no need to close */
6199 return ret;
6202 /* define a symbol. A value can also be provided with the '=' operator */
6203 void tcc_define_symbol(TCCState *s, const char *sym, const char *value)
6205 BufferedFile bf1, *bf = &bf1;
6207 pstrcpy(bf->buffer, IO_BUF_SIZE, sym);
6208 pstrcat(bf->buffer, IO_BUF_SIZE, " ");
6209 /* default value */
6210 if (!value)
6211 value = "1";
6212 pstrcat(bf->buffer, IO_BUF_SIZE, value);
6214 /* init file structure */
6215 bf->fd = -1;
6216 bf->buf_ptr = bf->buffer;
6217 bf->buf_end = bf->buffer + strlen(bf->buffer);
6218 bf->filename[0] = '\0';
6219 bf->line_num = 1;
6220 file = bf;
6222 include_stack_ptr = include_stack;
6224 /* parse with define parser */
6225 inp();
6226 ch = '\n'; /* needed to parse correctly first preprocessor command */
6227 next_nomacro();
6228 parse_define();
6229 file = NULL;
6232 void tcc_undefine_symbol(TCCState *s1, const char *sym)
6234 TokenSym *ts;
6235 Sym *s;
6236 ts = tok_alloc(sym, 0);
6237 s = sym_find1(&define_stack, tok);
6238 /* undefine symbol by putting an invalid name */
6239 if (s)
6240 sym_undef(&define_stack, s);
6243 static int put_elf_str(Section *s, const char *sym)
6245 int c, offset;
6246 offset = s->data_ptr - s->data;
6247 for(;;) {
6248 c = *sym++;
6249 *s->data_ptr++ = c;
6250 if (c == '\0')
6251 break;
6253 return offset;
6256 /* elf symbol hashing function */
6257 static unsigned long elf_hash(const unsigned char *name)
6259 unsigned long h = 0, g;
6261 while (*name) {
6262 h = (h << 4) + *name++;
6263 g = h & 0xf0000000;
6264 if (g)
6265 h ^= g >> 24;
6266 h &= ~g;
6268 return h;
6271 /* return the symbol number */
6272 static int put_elf_sym(Section *s,
6273 unsigned long value, unsigned long size,
6274 int info, int other, int shndx, const char *name)
6276 int name_offset, sym_index;
6277 int nbuckets, h;
6278 Elf32_Sym *sym;
6279 Section *hs;
6281 sym = (Elf32_Sym *)s->data_ptr;
6282 if (name)
6283 name_offset = put_elf_str(s->link, name);
6284 else
6285 name_offset = 0;
6286 /* XXX: endianness */
6287 sym->st_name = name_offset;
6288 sym->st_value = value;
6289 sym->st_size = size;
6290 sym->st_info = info;
6291 sym->st_other = other;
6292 sym->st_shndx = shndx;
6293 sym_index = sym - (Elf32_Sym *)s->data;
6294 hs = s->hash;
6295 if (hs) {
6296 /* only add global or weak symbols */
6297 if (ELF32_ST_BIND(info) != STB_LOCAL) {
6298 /* add another hashing entry */
6299 nbuckets = ((int *)hs->data)[0];
6300 h = elf_hash(name) % nbuckets;
6301 ((int *)hs->data)[2 + nbuckets + sym_index] = ((int *)hs->data)[2 + h];
6302 ((int *)hs->data)[2 + h] = sym_index;
6304 /* but still add room for all symbols */
6305 ((int *)hs->data)[1]++;
6306 hs->data_ptr += sizeof(int);
6308 s->data_ptr += sizeof(Elf32_Sym);
6309 return sym_index;
6312 /* find global ELF symbol 'name' and return its index. Return 0 if not
6313 found. */
6314 static int find_elf_sym(Section *s, const char *name)
6316 Elf32_Sym *sym;
6317 Section *hs;
6318 int nbuckets, sym_index, h;
6319 const char *name1;
6321 hs = s->hash;
6322 if (!hs)
6323 return 0;
6324 nbuckets = ((int *)hs->data)[0];
6325 h = elf_hash(name) % nbuckets;
6326 sym_index = ((int *)hs->data)[2 + h];
6327 while (sym_index != 0) {
6328 sym = &((Elf32_Sym *)s->data)[sym_index];
6329 name1 = s->link->data + sym->st_name;
6330 if (!strcmp(name, name1))
6331 return sym_index;
6332 sym_index = ((int *)hs->data)[2 + nbuckets + sym_index];
6334 return 0;
6337 /* return elf symbol value or error */
6338 static unsigned long get_elf_sym_val(const char *name)
6340 int sym_index;
6341 Elf32_Sym *sym;
6343 sym_index = find_elf_sym(symtab_section, name);
6344 if (!sym_index)
6345 error("%s not defined", name);
6346 sym = &((Elf32_Sym *)symtab_section->data)[sym_index];
6347 return sym->st_value;
6350 /* add an elf symbol : check if it is already defined and patch
6351 it. Return symbol index. NOTE that sh_num can be SHN_UNDEF. */
6352 static int add_elf_sym(Section *s, unsigned long value, unsigned long size,
6353 int info, int sh_num, const char *name)
6355 Elf32_Sym *esym;
6356 int sym_bind, sym_index, sym_type, esym_bind;
6358 sym_bind = ELF32_ST_BIND(info);
6359 sym_type = ELF32_ST_TYPE(info);
6361 if (sym_bind != STB_LOCAL) {
6362 /* we search global or weak symbols */
6363 sym_index = find_elf_sym(s, name);
6364 if (!sym_index)
6365 goto do_def;
6366 esym = &((Elf32_Sym *)s->data)[sym_index];
6367 if (esym->st_shndx != SHN_UNDEF) {
6368 esym_bind = ELF32_ST_BIND(esym->st_info);
6369 if (sh_num == SHN_UNDEF) {
6370 /* ignore adding of undefined symbol if the
6371 corresponding symbol is already defined */
6372 } else if (sym_bind == STB_GLOBAL && esym_bind == STB_WEAK) {
6373 /* global overrides weak, so patch */
6374 goto do_patch;
6375 } else if (sym_bind == STB_WEAK && esym_bind == STB_GLOBAL) {
6376 /* weak is ignored if already global */
6377 } else {
6378 #if 0
6379 printf("new_bind=%d new_shndx=%d last_bind=%d old_shndx=%d\n",
6380 sym_bind, sh_num, esym_bind, esym->st_shndx);
6381 #endif
6382 /* NOTE: we accept that two DLL define the same symbol */
6383 if (s != dynsymtab_section)
6384 error("'%s' defined twice", name);
6386 } else {
6387 do_patch:
6388 esym->st_info = ELF32_ST_INFO(sym_bind, sym_type);
6389 esym->st_shndx = sh_num;
6390 esym->st_value = value;
6391 esym->st_size = size;
6393 } else {
6394 do_def:
6395 sym_index = put_elf_sym(s, value, size,
6396 ELF32_ST_INFO(sym_bind, sym_type), 0,
6397 sh_num, name);
6399 return sym_index;
6402 /* update sym->c so that it points to an external symbol in section
6403 'section' with value 'value' */
6404 void put_extern_sym(Sym *sym, Section *section, unsigned long value)
6406 int sym_type, sym_bind, sh_num, info;
6407 Elf32_Sym *esym;
6408 const char *name;
6409 char buf[32];
6411 if (section)
6412 sh_num = section->sh_num;
6413 else
6414 sh_num = SHN_UNDEF;
6415 if (!sym->c) {
6416 if ((sym->t & VT_BTYPE) == VT_FUNC)
6417 sym_type = STT_FUNC;
6418 else
6419 sym_type = STT_OBJECT;
6420 if (sym->t & VT_STATIC)
6421 sym_bind = STB_LOCAL;
6422 else
6423 sym_bind = STB_GLOBAL;
6425 name = get_tok_str(sym->v, NULL);
6426 #ifdef CONFIG_TCC_BCHECK
6427 if (do_bounds_check) {
6428 /* if bound checking is activated, we change some function
6429 names by adding the "__bound" prefix */
6430 switch(sym->v) {
6431 case TOK_malloc:
6432 case TOK_free:
6433 case TOK_realloc:
6434 case TOK_memalign:
6435 case TOK_calloc:
6436 case TOK_memcpy:
6437 case TOK_memmove:
6438 case TOK_memset:
6439 case TOK_strlen:
6440 case TOK_strcpy:
6441 strcpy(buf, "__bound_");
6442 strcat(buf, name);
6443 name = buf;
6444 break;
6447 #endif
6448 info = ELF32_ST_INFO(sym_bind, sym_type);
6449 sym->c = add_elf_sym(symtab_section, value, 0, info, sh_num, name);
6450 } else {
6451 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
6452 esym->st_value = value;
6453 esym->st_shndx = sh_num;
6457 /* put relocation */
6458 static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
6459 int type, int symbol)
6461 char buf[256];
6462 Section *sr;
6463 Elf32_Rel *rel;
6465 sr = s->reloc;
6466 if (!sr) {
6467 /* if no relocation section, create it */
6468 snprintf(buf, sizeof(buf), ".rel%s", s->name);
6469 /* if the symtab is allocated, then we consider the relocation
6470 are also */
6471 sr = new_section(buf, SHT_REL, symtab->sh_flags);
6472 sr->sh_entsize = sizeof(Elf32_Rel);
6473 sr->link = symtab;
6474 sr->sh_info = s->sh_num;
6475 s->reloc = sr;
6477 rel = (Elf32_Rel *)sr->data_ptr;
6478 /* XXX: endianness */
6479 rel->r_offset = offset;
6480 rel->r_info = ELF32_R_INFO(symbol, type);
6481 sr->data_ptr += sizeof(Elf32_Rel);
6484 /* put stab debug information */
6486 typedef struct {
6487 unsigned long n_strx; /* index into string table of name */
6488 unsigned char n_type; /* type of symbol */
6489 unsigned char n_other; /* misc info (usually empty) */
6490 unsigned short n_desc; /* description field */
6491 unsigned long n_value; /* value of symbol */
6492 } Stab_Sym;
6494 static void put_stabs(const char *str, int type, int other, int desc, int value)
6496 Stab_Sym *sym;
6498 sym = (Stab_Sym *)stab_section->data_ptr;
6499 if (str) {
6500 sym->n_strx = put_elf_str(stabstr_section, str);
6501 } else {
6502 sym->n_strx = 0;
6504 sym->n_type = type;
6505 sym->n_other = other;
6506 sym->n_desc = desc;
6507 sym->n_value = value;
6509 stab_section->data_ptr += sizeof(Stab_Sym);
6512 static void put_stabn(int type, int other, int desc, int value)
6514 put_stabs(NULL, type, other, desc, value);
6517 static void put_stabd(int type, int other, int desc)
6519 put_stabs(NULL, type, other, desc, 0);
6522 /* In an ELF file symbol table, the local symbols must appear below
6523 the global and weak ones. Since TCC cannot sort it while generating
6524 the code, we must do it after. All the relocation tables are also
6525 modified to take into account the symbol table sorting */
6526 static void sort_syms(Section *s)
6528 int *old_to_new_syms;
6529 Elf32_Sym *new_syms;
6530 int nb_syms, i;
6531 Elf32_Sym *p, *q;
6532 Elf32_Rel *rel;
6533 Section *sr;
6534 int type, sym_index;
6536 nb_syms = (s->data_ptr - s->data) / sizeof(Elf32_Sym);
6537 new_syms = malloc(nb_syms * sizeof(Elf32_Sym));
6538 if (!new_syms)
6539 error("memory full");
6540 old_to_new_syms = malloc(nb_syms * sizeof(int));
6541 if (!old_to_new_syms)
6542 error("memory full");
6543 /* first pass for local symbols */
6544 p = (Elf32_Sym *)s->data;
6545 q = new_syms;
6546 for(i = 0; i < nb_syms; i++) {
6547 if (ELF32_ST_BIND(p->st_info) == STB_LOCAL) {
6548 old_to_new_syms[i] = q - new_syms;
6549 *q++ = *p;
6551 p++;
6553 /* save the number of local symbols in section header */
6554 s->sh_info = q - new_syms;
6556 /* then second pass for non local symbols */
6557 p = (Elf32_Sym *)s->data;
6558 for(i = 0; i < nb_syms; i++) {
6559 if (ELF32_ST_BIND(p->st_info) != STB_LOCAL) {
6560 old_to_new_syms[i] = q - new_syms;
6561 *q++ = *p;
6563 p++;
6566 /* we copy the new symbols to the old */
6567 memcpy(s->data, new_syms, nb_syms * sizeof(Elf32_Sym));
6568 free(new_syms);
6570 /* now we modify all the relocations */
6571 for(i = 1; i < nb_sections; i++) {
6572 sr = sections[i];
6573 if (sr->sh_type == SHT_REL && sr->link == s) {
6574 for(rel = (Elf32_Rel *)sr->data;
6575 rel < (Elf32_Rel *)sr->data_ptr;
6576 rel++) {
6577 sym_index = ELF32_R_SYM(rel->r_info);
6578 type = ELF32_R_TYPE(rel->r_info);
6579 sym_index = old_to_new_syms[sym_index];
6580 rel->r_info = ELF32_R_INFO(sym_index, type);
6585 free(old_to_new_syms);
6588 /* relocate common symbols in the .bss section */
6589 static void relocate_common_syms(void)
6591 Elf32_Sym *sym;
6592 unsigned long offset, align;
6594 for(sym = (Elf32_Sym *)symtab_section->data + 1;
6595 sym < (Elf32_Sym *)symtab_section->data_ptr;
6596 sym++) {
6597 if (sym->st_shndx == SHN_COMMON) {
6598 /* align symbol */
6599 align = sym->st_value;
6600 offset = bss_section->data_ptr - bss_section->data;
6601 offset = (offset + align - 1) & -align;
6602 sym->st_value = offset;
6603 sym->st_shndx = bss_section->sh_num;
6604 offset += sym->st_size;
6605 bss_section->data_ptr = bss_section->data + offset;
6610 static void *resolve_sym(const char *sym)
6612 return dlsym(NULL, sym);
6615 /* relocate symbol table, resolve undefined symbols if do_resolve is
6616 true and output error if undefined symbol. */
6617 static void relocate_syms(int do_resolve)
6619 Elf32_Sym *sym, *esym;
6620 int sym_bind, sh_num, sym_index;
6621 const char *name;
6622 unsigned long addr;
6624 for(sym = (Elf32_Sym *)symtab_section->data + 1;
6625 sym < (Elf32_Sym *)symtab_section->data_ptr;
6626 sym++) {
6627 sh_num = sym->st_shndx;
6628 if (sh_num == SHN_UNDEF) {
6629 name = strtab_section->data + sym->st_name;
6630 if (do_resolve) {
6631 name = symtab_section->link->data + sym->st_name;
6632 addr = (unsigned long)resolve_sym(name);
6633 if (addr) {
6634 sym->st_value = addr;
6635 goto found;
6637 } else if (dynsym) {
6638 /* if dynamic symbol exist, then use it */
6639 sym_index = find_elf_sym(dynsym, name);
6640 if (sym_index) {
6641 esym = &((Elf32_Sym *)dynsym->data)[sym_index];
6642 sym->st_value = esym->st_value;
6643 goto found;
6646 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
6647 it */
6648 if (!strcmp(name, "_fp_hw"))
6649 goto found;
6650 /* only weak symbols are accepted to be undefined. Their
6651 value is zero */
6652 sym_bind = ELF32_ST_BIND(sym->st_info);
6653 if (sym_bind == STB_WEAK) {
6654 sym->st_value = 0;
6655 } else {
6656 error("undefined symbol '%s'", name);
6658 } else if (sh_num < SHN_LORESERVE) {
6659 /* add section base */
6660 sym->st_value += sections[sym->st_shndx]->sh_addr;
6662 found: ;
6666 /* elf relocation, CPU dependant */
6667 static void elf_reloc(unsigned char *ptr,
6668 unsigned long addr, unsigned long val, int type,
6669 int sym_index)
6671 switch(type) {
6672 case R_386_32:
6673 *(int *)ptr += val;
6674 break;
6675 case R_386_PLT32:
6676 case R_386_PC32:
6677 *(int *)ptr += val - addr;
6678 break;
6679 case R_386_GLOB_DAT:
6680 case R_386_JMP_SLOT:
6681 *(int *)ptr = val;
6682 break;
6683 case R_386_GOTPC:
6684 *(int *)ptr += got->sh_addr - addr;
6685 break;
6686 case R_386_GOTOFF:
6687 *(int *)ptr += val - got->sh_addr;
6688 break;
6689 case R_386_GOT32:
6690 /* we load the got offset */
6691 *(int *)ptr += got_offsets[sym_index];
6692 break;
6697 /* relocate a given section */
6698 static void relocate_section(Section *s)
6700 Section *sr;
6701 Elf32_Rel *rel;
6702 Elf32_Sym *sym;
6703 int type, sym_index;
6704 unsigned char *ptr;
6705 unsigned long val;
6707 sr = s->reloc;
6708 for(rel = (Elf32_Rel *)sr->data;
6709 rel < (Elf32_Rel *)sr->data_ptr;
6710 rel++) {
6711 ptr = s->data + rel->r_offset;
6713 sym_index = ELF32_R_SYM(rel->r_info);
6714 sym = &((Elf32_Sym *)symtab_section->data)[sym_index];
6715 val = sym->st_value;
6716 type = ELF32_R_TYPE(rel->r_info);
6717 elf_reloc(ptr, s->sh_addr + rel->r_offset, val, type, sym_index);
6721 /* relocate relocation table in 'sr' */
6722 static void relocate_rel(Section *sr)
6724 Section *s;
6725 Elf32_Rel *rel;
6727 s = sections[sr->sh_info];
6728 for(rel = (Elf32_Rel *)sr->data;
6729 rel < (Elf32_Rel *)sr->data_ptr;
6730 rel++) {
6731 rel->r_offset += s->sh_addr;
6735 static void put_got_offset(int index, unsigned long val)
6737 int n;
6738 unsigned long *tab;
6740 if (index >= nb_got_offsets) {
6741 /* find immediately bigger power of 2 and reallocate array */
6742 n = 1;
6743 while (index >= n)
6744 n *= 2;
6745 tab = realloc(got_offsets, n * sizeof(unsigned long));
6746 if (!tab)
6747 error("memory full");
6748 got_offsets = tab;
6749 memset(got_offsets + nb_got_offsets, 0,
6750 (n - nb_got_offsets) * sizeof(unsigned long));
6751 nb_got_offsets = n;
6753 got_offsets[index] = val;
6756 /* XXX: suppress that */
6757 static void put32(unsigned char *p, unsigned int val)
6759 p[0] = val;
6760 p[1] = val >> 8;
6761 p[2] = val >> 16;
6762 p[3] = val >> 24;
6765 static void build_got(void)
6767 /* if no got, then create it */
6768 got = new_section(".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
6769 got->sh_entsize = 4;
6770 add_elf_sym(symtab_section, 0, 4, ELF32_ST_INFO(STB_GLOBAL, STT_OBJECT),
6771 got->sh_num, "_GLOBAL_OFFSET_TABLE_");
6772 /* keep space for _DYNAMIC pointer, if present */
6773 got->data_ptr += 4;
6775 /* two dummy got entries */
6776 put32(got->data_ptr, 0);
6777 got->data_ptr += 4;
6778 put32(got->data_ptr, 0);
6779 got->data_ptr += 4;
6782 /* put a got entry corresponding to a symbol in symtab_section. 'size'
6783 and 'info' can be modifed if more precise info comes from the DLL */
6784 static void put_got_entry(int reloc_type, unsigned long size, int info,
6785 int sym_index)
6787 int index;
6788 const char *name;
6789 Elf32_Sym *sym;
6790 unsigned long offset;
6792 if (!got)
6793 build_got();
6795 /* if a got entry already exists for that symbol, no need to add one */
6796 if (sym_index < nb_got_offsets &&
6797 got_offsets[sym_index] != 0)
6798 return;
6800 put_got_offset(sym_index, got->data_ptr - got->data);
6802 if (dynsym) {
6803 sym = &((Elf32_Sym *)symtab_section->data)[sym_index];
6804 name = symtab_section->link->data + sym->st_name;
6805 offset = sym->st_value;
6806 /* NOTE: we put temporarily the got offset */
6807 if (reloc_type == R_386_JMP_SLOT) {
6808 nb_plt_entries++;
6809 offset = got->data_ptr - got->data;
6811 index = put_elf_sym(dynsym, offset,
6812 size, info, 0, sym->st_shndx, name);
6813 /* put a got entry */
6814 put_elf_reloc(dynsym, got,
6815 got->data_ptr - got->data,
6816 reloc_type, index);
6818 put32(got->data_ptr, 0);
6819 got->data_ptr += 4;
6822 /* build GOT and PLT entries */
6823 static void build_got_entries(void)
6825 Section *s, *symtab;
6826 Elf32_Rel *rel;
6827 Elf32_Sym *sym;
6828 int i, type, reloc_type, sym_index;
6830 for(i = 1; i < nb_sections; i++) {
6831 s = sections[i];
6832 if (s->sh_type != SHT_REL)
6833 continue;
6834 /* no need to handle got relocations */
6835 if (s->link != symtab_section)
6836 continue;
6837 symtab = s->link;
6838 for(rel = (Elf32_Rel *)s->data;
6839 rel < (Elf32_Rel *)s->data_ptr;
6840 rel++) {
6841 type = ELF32_R_TYPE(rel->r_info);
6842 switch(type) {
6843 case R_386_GOT32:
6844 case R_386_GOTOFF:
6845 case R_386_GOTPC:
6846 case R_386_PLT32:
6847 if (!got)
6848 build_got();
6849 if (type == R_386_GOT32 || type == R_386_PLT32) {
6850 sym_index = ELF32_R_SYM(rel->r_info);
6851 sym = &((Elf32_Sym *)symtab_section->data)[sym_index];
6852 /* look at the symbol got offset. If none, then add one */
6853 if (type == R_386_GOT32)
6854 reloc_type = R_386_GLOB_DAT;
6855 else
6856 reloc_type = R_386_JMP_SLOT;
6857 put_got_entry(reloc_type, sym->st_size, sym->st_info,
6858 sym_index);
6860 break;
6861 default:
6862 break;
6868 static Section *new_section_hash(const char *name, int sh_flags,
6869 int nb_buckets, Section *symtab)
6871 Section *hash;
6872 hash = new_section(name, SHT_HASH, sh_flags);
6873 ((int *)hash->data)[0] = nb_buckets;
6874 ((int *)hash->data)[1] = 1;
6875 hash->sh_entsize = sizeof(int);
6876 hash->data_ptr += (2 + nb_buckets + 1) * sizeof(int);
6877 symtab->hash = hash;
6878 hash->link = symtab;
6879 return hash;
6882 /* put dynamic tag */
6883 static void put_dt(Section *dynamic, int dt, unsigned long val)
6885 Elf32_Dyn *dyn;
6886 dyn = (Elf32_Dyn *)dynamic->data_ptr;
6887 dyn->d_tag = dt;
6888 dyn->d_un.d_val = val;
6889 dynamic->data_ptr += sizeof(Elf32_Dyn);
6892 /* add tcc runtime libraries */
6893 static void tcc_add_runtime(TCCState *s1)
6895 char buf[1024];
6897 snprintf(buf, sizeof(buf), "%s/%s", tcc_lib_path, "libtcc1.o");
6898 tcc_add_file(s1, buf);
6899 #ifdef CONFIG_TCC_BCHECK
6900 if (do_bounds_check) {
6901 /* XXX: add an object file to do that */
6902 *(int *)bounds_section->data_ptr = 0;
6903 bounds_section->data_ptr += sizeof(int);
6904 add_elf_sym(symtab_section, 0, 0,
6905 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE),
6906 bounds_section->sh_num, "__bounds_start");
6907 add_elf_sym(symtab_section, (long)&rt_error, 0,
6908 ELF32_ST_INFO(STB_GLOBAL, STT_FUNC),
6909 SHN_ABS, "rt_error");
6910 /* add bound check code */
6911 snprintf(buf, sizeof(buf), "%s/%s", tcc_lib_path, "bcheck.o");
6912 tcc_add_file(s1, buf);
6914 #endif
6915 /* add libc if not memory output */
6916 if (s1->output_type != TCC_OUTPUT_MEMORY) {
6917 tcc_add_library(s1, "c");
6918 tcc_add_file(s1, CONFIG_TCC_CRT_PREFIX "/crtn.o");
6920 /* add various standard linker symbols */
6921 add_elf_sym(symtab_section,
6922 text_section->data_ptr - text_section->data, 0,
6923 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE),
6924 text_section->sh_num, "_etext");
6925 add_elf_sym(symtab_section,
6926 data_section->data_ptr - data_section->data, 0,
6927 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE),
6928 data_section->sh_num, "_edata");
6929 add_elf_sym(symtab_section,
6930 bss_section->data_ptr - bss_section->data, 0,
6931 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE),
6932 bss_section->sh_num, "_end");
6935 /* add dynamic sections so that the executable is dynamically linked */
6936 static char elf_interp[] = "/lib/ld-linux.so.2";
6938 #define ELF_START_ADDR 0x08048000
6939 #define ELF_PAGE_SIZE 0x1000
6941 /* output an ELF file */
6942 /* XXX: handle realloc'ed sections (instead of mmaping them) */
6943 /* XXX: suppress unneeded sections */
6944 int tcc_output_file(TCCState *s1, const char *filename)
6946 Elf32_Ehdr ehdr;
6947 FILE *f;
6948 int fd, mode;
6949 int *section_order;
6950 int shnum, i, phnum, file_offset, offset, size, j, tmp, sh_order_index, k;
6951 unsigned long addr;
6952 Section *strsec, *s;
6953 Elf32_Shdr shdr, *sh;
6954 Elf32_Phdr *phdr, *ph;
6955 Section *interp, *plt, *dynamic, *dynstr, *hash;
6956 unsigned char *saved_dynamic_data_ptr;
6957 Elf32_Sym *sym;
6958 int type, file_type;
6959 unsigned long rel_addr, rel_size;
6961 file_type = s1->output_type;
6963 if (file_type != TCC_OUTPUT_OBJ)
6964 tcc_add_runtime(s1);
6966 interp = NULL;
6967 dynamic = NULL;
6968 dynsym = NULL;
6969 got = NULL;
6970 nb_plt_entries = 0;
6971 plt = NULL; /* avoid warning */
6972 hash = NULL; /* avoid warning */
6973 dynstr = NULL; /* avoid warning */
6974 saved_dynamic_data_ptr = NULL; /* avoid warning */
6976 if (file_type != TCC_OUTPUT_OBJ) {
6978 relocate_common_syms();
6980 if (!static_link) {
6981 const char *name;
6982 int sym_index, index;
6983 Elf32_Sym *esym;
6985 if (file_type == TCC_OUTPUT_EXE) {
6986 /* add interpreter section only if executable */
6987 interp = new_section(".interp", SHT_PROGBITS, SHF_ALLOC);
6988 interp->sh_addralign = 1;
6989 strcpy(interp->data_ptr, elf_interp);
6990 interp->data_ptr += sizeof(elf_interp);
6993 /* add dynamic symbol table */
6994 dynsym = new_section(".dynsym", SHT_DYNSYM, SHF_ALLOC);
6995 dynsym->sh_entsize = sizeof(Elf32_Sym);
6996 dynstr = new_section(".dynstr", SHT_STRTAB, SHF_ALLOC);
6997 put_elf_str(dynstr, "");
6998 dynsym->link = dynstr;
6999 put_elf_sym(dynsym, 0, 0, 0, 0, 0, NULL);
7001 /* hash table */
7002 hash = new_section_hash(".hash", SHF_ALLOC,
7003 ELF_DYNSYM_HASH_SIZE, dynsym);
7005 /* add dynamic section */
7006 dynamic = new_section(".dynamic", SHT_DYNAMIC,
7007 SHF_ALLOC | SHF_WRITE);
7008 dynamic->link = dynstr;
7009 dynamic->sh_entsize = sizeof(Elf32_Dyn);
7011 /* add PLT */
7012 plt = new_section(".plt", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
7013 plt->sh_entsize = 4;
7015 /* scan for undefined symbols and see if they are in the
7016 dynamic symbols. If a symbol STT_FUNC is found, then we
7017 add it in the PLT. If a symbol STT_OBJECT is found, we
7018 add it in the .bss section with a suitable relocation */
7019 for(sym = (Elf32_Sym *)symtab_section->data + 1;
7020 sym < (Elf32_Sym *)symtab_section->data_ptr;
7021 sym++) {
7022 if (sym->st_shndx == SHN_UNDEF) {
7023 name = symtab_section->link->data + sym->st_name;
7024 sym_index = find_elf_sym(dynsymtab_section, name);
7025 if (sym_index) {
7026 esym = &((Elf32_Sym *)dynsymtab_section->data)[sym_index];
7027 type = ELF32_ST_TYPE(esym->st_info);
7028 if (type == STT_FUNC) {
7029 put_got_entry(R_386_JMP_SLOT, esym->st_size,
7030 esym->st_info,
7031 sym - (Elf32_Sym *)symtab_section->data);
7032 } else if (type == STT_OBJECT) {
7033 unsigned long offset;
7034 offset = bss_section->data_ptr - bss_section->data;
7035 /* XXX: which alignment ? */
7036 offset = (offset + 8 - 1) & -8;
7037 index = put_elf_sym(dynsym, offset, esym->st_size,
7038 esym->st_info, 0,
7039 bss_section->sh_num, name);
7040 put_elf_reloc(dynsym, bss_section,
7041 offset, R_386_COPY, index);
7042 offset += esym->st_size;
7043 bss_section->data_ptr = bss_section->data + offset;
7045 } else {
7046 /* STT_NOTYPE or STB_WEAK undefined symbols
7047 are accepted */
7048 /* XXX: STT_NOTYPE is only used to exclude the
7049 unreferenced '_fp_hw' symbol. need a better
7050 solution */
7051 if (ELF32_ST_TYPE(sym->st_info) == STT_NOTYPE ||
7052 ELF32_ST_BIND(sym->st_info) == STB_WEAK) {
7053 } else {
7054 error("undefined symbol '%s'", name);
7060 /* now look at unresolved dynamic symbols and export
7061 corresponding symbol */
7062 for(sym = (Elf32_Sym *)dynsymtab_section->data + 1;
7063 sym < (Elf32_Sym *)dynsymtab_section->data_ptr;
7064 sym++) {
7065 if (sym->st_shndx == SHN_UNDEF) {
7066 name = dynsymtab_section->link->data + sym->st_name;
7067 sym_index = find_elf_sym(symtab_section, name);
7068 if (sym_index) {
7069 } else {
7070 if (ELF32_ST_BIND(sym->st_info) == STB_WEAK) {
7071 /* weak symbols can stay undefined */
7072 } else {
7073 warning("undefined dynamic symbol '%s'", name);
7079 build_got_entries();
7081 /* update PLT/GOT sizes so that we can allocate their space */
7082 plt->data_ptr += 16 * (nb_plt_entries + 1);
7084 /* add a list of needed dlls */
7085 for(i = 0; i < nb_loaded_dlls; i++) {
7086 DLLReference *dllref = loaded_dlls[i];
7087 if (dllref->level == 0)
7088 put_dt(dynamic, DT_NEEDED, put_elf_str(dynstr, dllref->name));
7091 /* add necessary space for other entries */
7092 saved_dynamic_data_ptr = dynamic->data_ptr;
7093 dynamic->data_ptr += 8 * 9;
7094 } else {
7095 /* still need to build got entries in case of static link */
7096 build_got_entries();
7100 memset(&ehdr, 0, sizeof(ehdr));
7102 /* we add a section for symbols */
7103 strsec = new_section(".shstrtab", SHT_STRTAB, 0);
7104 put_elf_str(strsec, "");
7106 /* compute number of sections */
7107 shnum = nb_sections;
7109 /* this array is used to reorder sections in the output file */
7110 section_order = malloc(sizeof(int) * shnum);
7111 if (!section_order)
7112 error("memory full");
7113 section_order[0] = 0;
7114 sh_order_index = 1;
7116 /* compute number of program headers */
7117 switch(file_type) {
7118 default:
7119 case TCC_OUTPUT_OBJ:
7120 phnum = 0;
7121 break;
7122 case TCC_OUTPUT_EXE:
7123 if (!static_link)
7124 phnum = 4;
7125 else
7126 phnum = 2;
7127 break;
7128 case TCC_OUTPUT_DLL:
7129 phnum = 3;
7130 break;
7133 /* allocate strings for section names */
7134 for(i = 1; i < nb_sections; i++) {
7135 s = sections[i];
7136 s->sh_name = put_elf_str(strsec, s->name);
7137 s->sh_size = s->data_ptr - s->data;
7140 /* allocate program segment headers */
7141 phdr = malloc(phnum * sizeof(Elf32_Phdr));
7142 if (!phdr)
7143 error("memory full");
7144 memset(phdr, 0, phnum * sizeof(Elf32_Phdr));
7146 file_offset = sizeof(Elf32_Ehdr) + phnum * sizeof(Elf32_Phdr);
7147 if (phnum > 0) {
7148 /* compute section to program header mapping */
7149 if (file_type == TCC_OUTPUT_DLL)
7150 addr = 0;
7151 else
7152 addr = ELF_START_ADDR;
7154 /* dynamic relocation table information, for .dynamic section */
7155 rel_size = 0;
7156 rel_addr = 0;
7158 /* compute address after headers */
7159 addr += (file_offset & (ELF_PAGE_SIZE - 1));
7161 /* leave one program header for the program interpreter */
7162 ph = &phdr[0];
7163 if (interp)
7164 ph++;
7166 for(j = 0; j < 2; j++) {
7167 ph->p_type = PT_LOAD;
7168 if (j == 0)
7169 ph->p_flags = PF_R | PF_X;
7170 else
7171 ph->p_flags = PF_R | PF_W;
7172 ph->p_align = ELF_PAGE_SIZE;
7174 /* we do the following ordering: interp, symbol tables,
7175 relocations, progbits, nobits */
7176 /* XXX: do faster and simpler sorting */
7177 for(k = 0; k < 5; k++) {
7178 for(i = 1; i < nb_sections; i++) {
7179 s = sections[i];
7180 /* compute if section should be included */
7181 if (j == 0) {
7182 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
7183 SHF_ALLOC)
7184 continue;
7185 } else {
7186 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
7187 (SHF_ALLOC | SHF_WRITE))
7188 continue;
7190 if (s == interp) {
7191 if (k != 0)
7192 continue;
7193 } else if (s->sh_type == SHT_DYNSYM ||
7194 s->sh_type == SHT_STRTAB ||
7195 s->sh_type == SHT_HASH) {
7196 if (k != 1)
7197 continue;
7198 } else if (s->sh_type == SHT_REL) {
7199 if (k != 2)
7200 continue;
7201 } else if (s->sh_type == SHT_NOBITS) {
7202 if (k != 4)
7203 continue;
7204 } else {
7205 if (k != 3)
7206 continue;
7208 section_order[sh_order_index++] = i;
7210 /* section matches: we align it and add its size */
7211 tmp = file_offset;
7212 file_offset = (file_offset + s->sh_addralign - 1) &
7213 ~(s->sh_addralign - 1);
7214 s->sh_offset = file_offset;
7215 addr += file_offset - tmp;
7216 s->sh_addr = addr;
7218 /* update program header infos */
7219 if (ph->p_offset == 0) {
7220 ph->p_offset = file_offset;
7221 ph->p_vaddr = addr;
7222 ph->p_paddr = ph->p_vaddr;
7224 /* update dynamic relocation infos */
7225 if (s->sh_type == SHT_REL) {
7226 if (rel_size == 0)
7227 rel_addr = addr;
7228 rel_size += s->sh_size;
7230 addr += s->sh_size;
7231 if (s->sh_type != SHT_NOBITS)
7232 file_offset += s->sh_size;
7235 ph->p_filesz = file_offset - ph->p_offset;
7236 ph->p_memsz = addr - ph->p_vaddr;
7237 ph++;
7240 /* if interpreter, then add corresponing program header */
7241 if (interp) {
7242 ph = &phdr[0];
7244 ph->p_type = PT_INTERP;
7245 ph->p_offset = interp->sh_offset;
7246 ph->p_vaddr = interp->sh_addr;
7247 ph->p_paddr = ph->p_vaddr;
7248 ph->p_filesz = interp->sh_size;
7249 ph->p_memsz = interp->sh_size;
7250 ph->p_flags = PF_R;
7251 ph->p_align = interp->sh_addralign;
7254 /* if dynamic section, then add corresponing program header */
7255 if (dynamic) {
7256 int plt_offset;
7257 unsigned char *p;
7259 ph = &phdr[phnum - 1];
7261 ph->p_type = PT_DYNAMIC;
7262 ph->p_offset = dynamic->sh_offset;
7263 ph->p_vaddr = dynamic->sh_addr;
7264 ph->p_paddr = ph->p_vaddr;
7265 ph->p_filesz = dynamic->sh_size;
7266 ph->p_memsz = dynamic->sh_size;
7267 ph->p_flags = PF_R | PF_W;
7268 ph->p_align = dynamic->sh_addralign;
7270 /* put GOT dynamic section address */
7271 put32(got->data, dynamic->sh_addr);
7273 /* compute the PLT */
7274 plt->data_ptr = plt->data;
7276 /* first plt entry */
7277 p = plt->data_ptr;
7278 p[0] = 0xff; /* pushl got + 4 */
7279 p[1] = 0x35;
7280 put32(p + 2, got->sh_addr + 4);
7281 p[6] = 0xff; /* jmp *(got + 8) */
7282 p[7] = 0x25;
7283 put32(p + 8, got->sh_addr + 8);
7284 plt->data_ptr += 16;
7286 /* relocation symbols in .dynsym and build PLT. */
7287 plt_offset = 0;
7288 for(sym = (Elf32_Sym *)dynsym->data + 1;
7289 sym < (Elf32_Sym *)dynsym->data_ptr;
7290 sym++) {
7291 type = ELF32_ST_TYPE(sym->st_info);
7292 if (sym->st_shndx == SHN_UNDEF) {
7293 if (type == STT_FUNC) {
7294 /* one more entry in PLT */
7295 p = plt->data_ptr;
7296 p[0] = 0xff; /* jmp *(got + x) */
7297 p[1] = 0x25;
7298 put32(p + 2, got->sh_addr + sym->st_value);
7299 p[6] = 0x68; /* push $xxx */
7300 put32(p + 7, plt_offset);
7301 p[11] = 0xe9; /* jmp plt_start */
7302 put32(p + 12, -(plt->data_ptr + 16 - plt->data));
7304 /* patch symbol value to point to plt */
7305 sym->st_value = plt->sh_addr + p - plt->data;
7307 plt_offset += 8;
7308 plt->data_ptr += 16;
7310 } else if (sym->st_shndx < SHN_LORESERVE) {
7311 /* do symbol relocation */
7312 sym->st_value += sections[sym->st_shndx]->sh_addr;
7315 /* put dynamic section entries */
7317 dynamic->data_ptr = saved_dynamic_data_ptr;
7318 put_dt(dynamic, DT_HASH, hash->sh_addr);
7319 put_dt(dynamic, DT_STRTAB, dynstr->sh_addr);
7320 put_dt(dynamic, DT_SYMTAB, dynsym->sh_addr);
7321 put_dt(dynamic, DT_STRSZ, dynstr->data_ptr - dynstr->data);
7322 put_dt(dynamic, DT_SYMENT, sizeof(Elf32_Sym));
7323 put_dt(dynamic, DT_REL, rel_addr);
7324 put_dt(dynamic, DT_RELSZ, rel_size);
7325 put_dt(dynamic, DT_RELENT, sizeof(Elf32_Rel));
7326 put_dt(dynamic, DT_NULL, 0);
7329 ehdr.e_phentsize = sizeof(Elf32_Phdr);
7330 ehdr.e_phnum = phnum;
7331 ehdr.e_phoff = sizeof(Elf32_Ehdr);
7334 /* all other sections come after */
7335 for(i = 1; i < nb_sections; i++) {
7336 s = sections[i];
7337 if (phnum > 0 && (s->sh_flags & SHF_ALLOC))
7338 continue;
7339 section_order[sh_order_index++] = i;
7341 file_offset = (file_offset + s->sh_addralign - 1) &
7342 ~(s->sh_addralign - 1);
7343 s->sh_offset = file_offset;
7344 if (s->sh_type != SHT_NOBITS)
7345 file_offset += s->sh_size;
7348 /* if building executable or DLL, then relocate each section
7349 except the GOT which is already relocated */
7350 if (file_type != TCC_OUTPUT_OBJ) {
7351 relocate_syms(0);
7353 /* relocate sections */
7354 /* XXX: ignore sections with allocated relocations ? */
7355 for(i = 1; i < nb_sections; i++) {
7356 s = sections[i];
7357 if ((s->sh_flags & SHF_ALLOC)
7358 && s->reloc && s != got)
7359 relocate_section(s);
7362 /* relocate relocation entries */
7363 for(i = 1; i < nb_sections; i++) {
7364 s = sections[i];
7365 if ((s->sh_flags & SHF_ALLOC) &&
7366 s->sh_type == SHT_REL) {
7367 relocate_rel(s);
7371 /* get entry point address */
7372 ehdr.e_entry = get_elf_sym_val("_start");
7375 sort_syms(symtab_section);
7377 /* align to 4 */
7378 file_offset = (file_offset + 3) & -4;
7380 /* fill header */
7381 ehdr.e_ident[0] = ELFMAG0;
7382 ehdr.e_ident[1] = ELFMAG1;
7383 ehdr.e_ident[2] = ELFMAG2;
7384 ehdr.e_ident[3] = ELFMAG3;
7385 ehdr.e_ident[4] = ELFCLASS32;
7386 ehdr.e_ident[5] = ELFDATA2LSB;
7387 ehdr.e_ident[6] = EV_CURRENT;
7388 switch(file_type) {
7389 default:
7390 case TCC_OUTPUT_EXE:
7391 ehdr.e_type = ET_EXEC;
7392 break;
7393 case TCC_OUTPUT_DLL:
7394 ehdr.e_type = ET_DYN;
7395 break;
7396 case TCC_OUTPUT_OBJ:
7397 ehdr.e_type = ET_REL;
7398 break;
7400 ehdr.e_machine = EM_386;
7401 ehdr.e_version = EV_CURRENT;
7402 ehdr.e_shoff = file_offset;
7403 ehdr.e_ehsize = sizeof(Elf32_Ehdr);
7404 ehdr.e_shentsize = sizeof(Elf32_Shdr);
7405 ehdr.e_shnum = shnum;
7406 ehdr.e_shstrndx = shnum - 1;
7408 /* write elf file */
7409 if (file_type == TCC_OUTPUT_OBJ)
7410 mode = 0666;
7411 else
7412 mode = 0777;
7413 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, mode);
7414 if (fd < 0)
7415 error("could not write '%s'", filename);
7417 f = fdopen(fd, "w");
7418 fwrite(&ehdr, 1, sizeof(Elf32_Ehdr), f);
7419 fwrite(phdr, 1, phnum * sizeof(Elf32_Phdr), f);
7420 offset = sizeof(Elf32_Ehdr) + phnum * sizeof(Elf32_Phdr);
7421 for(i=1;i<nb_sections;i++) {
7422 s = sections[section_order[i]];
7423 if (s->sh_type != SHT_NOBITS) {
7424 while (offset < s->sh_offset) {
7425 fputc(0, f);
7426 offset++;
7428 size = s->data_ptr - s->data;
7429 fwrite(s->data, 1, size, f);
7430 offset += size;
7433 while (offset < ehdr.e_shoff) {
7434 fputc(0, f);
7435 offset++;
7438 /* output section headers */
7439 for(i=0;i<nb_sections;i++) {
7440 sh = &shdr;
7441 memset(sh, 0, sizeof(Elf32_Shdr));
7442 s = sections[i];
7443 if (s) {
7444 sh->sh_name = s->sh_name;
7445 sh->sh_type = s->sh_type;
7446 sh->sh_flags = s->sh_flags;
7447 sh->sh_entsize = s->sh_entsize;
7448 sh->sh_info = s->sh_info;
7449 if (s->link)
7450 sh->sh_link = s->link->sh_num;
7451 sh->sh_addralign = s->sh_addralign;
7452 sh->sh_addr = s->sh_addr;
7453 sh->sh_offset = s->sh_offset;
7454 sh->sh_size = s->sh_size;
7456 fwrite(sh, 1, sizeof(Elf32_Shdr), f);
7458 fclose(f);
7460 free(section_order);
7461 free(phdr);
7462 return 0;
7465 static void *load_data(int fd, unsigned long file_offset, unsigned long size)
7467 void *data;
7469 data = malloc(size);
7470 if (!data)
7471 error("memory full");
7472 lseek(fd, file_offset, SEEK_SET);
7473 read(fd, data, size);
7474 return data;
7477 typedef struct SectionMergeInfo {
7478 Section *s; /* corresponding existing section */
7479 unsigned long offset; /* offset of the new section in the existing section */
7480 int new_section; /* true if section 's' was added */
7481 } SectionMergeInfo;
7483 /* load an object file and merge it with current files */
7484 /* XXX: handle correctly stab (debug) info */
7485 static int tcc_load_object_file(TCCState *s1,
7486 int fd, unsigned long file_offset)
7488 Elf32_Ehdr ehdr;
7489 Elf32_Shdr *shdr, *sh;
7490 int size, i, j, offset, offseti, nb_syms, sym_index;
7491 unsigned char *strsec, *strtab;
7492 int *old_to_new_syms;
7493 char *sh_name, *name;
7494 SectionMergeInfo *sm_table, *sm;
7495 Elf32_Sym *sym, *symtab;
7496 Elf32_Rel *rel;
7497 Section *s;
7499 if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
7500 goto fail;
7501 if (ehdr.e_ident[0] != ELFMAG0 ||
7502 ehdr.e_ident[1] != ELFMAG1 ||
7503 ehdr.e_ident[2] != ELFMAG2 ||
7504 ehdr.e_ident[3] != ELFMAG3)
7505 goto fail;
7506 /* test if object file */
7507 if (ehdr.e_type != ET_REL)
7508 goto fail;
7509 /* test CPU specific stuff */
7510 if (ehdr.e_ident[5] != ELFDATA2LSB ||
7511 ehdr.e_machine != EM_386) {
7512 fail:
7513 error("invalid object file");
7515 /* read sections */
7516 shdr = load_data(fd, file_offset + ehdr.e_shoff,
7517 sizeof(Elf32_Shdr) * ehdr.e_shnum);
7518 sm_table = malloc(sizeof(SectionMergeInfo) * ehdr.e_shnum);
7519 if (!sm_table)
7520 error("memory full");
7521 memset(sm_table, 0, sizeof(SectionMergeInfo) * ehdr.e_shnum);
7523 /* load section names */
7524 sh = &shdr[ehdr.e_shstrndx];
7525 strsec = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
7527 /* load symtab and strtab */
7528 symtab = NULL;
7529 strtab = NULL;
7530 nb_syms = 0;
7531 for(i = 1; i < ehdr.e_shnum; i++) {
7532 sh = &shdr[i];
7533 if (sh->sh_type == SHT_SYMTAB) {
7534 if (symtab)
7535 error("object must contain only one symtab");
7536 nb_syms = sh->sh_size / sizeof(Elf32_Sym);
7537 symtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
7538 sm_table[i].s = symtab_section;
7540 /* now load strtab */
7541 sh = &shdr[sh->sh_link];
7542 strtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
7546 /* now examine each section and try to merge its content with the
7547 ones in memory */
7548 for(i = 1; i < ehdr.e_shnum; i++) {
7549 /* no need to examine section name strtab */
7550 if (i == ehdr.e_shstrndx)
7551 continue;
7552 sh = &shdr[i];
7553 sh_name = strsec + sh->sh_name;
7554 /* ignore sections types we do not handle */
7555 if (sh->sh_type != SHT_PROGBITS &&
7556 sh->sh_type != SHT_REL &&
7557 sh->sh_type != SHT_NOBITS)
7558 continue;
7559 if (sh->sh_addralign < 1)
7560 sh->sh_addralign = 1;
7561 /* find corresponding section, if any */
7562 for(j = 1; j < nb_sections;j++) {
7563 s = sections[j];
7564 if (!strcmp(s->name, sh_name))
7565 goto found;
7567 /* not found: create new section */
7568 s = new_section(sh_name, sh->sh_type, sh->sh_flags);
7569 /* take as much info as possible from the section. sh_link and
7570 sh_info will be updated later */
7571 s->sh_addralign = sh->sh_addralign;
7572 s->sh_entsize = sh->sh_entsize;
7573 sm_table[i].new_section = 1;
7574 found:
7575 if (sh->sh_type != s->sh_type)
7576 goto fail;
7578 /* align start of section */
7579 offset = s->data_ptr - s->data;
7580 size = sh->sh_addralign - 1;
7581 offset = (offset + size) & ~size;
7582 if (sh->sh_addralign > s->sh_addralign)
7583 s->sh_addralign = sh->sh_addralign;
7584 s->data_ptr = s->data + offset;
7585 sm_table[i].offset = offset;
7586 sm_table[i].s = s;
7587 /* concatenate sections */
7588 size = sh->sh_size;
7589 if (sh->sh_type != SHT_NOBITS) {
7590 lseek(fd, file_offset + sh->sh_offset, SEEK_SET);
7591 read(fd, s->data_ptr, size);
7593 s->data_ptr += size;
7596 /* second short pass to update sh_link and sh_info fields of new
7597 sections */
7598 sm = sm_table;
7599 for(i = 1; i < ehdr.e_shnum; i++) {
7600 s = sm_table[i].s;
7601 if (!s || !sm_table[i].new_section)
7602 continue;
7603 sh = &shdr[i];
7604 if (sh->sh_link > 0)
7605 s->link = sm_table[sh->sh_link].s;
7606 if (sh->sh_type == SHT_REL) {
7607 s->sh_info = sm_table[sh->sh_info].s->sh_num;
7608 /* update backward link */
7609 sections[s->sh_info]->reloc = s;
7613 /* resolve symbols */
7614 old_to_new_syms = malloc(nb_syms * sizeof(int));
7615 if (!old_to_new_syms)
7616 error("memory full");
7617 memset(old_to_new_syms, 0, nb_syms * sizeof(int));
7618 sym = symtab + 1;
7619 for(i = 1; i < nb_syms; i++, sym++) {
7620 if (sym->st_shndx != SHN_UNDEF &&
7621 sym->st_shndx < SHN_LORESERVE) {
7622 sm = &sm_table[sym->st_shndx];
7623 /* if no corresponding section added, no need to add symbol */
7624 if (!sm->s)
7625 continue;
7626 /* convert section number */
7627 sym->st_shndx = sm->s->sh_num;
7628 /* offset value */
7629 sym->st_value += sm->offset;
7631 /* add symbol */
7632 name = strtab + sym->st_name;
7633 sym_index = add_elf_sym(symtab_section, sym->st_value, sym->st_size,
7634 sym->st_info, sym->st_shndx, name);
7635 old_to_new_syms[i] = sym_index;
7638 /* third pass to patch relocation entries */
7639 for(i = 1; i < ehdr.e_shnum; i++) {
7640 s = sm_table[i].s;
7641 if (!s)
7642 continue;
7643 sh = &shdr[i];
7644 offset = sm_table[i].offset;
7645 switch(s->sh_type) {
7646 case SHT_REL:
7647 /* take relocation offset information */
7648 offseti = sm_table[sh->sh_info].offset;
7649 for(rel = (Elf32_Rel *)(s->data + offset);
7650 rel < (Elf32_Rel *)s->data_ptr;
7651 rel++) {
7652 int type;
7653 unsigned sym_index;
7654 /* convert symbol index */
7655 type = ELF32_R_TYPE(rel->r_info);
7656 sym_index = ELF32_R_SYM(rel->r_info);
7657 /* NOTE: only one symtab assumed */
7658 if (sym_index >= nb_syms)
7659 goto invalid_reloc;
7660 sym_index = old_to_new_syms[sym_index];
7661 if (!sym_index) {
7662 invalid_reloc:
7663 error("Invalid relocation entry");
7665 rel->r_info = ELF32_R_INFO(sym_index, type);
7666 /* offset the relocation offset */
7667 rel->r_offset += offseti;
7669 break;
7670 default:
7671 break;
7674 free(symtab);
7675 free(strtab);
7676 free(old_to_new_syms);
7677 free(sm_table);
7678 free(shdr);
7679 return 0;
7682 #define ARMAG "!<arch>\012" /* For COFF and a.out archives */
7684 typedef struct ArchiveHeader {
7685 char ar_name[16]; /* name of this member */
7686 char ar_date[12]; /* file mtime */
7687 char ar_uid[6]; /* owner uid; printed as decimal */
7688 char ar_gid[6]; /* owner gid; printed as decimal */
7689 char ar_mode[8]; /* file mode, printed as octal */
7690 char ar_size[10]; /* file size, printed as decimal */
7691 char ar_fmag[2]; /* should contain ARFMAG */
7692 } ArchiveHeader;
7694 /* load a '.a' file */
7695 static int tcc_load_archive(TCCState *s1, int fd)
7697 ArchiveHeader hdr;
7698 char ar_size[11];
7699 char ar_name[17];
7700 char magic[8];
7701 int size, len, i;
7702 unsigned long file_offset;
7704 /* skip magic which was already checked */
7705 read(fd, magic, sizeof(magic));
7707 for(;;) {
7708 len = read(fd, &hdr, sizeof(hdr));
7709 if (len == 0)
7710 break;
7711 if (len != sizeof(hdr))
7712 error("invalid archive");
7713 memcpy(ar_size, hdr.ar_size, sizeof(hdr.ar_size));
7714 ar_size[sizeof(hdr.ar_size)] = '\0';
7715 size = strtol(ar_size, NULL, 0);
7716 memcpy(ar_name, hdr.ar_name, sizeof(hdr.ar_name));
7717 for(i = sizeof(hdr.ar_name) - 1; i >= 0; i--) {
7718 if (ar_name[i] != ' ')
7719 break;
7721 ar_name[i + 1] = '\0';
7722 // printf("name='%s' size=%d %s\n", ar_name, size, ar_size);
7723 file_offset = lseek(fd, 0, SEEK_CUR);
7724 if (!strcmp(ar_name, "/") ||
7725 !strcmp(ar_name, "//") ||
7726 !strcmp(ar_name, "__.SYMDEF") ||
7727 !strcmp(ar_name, "__.SYMDEF/") ||
7728 !strcmp(ar_name, "ARFILENAMES/")) {
7729 /* skip symbol table or archive names */
7730 } else {
7731 tcc_load_object_file(s1, fd, file_offset);
7733 /* align to even */
7734 size = (size + 1) & ~1;
7735 lseek(fd, file_offset + size, SEEK_SET);
7737 return 0;
7740 /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL
7741 is referenced by the user (so it should be added as DT_NEEDED in
7742 the generated ELF file) */
7743 static int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level)
7745 Elf32_Ehdr ehdr;
7746 Elf32_Shdr *shdr, *sh, *sh1;
7747 int i, nb_syms, nb_dts, sym_bind;
7748 Elf32_Sym *sym, *dynsym;
7749 Elf32_Dyn *dt, *dynamic;
7750 unsigned char *dynstr;
7751 const char *name, *soname, *p;
7752 DLLReference *dllref;
7754 read(fd, &ehdr, sizeof(ehdr));
7756 /* test CPU specific stuff */
7757 if (ehdr.e_ident[5] != ELFDATA2LSB ||
7758 ehdr.e_machine != EM_386)
7759 error("bad architecture");
7761 /* read sections */
7762 shdr = load_data(fd, ehdr.e_shoff, sizeof(Elf32_Shdr) * ehdr.e_shnum);
7764 /* load dynamic section and dynamic symbols */
7765 nb_syms = 0;
7766 nb_dts = 0;
7767 dynamic = NULL;
7768 dynsym = NULL; /* avoid warning */
7769 dynstr = NULL; /* avoid warning */
7770 for(i = 0, sh = shdr; i < ehdr.e_shnum; i++, sh++) {
7771 switch(sh->sh_type) {
7772 case SHT_DYNAMIC:
7773 nb_dts = sh->sh_size / sizeof(Elf32_Dyn);
7774 dynamic = load_data(fd, sh->sh_offset, sh->sh_size);
7775 break;
7776 case SHT_DYNSYM:
7777 nb_syms = sh->sh_size / sizeof(Elf32_Sym);
7778 dynsym = load_data(fd, sh->sh_offset, sh->sh_size);
7779 sh1 = &shdr[sh->sh_link];
7780 dynstr = load_data(fd, sh1->sh_offset, sh1->sh_size);
7781 break;
7782 default:
7783 break;
7787 /* compute the real library name */
7788 soname = filename;
7789 p = strrchr(soname, '/');
7790 if (p)
7791 soname = p + 1;
7793 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
7794 if (dt->d_tag == DT_SONAME) {
7795 soname = dynstr + dt->d_un.d_val;
7799 /* if the dll is already loaded, do not load it */
7800 for(i = 0; i < nb_loaded_dlls; i++) {
7801 dllref = loaded_dlls[i];
7802 if (!strcmp(soname, dllref->name)) {
7803 /* but update level if needed */
7804 if (level < dllref->level)
7805 dllref->level = level;
7806 goto the_end;
7810 // printf("loading dll '%s'\n", soname);
7812 /* add the dll and its level */
7813 dllref = malloc(sizeof(DLLReference) + strlen(soname));
7814 dllref->level = level;
7815 strcpy(dllref->name, soname);
7816 dynarray_add((void ***)&loaded_dlls, &nb_loaded_dlls, dllref);
7818 /* add dynamic symbols in dynsym_section */
7819 for(i = 1, sym = dynsym + 1; i < nb_syms; i++, sym++) {
7820 sym_bind = ELF32_ST_BIND(sym->st_info);
7821 if (sym_bind == STB_LOCAL)
7822 continue;
7823 name = dynstr + sym->st_name;
7824 add_elf_sym(dynsymtab_section, sym->st_value, sym->st_size,
7825 sym->st_info, sym->st_shndx, name);
7828 /* load all referenced DLLs */
7829 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
7830 switch(dt->d_tag) {
7831 case DT_NEEDED:
7832 name = dynstr + dt->d_un.d_val;
7833 for(i = 0; i < nb_loaded_dlls; i++) {
7834 dllref = loaded_dlls[i];
7835 if (!strcmp(name, dllref->name))
7836 goto already_loaded;
7838 if (tcc_add_dll(s1, name, AFF_REFERENCED_DLL) < 0)
7839 error("referenced dll '%s' not found", name);
7840 already_loaded:
7841 break;
7844 the_end:
7845 free(shdr);
7846 return 0;
7849 /* return -2 if error and CH_EOF if eof */
7850 static void ld_skipspaces(void)
7852 while (ch == ' ' || ch == '\t' || ch == '\n')
7853 cinp();
7856 static int ld_get_cmd(char *cmd, int cmd_size)
7858 char *q;
7860 ld_skipspaces();
7861 if (ch == CH_EOF)
7862 return -1;
7863 q = cmd;
7864 for(;;) {
7865 if (!((ch >= 'a' && ch <= 'z') ||
7866 (ch >= 'A' && ch <= 'Z') ||
7867 (ch >= '0' && ch <= '9') ||
7868 strchr("/.-_+=$:\\,~?*", ch)))
7869 break;
7870 if ((q - cmd) >= (cmd_size - 1))
7871 return -2;
7872 *q++ = ch;
7873 cinp();
7875 *q = '\0';
7876 return 0;
7879 /* interpret a subset of GNU ldscripts to handle the dummy libc.so
7880 files */
7881 static int tcc_load_ldscript(TCCState *s1)
7883 char cmd[64];
7884 char filename[1024];
7885 int ret;
7887 inp();
7888 cinp();
7889 for(;;) {
7890 ret = ld_get_cmd(cmd, sizeof(cmd));
7891 if (ret == CH_EOF)
7892 return 0;
7893 else if (ret < 0)
7894 return -1;
7895 // printf("cmd='%s'\n", cmd);
7896 if (!strcmp(cmd, "INPUT") ||
7897 !strcmp(cmd, "GROUP")) {
7898 ld_skipspaces();
7899 if (ch != '(')
7900 expect("(");
7901 cinp();
7902 for(;;) {
7903 ld_get_cmd(filename, sizeof(filename));
7904 tcc_add_file(s1, filename);
7905 ld_skipspaces();
7906 if (ch == ',') {
7907 cinp();
7908 } else if (ch == ')') {
7909 cinp();
7910 break;
7911 } else if (ch == CH_EOF) {
7912 error("unexpected end of file");
7915 } else {
7916 return -1;
7919 return 0;
7922 /* print the position in the source file of PC value 'pc' by reading
7923 the stabs debug information */
7924 static void rt_printline(unsigned long wanted_pc)
7926 Stab_Sym *sym, *sym_end;
7927 char func_name[128];
7928 unsigned long func_addr, last_pc, pc;
7929 const char *incl_files[INCLUDE_STACK_SIZE];
7930 int incl_index, len, last_line_num, i;
7931 const char *str, *p;
7933 func_name[0] = '\0';
7934 func_addr = 0;
7935 incl_index = 0;
7936 last_pc = 0xffffffff;
7937 last_line_num = 1;
7938 sym = (Stab_Sym *)stab_section->data + 1;
7939 sym_end = (Stab_Sym *)stab_section->data_ptr;
7940 while (sym < sym_end) {
7941 switch(sym->n_type) {
7942 /* function start or end */
7943 case N_FUN:
7944 if (sym->n_strx == 0) {
7945 func_name[0] = '\0';
7946 func_addr = 0;
7947 } else {
7948 str = stabstr_section->data + sym->n_strx;
7949 p = strchr(str, ':');
7950 if (!p) {
7951 pstrcpy(func_name, sizeof(func_name), str);
7952 } else {
7953 len = p - str;
7954 if (len > sizeof(func_name) - 1)
7955 len = sizeof(func_name) - 1;
7956 memcpy(func_name, str, len);
7957 func_name[len] = '\0';
7959 func_addr = sym->n_value;
7961 break;
7962 /* line number info */
7963 case N_SLINE:
7964 pc = sym->n_value + func_addr;
7965 if (wanted_pc >= last_pc && wanted_pc < pc)
7966 goto found;
7967 last_pc = pc;
7968 last_line_num = sym->n_desc;
7969 break;
7970 /* include files */
7971 case N_BINCL:
7972 str = stabstr_section->data + sym->n_strx;
7973 add_incl:
7974 if (incl_index < INCLUDE_STACK_SIZE) {
7975 incl_files[incl_index++] = str;
7977 break;
7978 case N_EINCL:
7979 if (incl_index > 1)
7980 incl_index--;
7981 break;
7982 case N_SO:
7983 if (sym->n_strx == 0) {
7984 incl_index = 0; /* end of translation unit */
7985 } else {
7986 str = stabstr_section->data + sym->n_strx;
7987 /* do not add path */
7988 len = strlen(str);
7989 if (len > 0 && str[len - 1] != '/')
7990 goto add_incl;
7992 break;
7994 sym++;
7996 /* did not find line number info: */
7997 fprintf(stderr, "(no debug info, pc=0x%08lx): ", wanted_pc);
7998 return;
7999 found:
8000 for(i = 0; i < incl_index - 1; i++)
8001 fprintf(stderr, "In file included from %s\n",
8002 incl_files[i]);
8003 if (incl_index > 0) {
8004 fprintf(stderr, "%s:%d: ",
8005 incl_files[incl_index - 1], last_line_num);
8007 if (func_name[0] != '\0') {
8008 fprintf(stderr, "in function '%s()': ", func_name);
8012 /* emit a run time error at position 'pc' */
8013 void rt_error(unsigned long pc, const char *fmt, ...)
8015 va_list ap;
8016 va_start(ap, fmt);
8018 rt_printline(pc);
8019 vfprintf(stderr, fmt, ap);
8020 fprintf(stderr, "\n");
8021 exit(255);
8022 va_end(ap);
8025 #ifndef WIN32
8026 /* signal handler for fatal errors */
8027 static void sig_error(int signum, siginfo_t *siginf, void *puc)
8029 struct ucontext *uc = puc;
8030 unsigned long pc;
8032 #ifdef __i386__
8033 pc = uc->uc_mcontext.gregs[14];
8034 #else
8035 #error please put the right sigcontext field
8036 #endif
8038 switch(signum) {
8039 case SIGFPE:
8040 switch(siginf->si_code) {
8041 case FPE_INTDIV:
8042 case FPE_FLTDIV:
8043 rt_error(pc, "division by zero");
8044 break;
8045 default:
8046 rt_error(pc, "floating point exception");
8047 break;
8049 break;
8050 case SIGBUS:
8051 case SIGSEGV:
8052 rt_error(pc, "dereferencing invalid pointer");
8053 break;
8054 case SIGILL:
8055 rt_error(pc, "illegal instruction");
8056 break;
8057 case SIGABRT:
8058 rt_error(pc, "abort() called");
8059 break;
8060 default:
8061 rt_error(pc, "caught signal %d", signum);
8062 break;
8064 exit(255);
8066 #endif
8068 /* launch the compiled program with the given arguments */
8069 int tcc_run(TCCState *s1, int argc, char **argv)
8071 Section *s;
8072 int (*prog_main)(int, char **);
8073 void (*bound_init)(void);
8074 int i;
8076 tcc_add_runtime(s1);
8078 relocate_common_syms();
8080 /* compute relocation address : section are relocated in place */
8081 for(i = 1; i < nb_sections; i++) {
8082 s = sections[i];
8083 if (s->sh_flags & SHF_ALLOC)
8084 s->sh_addr = (unsigned long)s->data;
8087 relocate_syms(1);
8089 /* relocate each section */
8090 for(i = 1; i < nb_sections; i++) {
8091 s = sections[i];
8092 if ((s->sh_flags & SHF_ALLOC) && s->reloc)
8093 relocate_section(s);
8096 prog_main = (void *)get_elf_sym_val("main");
8098 if (do_debug) {
8099 #ifdef WIN32
8100 error("debug mode currently not available for Windows");
8101 #else
8102 struct sigaction sigact;
8103 /* install TCC signal handlers to print debug info on fatal
8104 runtime errors */
8105 sigact.sa_flags = SA_SIGINFO | SA_ONESHOT;
8106 sigact.sa_sigaction = sig_error;
8107 sigemptyset(&sigact.sa_mask);
8108 sigaction(SIGFPE, &sigact, NULL);
8109 sigaction(SIGILL, &sigact, NULL);
8110 sigaction(SIGSEGV, &sigact, NULL);
8111 sigaction(SIGBUS, &sigact, NULL);
8112 sigaction(SIGABRT, &sigact, NULL);
8113 #endif
8116 #ifdef CONFIG_TCC_BCHECK
8117 if (do_bounds_check) {
8118 /* XXX: use .init section so that it also work in binary ? */
8119 bound_init = (void *)get_elf_sym_val("__bound_init");
8120 bound_init();
8122 #endif
8123 return (*prog_main)(argc, argv);
8126 TCCState *tcc_new(void)
8128 char *p, *r;
8129 TCCState *s;
8131 s = malloc(sizeof(TCCState));
8132 if (!s)
8133 return NULL;
8134 s->output_type = TCC_OUTPUT_MEMORY;
8136 /* default include paths */
8137 tcc_add_include_path(s, "/usr/include");
8138 tcc_add_include_path(s, CONFIG_TCC_PREFIX "/lib/tcc/include");
8139 tcc_add_include_path(s, "/usr/local/include");
8141 /* add all tokens */
8142 tok_ident = TOK_IDENT;
8143 p = tcc_keywords;
8144 while (*p) {
8145 r = p;
8146 while (*r++);
8147 tok_alloc(p, r - p - 1);
8148 p = r;
8151 /* standard defines */
8152 tcc_define_symbol(s, "__STDC__", NULL);
8153 #if defined(TCC_TARGET_I386)
8154 tcc_define_symbol(s, "__i386__", NULL);
8155 #endif
8156 /* tiny C specific defines */
8157 tcc_define_symbol(s, "__TINYC__", NULL);
8159 /* default library paths */
8160 tcc_add_library_path(s, "/usr/local/lib");
8161 tcc_add_library_path(s, "/usr/lib");
8162 tcc_add_library_path(s, "/lib");
8164 /* no section zero */
8165 dynarray_add((void ***)&sections, &nb_sections, NULL);
8167 /* create standard sections */
8168 text_section = new_section(".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
8169 data_section = new_section(".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
8170 bss_section = new_section(".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
8172 /* symbols are always generated for linking stage */
8173 symtab_section = new_section(".symtab", SHT_SYMTAB, 0);
8174 symtab_section->sh_entsize = sizeof(Elf32_Sym);
8175 strtab_section = new_section(".strtab", SHT_STRTAB, 0);
8176 put_elf_str(strtab_section, "");
8177 symtab_section->link = strtab_section;
8178 put_elf_sym(symtab_section, 0, 0, 0, 0, 0, NULL);
8179 new_section_hash(".hashtab", SHF_PRIVATE,
8180 ELF_SYM_HASH_SIZE, symtab_section);
8182 /* private symbol table for dynamic symbols */
8183 dynsymtab_section = new_section(".dynsymtab", SHT_SYMTAB, SHF_PRIVATE);
8184 dynsymtab_section->sh_entsize = sizeof(Elf32_Sym);
8185 dynstrtab_section = new_section(".dynstrtab", SHT_STRTAB, SHF_PRIVATE);
8186 put_elf_str(dynstrtab_section, "");
8187 dynsymtab_section->link = dynstrtab_section;
8188 put_elf_sym(dynsymtab_section, 0, 0, 0, 0, 0, NULL);
8189 new_section_hash(".dynhashtab", SHF_PRIVATE,
8190 ELF_SYM_HASH_SIZE, dynsymtab_section);
8191 return s;
8194 void tcc_delete(TCCState *s)
8196 free(s);
8199 int tcc_add_include_path(TCCState *s, const char *pathname)
8201 char *pathname1;
8203 pathname1 = strdup(pathname);
8204 if (!pathname1)
8205 return -1;
8206 dynarray_add((void ***)&include_paths, &nb_include_paths, pathname1);
8207 return 0;
8210 static int tcc_add_file_internal(TCCState *s, const char *filename, int flags)
8212 const char *ext;
8213 Elf32_Ehdr ehdr;
8214 int fd;
8215 BufferedFile *saved_file;
8217 /* find source file type with extension */
8218 ext = strrchr(filename, '.');
8219 if (ext)
8220 ext++;
8222 /* open the file */
8223 saved_file = file;
8224 file = tcc_open(filename);
8225 if (!file) {
8226 if (flags & AFF_PRINT_ERROR) {
8227 error("file '%s' not found", filename);
8228 } else {
8229 file = saved_file;
8230 return -1;
8234 if (!ext || !strcmp(ext, "c")) {
8235 /* C file assumed */
8236 tcc_compile(s);
8237 } else {
8238 fd = file->fd;
8239 /* assume executable format: auto guess file type */
8240 if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
8241 error("could not read header");
8242 lseek(fd, 0, SEEK_SET);
8244 if (ehdr.e_ident[0] == ELFMAG0 &&
8245 ehdr.e_ident[1] == ELFMAG1 &&
8246 ehdr.e_ident[2] == ELFMAG2 &&
8247 ehdr.e_ident[3] == ELFMAG3) {
8248 file->line_num = 0; /* do not display line number if error */
8249 if (ehdr.e_type == ET_REL) {
8250 tcc_load_object_file(s, fd, 0);
8251 } else if (ehdr.e_type == ET_DYN) {
8252 tcc_load_dll(s, fd, filename, (flags & AFF_REFERENCED_DLL) != 0);
8253 } else {
8254 error("unrecognized ELF file");
8256 } else if (memcmp((char *)&ehdr, ARMAG, 8) == 0) {
8257 file->line_num = 0; /* do not display line number if error */
8258 tcc_load_archive(s, fd);
8259 } else {
8260 /* as GNU ld, consider it is an ld script if not recognized */
8261 if (tcc_load_ldscript(s) < 0)
8262 error("unrecognized file type");
8265 tcc_close(file);
8266 file = saved_file;
8267 return 0;
8270 void tcc_add_file(TCCState *s, const char *filename)
8272 tcc_add_file_internal(s, filename, AFF_PRINT_ERROR);
8275 int tcc_add_library_path(TCCState *s, const char *pathname)
8277 char *pathname1;
8279 pathname1 = strdup(pathname);
8280 if (!pathname1)
8281 return -1;
8282 dynarray_add((void ***)&library_paths, &nb_library_paths, pathname1);
8283 return 0;
8286 /* find and load a dll. Return non zero if not found */
8287 /* XXX: add '-rpath' option support ? */
8288 static int tcc_add_dll(TCCState *s, const char *filename, int flags)
8290 char buf[1024];
8291 int i;
8293 for(i = 0; i < nb_library_paths; i++) {
8294 snprintf(buf, sizeof(buf), "%s/%s",
8295 library_paths[i], filename);
8296 if (tcc_add_file_internal(s, buf, flags) == 0)
8297 return 0;
8299 return -1;
8302 /* the library name is the same as the argument of the '-l' option */
8303 int tcc_add_library(TCCState *s, const char *libraryname)
8305 char buf[1024];
8306 int i;
8307 void *h;
8309 /* if we output to memory, then we simply we dlopen(). */
8310 if (s->output_type == TCC_OUTPUT_MEMORY) {
8311 /* Since the libc is already loaded, we don't need to load it again */
8312 if (!strcmp(libraryname, "c"))
8313 return 0;
8314 snprintf(buf, sizeof(buf), "lib%s.so", libraryname);
8315 h = dlopen(buf, RTLD_GLOBAL | RTLD_LAZY);
8316 if (!h)
8317 return -1;
8318 return 0;
8321 /* first we look for the dynamic library if not static linking */
8322 if (!static_link) {
8323 snprintf(buf, sizeof(buf), "lib%s.so", libraryname);
8324 if (tcc_add_dll(s, buf, 0) == 0)
8325 return 0;
8328 /* then we look for the static library */
8329 for(i = 0; i < nb_library_paths; i++) {
8330 snprintf(buf, sizeof(buf), "%s/lib%s.a",
8331 library_paths[i], libraryname);
8332 if (tcc_add_file_internal(s, buf, 0) == 0)
8333 return 0;
8335 return -1;
8338 int tcc_add_symbol(TCCState *s, const char *name, unsigned long val)
8340 add_elf_sym(symtab_section, val, 0,
8341 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE),
8342 SHN_ABS, name);
8343 return 0;
8346 int tcc_set_output_type(TCCState *s, int output_type)
8348 s->output_type = output_type;
8350 /* add libc crt1/crti objects */
8351 if (output_type == TCC_OUTPUT_EXE ||
8352 output_type == TCC_OUTPUT_DLL) {
8353 if (output_type != TCC_OUTPUT_DLL)
8354 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crt1.o");
8355 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crti.o");
8357 return 0;
8360 #if !defined(LIBTCC)
8362 void help(void)
8364 printf("tcc version 0.9.8 - Tiny C Compiler - Copyright (C) 2001, 2002 Fabrice Bellard\n"
8365 "usage: tcc [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
8366 " [-g] [-b] [-Ldir] [-llib] [-shared] [-static]\n"
8367 " [--] infile1 [infile2... --] [infile_args...]\n"
8368 "\n"
8369 "General options:\n"
8370 " -c compile only - generate an object file\n"
8371 " -o outfile set output filename\n"
8372 " -- allows multiples input files if no -o option given. Also\n"
8373 " separate input files from runtime arguments\n"
8374 " -Bdir set tcc internal library path\n"
8375 " -bench output compilation statistics\n"
8376 "Preprocessor options:\n"
8377 " -Idir add include path 'dir'\n"
8378 " -Dsym[=val] define 'sym' with value 'val'\n"
8379 " -Usym undefine 'sym'\n"
8380 "C compiler options:\n"
8381 " -g generate runtime debug info\n"
8382 #ifdef CONFIG_TCC_BCHECK
8383 " -b compile with built-in memory and bounds checker (implies -g)\n"
8384 #endif
8385 "Linker options:\n"
8386 " -Ldir add library path 'dir'\n"
8387 " -llib link with dynamic library 'lib'\n"
8388 " -shared generate a shared library (NOT WORKING YET)\n"
8389 " -static static linking\n"
8393 int main(int argc, char **argv)
8395 char *r, *outfile;
8396 int optind, output_type, multiple_files, i;
8397 TCCState *s;
8398 char **libraries;
8399 int nb_libraries;
8401 s = tcc_new();
8402 output_type = TCC_OUTPUT_MEMORY;
8404 optind = 1;
8405 outfile = NULL;
8406 multiple_files = 0;
8407 libraries = NULL;
8408 nb_libraries = 0;
8409 while (1) {
8410 if (optind >= argc) {
8411 show_help:
8412 help();
8413 return 1;
8415 r = argv[optind];
8416 if (r[0] != '-')
8417 break;
8418 optind++;
8419 if (r[1] == '-') {
8420 /* '--' enables multiple files input */
8421 multiple_files = 1;
8422 } else if (r[1] == 'h' || r[1] == '?') {
8423 goto show_help;
8424 } else if (r[1] == 'I') {
8425 if (tcc_add_include_path(s, r + 2) < 0)
8426 error("too many include paths");
8427 } else if (r[1] == 'D') {
8428 char *sym, *value;
8429 sym = r + 2;
8430 value = strchr(sym, '=');
8431 if (value) {
8432 *value = '\0';
8433 value++;
8435 tcc_define_symbol(s, sym, value);
8436 } else if (r[1] == 'U') {
8437 tcc_undefine_symbol(s, r + 2);
8438 } else if (r[1] == 'L') {
8439 tcc_add_library_path(s, r + 2);
8440 } else if (r[1] == 'B') {
8441 /* set tcc utilities path (mainly for tcc development) */
8442 tcc_lib_path = r + 2;
8443 } else if (r[1] == 'l') {
8444 dynarray_add((void ***)&libraries, &nb_libraries, r + 2);
8445 } else if (!strcmp(r + 1, "bench")) {
8446 do_bench = 1;
8447 #ifdef CONFIG_TCC_BCHECK
8448 } else if (r[1] == 'b') {
8449 if (!do_bounds_check) {
8450 do_bounds_check = 1;
8451 /* define symbol */
8452 tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL);
8453 /* create bounds sections */
8454 bounds_section = new_section(".bounds",
8455 SHT_PROGBITS, SHF_ALLOC);
8456 lbounds_section = new_section(".lbounds",
8457 SHT_PROGBITS, SHF_ALLOC);
8458 /* debug is implied */
8459 goto debug_opt;
8461 #endif
8462 } else if (r[1] == 'g') {
8463 #ifdef CONFIG_TCC_BCHECK
8464 debug_opt:
8465 #endif
8466 if (!do_debug) {
8467 do_debug = 1;
8469 /* stab symbols */
8470 stab_section = new_section(".stab", SHT_PROGBITS, 0);
8471 stab_section->sh_entsize = sizeof(Stab_Sym);
8472 stabstr_section = new_section(".stabstr", SHT_STRTAB, 0);
8473 put_elf_str(stabstr_section, "");
8474 stab_section->link = stabstr_section;
8475 /* put first entry */
8476 put_stabs("", 0, 0, 0, 0);
8478 } else
8479 /* the following options are only for testing, so not
8480 documented */
8481 if (r[1] == 'c') {
8482 multiple_files = 1;
8483 output_type = TCC_OUTPUT_OBJ;
8484 } else if (!strcmp(r + 1, "static")) {
8485 static_link = 1;
8486 } else if (!strcmp(r + 1, "shared")) {
8487 output_type = TCC_OUTPUT_DLL;
8488 } else if (r[1] == 'o') {
8489 if (optind >= argc)
8490 goto show_help;
8491 multiple_files = 1;
8492 outfile = argv[optind++];
8493 } else {
8494 error("invalid option -- '%s'", r);
8498 /* if outfile provided without other options, we output an
8499 executable */
8500 if (outfile && output_type == TCC_OUTPUT_MEMORY)
8501 output_type = TCC_OUTPUT_EXE;
8503 /* warning if not supported features */
8504 if (output_type == TCC_OUTPUT_DLL)
8505 warning("dll output is currently not supported");
8506 #ifdef CONFIG_TCC_BCHECK
8507 if (do_bounds_check && output_type != TCC_OUTPUT_MEMORY)
8508 warning("bounds checking is currently only supported for in-memory execution");
8509 #endif
8511 tcc_set_output_type(s, output_type);
8513 tcc_add_file(s, argv[optind]);
8514 if (multiple_files) {
8515 while ((optind + 1) < argc) {
8516 optind++;
8517 r = argv[optind];
8518 if (r[0] == '-') {
8519 if (r[1] != '-')
8520 error("'--' expected");
8521 break;
8523 tcc_add_file(s, r);
8527 /* add specified libraries */
8528 for(i = 0; i < nb_libraries;i++) {
8529 if (tcc_add_library(s, libraries[i]) < 0)
8530 error("cannot find -l%s", libraries[i]);
8533 if (do_bench) {
8534 printf("total: %d idents, %d lines, %d bytes\n",
8535 tok_ident - TOK_IDENT, total_lines, total_bytes);
8538 if (s->output_type != TCC_OUTPUT_MEMORY) {
8539 tcc_output_file(s, outfile);
8540 return 0;
8541 } else {
8542 return tcc_run(s, argc - optind, argv + optind);
8546 #endif