added runtime library - fixed more relocations
[tinycc.git] / tcc.c
blob8bfc50b45c7c247b684381cab37066d3f7df01a6
1 /*
2 * TCC - Tiny C Compiler
3 *
4 * Copyright (c) 2001, 2002 Fabrice Bellard
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <stdarg.h>
23 #include <string.h>
24 #include <errno.h>
25 #include <math.h>
26 #include <unistd.h>
27 #include <signal.h>
28 #include <malloc.h>
29 #include <unistd.h>
30 #include <fcntl.h>
31 #ifndef WIN32
32 #include <sys/ucontext.h>
33 #include <sys/mman.h>
34 #endif
35 #include "elf.h"
36 #include "stab.h"
37 #ifndef CONFIG_TCC_STATIC
38 #include <dlfcn.h>
39 #endif
41 #include "libtcc.h"
43 //#define DEBUG
44 /* preprocessor debug */
45 //#define PP_DEBUG
47 /* target selection */
48 //#define TCC_TARGET_I386 /* i386 code generator */
49 //#define TCC_TARGET_IL /* .NET CLI generator */
51 /* default target is I386 */
52 #if !defined(TCC_TARGET_I386) && !defined(TCC_TARGET_IL)
53 #define TCC_TARGET_I386
54 #endif
56 #if !defined(WIN32) && !defined(TCC_UCLIBC) && !defined(TCC_TARGET_IL)
57 #define CONFIG_TCC_BCHECK /* enable bound checking code */
58 #endif
60 #ifndef CONFIG_TCC_PREFIX
61 #define CONFIG_TCC_PREFIX "/usr/local"
62 #endif
64 /* path to find crt1.o, crti.o and crtn.o. Only needed when generating
65 executables or dlls */
66 #define CONFIG_TCC_CRT_PREFIX "/usr/lib"
68 /* amount of virtual memory associated to a section (currently, we do
69 not realloc them) */
70 #define SECTION_VSIZE (1024 * 1024)
72 #define INCLUDE_STACK_SIZE 32
73 #define IFDEF_STACK_SIZE 64
74 #define VSTACK_SIZE 64
75 #define STRING_MAX_SIZE 1024
77 #define TOK_HASH_SIZE 2048 /* must be a power of two */
78 #define TOK_ALLOC_INCR 512 /* must be a power of two */
79 #define SYM_HASH_SIZE 1031
80 #define ELF_SYM_HASH_SIZE 2048
81 #define ELF_DYNSYM_HASH_SIZE 32
83 /* token symbol management */
84 typedef struct TokenSym {
85 struct TokenSym *hash_next;
86 int tok; /* token number */
87 int len;
88 char str[1];
89 } TokenSym;
91 /* constant value */
92 typedef union CValue {
93 long double ld;
94 double d;
95 float f;
96 int i;
97 unsigned int ui;
98 unsigned int ul; /* address (should be unsigned long on 64 bit cpu) */
99 long long ll;
100 unsigned long long ull;
101 struct TokenSym *ts;
102 struct Sym *sym;
103 void *ptr;
104 int tab[1];
105 } CValue;
107 /* value on stack */
108 typedef struct SValue {
109 int t; /* type */
110 unsigned short r; /* register + flags */
111 unsigned short r2; /* second register, used for 'long long'
112 type. If not used, set to VT_CONST */
113 CValue c; /* constant, if VT_CONST */
114 } SValue;
116 /* symbol management */
117 typedef struct Sym {
118 int v; /* symbol token */
119 int t; /* associated type */
120 int r; /* associated register */
121 int c; /* associated number */
122 struct Sym *next; /* next related symbol */
123 struct Sym *prev; /* prev symbol in stack */
124 struct Sym *hash_next; /* next symbol in hash table */
125 } Sym;
127 typedef struct SymStack {
128 struct Sym *top;
129 struct Sym *hash[SYM_HASH_SIZE];
130 } SymStack;
132 /* section definition */
133 /* XXX: use directly ELF structure for parameters ? */
134 /* special flag to indicate that the section should not be linked to
135 the other ones */
136 #define SHF_PRIVATE 0x80000000
138 typedef struct Section {
139 unsigned char *data; /* section data */
140 unsigned char *data_ptr; /* current data pointer */
141 int sh_name; /* elf section name (only used during output) */
142 int sh_num; /* elf section number */
143 int sh_type; /* elf section type */
144 int sh_flags; /* elf section flags */
145 int sh_info; /* elf section info */
146 int sh_addralign; /* elf section alignment */
147 int sh_entsize; /* elf entry size */
148 unsigned long sh_size; /* section size (only used during output) */
149 unsigned long sh_addr; /* address at which the section is relocated */
150 unsigned long sh_offset; /* address at which the section is relocated */
151 struct Section *link; /* link to another section */
152 struct Section *reloc; /* corresponding section for relocation, if any */
153 struct Section *hash; /* hash table for symbols */
154 struct Section *next;
155 char name[64]; /* section name */
156 } Section;
158 typedef struct DLLReference {
159 int level;
160 char name[1];
161 } DLLReference;
163 /* GNUC attribute definition */
164 typedef struct AttributeDef {
165 int aligned;
166 Section *section;
167 unsigned char func_call; /* FUNC_CDECL or FUNC_STDCALL */
168 } AttributeDef;
170 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
171 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
172 #define SYM_FIRST_ANOM (1 << (31 - VT_STRUCT_SHIFT)) /* first anonymous sym */
174 /* stored in 'Sym.c' field */
175 #define FUNC_NEW 1 /* ansi function prototype */
176 #define FUNC_OLD 2 /* old function prototype */
177 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
179 /* stored in 'Sym.r' field */
180 #define FUNC_CDECL 0 /* standard c call */
181 #define FUNC_STDCALL 1 /* pascal c call */
183 /* field 'Sym.t' for macros */
184 #define MACRO_OBJ 0 /* object like macro */
185 #define MACRO_FUNC 1 /* function like macro */
187 /* field 'Sym.t' for labels */
188 #define LABEL_FORWARD 1 /* label is forward defined */
190 /* type_decl() types */
191 #define TYPE_ABSTRACT 1 /* type without variable */
192 #define TYPE_DIRECT 2 /* type with variable */
194 #define IO_BUF_SIZE 8192
196 typedef struct BufferedFile {
197 unsigned char *buf_ptr;
198 unsigned char *buf_end;
199 int fd;
200 int line_num; /* current line number - here to simply code */
201 char filename[1024]; /* current filename - here to simply code */
202 unsigned char buffer[IO_BUF_SIZE + 1]; /* extra size for CH_EOB char */
203 } BufferedFile;
205 #define CH_EOB 0 /* end of buffer or '\0' char in file */
206 #define CH_EOF (-1) /* end of file */
208 /* parsing state (used to save parser state to reparse part of the
209 source several times) */
210 typedef struct ParseState {
211 int *macro_ptr;
212 int line_num;
213 int tok;
214 CValue tokc;
215 } ParseState;
217 /* used to record tokens */
218 typedef struct TokenString {
219 int *str;
220 int len;
221 int last_line_num;
222 } TokenString;
224 /* parser */
225 struct BufferedFile *file;
226 int ch, ch1, tok, tok1;
227 CValue tokc, tok1c;
229 /* sections */
230 Section **sections;
231 int nb_sections; /* number of sections, including first dummy section */
232 Section *text_section, *data_section, *bss_section; /* predefined sections */
233 Section *cur_text_section; /* current section where function code is
234 generated */
235 /* bound check related sections */
236 Section *bounds_section; /* contains global data bound description */
237 Section *lbounds_section; /* contains local data bound description */
238 /* symbol sections */
239 Section *symtab_section, *strtab_section;
240 /* temporary dynamic symbol sections (for dll loading) */
241 Section *dynsymtab_section, *dynstrtab_section;
242 /* exported dynamic symbol section */
243 Section *dynsym;
244 /* got handling */
245 Section *got;
246 unsigned long *got_offsets;
247 int nb_got_offsets;
248 int nb_plt_entries;
251 /* array of all loaded dlls (including those referenced by loaded
252 dlls) */
253 DLLReference **loaded_dlls;
254 int nb_loaded_dlls;
256 /* debug sections */
257 Section *stab_section, *stabstr_section;
259 char **library_paths;
260 int nb_library_paths;
262 /* loc : local variable index
263 ind : output code index
264 rsym: return symbol
265 anon_sym: anonymous symbol index
267 int rsym, anon_sym,
268 prog, ind, loc, const_wanted;
269 int global_expr; /* true if compound literals must be allocated
270 globally (used during initializers parsing */
271 int func_vt, func_vc; /* current function return type (used by
272 return instruction) */
273 int last_line_num, last_ind, func_ind; /* debug last line number and pc */
274 int tok_ident;
275 TokenSym **table_ident;
276 TokenSym *hash_ident[TOK_HASH_SIZE];
277 char token_buf[STRING_MAX_SIZE + 1];
278 char *funcname;
279 SymStack define_stack, global_stack, local_stack, label_stack;
281 SValue vstack[VSTACK_SIZE], *vtop;
282 int *macro_ptr, *macro_ptr_allocated;
283 BufferedFile *include_stack[INCLUDE_STACK_SIZE], **include_stack_ptr;
284 int ifdef_stack[IFDEF_STACK_SIZE], *ifdef_stack_ptr;
285 char **include_paths;
286 int nb_include_paths;
287 int char_pointer_type;
288 int func_old_type;
290 /* compile with debug symbol (and use them if error during execution) */
291 int do_debug = 0;
293 /* compile with built-in memory and bounds checker */
294 int do_bounds_check = 0;
296 /* display benchmark infos */
297 int do_bench = 0;
298 int total_lines;
299 int total_bytes;
301 /* use GNU C extensions */
302 int gnu_ext = 1;
304 /* use Tiny C extensions */
305 int tcc_ext = 1;
307 /* if true, static linking is performed */
308 int static_link = 0;
310 struct TCCState {
311 int output_type;
314 /* The current value can be: */
315 #define VT_VALMASK 0x00ff
316 #define VT_CONST 0x00f0 /* constant in vc
317 (must be first non register value) */
318 #define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */
319 #define VT_LOCAL 0x00f2 /* offset on stack */
320 #define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */
321 #define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */
322 #define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */
323 #define VT_LVAL 0x0100 /* var is an lvalue */
324 #define VT_SYM 0x0200 /* a symbol value is added */
325 #define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for
326 char/short stored in integer registers) */
327 #define VT_MUSTBOUND 0x0800 /* bound checking must be done before
328 dereferencing value */
329 #define VT_BOUNDED 0x8000 /* value is bounded. The address of the
330 bounding function call point is in vc */
331 #define VT_LVAL_BYTE 0x1000 /* lvalue is a byte */
332 #define VT_LVAL_SHORT 0x2000 /* lvalue is a short */
333 #define VT_LVAL_UNSIGNED 0x4000 /* lvalue is unsigned */
334 #define VT_LVAL_TYPE (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)
336 /* types */
337 #define VT_STRUCT_SHIFT 16 /* structure/enum name shift (16 bits left) */
339 #define VT_INT 0 /* integer type */
340 #define VT_BYTE 1 /* signed byte type */
341 #define VT_SHORT 2 /* short type */
342 #define VT_VOID 3 /* void type */
343 #define VT_PTR 4 /* pointer */
344 #define VT_ENUM 5 /* enum definition */
345 #define VT_FUNC 6 /* function type */
346 #define VT_STRUCT 7 /* struct/union definition */
347 #define VT_FLOAT 8 /* IEEE float */
348 #define VT_DOUBLE 9 /* IEEE double */
349 #define VT_LDOUBLE 10 /* IEEE long double */
350 #define VT_BOOL 11 /* ISOC99 boolean type */
351 #define VT_LLONG 12 /* 64 bit integer */
352 #define VT_LONG 13 /* long integer (NEVER USED as type, only
353 during parsing) */
354 #define VT_BTYPE 0x000f /* mask for basic type */
355 #define VT_UNSIGNED 0x0010 /* unsigned type */
356 #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
357 #define VT_BITFIELD 0x0040 /* bitfield modifier */
359 /* storage */
360 #define VT_EXTERN 0x00000080 /* extern definition */
361 #define VT_STATIC 0x00000100 /* static variable */
362 #define VT_TYPEDEF 0x00000200 /* typedef definition */
364 /* type mask (except storage) */
365 #define VT_TYPE (~(VT_EXTERN | VT_STATIC | VT_TYPEDEF))
367 /* token values */
369 /* warning: the following compare tokens depend on i386 asm code */
370 #define TOK_ULT 0x92
371 #define TOK_UGE 0x93
372 #define TOK_EQ 0x94
373 #define TOK_NE 0x95
374 #define TOK_ULE 0x96
375 #define TOK_UGT 0x97
376 #define TOK_LT 0x9c
377 #define TOK_GE 0x9d
378 #define TOK_LE 0x9e
379 #define TOK_GT 0x9f
381 #define TOK_LAND 0xa0
382 #define TOK_LOR 0xa1
384 #define TOK_DEC 0xa2
385 #define TOK_MID 0xa3 /* inc/dec, to void constant */
386 #define TOK_INC 0xa4
387 #define TOK_UDIV 0xb0 /* unsigned division */
388 #define TOK_UMOD 0xb1 /* unsigned modulo */
389 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
390 #define TOK_CINT 0xb3 /* number in tokc */
391 #define TOK_CCHAR 0xb4 /* char constant in tokc */
392 #define TOK_STR 0xb5 /* pointer to string in tokc */
393 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
394 #define TOK_LCHAR 0xb7
395 #define TOK_LSTR 0xb8
396 #define TOK_CFLOAT 0xb9 /* float constant */
397 #define TOK_LINENUM 0xba /* line number info */
398 #define TOK_CDOUBLE 0xc0 /* double constant */
399 #define TOK_CLDOUBLE 0xc1 /* long double constant */
400 #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
401 #define TOK_ADDC1 0xc3 /* add with carry generation */
402 #define TOK_ADDC2 0xc4 /* add with carry use */
403 #define TOK_SUBC1 0xc5 /* add with carry generation */
404 #define TOK_SUBC2 0xc6 /* add with carry use */
405 #define TOK_CUINT 0xc8 /* unsigned int constant */
406 #define TOK_CLLONG 0xc9 /* long long constant */
407 #define TOK_CULLONG 0xca /* unsigned long long constant */
408 #define TOK_ARROW 0xcb
409 #define TOK_DOTS 0xcc /* three dots */
410 #define TOK_SHR 0xcd /* unsigned shift right */
412 #define TOK_SHL 0x01 /* shift left */
413 #define TOK_SAR 0x02 /* signed shift right */
415 /* assignement operators : normal operator or 0x80 */
416 #define TOK_A_MOD 0xa5
417 #define TOK_A_AND 0xa6
418 #define TOK_A_MUL 0xaa
419 #define TOK_A_ADD 0xab
420 #define TOK_A_SUB 0xad
421 #define TOK_A_DIV 0xaf
422 #define TOK_A_XOR 0xde
423 #define TOK_A_OR 0xfc
424 #define TOK_A_SHL 0x81
425 #define TOK_A_SAR 0x82
427 #define TOK_EOF (-1) /* end of file */
429 /* all identificators and strings have token above that */
430 #define TOK_IDENT 256
432 enum {
433 TOK_INT = TOK_IDENT,
434 TOK_VOID,
435 TOK_CHAR,
436 TOK_IF,
437 TOK_ELSE,
438 TOK_WHILE,
439 TOK_BREAK,
440 TOK_RETURN,
441 TOK_FOR,
442 TOK_EXTERN,
443 TOK_STATIC,
444 TOK_UNSIGNED,
445 TOK_GOTO,
446 TOK_DO,
447 TOK_CONTINUE,
448 TOK_SWITCH,
449 TOK_CASE,
451 /* ignored types Must have contiguous values */
452 TOK_CONST,
453 TOK_VOLATILE,
454 TOK_LONG,
455 TOK_REGISTER,
456 TOK_SIGNED,
457 TOK___SIGNED__, /* gcc keyword */
458 TOK_AUTO,
459 TOK_INLINE,
460 TOK___INLINE__, /* gcc keyword */
461 TOK_RESTRICT,
463 /* unsupported type */
464 TOK_FLOAT,
465 TOK_DOUBLE,
466 TOK_BOOL,
468 TOK_SHORT,
469 TOK_STRUCT,
470 TOK_UNION,
471 TOK_TYPEDEF,
472 TOK_DEFAULT,
473 TOK_ENUM,
474 TOK_SIZEOF,
475 TOK___ATTRIBUTE__,
477 /* preprocessor only */
478 TOK_UIDENT, /* first "user" ident (not keyword) */
479 TOK_DEFINE = TOK_UIDENT,
480 TOK_INCLUDE,
481 TOK_IFDEF,
482 TOK_IFNDEF,
483 TOK_ELIF,
484 TOK_ENDIF,
485 TOK_DEFINED,
486 TOK_UNDEF,
487 TOK_ERROR,
488 TOK_LINE,
489 TOK___LINE__,
490 TOK___FILE__,
491 TOK___DATE__,
492 TOK___TIME__,
493 TOK___VA_ARGS__,
495 /* special identifiers */
496 TOK___FUNC__,
497 TOK_MAIN,
498 #define DEF(id, str) id,
499 #include "tcctok.h"
500 #undef DEF
503 char *tcc_keywords =
504 "int\0void\0char\0if\0else\0while\0break\0return\0for\0extern\0static\0"
505 "unsigned\0goto\0do\0continue\0switch\0case\0const\0volatile\0long\0"
506 "register\0signed\0__signed__\0auto\0inline\0__inline__\0restrict\0"
507 "float\0double\0_Bool\0short\0struct\0union\0typedef\0default\0enum\0"
508 "sizeof\0__attribute__\0"
509 /* the following are not keywords. They are included to ease parsing */
510 "define\0include\0ifdef\0ifndef\0elif\0endif\0"
511 "defined\0undef\0error\0line\0"
512 "__LINE__\0__FILE__\0__DATE__\0__TIME__\0__VA_ARGS__\0"
513 "__func__\0main\0"
514 /* builtin functions */
515 #define DEF(id, str) str "\0"
516 #include "tcctok.h"
517 #undef DEF
520 #ifdef WIN32
521 #define snprintf _snprintf
522 #endif
524 #if defined(WIN32) || defined(TCC_UCLIBC)
525 /* currently incorrect */
526 long double strtold(const char *nptr, char **endptr)
528 return (long double)strtod(nptr, endptr);
530 float strtof(const char *nptr, char **endptr)
532 return (float)strtod(nptr, endptr);
534 #else
535 /* XXX: need to define this to use them in non ISOC99 context */
536 extern float strtof (const char *__nptr, char **__endptr);
537 extern long double strtold (const char *__nptr, char **__endptr);
538 #endif
540 static char *pstrcpy(char *buf, int buf_size, const char *s);
541 static char *pstrcat(char *buf, int buf_size, const char *s);
543 void sum(int l);
544 void next(void);
545 void next_nomacro(void);
546 int expr_const(void);
547 void expr_eq(void);
548 void gexpr(void);
549 void decl(int l);
550 void decl_initializer(int t, Section *sec, unsigned long c, int first, int size_only);
551 void decl_initializer_alloc(int t, AttributeDef *ad, int r, int has_init,
552 int v, int scope);
553 int gv(int rc);
554 void gv2(int rc1, int rc2);
555 void move_reg(int r, int s);
556 void save_regs(int n);
557 void save_reg(int r);
558 void vpop(void);
559 void vswap(void);
560 void vdup(void);
561 int get_reg(int rc);
563 void macro_subst(TokenString *tok_str,
564 Sym **nested_list, int *macro_str);
565 int save_reg_forced(int r);
566 void gen_op(int op);
567 void force_charshort_cast(int t);
568 void gen_cast(int t);
569 void vstore(void);
570 Sym *sym_find(int v);
571 Sym *sym_push(int v, int t, int r, int c);
573 /* type handling */
574 int type_size(int t, int *a);
575 int pointed_type(int t);
576 int pointed_size(int t);
577 int is_compatible_types(int t1, int t2);
578 int parse_btype(int *type_ptr, AttributeDef *ad);
579 int type_decl(AttributeDef *ad, int *v, int t, int td);
581 void error(const char *fmt, ...);
582 void rt_error(unsigned long pc, const char *fmt, ...);
583 void vpushi(int v);
584 void vset(int t, int r, int v);
585 void type_to_str(char *buf, int buf_size,
586 int t, const char *varstr);
587 char *get_tok_str(int v, CValue *cv);
588 Sym *external_sym(int v, int u, int r);
590 /* section generation */
591 void put_extern_sym(Sym *sym, Section *section, unsigned long value);
592 void greloc(Section *s, Sym *sym, unsigned long addr, int type);
593 static int put_elf_str(Section *s, const char *sym);
594 static int put_elf_sym(Section *s,
595 unsigned long value, unsigned long size,
596 int info, int other, int shndx, const char *name);
597 static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
598 int type, int symbol);
599 static void put_stabs(const char *str, int type, int other, int desc, int value);
600 static void put_stabn(int type, int other, int desc, int value);
601 static void put_stabd(int type, int other, int desc);
602 static int tcc_add_dll(TCCState *s, const char *filename, int flags);
604 #define AFF_PRINT_ERROR 0x0001 /* print error if file not found */
605 #define AFF_REFERENCED_DLL 0x0002 /* load a referenced dll from another dll */
606 static int tcc_add_file_internal(TCCState *s, const char *filename, int flags);
608 /* true if float/double/long double type */
609 static inline int is_float(int t)
611 int bt;
612 bt = t & VT_BTYPE;
613 return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT;
616 #ifdef CONFIG_TCC_BCHECK
617 #include "bcheck.c"
618 #endif
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 /* push a reference to a section offset by adding a dummy symbol */
2498 void vpush_ref(int t, Section *sec, unsigned long offset)
2500 int v;
2501 Sym *sym;
2502 CValue cval;
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 cval.sym = sym;
2509 vsetc(t, VT_CONST | VT_SYM, &cval);
2512 /* push a reference to symbol v */
2513 void vpush_sym(int t, int v)
2515 Sym *sym;
2516 CValue cval;
2518 sym = external_sym(v, t, 0);
2519 cval.sym = sym;
2520 vsetc(t, VT_CONST | VT_SYM, &cval);
2523 void vset(int t, int r, int v)
2525 CValue cval;
2527 cval.i = v;
2528 vsetc(t, r, &cval);
2531 void vswap(void)
2533 SValue tmp;
2535 tmp = vtop[0];
2536 vtop[0] = vtop[-1];
2537 vtop[-1] = tmp;
2540 void vpushv(SValue *v)
2542 if (vtop >= vstack + VSTACK_SIZE)
2543 error("memory full");
2544 vtop++;
2545 *vtop = *v;
2548 void vdup(void)
2550 vpushv(vtop);
2553 /* save r to the memory stack, and mark it as being free */
2554 void save_reg(int r)
2556 int l, i, saved, t, size, align;
2557 SValue *p, sv;
2559 /* modify all stack values */
2560 saved = 0;
2561 l = 0;
2562 for(p=vstack;p<=vtop;p++) {
2563 i = p->r & VT_VALMASK;
2564 if ((p->r & VT_VALMASK) == r ||
2565 (p->r2 & VT_VALMASK) == r) {
2566 /* must save value on stack if not already done */
2567 if (!saved) {
2568 /* store register in the stack */
2569 t = p->t;
2570 if ((p->r & VT_LVAL) ||
2571 (!is_float(t) && (t & VT_BTYPE) != VT_LLONG))
2572 t = VT_INT;
2573 size = type_size(t, &align);
2574 loc = (loc - size) & -align;
2575 sv.t = t;
2576 sv.r = VT_LOCAL | VT_LVAL;
2577 sv.c.ul = loc;
2578 store(r, &sv);
2579 #ifdef TCC_TARGET_I386
2580 /* x86 specific: need to pop fp register ST0 if saved */
2581 if (r == REG_ST0) {
2582 o(0xd9dd); /* fstp %st(1) */
2584 #endif
2585 /* special long long case */
2586 if ((t & VT_BTYPE) == VT_LLONG) {
2587 sv.c.ul += 4;
2588 store(p->r2, &sv);
2590 l = loc;
2591 saved = 1;
2593 /* mark that stack entry as being saved on the stack */
2594 if (p->r & VT_LVAL)
2595 t = VT_LLOCAL;
2596 else
2597 t = VT_LOCAL;
2598 p->r = VT_LVAL | t;
2599 p->r2 = VT_CONST;
2600 p->c.ul = l;
2605 /* find a free register of class 'rc'. If none, save one register */
2606 int get_reg(int rc)
2608 int r;
2609 SValue *p;
2611 /* find a free register */
2612 for(r=0;r<NB_REGS;r++) {
2613 if (reg_classes[r] & rc) {
2614 for(p=vstack;p<=vtop;p++) {
2615 if ((p->r & VT_VALMASK) == r ||
2616 (p->r2 & VT_VALMASK) == r)
2617 goto notfound;
2619 return r;
2621 notfound: ;
2624 /* no register left : free the first one on the stack (VERY
2625 IMPORTANT to start from the bottom to ensure that we don't
2626 spill registers used in gen_opi()) */
2627 for(p=vstack;p<=vtop;p++) {
2628 r = p->r & VT_VALMASK;
2629 if (r < VT_CONST && (reg_classes[r] & rc)) {
2630 save_reg(r);
2631 break;
2634 return r;
2637 /* save registers up to (vtop - n) stack entry */
2638 void save_regs(int n)
2640 int r;
2641 SValue *p, *p1;
2642 p1 = vtop - n;
2643 for(p = vstack;p <= p1; p++) {
2644 r = p->r & VT_VALMASK;
2645 if (r < VT_CONST) {
2646 save_reg(r);
2651 /* move register 's' to 'r', and flush previous value of r to memory
2652 if needed */
2653 void move_reg(int r, int s)
2655 SValue sv;
2657 if (r != s) {
2658 save_reg(r);
2659 sv.t = VT_INT;
2660 sv.r = s;
2661 sv.c.ul = 0;
2662 load(r, &sv);
2666 /* get address of vtop (vtop MUST BE an lvalue) */
2667 void gaddrof(void)
2669 vtop->r &= ~VT_LVAL;
2670 /* tricky: if saved lvalue, then we can go back to lvalue */
2671 if ((vtop->r & VT_VALMASK) == VT_LLOCAL)
2672 vtop->r = (vtop->r & ~VT_VALMASK) | VT_LOCAL | VT_LVAL;
2675 #ifdef CONFIG_TCC_BCHECK
2676 /* generate lvalue bound code */
2677 void gbound(void)
2679 int lval_type;
2681 vtop->r &= ~VT_MUSTBOUND;
2682 /* if lvalue, then use checking code before dereferencing */
2683 if (vtop->r & VT_LVAL) {
2684 /* if not VT_BOUNDED value, then make one */
2685 if (!(vtop->r & VT_BOUNDED)) {
2686 lval_type = vtop->r & (VT_LVAL_TYPE | VT_LVAL);
2687 gaddrof();
2688 vpushi(0);
2689 gen_bounded_ptr_add();
2690 vtop->r |= lval_type;
2692 /* then check for dereferencing */
2693 gen_bounded_ptr_deref();
2696 #endif
2698 /* store vtop a register belonging to class 'rc'. lvalues are
2699 converted to values. Cannot be used if cannot be converted to
2700 register value (such as structures). */
2701 int gv(int rc)
2703 int r, r2, rc2, bit_pos, bit_size, size, align, i, data_offset;
2704 unsigned long long ll;
2706 /* NOTE: get_reg can modify vstack[] */
2707 if (vtop->t & VT_BITFIELD) {
2708 bit_pos = (vtop->t >> VT_STRUCT_SHIFT) & 0x3f;
2709 bit_size = (vtop->t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
2710 /* remove bit field info to avoid loops */
2711 vtop->t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
2712 /* generate shifts */
2713 vpushi(32 - (bit_pos + bit_size));
2714 gen_op(TOK_SHL);
2715 vpushi(32 - bit_size);
2716 /* NOTE: transformed to SHR if unsigned */
2717 gen_op(TOK_SAR);
2718 r = gv(rc);
2719 } else {
2720 if (is_float(vtop->t) &&
2721 (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
2722 int v;
2723 Sym *sym;
2725 /* XXX: unify with initializers handling ? */
2726 /* CPUs usually cannot use float constants, so we store them
2727 generically in data segment */
2728 size = type_size(vtop->t, &align);
2729 data_offset = data_section->data_ptr - data_section->data;
2730 data_offset = (data_offset + align - 1) & -align;
2731 /* XXX: not portable yet */
2732 size = size >> 2;
2733 for(i=0;i<size;i++)
2734 ((int *)(data_section->data + data_offset))[i] = vtop->c.tab[i];
2736 v = anon_sym++;
2737 sym = sym_push1(&global_stack, v, vtop->t | VT_STATIC, 0);
2738 sym->r = VT_CONST | VT_SYM;
2739 put_extern_sym(sym, data_section, data_offset);
2741 vtop->r |= VT_LVAL | VT_SYM;
2742 vtop->c.sym = sym;
2743 data_offset += size << 2;
2744 data_section->data_ptr = data_section->data + data_offset;
2746 #ifdef CONFIG_TCC_BCHECK
2747 if (vtop->r & VT_MUSTBOUND)
2748 gbound();
2749 #endif
2751 r = vtop->r & VT_VALMASK;
2752 /* need to reload if:
2753 - constant
2754 - lvalue (need to dereference pointer)
2755 - already a register, but not in the right class */
2756 if (r >= VT_CONST ||
2757 (vtop->r & VT_LVAL) ||
2758 !(reg_classes[r] & rc) ||
2759 ((vtop->t & VT_BTYPE) == VT_LLONG &&
2760 !(reg_classes[vtop->r2] & rc))) {
2761 r = get_reg(rc);
2762 if ((vtop->t & VT_BTYPE) == VT_LLONG) {
2763 /* two register type load : expand to two words
2764 temporarily */
2765 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
2766 /* load constant */
2767 ll = vtop->c.ull;
2768 vtop->c.ui = ll; /* first word */
2769 load(r, vtop);
2770 vtop->r = r; /* save register value */
2771 vpushi(ll >> 32); /* second word */
2772 } else if (r >= VT_CONST ||
2773 (vtop->r & VT_LVAL)) {
2774 /* load from memory */
2775 load(r, vtop);
2776 vdup();
2777 vtop[-1].r = r; /* save register value */
2778 /* increment pointer to get second word */
2779 vtop->t = VT_INT;
2780 gaddrof();
2781 vpushi(4);
2782 gen_op('+');
2783 vtop->r |= VT_LVAL;
2784 } else {
2785 /* move registers */
2786 load(r, vtop);
2787 vdup();
2788 vtop[-1].r = r; /* save register value */
2789 vtop->r = vtop[-1].r2;
2791 /* allocate second register */
2792 rc2 = RC_INT;
2793 if (rc == RC_IRET)
2794 rc2 = RC_LRET;
2795 r2 = get_reg(rc2);
2796 load(r2, vtop);
2797 vpop();
2798 /* write second register */
2799 vtop->r2 = r2;
2800 } else if ((vtop->r & VT_LVAL) && !is_float(vtop->t)) {
2801 int t1, t;
2802 /* lvalue of scalar type : need to use lvalue type
2803 because of possible cast */
2804 t = vtop->t;
2805 t1 = t;
2806 /* compute memory access type */
2807 if (vtop->r & VT_LVAL_BYTE)
2808 t = VT_BYTE;
2809 else if (vtop->r & VT_LVAL_SHORT)
2810 t = VT_SHORT;
2811 if (vtop->r & VT_LVAL_UNSIGNED)
2812 t |= VT_UNSIGNED;
2813 vtop->t = t;
2814 load(r, vtop);
2815 /* restore wanted type */
2816 vtop->t = t1;
2817 } else {
2818 /* one register type load */
2819 load(r, vtop);
2822 vtop->r = r;
2824 return r;
2827 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
2828 void gv2(int rc1, int rc2)
2830 /* generate more generic register first */
2831 if (rc1 <= rc2) {
2832 vswap();
2833 gv(rc1);
2834 vswap();
2835 gv(rc2);
2836 /* test if reload is needed for first register */
2837 if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
2838 vswap();
2839 gv(rc1);
2840 vswap();
2842 } else {
2843 gv(rc2);
2844 vswap();
2845 gv(rc1);
2846 vswap();
2847 /* test if reload is needed for first register */
2848 if ((vtop[0].r & VT_VALMASK) >= VT_CONST) {
2849 gv(rc2);
2854 /* expand long long on stack in two int registers */
2855 void lexpand(void)
2857 int u;
2859 u = vtop->t & VT_UNSIGNED;
2860 gv(RC_INT);
2861 vdup();
2862 vtop[0].r = vtop[-1].r2;
2863 vtop[0].r2 = VT_CONST;
2864 vtop[-1].r2 = VT_CONST;
2865 vtop[0].t = VT_INT | u;
2866 vtop[-1].t = VT_INT | u;
2869 /* build a long long from two ints */
2870 void lbuild(int t)
2872 gv2(RC_INT, RC_INT);
2873 vtop[-1].r2 = vtop[0].r;
2874 vtop[-1].t = t;
2875 vpop();
2878 /* rotate n first stack elements to the bottom */
2879 void vrotb(int n)
2881 int i;
2882 SValue tmp;
2884 tmp = vtop[-n + 1];
2885 for(i=-n+1;i!=0;i++)
2886 vtop[i] = vtop[i+1];
2887 vtop[0] = tmp;
2890 /* pop stack value */
2891 void vpop(void)
2893 int v;
2894 v = vtop->r & VT_VALMASK;
2895 #ifdef TCC_TARGET_I386
2896 /* for x86, we need to pop the FP stack */
2897 if (v == REG_ST0) {
2898 o(0xd9dd); /* fstp %st(1) */
2899 } else
2900 #endif
2901 if (v == VT_JMP || v == VT_JMPI) {
2902 /* need to put correct jump if && or || without test */
2903 gsym(vtop->c.ul);
2905 vtop--;
2908 /* convert stack entry to register and duplicate its value in another
2909 register */
2910 void gv_dup(void)
2912 int rc, t, r, r1;
2913 SValue sv;
2915 t = vtop->t;
2916 if ((t & VT_BTYPE) == VT_LLONG) {
2917 lexpand();
2918 gv_dup();
2919 vswap();
2920 vrotb(3);
2921 gv_dup();
2922 vrotb(4);
2923 /* stack: H L L1 H1 */
2924 lbuild(t);
2925 vrotb(3);
2926 vrotb(3);
2927 vswap();
2928 lbuild(t);
2929 vswap();
2930 } else {
2931 /* duplicate value */
2932 rc = RC_INT;
2933 sv.t = VT_INT;
2934 if (is_float(t)) {
2935 rc = RC_FLOAT;
2936 sv.t = t;
2938 r = gv(rc);
2939 r1 = get_reg(rc);
2940 sv.r = r;
2941 sv.c.ul = 0;
2942 load(r1, &sv); /* move r to r1 */
2943 vdup();
2944 /* duplicates value */
2945 vtop->r = r1;
2949 /* generate CPU independent (unsigned) long long operations */
2950 void gen_opl(int op)
2952 int t, a, b, op1, c, i;
2953 int func;
2954 GFuncContext gf;
2955 SValue tmp;
2957 switch(op) {
2958 case '/':
2959 case TOK_PDIV:
2960 func = TOK___divdi3;
2961 goto gen_func;
2962 case TOK_UDIV:
2963 func = TOK___udivdi3;
2964 goto gen_func;
2965 case '%':
2966 func = TOK___moddi3;
2967 goto gen_func;
2968 case TOK_UMOD:
2969 func = TOK___umoddi3;
2970 gen_func:
2971 /* call generic long long function */
2972 gfunc_start(&gf, FUNC_CDECL);
2973 gfunc_param(&gf);
2974 gfunc_param(&gf);
2975 vpush_sym(func_old_type, func);
2976 gfunc_call(&gf);
2977 vpushi(0);
2978 vtop->r = REG_IRET;
2979 vtop->r2 = REG_LRET;
2980 break;
2981 case '^':
2982 case '&':
2983 case '|':
2984 case '*':
2985 case '+':
2986 case '-':
2987 t = vtop->t;
2988 vswap();
2989 lexpand();
2990 vrotb(3);
2991 lexpand();
2992 /* stack: L1 H1 L2 H2 */
2993 tmp = vtop[0];
2994 vtop[0] = vtop[-3];
2995 vtop[-3] = tmp;
2996 tmp = vtop[-2];
2997 vtop[-2] = vtop[-3];
2998 vtop[-3] = tmp;
2999 vswap();
3000 /* stack: H1 H2 L1 L2 */
3001 if (op == '*') {
3002 vpushv(vtop - 1);
3003 vpushv(vtop - 1);
3004 gen_op(TOK_UMULL);
3005 lexpand();
3006 /* stack: H1 H2 L1 L2 ML MH */
3007 for(i=0;i<4;i++)
3008 vrotb(6);
3009 /* stack: ML MH H1 H2 L1 L2 */
3010 tmp = vtop[0];
3011 vtop[0] = vtop[-2];
3012 vtop[-2] = tmp;
3013 /* stack: ML MH H1 L2 H2 L1 */
3014 gen_op('*');
3015 vrotb(3);
3016 vrotb(3);
3017 gen_op('*');
3018 /* stack: ML MH M1 M2 */
3019 gen_op('+');
3020 gen_op('+');
3021 } else if (op == '+' || op == '-') {
3022 /* XXX: add non carry method too (for MIPS or alpha) */
3023 if (op == '+')
3024 op1 = TOK_ADDC1;
3025 else
3026 op1 = TOK_SUBC1;
3027 gen_op(op1);
3028 /* stack: H1 H2 (L1 op L2) */
3029 vrotb(3);
3030 vrotb(3);
3031 gen_op(op1 + 1); /* TOK_xxxC2 */
3032 } else {
3033 gen_op(op);
3034 /* stack: H1 H2 (L1 op L2) */
3035 vrotb(3);
3036 vrotb(3);
3037 /* stack: (L1 op L2) H1 H2 */
3038 gen_op(op);
3039 /* stack: (L1 op L2) (H1 op H2) */
3041 /* stack: L H */
3042 lbuild(t);
3043 break;
3044 case TOK_SAR:
3045 case TOK_SHR:
3046 case TOK_SHL:
3047 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
3048 t = vtop[-1].t;
3049 vswap();
3050 lexpand();
3051 vrotb(3);
3052 /* stack: L H shift */
3053 c = (int)vtop->c.i;
3054 /* constant: simpler */
3055 /* NOTE: all comments are for SHL. the other cases are
3056 done by swaping words */
3057 vpop();
3058 if (op != TOK_SHL)
3059 vswap();
3060 if (c >= 32) {
3061 /* stack: L H */
3062 vpop();
3063 if (c > 32) {
3064 vpushi(c - 32);
3065 gen_op(op);
3067 if (op != TOK_SAR) {
3068 vpushi(0);
3069 } else {
3070 gv_dup();
3071 vpushi(31);
3072 gen_op(TOK_SAR);
3074 vswap();
3075 } else {
3076 vswap();
3077 gv_dup();
3078 /* stack: H L L */
3079 vpushi(c);
3080 gen_op(op);
3081 vswap();
3082 vpushi(32 - c);
3083 if (op == TOK_SHL)
3084 gen_op(TOK_SHR);
3085 else
3086 gen_op(TOK_SHL);
3087 vrotb(3);
3088 /* stack: L L H */
3089 vpushi(c);
3090 gen_op(op);
3091 gen_op('|');
3093 if (op != TOK_SHL)
3094 vswap();
3095 lbuild(t);
3096 } else {
3097 /* XXX: should provide a faster fallback on x86 ? */
3098 switch(op) {
3099 case TOK_SAR:
3100 func = TOK___sardi3;
3101 goto gen_func;
3102 case TOK_SHR:
3103 func = TOK___shrdi3;
3104 goto gen_func;
3105 case TOK_SHL:
3106 func = TOK___shldi3;
3107 goto gen_func;
3110 break;
3111 default:
3112 /* compare operations */
3113 t = vtop->t;
3114 vswap();
3115 lexpand();
3116 vrotb(3);
3117 lexpand();
3118 /* stack: L1 H1 L2 H2 */
3119 tmp = vtop[-1];
3120 vtop[-1] = vtop[-2];
3121 vtop[-2] = tmp;
3122 /* stack: L1 L2 H1 H2 */
3123 /* compare high */
3124 op1 = op;
3125 /* when values are equal, we need to compare low words. since
3126 the jump is inverted, we invert the test too. */
3127 if (op1 == TOK_LT)
3128 op1 = TOK_LE;
3129 else if (op1 == TOK_GT)
3130 op1 = TOK_GE;
3131 else if (op1 == TOK_ULT)
3132 op1 = TOK_ULE;
3133 else if (op1 == TOK_UGT)
3134 op1 = TOK_UGE;
3135 a = 0;
3136 b = 0;
3137 gen_op(op1);
3138 if (op1 != TOK_NE) {
3139 a = gtst(1, 0);
3141 if (op != TOK_EQ) {
3142 /* generate non equal test */
3143 /* XXX: NOT PORTABLE yet */
3144 if (a == 0) {
3145 b = gtst(0, 0);
3146 } else {
3147 #ifdef TCC_TARGET_I386
3148 b = psym(0x850f, 0);
3149 #else
3150 error("not implemented");
3151 #endif
3154 /* compare low */
3155 gen_op(op);
3156 a = gtst(1, a);
3157 gsym(b);
3158 vset(VT_INT, VT_JMPI, a);
3159 break;
3163 /* handle integer constant optimizations and various machine
3164 independant opt */
3165 void gen_opic(int op)
3167 int fc, c1, c2, n;
3168 SValue *v1, *v2;
3170 v1 = vtop - 1;
3171 v2 = vtop;
3172 /* currently, we cannot do computations with forward symbols */
3173 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
3174 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
3175 if (c1 && c2) {
3176 fc = v2->c.i;
3177 switch(op) {
3178 case '+': v1->c.i += fc; break;
3179 case '-': v1->c.i -= fc; break;
3180 case '&': v1->c.i &= fc; break;
3181 case '^': v1->c.i ^= fc; break;
3182 case '|': v1->c.i |= fc; break;
3183 case '*': v1->c.i *= fc; break;
3185 case TOK_PDIV:
3186 case '/':
3187 case '%':
3188 case TOK_UDIV:
3189 case TOK_UMOD:
3190 /* if division by zero, generate explicit division */
3191 if (fc == 0) {
3192 if (const_wanted)
3193 error("division by zero in constant");
3194 goto general_case;
3196 switch(op) {
3197 default: v1->c.i /= fc; break;
3198 case '%': v1->c.i %= fc; break;
3199 case TOK_UDIV: v1->c.i = (unsigned)v1->c.i / fc; break;
3200 case TOK_UMOD: v1->c.i = (unsigned)v1->c.i % fc; break;
3202 break;
3203 case TOK_SHL: v1->c.i <<= fc; break;
3204 case TOK_SHR: v1->c.i = (unsigned)v1->c.i >> fc; break;
3205 case TOK_SAR: v1->c.i >>= fc; break;
3206 /* tests */
3207 case TOK_ULT: v1->c.i = (unsigned)v1->c.i < (unsigned)fc; break;
3208 case TOK_UGE: v1->c.i = (unsigned)v1->c.i >= (unsigned)fc; break;
3209 case TOK_EQ: v1->c.i = v1->c.i == fc; break;
3210 case TOK_NE: v1->c.i = v1->c.i != fc; break;
3211 case TOK_ULE: v1->c.i = (unsigned)v1->c.i <= (unsigned)fc; break;
3212 case TOK_UGT: v1->c.i = (unsigned)v1->c.i > (unsigned)fc; break;
3213 case TOK_LT: v1->c.i = v1->c.i < fc; break;
3214 case TOK_GE: v1->c.i = v1->c.i >= fc; break;
3215 case TOK_LE: v1->c.i = v1->c.i <= fc; break;
3216 case TOK_GT: v1->c.i = v1->c.i > fc; break;
3217 /* logical */
3218 case TOK_LAND: v1->c.i = v1->c.i && fc; break;
3219 case TOK_LOR: v1->c.i = v1->c.i || fc; break;
3220 default:
3221 goto general_case;
3223 vtop--;
3224 } else {
3225 /* if commutative ops, put c2 as constant */
3226 if (c1 && (op == '+' || op == '&' || op == '^' ||
3227 op == '|' || op == '*')) {
3228 vswap();
3229 swap(&c1, &c2);
3231 fc = vtop->c.i;
3232 if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
3233 op == TOK_PDIV) &&
3234 fc == 1) ||
3235 ((op == '+' || op == '-' || op == '|' || op == '^' ||
3236 op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
3237 fc == 0) ||
3238 (op == '&' &&
3239 fc == -1))) {
3240 /* nothing to do */
3241 vtop--;
3242 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
3243 /* try to use shifts instead of muls or divs */
3244 if (fc > 0 && (fc & (fc - 1)) == 0) {
3245 n = -1;
3246 while (fc) {
3247 fc >>= 1;
3248 n++;
3250 vtop->c.i = n;
3251 if (op == '*')
3252 op = TOK_SHL;
3253 else if (op == TOK_PDIV)
3254 op = TOK_SAR;
3255 else
3256 op = TOK_SHR;
3258 goto general_case;
3259 } else {
3260 general_case:
3261 /* call low level op generator */
3262 gen_opi(op);
3267 /* generate a floating point operation with constant propagation */
3268 void gen_opif(int op)
3270 int c1, c2;
3271 SValue *v1, *v2;
3272 long double f1, f2;
3274 v1 = vtop - 1;
3275 v2 = vtop;
3276 /* currently, we cannot do computations with forward symbols */
3277 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
3278 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
3279 if (c1 && c2) {
3280 if (v1->t == VT_FLOAT) {
3281 f1 = v1->c.f;
3282 f2 = v2->c.f;
3283 } else if (v1->t == VT_DOUBLE) {
3284 f1 = v1->c.d;
3285 f2 = v2->c.d;
3286 } else {
3287 f1 = v1->c.ld;
3288 f2 = v2->c.ld;
3291 /* NOTE: we only do constant propagation if finite number (not
3292 NaN or infinity) (ANSI spec) */
3293 if (!ieee_finite(f1) || !ieee_finite(f2))
3294 goto general_case;
3296 switch(op) {
3297 case '+': f1 += f2; break;
3298 case '-': f1 -= f2; break;
3299 case '*': f1 *= f2; break;
3300 case '/':
3301 if (f2 == 0.0) {
3302 if (const_wanted)
3303 error("division by zero in constant");
3304 goto general_case;
3306 f1 /= f2;
3307 break;
3308 /* XXX: also handles tests ? */
3309 default:
3310 goto general_case;
3312 /* XXX: overflow test ? */
3313 if (v1->t == VT_FLOAT) {
3314 v1->c.f = f1;
3315 } else if (v1->t == VT_DOUBLE) {
3316 v1->c.d = f1;
3317 } else {
3318 v1->c.ld = f1;
3320 vtop--;
3321 } else {
3322 general_case:
3323 gen_opf(op);
3328 int pointed_size(int t)
3330 return type_size(pointed_type(t), &t);
3333 #if 0
3334 void check_pointer_types(SValue *p1, SValue *p2)
3336 char buf1[256], buf2[256];
3337 int t1, t2;
3338 t1 = p1->t;
3339 t2 = p2->t;
3340 if (!is_compatible_types(t1, t2)) {
3341 type_to_str(buf1, sizeof(buf1), t1, NULL);
3342 type_to_str(buf2, sizeof(buf2), t2, NULL);
3343 error("incompatible pointers '%s' and '%s'", buf1, buf2);
3346 #endif
3348 /* generic gen_op: handles types problems */
3349 void gen_op(int op)
3351 int u, t1, t2, bt1, bt2, t;
3353 t1 = vtop[-1].t;
3354 t2 = vtop[0].t;
3355 bt1 = t1 & VT_BTYPE;
3356 bt2 = t2 & VT_BTYPE;
3358 if (bt1 == VT_PTR || bt2 == VT_PTR) {
3359 /* at least one operand is a pointer */
3360 /* relationnal op: must be both pointers */
3361 if (op >= TOK_ULT && op <= TOK_GT) {
3362 // check_pointer_types(vtop, vtop - 1);
3363 /* pointers are handled are unsigned */
3364 t = VT_INT | VT_UNSIGNED;
3365 goto std_op;
3367 /* if both pointers, then it must be the '-' op */
3368 if ((t1 & VT_BTYPE) == VT_PTR &&
3369 (t2 & VT_BTYPE) == VT_PTR) {
3370 if (op != '-')
3371 error("cannot use pointers here");
3372 // check_pointer_types(vtop - 1, vtop);
3373 /* XXX: check that types are compatible */
3374 u = pointed_size(t1);
3375 gen_opic(op);
3376 /* set to integer type */
3377 vtop->t = VT_INT;
3378 vpushi(u);
3379 gen_op(TOK_PDIV);
3380 } else {
3381 /* exactly one pointer : must be '+' or '-'. */
3382 if (op != '-' && op != '+')
3383 error("cannot use pointers here");
3384 /* Put pointer as first operand */
3385 if ((t2 & VT_BTYPE) == VT_PTR) {
3386 vswap();
3387 swap(&t1, &t2);
3389 /* XXX: cast to int ? (long long case) */
3390 vpushi(pointed_size(vtop[-1].t));
3391 gen_op('*');
3392 #ifdef CONFIG_TCC_BCHECK
3393 /* if evaluating constant expression, no code should be
3394 generated, so no bound check */
3395 if (do_bounds_check && !const_wanted) {
3396 /* if bounded pointers, we generate a special code to
3397 test bounds */
3398 if (op == '-') {
3399 vpushi(0);
3400 vswap();
3401 gen_op('-');
3403 gen_bounded_ptr_add();
3404 } else
3405 #endif
3407 gen_opic(op);
3409 /* put again type if gen_opic() swaped operands */
3410 vtop->t = t1;
3412 } else if (is_float(bt1) || is_float(bt2)) {
3413 /* compute bigger type and do implicit casts */
3414 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
3415 t = VT_LDOUBLE;
3416 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
3417 t = VT_DOUBLE;
3418 } else {
3419 t = VT_FLOAT;
3421 /* floats can only be used for a few operations */
3422 if (op != '+' && op != '-' && op != '*' && op != '/' &&
3423 (op < TOK_ULT || op > TOK_GT))
3424 error("invalid operands for binary operation");
3425 goto std_op;
3426 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
3427 /* cast to biggest op */
3428 t = VT_LLONG;
3429 /* convert to unsigned if it does not fit in a long long */
3430 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
3431 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
3432 t |= VT_UNSIGNED;
3433 goto std_op;
3434 } else {
3435 /* integer operations */
3436 t = VT_INT;
3437 /* convert to unsigned if it does not fit in an integer */
3438 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
3439 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
3440 t |= VT_UNSIGNED;
3441 std_op:
3442 /* XXX: currently, some unsigned operations are explicit, so
3443 we modify them here */
3444 if (t & VT_UNSIGNED) {
3445 if (op == TOK_SAR)
3446 op = TOK_SHR;
3447 else if (op == '/')
3448 op = TOK_UDIV;
3449 else if (op == '%')
3450 op = TOK_UMOD;
3451 else if (op == TOK_LT)
3452 op = TOK_ULT;
3453 else if (op == TOK_GT)
3454 op = TOK_UGT;
3455 else if (op == TOK_LE)
3456 op = TOK_ULE;
3457 else if (op == TOK_GE)
3458 op = TOK_UGE;
3460 vswap();
3461 gen_cast(t);
3462 vswap();
3463 /* special case for shifts and long long: we keep the shift as
3464 an integer */
3465 if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL)
3466 gen_cast(VT_INT);
3467 else
3468 gen_cast(t);
3469 if (is_float(t))
3470 gen_opif(op);
3471 else if ((t & VT_BTYPE) == VT_LLONG)
3472 gen_opl(op);
3473 else
3474 gen_opic(op);
3475 if (op >= TOK_ULT && op <= TOK_GT) {
3476 /* relationnal op: the result is an int */
3477 vtop->t = VT_INT;
3478 } else {
3479 vtop->t = t;
3484 /* generic itof for unsigned long long case */
3485 void gen_cvt_itof1(int t)
3487 GFuncContext gf;
3489 if ((vtop->t & (VT_BTYPE | VT_UNSIGNED)) ==
3490 (VT_LLONG | VT_UNSIGNED)) {
3492 gfunc_start(&gf, FUNC_CDECL);
3493 gfunc_param(&gf);
3494 if (t == VT_FLOAT)
3495 vpush_sym(func_old_type, TOK___ulltof);
3496 else if (t == VT_DOUBLE)
3497 vpush_sym(func_old_type, TOK___ulltod);
3498 else
3499 vpush_sym(func_old_type, TOK___ulltold);
3500 gfunc_call(&gf);
3501 vpushi(0);
3502 vtop->r = REG_FRET;
3503 } else {
3504 gen_cvt_itof(t);
3508 /* generic ftoi for unsigned long long case */
3509 void gen_cvt_ftoi1(int t)
3511 GFuncContext gf;
3512 int st;
3514 if (t == (VT_LLONG | VT_UNSIGNED)) {
3515 /* not handled natively */
3516 gfunc_start(&gf, FUNC_CDECL);
3517 st = vtop->t & VT_BTYPE;
3518 gfunc_param(&gf);
3519 if (st == VT_FLOAT)
3520 vpush_sym(func_old_type, TOK___fixunssfdi);
3521 else if (st == VT_DOUBLE)
3522 vpush_sym(func_old_type, TOK___fixunsdfdi);
3523 else
3524 vpush_sym(func_old_type, TOK___fixunsxfdi);
3525 gfunc_call(&gf);
3526 vpushi(0);
3527 vtop->r = REG_IRET;
3528 vtop->r2 = REG_LRET;
3529 } else {
3530 gen_cvt_ftoi(t);
3534 /* force char or short cast */
3535 void force_charshort_cast(int t)
3537 int bits, dbt;
3538 dbt = t & VT_BTYPE;
3539 /* XXX: add optimization if lvalue : just change type and offset */
3540 if (dbt == VT_BYTE)
3541 bits = 8;
3542 else
3543 bits = 16;
3544 if (t & VT_UNSIGNED) {
3545 vpushi((1 << bits) - 1);
3546 gen_op('&');
3547 } else {
3548 bits = 32 - bits;
3549 vpushi(bits);
3550 gen_op(TOK_SHL);
3551 vpushi(bits);
3552 gen_op(TOK_SAR);
3556 /* cast 'vtop' to 't' type */
3557 void gen_cast(int t)
3559 int sbt, dbt, sf, df, c;
3561 /* special delayed cast for char/short */
3562 /* XXX: in some cases (multiple cascaded casts), it may still
3563 be incorrect */
3564 if (vtop->r & VT_MUSTCAST) {
3565 vtop->r &= ~VT_MUSTCAST;
3566 force_charshort_cast(vtop->t);
3569 dbt = t & (VT_BTYPE | VT_UNSIGNED);
3570 sbt = vtop->t & (VT_BTYPE | VT_UNSIGNED);
3572 if (sbt != dbt) {
3573 sf = is_float(sbt);
3574 df = is_float(dbt);
3575 c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
3576 if (sf && df) {
3577 /* convert from fp to fp */
3578 if (c) {
3579 /* constant case: we can do it now */
3580 /* XXX: in ISOC, cannot do it if error in convert */
3581 if (dbt == VT_FLOAT && sbt == VT_DOUBLE)
3582 vtop->c.f = (float)vtop->c.d;
3583 else if (dbt == VT_FLOAT && sbt == VT_LDOUBLE)
3584 vtop->c.f = (float)vtop->c.ld;
3585 else if (dbt == VT_DOUBLE && sbt == VT_FLOAT)
3586 vtop->c.d = (double)vtop->c.f;
3587 else if (dbt == VT_DOUBLE && sbt == VT_LDOUBLE)
3588 vtop->c.d = (double)vtop->c.ld;
3589 else if (dbt == VT_LDOUBLE && sbt == VT_FLOAT)
3590 vtop->c.ld = (long double)vtop->c.f;
3591 else if (dbt == VT_LDOUBLE && sbt == VT_DOUBLE)
3592 vtop->c.ld = (long double)vtop->c.d;
3593 } else {
3594 /* non constant case: generate code */
3595 gen_cvt_ftof(dbt);
3597 } else if (df) {
3598 /* convert int to fp */
3599 if (c) {
3600 switch(sbt) {
3601 case VT_LLONG | VT_UNSIGNED:
3602 case VT_LLONG:
3603 /* XXX: add const cases for long long */
3604 goto do_itof;
3605 case VT_INT | VT_UNSIGNED:
3606 switch(dbt) {
3607 case VT_FLOAT: vtop->c.f = (float)vtop->c.ui; break;
3608 case VT_DOUBLE: vtop->c.d = (double)vtop->c.ui; break;
3609 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.ui; break;
3611 break;
3612 default:
3613 switch(dbt) {
3614 case VT_FLOAT: vtop->c.f = (float)vtop->c.i; break;
3615 case VT_DOUBLE: vtop->c.d = (double)vtop->c.i; break;
3616 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.i; break;
3618 break;
3620 } else {
3621 do_itof:
3622 gen_cvt_itof1(dbt);
3624 } else if (sf) {
3625 /* convert fp to int */
3626 /* we handle char/short/etc... with generic code */
3627 if (dbt != (VT_INT | VT_UNSIGNED) &&
3628 dbt != (VT_LLONG | VT_UNSIGNED) &&
3629 dbt != VT_LLONG)
3630 dbt = VT_INT;
3631 if (c) {
3632 switch(dbt) {
3633 case VT_LLONG | VT_UNSIGNED:
3634 case VT_LLONG:
3635 /* XXX: add const cases for long long */
3636 goto do_ftoi;
3637 case VT_INT | VT_UNSIGNED:
3638 switch(sbt) {
3639 case VT_FLOAT: vtop->c.ui = (unsigned int)vtop->c.d; break;
3640 case VT_DOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
3641 case VT_LDOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
3643 break;
3644 default:
3645 /* int case */
3646 switch(sbt) {
3647 case VT_FLOAT: vtop->c.i = (int)vtop->c.d; break;
3648 case VT_DOUBLE: vtop->c.i = (int)vtop->c.d; break;
3649 case VT_LDOUBLE: vtop->c.i = (int)vtop->c.d; break;
3651 break;
3653 } else {
3654 do_ftoi:
3655 gen_cvt_ftoi1(dbt);
3657 if (dbt == VT_INT && (t & (VT_BTYPE | VT_UNSIGNED)) != dbt) {
3658 /* additionnal cast for char/short/bool... */
3659 vtop->t = dbt;
3660 gen_cast(t);
3662 } else if ((dbt & VT_BTYPE) == VT_LLONG) {
3663 if ((sbt & VT_BTYPE) != VT_LLONG) {
3664 /* scalar to long long */
3665 if (c) {
3666 if (sbt == (VT_INT | VT_UNSIGNED))
3667 vtop->c.ll = vtop->c.ui;
3668 else
3669 vtop->c.ll = vtop->c.i;
3670 } else {
3671 /* machine independant conversion */
3672 gv(RC_INT);
3673 /* generate high word */
3674 if (sbt == (VT_INT | VT_UNSIGNED)) {
3675 vpushi(0);
3676 gv(RC_INT);
3677 } else {
3678 gv_dup();
3679 vpushi(31);
3680 gen_op(TOK_SAR);
3682 /* patch second register */
3683 vtop[-1].r2 = vtop->r;
3684 vpop();
3687 } else if (dbt == VT_BOOL) {
3688 /* scalar to bool */
3689 vpushi(0);
3690 gen_op(TOK_NE);
3691 } else if ((dbt & VT_BTYPE) == VT_BYTE ||
3692 (dbt & VT_BTYPE) == VT_SHORT) {
3693 force_charshort_cast(t);
3694 } else if ((dbt & VT_BTYPE) == VT_INT) {
3695 /* scalar to int */
3696 if (sbt == VT_LLONG) {
3697 /* from long long: just take low order word */
3698 lexpand();
3699 vpop();
3701 /* if lvalue and single word type, nothing to do because
3702 the lvalue already contains the real type size (see
3703 VT_LVAL_xxx constants) */
3706 vtop->t = t;
3709 /* return type size. Put alignment at 'a' */
3710 int type_size(int t, int *a)
3712 Sym *s;
3713 int bt;
3715 bt = t & VT_BTYPE;
3716 if (bt == VT_STRUCT) {
3717 /* struct/union */
3718 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
3719 *a = 4; /* XXX: cannot store it yet. Doing that is safe */
3720 return s->c;
3721 } else if (bt == VT_PTR) {
3722 if (t & VT_ARRAY) {
3723 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
3724 return type_size(s->t, a) * s->c;
3725 } else {
3726 *a = PTR_SIZE;
3727 return PTR_SIZE;
3729 } else if (bt == VT_LDOUBLE) {
3730 *a = LDOUBLE_ALIGN;
3731 return LDOUBLE_SIZE;
3732 } else if (bt == VT_DOUBLE || bt == VT_LLONG) {
3733 *a = 8;
3734 return 8;
3735 } else if (bt == VT_INT || bt == VT_ENUM || bt == VT_FLOAT) {
3736 *a = 4;
3737 return 4;
3738 } else if (bt == VT_SHORT) {
3739 *a = 2;
3740 return 2;
3741 } else {
3742 /* char, void, function, _Bool */
3743 *a = 1;
3744 return 1;
3748 /* return the pointed type of t */
3749 int pointed_type(int t)
3751 Sym *s;
3752 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
3753 return s->t | (t & ~VT_TYPE);
3756 int mk_pointer(int t)
3758 int p;
3759 p = anon_sym++;
3760 sym_push(p, t, 0, -1);
3761 return VT_PTR | (p << VT_STRUCT_SHIFT) | (t & ~VT_TYPE);
3764 int is_compatible_types(int t1, int t2)
3766 Sym *s1, *s2;
3767 int bt1, bt2;
3769 t1 &= VT_TYPE;
3770 t2 &= VT_TYPE;
3771 bt1 = t1 & VT_BTYPE;
3772 bt2 = t2 & VT_BTYPE;
3773 if (bt1 == VT_PTR) {
3774 t1 = pointed_type(t1);
3775 /* if function, then convert implicitely to function pointer */
3776 if (bt2 != VT_FUNC) {
3777 if (bt2 != VT_PTR)
3778 return 0;
3779 t2 = pointed_type(t2);
3781 /* void matches everything */
3782 t1 &= VT_TYPE;
3783 t2 &= VT_TYPE;
3784 if (t1 == VT_VOID || t2 == VT_VOID)
3785 return 1;
3786 return is_compatible_types(t1, t2);
3787 } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
3788 return (t2 == t1);
3789 } else if (bt1 == VT_FUNC) {
3790 if (bt2 != VT_FUNC)
3791 return 0;
3792 s1 = sym_find(((unsigned)t1 >> VT_STRUCT_SHIFT));
3793 s2 = sym_find(((unsigned)t2 >> VT_STRUCT_SHIFT));
3794 if (!is_compatible_types(s1->t, s2->t))
3795 return 0;
3796 /* XXX: not complete */
3797 if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
3798 return 1;
3799 if (s1->c != s2->c)
3800 return 0;
3801 while (s1 != NULL) {
3802 if (s2 == NULL)
3803 return 0;
3804 if (!is_compatible_types(s1->t, s2->t))
3805 return 0;
3806 s1 = s1->next;
3807 s2 = s2->next;
3809 if (s2)
3810 return 0;
3811 return 1;
3812 } else {
3813 /* XXX: not complete */
3814 return 1;
3818 /* print a type. If 'varstr' is not NULL, then the variable is also
3819 printed in the type */
3820 /* XXX: union */
3821 /* XXX: add array and function pointers */
3822 void type_to_str(char *buf, int buf_size,
3823 int t, const char *varstr)
3825 int bt, v;
3826 Sym *s, *sa;
3827 char buf1[256];
3828 const char *tstr;
3830 t = t & VT_TYPE;
3831 bt = t & VT_BTYPE;
3832 buf[0] = '\0';
3833 if (t & VT_UNSIGNED)
3834 pstrcat(buf, buf_size, "unsigned ");
3835 switch(bt) {
3836 case VT_VOID:
3837 tstr = "void";
3838 goto add_tstr;
3839 case VT_BOOL:
3840 tstr = "_Bool";
3841 goto add_tstr;
3842 case VT_BYTE:
3843 tstr = "char";
3844 goto add_tstr;
3845 case VT_SHORT:
3846 tstr = "short";
3847 goto add_tstr;
3848 case VT_INT:
3849 tstr = "int";
3850 goto add_tstr;
3851 case VT_LONG:
3852 tstr = "long";
3853 goto add_tstr;
3854 case VT_LLONG:
3855 tstr = "long long";
3856 goto add_tstr;
3857 case VT_FLOAT:
3858 tstr = "float";
3859 goto add_tstr;
3860 case VT_DOUBLE:
3861 tstr = "double";
3862 goto add_tstr;
3863 case VT_LDOUBLE:
3864 tstr = "long double";
3865 add_tstr:
3866 pstrcat(buf, buf_size, tstr);
3867 break;
3868 case VT_ENUM:
3869 case VT_STRUCT:
3870 if (bt == VT_STRUCT)
3871 tstr = "struct ";
3872 else
3873 tstr = "enum ";
3874 pstrcat(buf, buf_size, tstr);
3875 v = (unsigned)t >> VT_STRUCT_SHIFT;
3876 if (v >= SYM_FIRST_ANOM)
3877 pstrcat(buf, buf_size, "<anonymous>");
3878 else
3879 pstrcat(buf, buf_size, get_tok_str(v, NULL));
3880 break;
3881 case VT_FUNC:
3882 s = sym_find((unsigned)t >> VT_STRUCT_SHIFT);
3883 type_to_str(buf, buf_size, s->t, varstr);
3884 pstrcat(buf, buf_size, "(");
3885 sa = s->next;
3886 while (sa != NULL) {
3887 type_to_str(buf1, sizeof(buf1), sa->t, NULL);
3888 pstrcat(buf, buf_size, buf1);
3889 sa = sa->next;
3890 if (sa)
3891 pstrcat(buf, buf_size, ", ");
3893 pstrcat(buf, buf_size, ")");
3894 goto no_var;
3895 case VT_PTR:
3896 s = sym_find((unsigned)t >> VT_STRUCT_SHIFT);
3897 pstrcpy(buf1, sizeof(buf1), "*");
3898 if (varstr)
3899 pstrcat(buf1, sizeof(buf1), varstr);
3900 type_to_str(buf, buf_size, s->t, buf1);
3901 goto no_var;
3903 if (varstr) {
3904 pstrcat(buf, buf_size, " ");
3905 pstrcat(buf, buf_size, varstr);
3907 no_var: ;
3910 /* verify type compatibility to store vtop in 'dt' type, and generate
3911 casts if needed. */
3912 void gen_assign_cast(int dt)
3914 int st;
3915 char buf1[256], buf2[256];
3917 st = vtop->t; /* source type */
3918 if ((dt & VT_BTYPE) == VT_PTR) {
3919 /* special cases for pointers */
3920 /* a function is implicitely a function pointer */
3921 if ((st & VT_BTYPE) == VT_FUNC) {
3922 if (!is_compatible_types(pointed_type(dt), st))
3923 goto error;
3924 else
3925 goto type_ok;
3927 /* '0' can also be a pointer */
3928 if ((st & VT_BTYPE) == VT_INT &&
3929 ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) &&
3930 vtop->c.i == 0)
3931 goto type_ok;
3933 if (!is_compatible_types(dt, st)) {
3934 error:
3935 type_to_str(buf1, sizeof(buf1), st, NULL);
3936 type_to_str(buf2, sizeof(buf2), dt, NULL);
3937 error("cannot cast '%s' to '%s'", buf1, buf2);
3939 type_ok:
3940 gen_cast(dt);
3943 /* store vtop in lvalue pushed on stack */
3944 void vstore(void)
3946 int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
3947 GFuncContext gf;
3949 ft = vtop[-1].t;
3950 sbt = vtop->t & VT_BTYPE;
3951 dbt = ft & VT_BTYPE;
3952 if (((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
3953 (sbt == VT_INT && dbt == VT_SHORT)) {
3954 /* optimize char/short casts */
3955 delayed_cast = VT_MUSTCAST;
3956 vtop->t = ft & VT_TYPE;
3957 } else {
3958 delayed_cast = 0;
3959 gen_assign_cast(ft & VT_TYPE);
3962 if (sbt == VT_STRUCT) {
3963 /* if structure, only generate pointer */
3964 /* structure assignment : generate memcpy */
3965 /* XXX: optimize if small size */
3966 vdup();
3967 gfunc_start(&gf, FUNC_CDECL);
3968 /* type size */
3969 size = type_size(vtop->t, &align);
3970 vpushi(size);
3971 gfunc_param(&gf);
3972 /* source */
3973 vtop->t = VT_INT;
3974 gaddrof();
3975 gfunc_param(&gf);
3976 /* destination */
3977 vswap();
3978 vtop->t = VT_INT;
3979 gaddrof();
3980 gfunc_param(&gf);
3982 save_regs(0);
3983 vpush_sym(func_old_type, TOK_memcpy);
3984 gfunc_call(&gf);
3985 /* leave source on stack */
3986 } else if (ft & VT_BITFIELD) {
3987 /* bitfield store handling */
3988 bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
3989 bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
3990 /* remove bit field info to avoid loops */
3991 vtop[-1].t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
3993 /* duplicate destination */
3994 vdup();
3995 vtop[-1] = vtop[-2];
3997 /* mask and shift source */
3998 vpushi((1 << bit_size) - 1);
3999 gen_op('&');
4000 vpushi(bit_pos);
4001 gen_op(TOK_SHL);
4002 /* load destination, mask and or with source */
4003 vswap();
4004 vpushi(~(((1 << bit_size) - 1) << bit_pos));
4005 gen_op('&');
4006 gen_op('|');
4007 /* store result */
4008 vstore();
4009 } else {
4010 #ifdef CONFIG_TCC_BCHECK
4011 /* bound check case */
4012 if (vtop[-1].r & VT_MUSTBOUND) {
4013 vswap();
4014 gbound();
4015 vswap();
4017 #endif
4018 rc = RC_INT;
4019 if (is_float(ft))
4020 rc = RC_FLOAT;
4021 r = gv(rc); /* generate value */
4022 /* if lvalue was saved on stack, must read it */
4023 if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
4024 SValue sv;
4025 t = get_reg(RC_INT);
4026 sv.t = VT_INT;
4027 sv.r = VT_LOCAL | VT_LVAL;
4028 sv.c.ul = vtop[-1].c.ul;
4029 load(t, &sv);
4030 vtop[-1].r = t | VT_LVAL;
4032 store(r, vtop - 1);
4033 /* two word case handling : store second register at word + 4 */
4034 if ((ft & VT_BTYPE) == VT_LLONG) {
4035 vswap();
4036 /* convert to int to increment easily */
4037 vtop->t = VT_INT;
4038 gaddrof();
4039 vpushi(4);
4040 gen_op('+');
4041 vtop->r |= VT_LVAL;
4042 vswap();
4043 /* XXX: it works because r2 is spilled last ! */
4044 store(vtop->r2, vtop - 1);
4046 vswap();
4047 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
4048 vtop->r |= delayed_cast;
4052 /* post defines POST/PRE add. c is the token ++ or -- */
4053 void inc(int post, int c)
4055 test_lvalue();
4056 vdup(); /* save lvalue */
4057 if (post) {
4058 gv_dup(); /* duplicate value */
4059 vrotb(3);
4060 vrotb(3);
4062 /* add constant */
4063 vpushi(c - TOK_MID);
4064 gen_op('+');
4065 vstore(); /* store value */
4066 if (post)
4067 vpop(); /* if post op, return saved value */
4070 /* Parse GNUC __attribute__ extension. Currently, the following
4071 extensions are recognized:
4072 - aligned(n) : set data/function alignment.
4073 - section(x) : generate data/code in this section.
4074 - unused : currently ignored, but may be used someday.
4076 void parse_attribute(AttributeDef *ad)
4078 int t, n;
4080 next();
4081 skip('(');
4082 skip('(');
4083 while (tok != ')') {
4084 if (tok < TOK_IDENT)
4085 expect("attribute name");
4086 t = tok;
4087 next();
4088 switch(t) {
4089 case TOK_SECTION:
4090 case TOK___SECTION__:
4091 skip('(');
4092 if (tok != TOK_STR)
4093 expect("section name");
4094 ad->section = find_section(tokc.ts->str);
4095 next();
4096 skip(')');
4097 break;
4098 case TOK_ALIGNED:
4099 case TOK___ALIGNED__:
4100 skip('(');
4101 n = expr_const();
4102 if (n <= 0 || (n & (n - 1)) != 0)
4103 error("alignment must be a positive power of two");
4104 ad->aligned = n;
4105 skip(')');
4106 break;
4107 case TOK_UNUSED:
4108 case TOK___UNUSED__:
4109 /* currently, no need to handle it because tcc does not
4110 track unused objects */
4111 break;
4112 case TOK_NORETURN:
4113 case TOK___NORETURN__:
4114 /* currently, no need to handle it because tcc does not
4115 track unused objects */
4116 break;
4117 case TOK_CDECL:
4118 case TOK___CDECL:
4119 case TOK___CDECL__:
4120 ad->func_call = FUNC_CDECL;
4121 break;
4122 case TOK_STDCALL:
4123 case TOK___STDCALL:
4124 case TOK___STDCALL__:
4125 ad->func_call = FUNC_STDCALL;
4126 break;
4127 default:
4128 warning("'%s' attribute ignored", get_tok_str(t, NULL));
4129 /* skip parameters */
4130 /* XXX: skip parenthesis too */
4131 if (tok == '(') {
4132 next();
4133 while (tok != ')' && tok != -1)
4134 next();
4135 next();
4137 break;
4139 if (tok != ',')
4140 break;
4141 next();
4143 skip(')');
4144 skip(')');
4147 /* enum/struct/union declaration */
4148 int struct_decl(int u)
4150 int a, t, b, v, size, align, maxalign, c, offset;
4151 int bit_size, bit_pos, bsize, bt, lbit_pos;
4152 Sym *s, *ss, **ps;
4153 AttributeDef ad;
4155 a = tok; /* save decl type */
4156 next();
4157 if (tok != '{') {
4158 v = tok;
4159 next();
4160 /* struct already defined ? return it */
4161 /* XXX: check consistency */
4162 s = sym_find(v | SYM_STRUCT);
4163 if (s) {
4164 if (s->t != a)
4165 error("invalid type");
4166 goto do_decl;
4168 } else {
4169 v = anon_sym++;
4171 s = sym_push(v | SYM_STRUCT, a, 0, 0);
4172 /* put struct/union/enum name in type */
4173 do_decl:
4174 u = u | (v << VT_STRUCT_SHIFT);
4176 if (tok == '{') {
4177 next();
4178 if (s->c)
4179 error("struct/union/enum already defined");
4180 /* cannot be empty */
4181 c = 0;
4182 maxalign = 0;
4183 ps = &s->next;
4184 bit_pos = 0;
4185 offset = 0;
4186 while (1) {
4187 if (a == TOK_ENUM) {
4188 v = tok;
4189 next();
4190 if (tok == '=') {
4191 next();
4192 c = expr_const();
4194 /* enum symbols have static storage */
4195 sym_push(v, VT_STATIC | VT_INT, VT_CONST, c);
4196 if (tok == ',')
4197 next();
4198 c++;
4199 } else {
4200 parse_btype(&b, &ad);
4201 while (1) {
4202 bit_size = -1;
4203 v = 0;
4204 if (tok != ':') {
4205 t = type_decl(&ad, &v, b, TYPE_DIRECT);
4206 if ((t & VT_BTYPE) == VT_FUNC ||
4207 (t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN)))
4208 error("invalid type for '%s'",
4209 get_tok_str(v, NULL));
4210 } else {
4211 t = b;
4213 if (tok == ':') {
4214 next();
4215 bit_size = expr_const();
4216 /* XXX: handle v = 0 case for messages */
4217 if (bit_size < 0)
4218 error("negative width in bit-field '%s'",
4219 get_tok_str(v, NULL));
4220 if (v && bit_size == 0)
4221 error("zero width for bit-field '%s'",
4222 get_tok_str(v, NULL));
4224 size = type_size(t, &align);
4225 lbit_pos = 0;
4226 if (bit_size >= 0) {
4227 bt = t & VT_BTYPE;
4228 if (bt != VT_INT &&
4229 bt != VT_BYTE &&
4230 bt != VT_SHORT)
4231 error("bitfields must have scalar type");
4232 bsize = size * 8;
4233 if (bit_size > bsize) {
4234 error("width of '%s' exceeds its type",
4235 get_tok_str(v, NULL));
4236 } else if (bit_size == bsize) {
4237 /* no need for bit fields */
4238 bit_pos = 0;
4239 } else if (bit_size == 0) {
4240 /* XXX: what to do if only padding in a
4241 structure ? */
4242 /* zero size: means to pad */
4243 if (bit_pos > 0)
4244 bit_pos = bsize;
4245 } else {
4246 /* we do not have enough room ? */
4247 if ((bit_pos + bit_size) > bsize)
4248 bit_pos = 0;
4249 lbit_pos = bit_pos;
4250 /* XXX: handle LSB first */
4251 t |= VT_BITFIELD |
4252 (bit_pos << VT_STRUCT_SHIFT) |
4253 (bit_size << (VT_STRUCT_SHIFT + 6));
4254 bit_pos += bit_size;
4256 } else {
4257 bit_pos = 0;
4259 if (v) {
4260 /* add new memory data only if starting
4261 bit field */
4262 if (lbit_pos == 0) {
4263 if (a == TOK_STRUCT) {
4264 c = (c + align - 1) & -align;
4265 offset = c;
4266 c += size;
4267 } else {
4268 offset = 0;
4269 if (size > c)
4270 c = size;
4272 if (align > maxalign)
4273 maxalign = align;
4275 #if 0
4276 printf("add field %s offset=%d",
4277 get_tok_str(v, NULL), offset);
4278 if (t & VT_BITFIELD) {
4279 printf(" pos=%d size=%d",
4280 (t >> VT_STRUCT_SHIFT) & 0x3f,
4281 (t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
4283 printf("\n");
4284 #endif
4285 ss = sym_push(v | SYM_FIELD, t, 0, offset);
4286 *ps = ss;
4287 ps = &ss->next;
4289 if (tok == ';' || tok == -1)
4290 break;
4291 skip(',');
4293 skip(';');
4295 if (tok == '}')
4296 break;
4298 skip('}');
4299 /* size for struct/union, dummy for enum */
4300 s->c = (c + maxalign - 1) & -maxalign;
4302 return u;
4305 /* return 0 if no type declaration. otherwise, return the basic type
4306 and skip it.
4308 int parse_btype(int *type_ptr, AttributeDef *ad)
4310 int t, u, type_found;
4311 Sym *s;
4313 memset(ad, 0, sizeof(AttributeDef));
4314 type_found = 0;
4315 t = 0;
4316 while(1) {
4317 switch(tok) {
4318 /* basic types */
4319 case TOK_CHAR:
4320 u = VT_BYTE;
4321 basic_type:
4322 next();
4323 basic_type1:
4324 if ((t & VT_BTYPE) != 0)
4325 error("too many basic types");
4326 t |= u;
4327 break;
4328 case TOK_VOID:
4329 u = VT_VOID;
4330 goto basic_type;
4331 case TOK_SHORT:
4332 u = VT_SHORT;
4333 goto basic_type;
4334 case TOK_INT:
4335 next();
4336 break;
4337 case TOK_LONG:
4338 next();
4339 if ((t & VT_BTYPE) == VT_DOUBLE) {
4340 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
4341 } else if ((t & VT_BTYPE) == VT_LONG) {
4342 t = (t & ~VT_BTYPE) | VT_LLONG;
4343 } else {
4344 u = VT_LONG;
4345 goto basic_type1;
4347 break;
4348 case TOK_BOOL:
4349 u = VT_BOOL;
4350 goto basic_type;
4351 case TOK_FLOAT:
4352 u = VT_FLOAT;
4353 goto basic_type;
4354 case TOK_DOUBLE:
4355 next();
4356 if ((t & VT_BTYPE) == VT_LONG) {
4357 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
4358 } else {
4359 u = VT_DOUBLE;
4360 goto basic_type1;
4362 break;
4363 case TOK_ENUM:
4364 u = struct_decl(VT_ENUM);
4365 goto basic_type1;
4366 case TOK_STRUCT:
4367 case TOK_UNION:
4368 u = struct_decl(VT_STRUCT);
4369 goto basic_type1;
4371 /* type modifiers */
4372 case TOK_CONST:
4373 case TOK_VOLATILE:
4374 case TOK_REGISTER:
4375 case TOK_SIGNED:
4376 case TOK___SIGNED__:
4377 case TOK_AUTO:
4378 case TOK_INLINE:
4379 case TOK___INLINE__:
4380 case TOK_RESTRICT:
4381 next();
4382 break;
4383 case TOK_UNSIGNED:
4384 t |= VT_UNSIGNED;
4385 next();
4386 break;
4388 /* storage */
4389 case TOK_EXTERN:
4390 t |= VT_EXTERN;
4391 next();
4392 break;
4393 case TOK_STATIC:
4394 t |= VT_STATIC;
4395 next();
4396 break;
4397 case TOK_TYPEDEF:
4398 t |= VT_TYPEDEF;
4399 next();
4400 break;
4401 /* GNUC attribute */
4402 case TOK___ATTRIBUTE__:
4403 parse_attribute(ad);
4404 break;
4405 default:
4406 s = sym_find(tok);
4407 if (!s || !(s->t & VT_TYPEDEF))
4408 goto the_end;
4409 t |= (s->t & ~VT_TYPEDEF);
4410 next();
4411 break;
4413 type_found = 1;
4415 the_end:
4416 /* long is never used as type */
4417 if ((t & VT_BTYPE) == VT_LONG)
4418 t = (t & ~VT_BTYPE) | VT_INT;
4419 *type_ptr = t;
4420 return type_found;
4423 int post_type(int t, AttributeDef *ad)
4425 int p, n, pt, l, t1;
4426 Sym **plast, *s, *first;
4427 AttributeDef ad1;
4429 if (tok == '(') {
4430 /* function declaration */
4431 next();
4432 l = 0;
4433 first = NULL;
4434 plast = &first;
4435 while (tok != ')') {
4436 /* read param name and compute offset */
4437 if (l != FUNC_OLD) {
4438 if (!parse_btype(&pt, &ad1)) {
4439 if (l) {
4440 error("invalid type");
4441 } else {
4442 l = FUNC_OLD;
4443 goto old_proto;
4446 l = FUNC_NEW;
4447 if ((pt & VT_BTYPE) == VT_VOID && tok == ')')
4448 break;
4449 pt = type_decl(&ad1, &n, pt, TYPE_DIRECT | TYPE_ABSTRACT);
4450 if ((pt & VT_BTYPE) == VT_VOID)
4451 error("parameter declared as void");
4452 } else {
4453 old_proto:
4454 n = tok;
4455 pt = VT_INT;
4456 next();
4458 /* array must be transformed to pointer according to ANSI C */
4459 pt &= ~VT_ARRAY;
4460 s = sym_push(n | SYM_FIELD, pt, 0, 0);
4461 *plast = s;
4462 plast = &s->next;
4463 if (tok == ',') {
4464 next();
4465 if (l == FUNC_NEW && tok == TOK_DOTS) {
4466 l = FUNC_ELLIPSIS;
4467 next();
4468 break;
4472 /* if no parameters, then old type prototype */
4473 if (l == 0)
4474 l = FUNC_OLD;
4475 skip(')');
4476 t1 = t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN);
4477 t = post_type(t & ~(VT_TYPEDEF | VT_STATIC | VT_EXTERN), ad);
4478 /* we push a anonymous symbol which will contain the function prototype */
4479 p = anon_sym++;
4480 s = sym_push(p, t, ad->func_call, l);
4481 s->next = first;
4482 t = t1 | VT_FUNC | (p << VT_STRUCT_SHIFT);
4483 } else if (tok == '[') {
4484 /* array definition */
4485 next();
4486 n = -1;
4487 if (tok != ']') {
4488 n = expr_const();
4489 if (n < 0)
4490 error("invalid array size");
4492 skip(']');
4493 /* parse next post type */
4494 t1 = t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN);
4495 t = post_type(t & ~(VT_TYPEDEF | VT_STATIC | VT_EXTERN), ad);
4497 /* we push a anonymous symbol which will contain the array
4498 element type */
4499 p = anon_sym++;
4500 sym_push(p, t, 0, n);
4501 t = t1 | VT_ARRAY | VT_PTR | (p << VT_STRUCT_SHIFT);
4503 return t;
4506 /* Read a type declaration (except basic type), and return the
4507 type. 'td' is a bitmask indicating which kind of type decl is
4508 expected. 't' should contain the basic type. 'ad' is the attribute
4509 definition of the basic type. It can be modified by type_decl(). */
4510 int type_decl(AttributeDef *ad, int *v, int t, int td)
4512 int u, p;
4513 Sym *s;
4515 while (tok == '*') {
4516 next();
4517 while (tok == TOK_CONST || tok == TOK_VOLATILE || tok == TOK_RESTRICT)
4518 next();
4519 t = mk_pointer(t);
4522 /* recursive type */
4523 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
4524 if (tok == '(') {
4525 next();
4526 /* XXX: this is not correct to modify 'ad' at this point, but
4527 the syntax is not clear */
4528 if (tok == TOK___ATTRIBUTE__)
4529 parse_attribute(ad);
4530 u = type_decl(ad, v, 0, td);
4531 skip(')');
4532 } else {
4533 u = 0;
4534 /* type identifier */
4535 if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
4536 *v = tok;
4537 next();
4538 } else {
4539 if (!(td & TYPE_ABSTRACT))
4540 expect("identifier");
4541 *v = 0;
4544 /* append t at the end of u */
4545 t = post_type(t, ad);
4546 if (tok == TOK___ATTRIBUTE__)
4547 parse_attribute(ad);
4548 if (!u)
4549 return t;
4550 p = u;
4551 while(1) {
4552 s = sym_find((unsigned)p >> VT_STRUCT_SHIFT);
4553 p = s->t;
4554 if (!p) {
4555 s->t = t;
4556 break;
4559 return u;
4562 /* define a new external reference to a symbol 'v' of type 'u' */
4563 Sym *external_sym(int v, int u, int r)
4565 Sym *s;
4567 s = sym_find(v);
4568 if (!s) {
4569 /* push forward reference */
4570 s = sym_push1(&global_stack,
4571 v, u | VT_EXTERN, 0);
4572 s->r = r | VT_CONST | VT_SYM;
4574 return s;
4577 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
4578 static int lvalue_type(int t)
4580 int bt, r;
4581 r = VT_LVAL;
4582 bt = t & VT_BTYPE;
4583 if (bt == VT_BYTE)
4584 r |= VT_LVAL_BYTE;
4585 else if (bt == VT_SHORT)
4586 r |= VT_LVAL_SHORT;
4587 else
4588 return r;
4589 if (t & VT_UNSIGNED)
4590 r |= VT_LVAL_UNSIGNED;
4591 return r;
4594 /* indirection with full error checking and bound check */
4595 static void indir(void)
4597 if ((vtop->t & VT_BTYPE) != VT_PTR)
4598 expect("pointer");
4599 if (vtop->r & VT_LVAL)
4600 gv(RC_INT);
4601 vtop->t = pointed_type(vtop->t);
4602 /* an array is never an lvalue */
4603 if (!(vtop->t & VT_ARRAY)) {
4604 vtop->r |= lvalue_type(vtop->t);
4605 /* if bound checking, the referenced pointer must be checked */
4606 if (do_bounds_check)
4607 vtop->r |= VT_MUSTBOUND;
4611 /* pass a parameter to a function and do type checking and casting */
4612 void gfunc_param_typed(GFuncContext *gf, Sym *func, Sym *arg)
4614 int func_type;
4615 func_type = func->c;
4616 if (func_type == FUNC_OLD ||
4617 (func_type == FUNC_ELLIPSIS && arg == NULL)) {
4618 /* default casting : only need to convert float to double */
4619 if ((vtop->t & VT_BTYPE) == VT_FLOAT)
4620 gen_cast(VT_DOUBLE);
4621 } else if (arg == NULL) {
4622 error("too many arguments to function");
4623 } else {
4624 gen_assign_cast(arg->t);
4626 gfunc_param(gf);
4629 void unary(void)
4631 int n, t, ft, fc, align, size, r, data_offset;
4632 Sym *s;
4633 GFuncContext gf;
4634 AttributeDef ad;
4636 if (tok == TOK_CINT || tok == TOK_CCHAR || tok == TOK_LCHAR) {
4637 vpushi(tokc.i);
4638 next();
4639 } else if (tok == TOK_CUINT) {
4640 vsetc(VT_INT | VT_UNSIGNED, VT_CONST, &tokc);
4641 next();
4642 } else if (tok == TOK_CLLONG) {
4643 vsetc(VT_LLONG, VT_CONST, &tokc);
4644 next();
4645 } else if (tok == TOK_CULLONG) {
4646 vsetc(VT_LLONG | VT_UNSIGNED, VT_CONST, &tokc);
4647 next();
4648 } else if (tok == TOK_CFLOAT) {
4649 vsetc(VT_FLOAT, VT_CONST, &tokc);
4650 next();
4651 } else if (tok == TOK_CDOUBLE) {
4652 vsetc(VT_DOUBLE, VT_CONST, &tokc);
4653 next();
4654 } else if (tok == TOK_CLDOUBLE) {
4655 vsetc(VT_LDOUBLE, VT_CONST, &tokc);
4656 next();
4657 } else if (tok == TOK___FUNC__) {
4658 /* special function name identifier */
4659 /* generate (char *) type */
4660 data_offset = data_section->data_ptr - data_section->data;
4661 vpush_ref(mk_pointer(VT_BYTE), data_section, data_offset);
4662 strcpy(data_section->data + data_offset, funcname);
4663 data_offset += strlen(funcname) + 1;
4664 data_section->data_ptr = data_section->data + data_offset;
4665 next();
4666 } else if (tok == TOK_LSTR) {
4667 t = VT_INT;
4668 goto str_init;
4669 } else if (tok == TOK_STR) {
4670 /* string parsing */
4671 t = VT_BYTE;
4672 str_init:
4673 type_size(t, &align);
4674 data_offset = data_section->data_ptr - data_section->data;
4675 data_offset = (data_offset + align - 1) & -align;
4676 fc = data_offset;
4677 /* we must declare it as an array first to use initializer parser */
4678 t = VT_ARRAY | mk_pointer(t);
4679 decl_initializer(t, data_section, data_offset, 1, 0);
4680 data_offset += type_size(t, &align);
4681 /* put it as pointer */
4682 vpush_ref(t & ~VT_ARRAY, data_section, fc);
4683 data_section->data_ptr = data_section->data + data_offset;
4684 } else {
4685 t = tok;
4686 next();
4687 if (t == '(') {
4688 /* cast ? */
4689 if (parse_btype(&t, &ad)) {
4690 ft = type_decl(&ad, &n, t, TYPE_ABSTRACT);
4691 skip(')');
4692 /* check ISOC99 compound literal */
4693 if (tok == '{') {
4694 /* data is allocated locally by default */
4695 if (global_expr)
4696 r = VT_CONST;
4697 else
4698 r = VT_LOCAL;
4699 /* all except arrays are lvalues */
4700 if (!(ft & VT_ARRAY))
4701 r |= lvalue_type(ft);
4702 memset(&ad, 0, sizeof(AttributeDef));
4703 decl_initializer_alloc(ft, &ad, r, 1, 0, 0);
4704 } else {
4705 unary();
4706 gen_cast(ft);
4708 } else {
4709 gexpr();
4710 skip(')');
4712 } else if (t == '*') {
4713 unary();
4714 indir();
4715 } else if (t == '&') {
4716 unary();
4717 /* functions names must be treated as function pointers,
4718 except for unary '&' and sizeof. Since we consider that
4719 functions are not lvalues, we only have to handle it
4720 there and in function calls. */
4721 /* arrays can also be used although they are not lvalues */
4722 if ((vtop->t & VT_BTYPE) != VT_FUNC &&
4723 !(vtop->t & VT_ARRAY))
4724 test_lvalue();
4725 vtop->t = mk_pointer(vtop->t);
4726 gaddrof();
4727 } else
4728 if (t == '!') {
4729 unary();
4730 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST)
4731 vtop->c.i = !vtop->c.i;
4732 else if ((vtop->r & VT_VALMASK) == VT_CMP)
4733 vtop->c.i = vtop->c.i ^ 1;
4734 else
4735 vset(VT_INT, VT_JMP, gtst(1, 0));
4736 } else
4737 if (t == '~') {
4738 unary();
4739 vpushi(-1);
4740 gen_op('^');
4741 } else
4742 if (t == '+') {
4743 unary();
4744 } else
4745 if (t == TOK_SIZEOF) {
4746 if (tok == '(') {
4747 next();
4748 if (parse_btype(&t, &ad)) {
4749 t = type_decl(&ad, &n, t, TYPE_ABSTRACT);
4750 } else {
4751 /* XXX: some code could be generated: add eval
4752 flag */
4753 gexpr();
4754 t = vtop->t;
4755 vpop();
4757 skip(')');
4758 } else {
4759 unary();
4760 t = vtop->t;
4761 vpop();
4763 vpushi(type_size(t, &t));
4764 } else
4765 if (t == TOK_INC || t == TOK_DEC) {
4766 unary();
4767 inc(0, t);
4768 } else if (t == '-') {
4769 vpushi(0);
4770 unary();
4771 gen_op('-');
4772 } else
4774 if (t < TOK_UIDENT)
4775 expect("identifier");
4776 s = sym_find(t);
4777 if (!s) {
4778 if (tok != '(')
4779 error("'%s' undeclared", get_tok_str(t, NULL));
4780 /* for simple function calls, we tolerate undeclared
4781 external reference to int() function */
4782 s = external_sym(t, func_old_type, 0);
4784 vset(s->t, s->r, s->c);
4785 /* if forward reference, we must point to s */
4786 if (vtop->r & VT_SYM)
4787 vtop->c.sym = s;
4791 /* post operations */
4792 while (1) {
4793 if (tok == TOK_INC || tok == TOK_DEC) {
4794 inc(1, tok);
4795 next();
4796 } else if (tok == '.' || tok == TOK_ARROW) {
4797 /* field */
4798 if (tok == TOK_ARROW)
4799 indir();
4800 test_lvalue();
4801 gaddrof();
4802 next();
4803 /* expect pointer on structure */
4804 if ((vtop->t & VT_BTYPE) != VT_STRUCT)
4805 expect("struct or union");
4806 s = sym_find(((unsigned)vtop->t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
4807 /* find field */
4808 tok |= SYM_FIELD;
4809 while ((s = s->next) != NULL) {
4810 if (s->v == tok)
4811 break;
4813 if (!s)
4814 error("field not found");
4815 /* add field offset to pointer */
4816 vtop->t = char_pointer_type; /* change type to 'char *' */
4817 vpushi(s->c);
4818 gen_op('+');
4819 /* change type to field type, and set to lvalue */
4820 vtop->t = s->t;
4821 /* an array is never an lvalue */
4822 if (!(vtop->t & VT_ARRAY))
4823 vtop->r |= lvalue_type(vtop->t);
4824 next();
4825 } else if (tok == '[') {
4826 next();
4827 gexpr();
4828 gen_op('+');
4829 indir();
4830 skip(']');
4831 } else if (tok == '(') {
4832 SValue ret;
4833 Sym *sa;
4835 /* function call */
4836 if ((vtop->t & VT_BTYPE) != VT_FUNC) {
4837 /* pointer test (no array accepted) */
4838 if ((vtop->t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
4839 vtop->t = pointed_type(vtop->t);
4840 if ((vtop->t & VT_BTYPE) != VT_FUNC)
4841 goto error_func;
4842 } else {
4843 error_func:
4844 expect("function pointer");
4846 } else {
4847 vtop->r &= ~VT_LVAL; /* no lvalue */
4849 /* get return type */
4850 s = sym_find((unsigned)vtop->t >> VT_STRUCT_SHIFT);
4851 save_regs(0); /* save used temporary registers */
4852 gfunc_start(&gf, s->r);
4853 next();
4854 sa = s->next; /* first parameter */
4855 #ifdef INVERT_FUNC_PARAMS
4857 int parlevel;
4858 Sym *args, *s1;
4859 ParseState saved_parse_state;
4860 TokenString str;
4862 /* read each argument and store it on a stack */
4863 /* XXX: merge it with macro args ? */
4864 args = NULL;
4865 if (tok != ')') {
4866 for(;;) {
4867 tok_str_new(&str);
4868 parlevel = 0;
4869 while ((parlevel > 0 || (tok != ')' && tok != ',')) &&
4870 tok != -1) {
4871 if (tok == '(')
4872 parlevel++;
4873 else if (tok == ')')
4874 parlevel--;
4875 tok_str_add_tok(&str);
4876 next();
4878 tok_str_add(&str, -1); /* end of file added */
4879 tok_str_add(&str, 0);
4880 s1 = sym_push2(&args, 0, 0, (int)str.str);
4881 s1->next = sa; /* add reference to argument */
4882 if (sa)
4883 sa = sa->next;
4884 if (tok == ')')
4885 break;
4886 skip(',');
4890 /* now generate code in reverse order by reading the stack */
4891 save_parse_state(&saved_parse_state);
4892 while (args) {
4893 macro_ptr = (int *)args->c;
4894 next();
4895 expr_eq();
4896 if (tok != -1)
4897 expect("',' or ')'");
4898 gfunc_param_typed(&gf, s, args->next);
4899 s1 = args->prev;
4900 free((int *)args->c);
4901 free(args);
4902 args = s1;
4904 restore_parse_state(&saved_parse_state);
4906 #endif
4907 /* compute first implicit argument if a structure is returned */
4908 if ((s->t & VT_BTYPE) == VT_STRUCT) {
4909 /* get some space for the returned structure */
4910 size = type_size(s->t, &align);
4911 loc = (loc - size) & -align;
4912 ret.t = s->t;
4913 ret.r = VT_LOCAL | VT_LVAL;
4914 /* pass it as 'int' to avoid structure arg passing
4915 problems */
4916 vset(VT_INT, VT_LOCAL, loc);
4917 ret.c = vtop->c;
4918 gfunc_param(&gf);
4919 } else {
4920 ret.t = s->t;
4921 ret.r2 = VT_CONST;
4922 /* return in register */
4923 if (is_float(ret.t)) {
4924 ret.r = REG_FRET;
4925 } else {
4926 if ((ret.t & VT_BTYPE) == VT_LLONG)
4927 ret.r2 = REG_LRET;
4928 ret.r = REG_IRET;
4930 ret.c.i = 0;
4932 #ifndef INVERT_FUNC_PARAMS
4933 if (tok != ')') {
4934 for(;;) {
4935 expr_eq();
4936 gfunc_param_typed(&gf, s, sa);
4937 if (sa)
4938 sa = sa->next;
4939 if (tok == ')')
4940 break;
4941 skip(',');
4944 #endif
4945 if (sa)
4946 error("too few arguments to function");
4947 skip(')');
4948 gfunc_call(&gf);
4949 /* return value */
4950 vsetc(ret.t, ret.r, &ret.c);
4951 vtop->r2 = ret.r2;
4952 } else {
4953 break;
4958 void uneq(void)
4960 int t;
4962 unary();
4963 if (tok == '=' ||
4964 (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
4965 tok == TOK_A_XOR || tok == TOK_A_OR ||
4966 tok == TOK_A_SHL || tok == TOK_A_SAR) {
4967 test_lvalue();
4968 t = tok;
4969 next();
4970 if (t == '=') {
4971 expr_eq();
4972 } else {
4973 vdup();
4974 expr_eq();
4975 gen_op(t & 0x7f);
4977 vstore();
4981 void sum(int l)
4983 int t;
4985 if (l == 0)
4986 uneq();
4987 else {
4988 sum(--l);
4989 while ((l == 0 && (tok == '*' || tok == '/' || tok == '%')) ||
4990 (l == 1 && (tok == '+' || tok == '-')) ||
4991 (l == 2 && (tok == TOK_SHL || tok == TOK_SAR)) ||
4992 (l == 3 && ((tok >= TOK_ULE && tok <= TOK_GT) ||
4993 tok == TOK_ULT || tok == TOK_UGE)) ||
4994 (l == 4 && (tok == TOK_EQ || tok == TOK_NE)) ||
4995 (l == 5 && tok == '&') ||
4996 (l == 6 && tok == '^') ||
4997 (l == 7 && tok == '|') ||
4998 (l == 8 && tok == TOK_LAND) ||
4999 (l == 9 && tok == TOK_LOR)) {
5000 t = tok;
5001 next();
5002 sum(l);
5003 gen_op(t);
5008 /* only used if non constant */
5009 void eand(void)
5011 int t;
5013 sum(8);
5014 t = 0;
5015 while (1) {
5016 if (tok != TOK_LAND) {
5017 if (t) {
5018 t = gtst(1, t);
5019 vset(VT_INT, VT_JMPI, t);
5021 break;
5023 t = gtst(1, t);
5024 next();
5025 sum(8);
5029 void eor(void)
5031 int t;
5033 eand();
5034 t = 0;
5035 while (1) {
5036 if (tok != TOK_LOR) {
5037 if (t) {
5038 t = gtst(0, t);
5039 vset(VT_INT, VT_JMP, t);
5041 break;
5043 t = gtst(0, t);
5044 next();
5045 eand();
5049 /* XXX: better constant handling */
5050 void expr_eq(void)
5052 int t, u, c, r1, r2, rc;
5054 if (const_wanted) {
5055 sum(10);
5056 if (tok == '?') {
5057 c = vtop->c.i;
5058 vpop();
5059 next();
5060 gexpr();
5061 t = vtop->c.i;
5062 vpop();
5063 skip(':');
5064 expr_eq();
5065 if (c)
5066 vtop->c.i = t;
5068 } else {
5069 eor();
5070 if (tok == '?') {
5071 next();
5072 save_regs(1); /* we need to save all registers here except
5073 at the top because it is a branch point */
5074 t = gtst(1, 0);
5075 gexpr();
5076 /* XXX: long long handling ? */
5077 rc = RC_INT;
5078 if (is_float(vtop->t))
5079 rc = RC_FLOAT;
5080 r1 = gv(rc);
5081 vtop--; /* no vpop so that FP stack is not flushed */
5082 skip(':');
5083 u = gjmp(0);
5085 gsym(t);
5086 expr_eq();
5087 r2 = gv(rc);
5088 move_reg(r1, r2);
5089 vtop->r = r1;
5090 gsym(u);
5095 void gexpr(void)
5097 while (1) {
5098 expr_eq();
5099 if (tok != ',')
5100 break;
5101 vpop();
5102 next();
5106 /* parse a constant expression and return value in vtop */
5107 void expr_const1(void)
5109 int a;
5110 a = const_wanted;
5111 const_wanted = 1;
5112 expr_eq();
5113 if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST)
5114 expect("constant");
5115 const_wanted = a;
5118 /* parse an integer constant and return its value */
5119 int expr_const(void)
5121 int c;
5122 expr_const1();
5123 c = vtop->c.i;
5124 vpop();
5125 return c;
5128 /* return the label token if current token is a label, otherwise
5129 return zero */
5130 int is_label(void)
5132 int t;
5133 CValue c;
5135 /* fast test first */
5136 if (tok < TOK_UIDENT)
5137 return 0;
5138 /* no need to save tokc since we expect an identifier */
5139 t = tok;
5140 c = tokc;
5141 next();
5142 if (tok == ':') {
5143 next();
5144 return t;
5145 } else {
5146 /* XXX: may not work in all cases (macros ?) */
5147 tok1 = tok;
5148 tok1c = tokc;
5149 tok = t;
5150 tokc = c;
5151 return 0;
5155 void block(int *bsym, int *csym, int *case_sym, int *def_sym, int case_reg)
5157 int a, b, c, d;
5158 Sym *s;
5160 /* generate line number info */
5161 if (do_debug &&
5162 (last_line_num != file->line_num || last_ind != ind)) {
5163 put_stabn(N_SLINE, 0, file->line_num, ind - func_ind);
5164 last_ind = ind;
5165 last_line_num = file->line_num;
5168 if (tok == TOK_IF) {
5169 /* if test */
5170 next();
5171 skip('(');
5172 gexpr();
5173 skip(')');
5174 a = gtst(1, 0);
5175 block(bsym, csym, case_sym, def_sym, case_reg);
5176 c = tok;
5177 if (c == TOK_ELSE) {
5178 next();
5179 d = gjmp(0);
5180 gsym(a);
5181 block(bsym, csym, case_sym, def_sym, case_reg);
5182 gsym(d); /* patch else jmp */
5183 } else
5184 gsym(a);
5185 } else if (tok == TOK_WHILE) {
5186 next();
5187 d = ind;
5188 skip('(');
5189 gexpr();
5190 skip(')');
5191 a = gtst(1, 0);
5192 b = 0;
5193 block(&a, &b, case_sym, def_sym, case_reg);
5194 gjmp_addr(d);
5195 gsym(a);
5196 gsym_addr(b, d);
5197 } else if (tok == '{') {
5198 next();
5199 /* declarations */
5200 s = local_stack.top;
5201 while (tok != '}') {
5202 decl(VT_LOCAL);
5203 if (tok != '}')
5204 block(bsym, csym, case_sym, def_sym, case_reg);
5206 /* pop locally defined symbols */
5207 sym_pop(&local_stack, s);
5208 next();
5209 } else if (tok == TOK_RETURN) {
5210 next();
5211 if (tok != ';') {
5212 gexpr();
5213 gen_assign_cast(func_vt);
5214 if ((func_vt & VT_BTYPE) == VT_STRUCT) {
5215 /* if returning structure, must copy it to implicit
5216 first pointer arg location */
5217 vset(mk_pointer(func_vt), VT_LOCAL | VT_LVAL, func_vc);
5218 indir();
5219 vswap();
5220 /* copy structure value to pointer */
5221 vstore();
5222 } else if (is_float(func_vt)) {
5223 gv(RC_FRET);
5224 } else {
5225 gv(RC_IRET);
5227 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
5229 skip(';');
5230 rsym = gjmp(rsym); /* jmp */
5231 } else if (tok == TOK_BREAK) {
5232 /* compute jump */
5233 if (!bsym)
5234 error("cannot break");
5235 *bsym = gjmp(*bsym);
5236 next();
5237 skip(';');
5238 } else if (tok == TOK_CONTINUE) {
5239 /* compute jump */
5240 if (!csym)
5241 error("cannot continue");
5242 *csym = gjmp(*csym);
5243 next();
5244 skip(';');
5245 } else if (tok == TOK_FOR) {
5246 int e;
5247 next();
5248 skip('(');
5249 if (tok != ';') {
5250 gexpr();
5251 vpop();
5253 skip(';');
5254 d = ind;
5255 c = ind;
5256 a = 0;
5257 b = 0;
5258 if (tok != ';') {
5259 gexpr();
5260 a = gtst(1, 0);
5262 skip(';');
5263 if (tok != ')') {
5264 e = gjmp(0);
5265 c = ind;
5266 gexpr();
5267 vpop();
5268 gjmp_addr(d);
5269 gsym(e);
5271 skip(')');
5272 block(&a, &b, case_sym, def_sym, case_reg);
5273 gjmp_addr(c);
5274 gsym(a);
5275 gsym_addr(b, c);
5276 } else
5277 if (tok == TOK_DO) {
5278 next();
5279 a = 0;
5280 b = 0;
5281 d = ind;
5282 block(&a, &b, case_sym, def_sym, case_reg);
5283 skip(TOK_WHILE);
5284 skip('(');
5285 gsym(b);
5286 gexpr();
5287 c = gtst(0, 0);
5288 gsym_addr(c, d);
5289 skip(')');
5290 gsym(a);
5291 skip(';');
5292 } else
5293 if (tok == TOK_SWITCH) {
5294 next();
5295 skip('(');
5296 gexpr();
5297 /* XXX: other types than integer */
5298 case_reg = gv(RC_INT);
5299 vpop();
5300 skip(')');
5301 a = 0;
5302 b = gjmp(0); /* jump to first case */
5303 c = 0;
5304 block(&a, csym, &b, &c, case_reg);
5305 /* if no default, jmp after switch */
5306 if (c == 0)
5307 c = ind;
5308 /* default label */
5309 gsym_addr(b, c);
5310 /* break label */
5311 gsym(a);
5312 } else
5313 if (tok == TOK_CASE) {
5314 int v1, v2;
5315 if (!case_sym)
5316 expect("switch");
5317 next();
5318 v1 = expr_const();
5319 v2 = v1;
5320 if (gnu_ext && tok == TOK_DOTS) {
5321 next();
5322 v2 = expr_const();
5323 if (v2 < v1)
5324 warning("empty case range");
5326 /* since a case is like a label, we must skip it with a jmp */
5327 b = gjmp(0);
5328 gsym(*case_sym);
5329 vset(VT_INT, case_reg, 0);
5330 vpushi(v1);
5331 if (v1 == v2) {
5332 gen_op(TOK_EQ);
5333 *case_sym = gtst(1, 0);
5334 } else {
5335 gen_op(TOK_GE);
5336 *case_sym = gtst(1, 0);
5337 vset(VT_INT, case_reg, 0);
5338 vpushi(v2);
5339 gen_op(TOK_LE);
5340 *case_sym = gtst(1, *case_sym);
5342 gsym(b);
5343 skip(':');
5344 block(bsym, csym, case_sym, def_sym, case_reg);
5345 } else
5346 if (tok == TOK_DEFAULT) {
5347 next();
5348 skip(':');
5349 if (!def_sym)
5350 expect("switch");
5351 if (*def_sym)
5352 error("too many 'default'");
5353 *def_sym = ind;
5354 block(bsym, csym, case_sym, def_sym, case_reg);
5355 } else
5356 if (tok == TOK_GOTO) {
5357 next();
5358 s = sym_find1(&label_stack, tok);
5359 /* put forward definition if needed */
5360 if (!s)
5361 s = sym_push1(&label_stack, tok, LABEL_FORWARD, 0);
5362 /* label already defined */
5363 if (s->t & LABEL_FORWARD)
5364 s->c = gjmp(s->c);
5365 else
5366 gjmp_addr(s->c);
5367 next();
5368 skip(';');
5369 } else {
5370 b = is_label();
5371 if (b) {
5372 /* label case */
5373 s = sym_find1(&label_stack, b);
5374 if (s) {
5375 if (!(s->t & LABEL_FORWARD))
5376 error("multiple defined label");
5377 gsym(s->c);
5378 s->c = ind;
5379 s->t = 0;
5380 } else {
5381 sym_push1(&label_stack, b, 0, ind);
5383 /* we accept this, but it is a mistake */
5384 if (tok == '}')
5385 warning("deprecated use of label at end of compound statement");
5386 else
5387 block(bsym, csym, case_sym, def_sym, case_reg);
5388 } else {
5389 /* expression case */
5390 if (tok != ';') {
5391 gexpr();
5392 vpop();
5394 skip(';');
5399 /* t is the array or struct type. c is the array or struct
5400 address. cur_index/cur_field is the pointer to the current
5401 value. 'size_only' is true if only size info is needed (only used
5402 in arrays) */
5403 void decl_designator(int t, Section *sec, unsigned long c,
5404 int *cur_index, Sym **cur_field,
5405 int size_only)
5407 Sym *s, *f;
5408 int notfirst, index, align, l;
5410 notfirst = 0;
5411 if (gnu_ext && (l = is_label()) != 0)
5412 goto struct_field;
5414 while (tok == '[' || tok == '.') {
5415 if (tok == '[') {
5416 if (!(t & VT_ARRAY))
5417 expect("array type");
5418 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
5419 next();
5420 index = expr_const();
5421 if (index < 0 || (s->c >= 0 && index >= s->c))
5422 expect("invalid index");
5423 skip(']');
5424 if (!notfirst)
5425 *cur_index = index;
5426 t = pointed_type(t);
5427 c += index * type_size(t, &align);
5428 } else {
5429 next();
5430 l = tok;
5431 next();
5432 struct_field:
5433 if ((t & VT_BTYPE) != VT_STRUCT)
5434 expect("struct/union type");
5435 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
5436 l |= SYM_FIELD;
5437 f = s->next;
5438 while (f) {
5439 if (f->v == l)
5440 break;
5441 f = f->next;
5443 if (!f)
5444 expect("field");
5445 if (!notfirst)
5446 *cur_field = f;
5447 t = f->t | (t & ~VT_TYPE);
5448 c += f->c;
5450 notfirst = 1;
5452 if (notfirst) {
5453 if (tok == '=') {
5454 next();
5455 } else {
5456 if (!gnu_ext)
5457 expect("=");
5459 } else {
5460 if (t & VT_ARRAY) {
5461 index = *cur_index;
5462 t = pointed_type(t);
5463 c += index * type_size(t, &align);
5464 } else {
5465 f = *cur_field;
5466 if (!f)
5467 error("too many field init");
5468 t = f->t | (t & ~VT_TYPE);
5469 c += f->c;
5472 decl_initializer(t, sec, c, 0, size_only);
5475 #define EXPR_VAL 0
5476 #define EXPR_CONST 1
5477 #define EXPR_ANY 2
5479 /* store a value or an expression directly in global data or in local array */
5480 void init_putv(int t, Section *sec, unsigned long c,
5481 int v, int expr_type)
5483 int saved_global_expr, bt;
5484 void *ptr;
5486 switch(expr_type) {
5487 case EXPR_VAL:
5488 vpushi(v);
5489 break;
5490 case EXPR_CONST:
5491 /* compound literals must be allocated globally in this case */
5492 saved_global_expr = global_expr;
5493 global_expr = 1;
5494 expr_const1();
5495 global_expr = saved_global_expr;
5496 break;
5497 case EXPR_ANY:
5498 expr_eq();
5499 break;
5502 if (sec) {
5503 /* XXX: not portable */
5504 /* XXX: generate error if incorrect relocation */
5505 gen_assign_cast(t);
5506 bt = t & VT_BTYPE;
5507 ptr = sec->data + c;
5508 if ((vtop->r & VT_SYM) &&
5509 (bt == VT_BYTE ||
5510 bt == VT_SHORT ||
5511 bt == VT_DOUBLE ||
5512 bt == VT_LDOUBLE ||
5513 bt == VT_LLONG))
5514 error("initializer element is not computable at load time");
5515 switch(bt) {
5516 case VT_BYTE:
5517 *(char *)ptr = vtop->c.i;
5518 break;
5519 case VT_SHORT:
5520 *(short *)ptr = vtop->c.i;
5521 break;
5522 case VT_DOUBLE:
5523 *(double *)ptr = vtop->c.d;
5524 break;
5525 case VT_LDOUBLE:
5526 *(long double *)ptr = vtop->c.ld;
5527 break;
5528 case VT_LLONG:
5529 *(long long *)ptr = vtop->c.ll;
5530 break;
5531 default:
5532 if (vtop->r & VT_SYM) {
5533 greloc(sec, vtop->c.sym, c, R_DATA_32);
5534 *(int *)ptr = 0;
5535 } else {
5536 *(int *)ptr = vtop->c.i;
5538 break;
5540 vtop--;
5541 } else {
5542 vset(t, VT_LOCAL, c);
5543 vswap();
5544 vstore();
5545 vpop();
5549 /* put zeros for variable based init */
5550 void init_putz(int t, Section *sec, unsigned long c, int size)
5552 GFuncContext gf;
5554 if (sec) {
5555 /* nothing to do because globals are already set to zero */
5556 } else {
5557 gfunc_start(&gf, FUNC_CDECL);
5558 vpushi(size);
5559 gfunc_param(&gf);
5560 vpushi(0);
5561 gfunc_param(&gf);
5562 vset(VT_INT, VT_LOCAL, c);
5563 gfunc_param(&gf);
5564 vpush_sym(func_old_type, TOK_memset);
5565 gfunc_call(&gf);
5569 /* 't' contains the type and storage info. 'c' is the offset of the
5570 object in section 'sec'. If 'sec' is NULL, it means stack based
5571 allocation. 'first' is true if array '{' must be read (multi
5572 dimension implicit array init handling). 'size_only' is true if
5573 size only evaluation is wanted (only for arrays). */
5574 void decl_initializer(int t, Section *sec, unsigned long c, int first, int size_only)
5576 int index, array_length, n, no_oblock, nb, parlevel, i;
5577 int t1, size1, align1, expr_type;
5578 Sym *s, *f;
5579 TokenSym *ts;
5581 if (t & VT_ARRAY) {
5582 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
5583 n = s->c;
5584 array_length = 0;
5585 t1 = pointed_type(t);
5586 size1 = type_size(t1, &align1);
5588 no_oblock = 1;
5589 if ((first && tok != TOK_LSTR && tok != TOK_STR) ||
5590 tok == '{') {
5591 skip('{');
5592 no_oblock = 0;
5595 /* only parse strings here if correct type (otherwise: handle
5596 them as ((w)char *) expressions */
5597 if ((tok == TOK_LSTR &&
5598 (t1 & VT_BTYPE) == VT_INT) ||
5599 (tok == TOK_STR &&
5600 (t1 & VT_BTYPE) == VT_BYTE)) {
5601 /* XXX: move multiple string parsing in parser ? */
5602 while (tok == TOK_STR || tok == TOK_LSTR) {
5603 ts = tokc.ts;
5604 /* compute maximum number of chars wanted */
5605 nb = ts->len;
5606 if (n >= 0 && nb > (n - array_length))
5607 nb = n - array_length;
5608 if (!size_only) {
5609 if (ts->len > nb)
5610 warning("initializer-string for array is too long");
5611 for(i=0;i<nb;i++) {
5612 init_putv(t1, sec, c + (array_length + i) * size1,
5613 ts->str[i], EXPR_VAL);
5616 array_length += nb;
5617 next();
5619 /* only add trailing zero if enough storage (no
5620 warning in this case since it is standard) */
5621 if (n < 0 || array_length < n) {
5622 if (!size_only) {
5623 init_putv(t1, sec, c + (array_length * size1), 0, EXPR_VAL);
5625 array_length++;
5627 } else {
5628 index = 0;
5629 while (tok != '}') {
5630 decl_designator(t, sec, c, &index, NULL, size_only);
5631 if (n >= 0 && index >= n)
5632 error("index too large");
5633 /* must put zero in holes (note that doing it that way
5634 ensures that it even works with designators) */
5635 if (!size_only && array_length < index) {
5636 init_putz(t1, sec, c + array_length * size1,
5637 (index - array_length) * size1);
5639 index++;
5640 if (index > array_length)
5641 array_length = index;
5642 /* special test for multi dimensional arrays (may not
5643 be strictly correct if designators are used at the
5644 same time) */
5645 if (index >= n && no_oblock)
5646 break;
5647 if (tok == '}')
5648 break;
5649 skip(',');
5652 if (!no_oblock)
5653 skip('}');
5654 /* put zeros at the end */
5655 if (!size_only && n >= 0 && array_length < n) {
5656 init_putz(t1, sec, c + array_length * size1,
5657 (n - array_length) * size1);
5659 /* patch type size if needed */
5660 if (n < 0)
5661 s->c = array_length;
5662 } else if ((t & VT_BTYPE) == VT_STRUCT && tok == '{') {
5663 /* XXX: union needs only one init */
5664 next();
5665 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
5666 f = s->next;
5667 array_length = 0;
5668 index = 0;
5669 n = s->c;
5670 while (tok != '}') {
5671 decl_designator(t, sec, c, NULL, &f, size_only);
5672 /* fill with zero between fields */
5673 index = f->c;
5674 if (!size_only && array_length < index) {
5675 init_putz(t, sec, c + array_length,
5676 index - array_length);
5678 index = index + type_size(f->t, &align1);
5679 if (index > array_length)
5680 array_length = index;
5681 if (tok == '}')
5682 break;
5683 skip(',');
5684 f = f->next;
5686 /* put zeros at the end */
5687 if (!size_only && array_length < n) {
5688 init_putz(t, sec, c + array_length,
5689 n - array_length);
5691 skip('}');
5692 } else if (tok == '{') {
5693 next();
5694 decl_initializer(t, sec, c, first, size_only);
5695 skip('}');
5696 } else if (size_only) {
5697 /* just skip expression */
5698 parlevel = 0;
5699 while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
5700 tok != -1) {
5701 if (tok == '(')
5702 parlevel++;
5703 else if (tok == ')')
5704 parlevel--;
5705 next();
5707 } else {
5708 /* currently, we always use constant expression for globals
5709 (may change for scripting case) */
5710 expr_type = EXPR_CONST;
5711 if (!sec)
5712 expr_type = EXPR_ANY;
5713 init_putv(t, sec, c, 0, expr_type);
5717 /* parse an initializer for type 't' if 'has_init' is true, and
5718 allocate space in local or global data space ('r' is either
5719 VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
5720 variable 'v' of scope 'scope' is declared before initializers are
5721 parsed. If 'v' is zero, then a reference to the new object is put
5722 in the value stack. */
5723 void decl_initializer_alloc(int t, AttributeDef *ad, int r, int has_init,
5724 int v, int scope)
5726 int size, align, addr, data_offset;
5727 int level;
5728 ParseState saved_parse_state;
5729 TokenString init_str;
5730 Section *sec;
5732 size = type_size(t, &align);
5733 /* If unknown size, we must evaluate it before
5734 evaluating initializers because
5735 initializers can generate global data too
5736 (e.g. string pointers or ISOC99 compound
5737 literals). It also simplifies local
5738 initializers handling */
5739 tok_str_new(&init_str);
5740 if (size < 0) {
5741 if (!has_init)
5742 error("unknown type size");
5743 /* get all init string */
5744 level = 0;
5745 while (level > 0 || (tok != ',' && tok != ';')) {
5746 if (tok < 0)
5747 error("unexpected end of file in initializer");
5748 tok_str_add_tok(&init_str);
5749 if (tok == '{')
5750 level++;
5751 else if (tok == '}') {
5752 if (level == 0)
5753 break;
5754 level--;
5756 next();
5758 tok_str_add(&init_str, -1);
5759 tok_str_add(&init_str, 0);
5761 /* compute size */
5762 save_parse_state(&saved_parse_state);
5764 macro_ptr = init_str.str;
5765 next();
5766 decl_initializer(t, NULL, 0, 1, 1);
5767 /* prepare second initializer parsing */
5768 macro_ptr = init_str.str;
5769 next();
5771 /* if still unknown size, error */
5772 size = type_size(t, &align);
5773 if (size < 0)
5774 error("unknown type size");
5776 /* take into account specified alignment if bigger */
5777 if (ad->aligned > align)
5778 align = ad->aligned;
5779 if ((r & VT_VALMASK) == VT_LOCAL) {
5780 sec = NULL;
5781 if (do_bounds_check && (t & VT_ARRAY))
5782 loc--;
5783 #ifdef TCC_TARGET_IL
5784 /* XXX: ugly patch to allocate local variables for IL, just
5785 for testing */
5786 addr = loc;
5787 loc++;
5788 #else
5789 loc = (loc - size) & -align;
5790 addr = loc;
5791 #endif
5792 /* handles bounds */
5793 /* XXX: currently, since we do only one pass, we cannot track
5794 '&' operators, so we add only arrays */
5795 if (do_bounds_check && (t & VT_ARRAY)) {
5796 int *bounds_ptr;
5797 /* add padding between regions */
5798 loc--;
5799 /* then add local bound info */
5800 bounds_ptr = (int *)lbounds_section->data_ptr;
5801 *bounds_ptr++ = addr;
5802 *bounds_ptr++ = size;
5803 lbounds_section->data_ptr = (unsigned char *)bounds_ptr;
5805 } else {
5806 /* compute section */
5807 sec = ad->section;
5808 if (!sec) {
5809 if (has_init)
5810 sec = data_section;
5811 else
5812 sec = bss_section;
5814 data_offset = sec->data_ptr - sec->data;
5815 data_offset = (data_offset + align - 1) & -align;
5816 addr = data_offset;
5817 /* very important to increment global pointer at this time
5818 because initializers themselves can create new initializers */
5819 data_offset += size;
5820 /* handles bounds */
5821 if (do_bounds_check) {
5822 int *bounds_ptr;
5823 /* first, we need to add at least one byte between each region */
5824 data_offset++;
5825 /* then add global bound info */
5826 bounds_ptr = (int *)bounds_section->data_ptr;
5827 /* XXX: add relocation */
5828 *bounds_ptr++ = addr + (unsigned long)sec->data;
5829 *bounds_ptr++ = size;
5830 bounds_section->data_ptr = (unsigned char *)bounds_ptr;
5832 sec->data_ptr = sec->data + data_offset;
5834 if (v) {
5835 Sym *sym;
5837 if (!sec) {
5838 /* local variable */
5839 sym_push(v, t, r, addr);
5840 } else {
5841 if (scope == VT_CONST) {
5842 /* global scope: see if already defined */
5843 sym = sym_find(v);
5844 if (!sym)
5845 goto do_def;
5846 if (!is_compatible_types(sym->t, t))
5847 error("incompatible types for redefinition of '%s'",
5848 get_tok_str(v, NULL));
5849 if (!(sym->t & VT_EXTERN))
5850 error("redefinition of '%s'", get_tok_str(v, NULL));
5851 sym->t &= ~VT_EXTERN;
5852 } else {
5853 do_def:
5854 sym = sym_push(v, t, r | VT_SYM, 0);
5856 put_extern_sym(sym, sec, addr);
5858 } else {
5859 if (!sec) {
5860 /* push local reference */
5861 vset(t, r, addr);
5862 } else {
5863 /* push global reference */
5864 vpush_ref(t, sec, addr);
5867 if (has_init) {
5868 decl_initializer(t, sec, addr, 1, 0);
5869 /* restore parse state if needed */
5870 if (init_str.str) {
5871 free(init_str.str);
5872 restore_parse_state(&saved_parse_state);
5877 void put_func_debug(int t)
5879 char buf[512];
5881 /* stabs info */
5882 /* XXX: we put here a dummy type */
5883 snprintf(buf, sizeof(buf), "%s:%c1",
5884 funcname, t & VT_STATIC ? 'f' : 'F');
5885 put_stabs(buf, N_FUN, 0, file->line_num, ind);
5886 func_ind = ind;
5887 last_ind = 0;
5888 last_line_num = 0;
5891 /* not finished : try to put some local vars in registers */
5892 //#define CONFIG_REG_VARS
5894 #ifdef CONFIG_REG_VARS
5895 void add_var_ref(int t)
5897 printf("%s:%d: &%s\n",
5898 file->filename, file->line_num,
5899 get_tok_str(t, NULL));
5902 /* first pass on a function with heuristic to extract variable usage
5903 and pointer references to local variables for register allocation */
5904 void analyse_function(void)
5906 int level, t;
5908 for(;;) {
5909 if (tok == -1)
5910 break;
5911 /* any symbol coming after '&' is considered as being a
5912 variable whose reference is taken. It is highly unaccurate
5913 but it is difficult to do better without a complete parse */
5914 if (tok == '&') {
5915 next();
5916 /* if '& number', then no need to examine next tokens */
5917 if (tok == TOK_CINT ||
5918 tok == TOK_CUINT ||
5919 tok == TOK_CLLONG ||
5920 tok == TOK_CULLONG) {
5921 continue;
5922 } else if (tok >= TOK_UIDENT) {
5923 /* if '& ident [' or '& ident ->', then ident address
5924 is not needed */
5925 t = tok;
5926 next();
5927 if (tok != '[' && tok != TOK_ARROW)
5928 add_var_ref(t);
5929 } else {
5930 level = 0;
5931 while (tok != '}' && tok != ';' &&
5932 !((tok == ',' || tok == ')') && level == 0)) {
5933 if (tok >= TOK_UIDENT) {
5934 add_var_ref(tok);
5935 } else if (tok == '(') {
5936 level++;
5937 } else if (tok == ')') {
5938 level--;
5940 next();
5943 } else {
5944 next();
5948 #endif
5950 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
5951 void decl(int l)
5953 int t, b, v, has_init, r;
5954 Sym *sym;
5955 AttributeDef ad;
5957 while (1) {
5958 if (!parse_btype(&b, &ad)) {
5959 /* skip redundant ';' */
5960 /* XXX: find more elegant solution */
5961 if (tok == ';') {
5962 next();
5963 continue;
5965 /* special test for old K&R protos without explicit int
5966 type. Only accepted when defining global data */
5967 if (l == VT_LOCAL || tok < TOK_DEFINE)
5968 break;
5969 b = VT_INT;
5971 if (((b & VT_BTYPE) == VT_ENUM ||
5972 (b & VT_BTYPE) == VT_STRUCT) &&
5973 tok == ';') {
5974 /* we accept no variable after */
5975 next();
5976 continue;
5978 while (1) { /* iterate thru each declaration */
5979 t = type_decl(&ad, &v, b, TYPE_DIRECT);
5980 #if 0
5982 char buf[500];
5983 type_to_str(buf, sizeof(buf), t, get_tok_str(v, NULL));
5984 printf("type = '%s'\n", buf);
5986 #endif
5987 if (tok == '{') {
5988 #ifdef CONFIG_REG_VARS
5989 TokenString func_str;
5990 ParseState saved_parse_state;
5991 int block_level;
5992 #endif
5994 if (l == VT_LOCAL)
5995 error("cannot use local functions");
5996 if (!(t & VT_FUNC))
5997 expect("function definition");
5999 #ifdef CONFIG_REG_VARS
6000 /* parse all function code and record it */
6002 tok_str_new(&func_str);
6004 block_level = 0;
6005 for(;;) {
6006 int t;
6007 if (tok == -1)
6008 error("unexpected end of file");
6009 tok_str_add_tok(&func_str);
6010 t = tok;
6011 next();
6012 if (t == '{') {
6013 block_level++;
6014 } else if (t == '}') {
6015 block_level--;
6016 if (block_level == 0)
6017 break;
6020 tok_str_add(&func_str, -1);
6021 tok_str_add(&func_str, 0);
6023 save_parse_state(&saved_parse_state);
6025 macro_ptr = func_str.str;
6026 next();
6027 analyse_function();
6028 #endif
6030 /* compute text section */
6031 cur_text_section = ad.section;
6032 if (!cur_text_section)
6033 cur_text_section = text_section;
6034 ind = (int)cur_text_section->data_ptr;
6035 funcname = get_tok_str(v, NULL);
6036 sym = sym_find(v);
6037 if (sym) {
6038 /* if symbol is already defined, then put complete type */
6039 sym->t = t;
6040 } else {
6041 /* put function symbol */
6042 sym = sym_push1(&global_stack, v, t, 0);
6044 put_extern_sym(sym, cur_text_section,
6045 ind - (int)cur_text_section->data);
6046 sym->r = VT_SYM | VT_CONST;
6047 /* put debug symbol */
6048 if (do_debug)
6049 put_func_debug(t);
6050 /* push a dummy symbol to enable local sym storage */
6051 sym_push1(&local_stack, 0, 0, 0);
6052 gfunc_prolog(t);
6053 loc = 0;
6054 rsym = 0;
6055 #ifdef CONFIG_REG_VARS
6056 macro_ptr = func_str.str;
6057 next();
6058 #endif
6059 block(NULL, NULL, NULL, NULL, 0);
6060 gsym(rsym);
6061 gfunc_epilog();
6062 cur_text_section->data_ptr = (unsigned char *)ind;
6063 sym_pop(&label_stack, NULL); /* reset label stack */
6064 sym_pop(&local_stack, NULL); /* reset local stack */
6065 /* end of function */
6066 if (do_debug) {
6067 put_stabn(N_FUN, 0, 0, ind - func_ind);
6069 funcname = ""; /* for safety */
6070 func_vt = VT_VOID; /* for safety */
6071 ind = 0; /* for safety */
6073 #ifdef CONFIG_REG_VARS
6074 free(func_str.str);
6075 restore_parse_state(&saved_parse_state);
6076 #endif
6077 break;
6078 } else {
6079 if (b & VT_TYPEDEF) {
6080 /* save typedefed type */
6081 /* XXX: test storage specifiers ? */
6082 sym_push(v, t | VT_TYPEDEF, 0, 0);
6083 } else if ((t & VT_BTYPE) == VT_FUNC) {
6084 /* external function definition */
6085 external_sym(v, t, 0);
6086 } else {
6087 /* not lvalue if array */
6088 r = 0;
6089 if (!(t & VT_ARRAY))
6090 r |= lvalue_type(t);
6091 if (b & VT_EXTERN) {
6092 /* external variable */
6093 external_sym(v, t, r);
6094 } else {
6095 if (t & VT_STATIC)
6096 r |= VT_CONST;
6097 else
6098 r |= l;
6099 has_init = (tok == '=');
6100 if (has_init)
6101 next();
6102 decl_initializer_alloc(t, &ad, r,
6103 has_init, v, l);
6106 if (tok != ',') {
6107 skip(';');
6108 break;
6110 next();
6116 /* compile the C file opened in 'file'. Return non zero if errors. */
6117 static int tcc_compile(TCCState *s)
6119 Sym *define_start;
6120 char buf[512];
6121 int p;
6123 funcname = "";
6124 include_stack_ptr = include_stack;
6125 ifdef_stack_ptr = ifdef_stack;
6127 vtop = vstack - 1;
6128 anon_sym = SYM_FIRST_ANOM;
6130 /* file info: full path + filename */
6131 if (do_debug) {
6132 getcwd(buf, sizeof(buf));
6133 pstrcat(buf, sizeof(buf), "/");
6134 put_stabs(buf, N_SO, 0, 0, (unsigned long)text_section->data_ptr);
6135 put_stabs(file->filename, N_SO, 0, 0,
6136 (unsigned long)text_section->data_ptr);
6138 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
6139 symbols can be safely used */
6140 put_elf_sym(symtab_section, 0, 0,
6141 ELF32_ST_INFO(STB_LOCAL, STT_FILE), 0,
6142 SHN_ABS, file->filename);
6144 /* define common 'char *' type because it is often used internally
6145 for arrays and struct dereference */
6146 char_pointer_type = mk_pointer(VT_BYTE);
6147 /* define an old type function 'int func()' */
6148 p = anon_sym++;
6149 sym_push1(&global_stack, p, 0, FUNC_OLD);
6150 func_old_type = VT_FUNC | (p << VT_STRUCT_SHIFT);
6152 define_start = define_stack.top;
6153 inp();
6154 ch = '\n'; /* needed to parse correctly first preprocessor command */
6155 next();
6156 decl(VT_CONST);
6157 if (tok != -1)
6158 expect("declaration");
6160 /* end of translation unit info */
6161 if (do_debug) {
6162 put_stabn(N_SO, 0, 0, (unsigned long)text_section->data_ptr);
6165 /* reset define stack, but leave -Dsymbols (may be incorrect if
6166 they are undefined) */
6167 sym_pop(&define_stack, define_start);
6169 sym_pop(&global_stack, NULL);
6171 return 0;
6174 int tcc_compile_string(TCCState *s, const char *str)
6176 BufferedFile bf1, *bf = &bf1;
6177 int ret;
6179 /* init file structure */
6180 bf->fd = -1;
6181 bf->buf_ptr = (char *)str;
6182 bf->buf_end = (char *)str + strlen(bf->buffer);
6183 pstrcpy(bf->filename, sizeof(bf->filename), "<string>");
6184 bf->line_num = 1;
6185 file = bf;
6187 ret = tcc_compile(s);
6189 /* currently, no need to close */
6190 return ret;
6193 /* define a symbol. A value can also be provided with the '=' operator */
6194 void tcc_define_symbol(TCCState *s, const char *sym, const char *value)
6196 BufferedFile bf1, *bf = &bf1;
6198 pstrcpy(bf->buffer, IO_BUF_SIZE, sym);
6199 pstrcat(bf->buffer, IO_BUF_SIZE, " ");
6200 /* default value */
6201 if (!value)
6202 value = "1";
6203 pstrcat(bf->buffer, IO_BUF_SIZE, value);
6205 /* init file structure */
6206 bf->fd = -1;
6207 bf->buf_ptr = bf->buffer;
6208 bf->buf_end = bf->buffer + strlen(bf->buffer);
6209 bf->filename[0] = '\0';
6210 bf->line_num = 1;
6211 file = bf;
6213 include_stack_ptr = include_stack;
6215 /* parse with define parser */
6216 inp();
6217 ch = '\n'; /* needed to parse correctly first preprocessor command */
6218 next_nomacro();
6219 parse_define();
6220 file = NULL;
6223 void tcc_undefine_symbol(TCCState *s1, const char *sym)
6225 TokenSym *ts;
6226 Sym *s;
6227 ts = tok_alloc(sym, 0);
6228 s = sym_find1(&define_stack, tok);
6229 /* undefine symbol by putting an invalid name */
6230 if (s)
6231 sym_undef(&define_stack, s);
6234 static int put_elf_str(Section *s, const char *sym)
6236 int c, offset;
6237 offset = s->data_ptr - s->data;
6238 for(;;) {
6239 c = *sym++;
6240 *s->data_ptr++ = c;
6241 if (c == '\0')
6242 break;
6244 return offset;
6247 /* elf symbol hashing function */
6248 static unsigned long elf_hash(const unsigned char *name)
6250 unsigned long h = 0, g;
6252 while (*name) {
6253 h = (h << 4) + *name++;
6254 g = h & 0xf0000000;
6255 if (g)
6256 h ^= g >> 24;
6257 h &= ~g;
6259 return h;
6262 /* return the symbol number */
6263 static int put_elf_sym(Section *s,
6264 unsigned long value, unsigned long size,
6265 int info, int other, int shndx, const char *name)
6267 int name_offset, sym_index;
6268 int nbuckets, h;
6269 Elf32_Sym *sym;
6270 Section *hs;
6272 sym = (Elf32_Sym *)s->data_ptr;
6273 if (name)
6274 name_offset = put_elf_str(s->link, name);
6275 else
6276 name_offset = 0;
6277 /* XXX: endianness */
6278 sym->st_name = name_offset;
6279 sym->st_value = value;
6280 sym->st_size = size;
6281 sym->st_info = info;
6282 sym->st_other = other;
6283 sym->st_shndx = shndx;
6284 sym_index = sym - (Elf32_Sym *)s->data;
6285 hs = s->hash;
6286 if (hs) {
6287 /* only add global or weak symbols */
6288 if (ELF32_ST_BIND(info) != STB_LOCAL) {
6289 /* add another hashing entry */
6290 nbuckets = ((int *)hs->data)[0];
6291 h = elf_hash(name) % nbuckets;
6292 ((int *)hs->data)[2 + nbuckets + sym_index] = ((int *)hs->data)[2 + h];
6293 ((int *)hs->data)[2 + h] = sym_index;
6295 /* but still add room for all symbols */
6296 ((int *)hs->data)[1]++;
6297 hs->data_ptr += sizeof(int);
6299 s->data_ptr += sizeof(Elf32_Sym);
6300 return sym_index;
6303 /* find global ELF symbol 'name' and return its index. Return 0 if not
6304 found. */
6305 static int find_elf_sym(Section *s, const char *name)
6307 Elf32_Sym *sym;
6308 Section *hs;
6309 int nbuckets, sym_index, h;
6310 const char *name1;
6312 hs = s->hash;
6313 if (!hs)
6314 return 0;
6315 nbuckets = ((int *)hs->data)[0];
6316 h = elf_hash(name) % nbuckets;
6317 sym_index = ((int *)hs->data)[2 + h];
6318 while (sym_index != 0) {
6319 sym = &((Elf32_Sym *)s->data)[sym_index];
6320 name1 = s->link->data + sym->st_name;
6321 if (!strcmp(name, name1))
6322 return sym_index;
6323 sym_index = ((int *)hs->data)[2 + nbuckets + sym_index];
6325 return 0;
6328 /* return elf symbol value or error */
6329 static unsigned long get_elf_sym_val(const char *name)
6331 int sym_index;
6332 Elf32_Sym *sym;
6334 sym_index = find_elf_sym(symtab_section, name);
6335 if (!sym_index)
6336 error("%s not defined", name);
6337 sym = &((Elf32_Sym *)symtab_section->data)[sym_index];
6338 return sym->st_value;
6341 /* add an elf symbol : check if it is already defined and patch
6342 it. Return symbol index. NOTE that sh_num can be SHN_UNDEF. */
6343 static int add_elf_sym(Section *s, unsigned long value, unsigned long size,
6344 int info, int sh_num, const char *name)
6346 Elf32_Sym *esym;
6347 int sym_bind, sym_index, sym_type, esym_bind;
6349 sym_bind = ELF32_ST_BIND(info);
6350 sym_type = ELF32_ST_TYPE(info);
6352 if (sym_bind != STB_LOCAL) {
6353 /* we search global or weak symbols */
6354 sym_index = find_elf_sym(s, name);
6355 if (!sym_index)
6356 goto do_def;
6357 esym = &((Elf32_Sym *)s->data)[sym_index];
6358 if (esym->st_shndx != SHN_UNDEF) {
6359 esym_bind = ELF32_ST_BIND(esym->st_info);
6360 if (sh_num == SHN_UNDEF) {
6361 /* ignore adding of undefined symbol if the
6362 corresponding symbol is already defined */
6363 } else if (sym_bind == STB_GLOBAL && esym_bind == STB_WEAK) {
6364 /* global overrides weak, so patch */
6365 goto do_patch;
6366 } else if (sym_bind == STB_WEAK && esym_bind == STB_GLOBAL) {
6367 /* weak is ignored if already global */
6368 } else {
6369 #if 0
6370 printf("new_bind=%d new_shndx=%d last_bind=%d old_shndx=%d\n",
6371 sym_bind, sh_num, esym_bind, esym->st_shndx);
6372 #endif
6373 /* NOTE: we accept that two DLL define the same symbol */
6374 if (s != dynsymtab_section)
6375 error("'%s' defined twice", name);
6377 } else {
6378 do_patch:
6379 esym->st_info = ELF32_ST_INFO(sym_bind, sym_type);
6380 esym->st_shndx = sh_num;
6381 esym->st_value = value;
6382 esym->st_size = size;
6384 } else {
6385 do_def:
6386 sym_index = put_elf_sym(s, value, size,
6387 ELF32_ST_INFO(sym_bind, sym_type), 0,
6388 sh_num, name);
6390 return sym_index;
6393 /* update sym->c so that it points to an external symbol in section
6394 'section' with value 'value' */
6395 void put_extern_sym(Sym *sym, Section *section, unsigned long value)
6397 int sym_type, sym_bind, sh_num, info;
6398 Elf32_Sym *esym;
6399 const char *name;
6401 if (section)
6402 sh_num = section->sh_num;
6403 else
6404 sh_num = SHN_UNDEF;
6405 if (!sym->c) {
6406 if ((sym->t & VT_BTYPE) == VT_FUNC)
6407 sym_type = STT_FUNC;
6408 else
6409 sym_type = STT_OBJECT;
6410 if (sym->t & VT_STATIC)
6411 sym_bind = STB_LOCAL;
6412 else
6413 sym_bind = STB_GLOBAL;
6414 name = get_tok_str(sym->v, NULL);
6415 info = ELF32_ST_INFO(sym_bind, sym_type);
6416 sym->c = add_elf_sym(symtab_section, value, 0, info, sh_num, name);
6417 } else {
6418 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
6419 esym->st_value = value;
6420 esym->st_shndx = sh_num;
6424 /* put relocation */
6425 static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
6426 int type, int symbol)
6428 char buf[256];
6429 Section *sr;
6430 Elf32_Rel *rel;
6432 sr = s->reloc;
6433 if (!sr) {
6434 /* if no relocation section, create it */
6435 snprintf(buf, sizeof(buf), ".rel%s", s->name);
6436 /* if the symtab is allocated, then we consider the relocation
6437 are also */
6438 sr = new_section(buf, SHT_REL, symtab->sh_flags);
6439 sr->sh_entsize = sizeof(Elf32_Rel);
6440 sr->link = symtab;
6441 sr->sh_info = s->sh_num;
6442 s->reloc = sr;
6444 rel = (Elf32_Rel *)sr->data_ptr;
6445 /* XXX: endianness */
6446 rel->r_offset = offset;
6447 rel->r_info = ELF32_R_INFO(symbol, type);
6448 sr->data_ptr += sizeof(Elf32_Rel);
6451 /* put stab debug information */
6453 typedef struct {
6454 unsigned long n_strx; /* index into string table of name */
6455 unsigned char n_type; /* type of symbol */
6456 unsigned char n_other; /* misc info (usually empty) */
6457 unsigned short n_desc; /* description field */
6458 unsigned long n_value; /* value of symbol */
6459 } Stab_Sym;
6461 static void put_stabs(const char *str, int type, int other, int desc, int value)
6463 Stab_Sym *sym;
6465 sym = (Stab_Sym *)stab_section->data_ptr;
6466 if (str) {
6467 sym->n_strx = put_elf_str(stabstr_section, str);
6468 } else {
6469 sym->n_strx = 0;
6471 sym->n_type = type;
6472 sym->n_other = other;
6473 sym->n_desc = desc;
6474 sym->n_value = value;
6476 stab_section->data_ptr += sizeof(Stab_Sym);
6479 static void put_stabn(int type, int other, int desc, int value)
6481 put_stabs(NULL, type, other, desc, value);
6484 static void put_stabd(int type, int other, int desc)
6486 put_stabs(NULL, type, other, desc, 0);
6489 /* In an ELF file symbol table, the local symbols must appear below
6490 the global and weak ones. Since TCC cannot sort it while generating
6491 the code, we must do it after. All the relocation tables are also
6492 modified to take into account the symbol table sorting */
6493 static void sort_syms(Section *s)
6495 int *old_to_new_syms;
6496 Elf32_Sym *new_syms;
6497 int nb_syms, i;
6498 Elf32_Sym *p, *q;
6499 Elf32_Rel *rel;
6500 Section *sr;
6501 int type, sym_index;
6503 nb_syms = (s->data_ptr - s->data) / sizeof(Elf32_Sym);
6504 new_syms = malloc(nb_syms * sizeof(Elf32_Sym));
6505 if (!new_syms)
6506 error("memory full");
6507 old_to_new_syms = malloc(nb_syms * sizeof(int));
6508 if (!old_to_new_syms)
6509 error("memory full");
6510 /* first pass for local symbols */
6511 p = (Elf32_Sym *)s->data;
6512 q = new_syms;
6513 for(i = 0; i < nb_syms; i++) {
6514 if (ELF32_ST_BIND(p->st_info) == STB_LOCAL) {
6515 old_to_new_syms[i] = q - new_syms;
6516 *q++ = *p;
6518 p++;
6520 /* save the number of local symbols in section header */
6521 s->sh_info = q - new_syms;
6523 /* then second pass for non local symbols */
6524 p = (Elf32_Sym *)s->data;
6525 for(i = 0; i < nb_syms; i++) {
6526 if (ELF32_ST_BIND(p->st_info) != STB_LOCAL) {
6527 old_to_new_syms[i] = q - new_syms;
6528 *q++ = *p;
6530 p++;
6533 /* we copy the new symbols to the old */
6534 memcpy(s->data, new_syms, nb_syms * sizeof(Elf32_Sym));
6535 free(new_syms);
6537 /* now we modify all the relocations */
6538 for(i = 1; i < nb_sections; i++) {
6539 sr = sections[i];
6540 if (sr->sh_type == SHT_REL && sr->link == s) {
6541 for(rel = (Elf32_Rel *)sr->data;
6542 rel < (Elf32_Rel *)sr->data_ptr;
6543 rel++) {
6544 sym_index = ELF32_R_SYM(rel->r_info);
6545 type = ELF32_R_TYPE(rel->r_info);
6546 sym_index = old_to_new_syms[sym_index];
6547 rel->r_info = ELF32_R_INFO(sym_index, type);
6552 free(old_to_new_syms);
6555 /* relocate common symbols in the .bss section */
6556 static void relocate_common_syms(void)
6558 Elf32_Sym *sym;
6559 unsigned long offset, align;
6561 for(sym = (Elf32_Sym *)symtab_section->data + 1;
6562 sym < (Elf32_Sym *)symtab_section->data_ptr;
6563 sym++) {
6564 if (sym->st_shndx == SHN_COMMON) {
6565 /* align symbol */
6566 align = sym->st_value;
6567 offset = bss_section->data_ptr - bss_section->data;
6568 offset = (offset + align - 1) & -align;
6569 sym->st_value = offset;
6570 sym->st_shndx = bss_section->sh_num;
6571 offset += sym->st_size;
6572 bss_section->data_ptr = bss_section->data + offset;
6577 static void *resolve_sym(const char *sym)
6579 #ifdef CONFIG_TCC_BCHECK
6580 if (do_bounds_check) {
6581 void *ptr;
6582 ptr = bound_resolve_sym(sym);
6583 if (ptr)
6584 return ptr;
6586 #endif
6587 return dlsym(NULL, sym);
6590 /* relocate symbol table, resolve undefined symbols if do_resolve is
6591 true and output error if undefined symbol. */
6592 static void relocate_syms(int do_resolve)
6594 Elf32_Sym *sym, *esym;
6595 int sym_bind, sh_num, sym_index;
6596 const char *name;
6597 unsigned long addr;
6599 for(sym = (Elf32_Sym *)symtab_section->data + 1;
6600 sym < (Elf32_Sym *)symtab_section->data_ptr;
6601 sym++) {
6602 sh_num = sym->st_shndx;
6603 if (sh_num == SHN_UNDEF) {
6604 name = strtab_section->data + sym->st_name;
6605 if (do_resolve) {
6606 name = symtab_section->link->data + sym->st_name;
6607 addr = (unsigned long)resolve_sym(name);
6608 if (addr) {
6609 sym->st_value = addr;
6610 goto found;
6612 } else if (dynsym) {
6613 /* if dynamic symbol exist, then use it */
6614 sym_index = find_elf_sym(dynsym, name);
6615 if (sym_index) {
6616 esym = &((Elf32_Sym *)dynsym->data)[sym_index];
6617 sym->st_value = esym->st_value;
6618 goto found;
6621 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
6622 it */
6623 if (!strcmp(name, "_fp_hw"))
6624 goto found;
6625 /* only weak symbols are accepted to be undefined. Their
6626 value is zero */
6627 sym_bind = ELF32_ST_BIND(sym->st_info);
6628 if (sym_bind == STB_WEAK) {
6629 sym->st_value = 0;
6630 } else {
6631 error("undefined symbol '%s'", name);
6633 } else if (sh_num < SHN_LORESERVE) {
6634 /* add section base */
6635 sym->st_value += sections[sym->st_shndx]->sh_addr;
6637 found: ;
6641 /* elf relocation, CPU dependant */
6642 static void elf_reloc(unsigned char *ptr,
6643 unsigned long addr, unsigned long val, int type,
6644 int sym_index)
6646 switch(type) {
6647 case R_386_32:
6648 *(int *)ptr += val;
6649 break;
6650 case R_386_PLT32:
6651 case R_386_PC32:
6652 *(int *)ptr += val - addr;
6653 break;
6654 case R_386_GLOB_DAT:
6655 case R_386_JMP_SLOT:
6656 *(int *)ptr = val;
6657 break;
6658 case R_386_GOTPC:
6659 *(int *)ptr += got->sh_addr - addr;
6660 break;
6661 case R_386_GOTOFF:
6662 *(int *)ptr += val - got->sh_addr;
6663 break;
6664 case R_386_GOT32:
6665 /* we load the got offset */
6666 *(int *)ptr += got_offsets[sym_index];
6667 break;
6672 /* relocate a given section */
6673 static void relocate_section(Section *s)
6675 Section *sr;
6676 Elf32_Rel *rel;
6677 Elf32_Sym *sym;
6678 int type, sym_index;
6679 unsigned char *ptr;
6680 unsigned long val;
6682 sr = s->reloc;
6683 for(rel = (Elf32_Rel *)sr->data;
6684 rel < (Elf32_Rel *)sr->data_ptr;
6685 rel++) {
6686 ptr = s->data + rel->r_offset;
6688 sym_index = ELF32_R_SYM(rel->r_info);
6689 sym = &((Elf32_Sym *)symtab_section->data)[sym_index];
6690 val = sym->st_value;
6691 type = ELF32_R_TYPE(rel->r_info);
6692 elf_reloc(ptr, s->sh_addr + rel->r_offset, val, type, sym_index);
6696 /* relocate relocation table in 'sr' */
6697 static void relocate_rel(Section *sr)
6699 Section *s;
6700 Elf32_Rel *rel;
6702 s = sections[sr->sh_info];
6703 for(rel = (Elf32_Rel *)sr->data;
6704 rel < (Elf32_Rel *)sr->data_ptr;
6705 rel++) {
6706 rel->r_offset += s->sh_addr;
6710 static void put_got_offset(int index, unsigned long val)
6712 int n;
6713 unsigned long *tab;
6715 if (index >= nb_got_offsets) {
6716 /* find immediately bigger power of 2 and reallocate array */
6717 n = 1;
6718 while (index >= n)
6719 n *= 2;
6720 tab = realloc(got_offsets, n * sizeof(unsigned long));
6721 if (!tab)
6722 error("memory full");
6723 got_offsets = tab;
6724 memset(got_offsets + nb_got_offsets, 0,
6725 (n - nb_got_offsets) * sizeof(unsigned long));
6726 nb_got_offsets = n;
6728 got_offsets[index] = val;
6731 /* XXX: suppress that */
6732 static void put32(unsigned char *p, unsigned int val)
6734 p[0] = val;
6735 p[1] = val >> 8;
6736 p[2] = val >> 16;
6737 p[3] = val >> 24;
6740 static void build_got(void)
6742 /* if no got, then create it */
6743 got = new_section(".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
6744 got->sh_entsize = 4;
6745 add_elf_sym(symtab_section, 0, 4, ELF32_ST_INFO(STB_GLOBAL, STT_OBJECT),
6746 got->sh_num, "_GLOBAL_OFFSET_TABLE_");
6747 /* keep space for _DYNAMIC pointer, if present */
6748 got->data_ptr += 4;
6750 /* two dummy got entries */
6751 put32(got->data_ptr, 0);
6752 got->data_ptr += 4;
6753 put32(got->data_ptr, 0);
6754 got->data_ptr += 4;
6757 /* put a got entry corresponding to a symbol in symtab_section. 'size'
6758 and 'info' can be modifed if more precise info comes from the DLL */
6759 static void put_got_entry(int reloc_type, unsigned long size, int info,
6760 int sym_index)
6762 int index;
6763 const char *name;
6764 Elf32_Sym *sym;
6765 unsigned long offset;
6767 if (!got)
6768 build_got();
6770 /* if a got entry already exists for that symbol, no need to add one */
6771 if (sym_index < nb_got_offsets &&
6772 got_offsets[sym_index] != 0)
6773 return;
6775 put_got_offset(sym_index, got->data_ptr - got->data);
6777 if (dynsym) {
6778 sym = &((Elf32_Sym *)symtab_section->data)[sym_index];
6779 name = symtab_section->link->data + sym->st_name;
6780 offset = sym->st_value;
6781 /* NOTE: we put temporarily the got offset */
6782 if (reloc_type == R_386_JMP_SLOT) {
6783 nb_plt_entries++;
6784 offset = got->data_ptr - got->data;
6786 index = put_elf_sym(dynsym, offset,
6787 size, info, 0, sym->st_shndx, name);
6788 /* put a got entry */
6789 put_elf_reloc(dynsym, got,
6790 got->data_ptr - got->data,
6791 reloc_type, index);
6793 put32(got->data_ptr, 0);
6794 got->data_ptr += 4;
6797 /* build GOT and PLT entries */
6798 static void build_got_entries(void)
6800 Section *s, *symtab;
6801 Elf32_Rel *rel;
6802 Elf32_Sym *sym;
6803 int i, type, reloc_type, sym_index;
6805 for(i = 1; i < nb_sections; i++) {
6806 s = sections[i];
6807 if (s->sh_type != SHT_REL)
6808 continue;
6809 /* no need to handle got relocations */
6810 if (s->link != symtab_section)
6811 continue;
6812 symtab = s->link;
6813 for(rel = (Elf32_Rel *)s->data;
6814 rel < (Elf32_Rel *)s->data_ptr;
6815 rel++) {
6816 type = ELF32_R_TYPE(rel->r_info);
6817 switch(type) {
6818 case R_386_GOT32:
6819 case R_386_GOTOFF:
6820 case R_386_GOTPC:
6821 case R_386_PLT32:
6822 if (!got)
6823 build_got();
6824 if (type == R_386_GOT32 || type == R_386_PLT32) {
6825 sym_index = ELF32_R_SYM(rel->r_info);
6826 sym = &((Elf32_Sym *)symtab_section->data)[sym_index];
6827 /* look at the symbol got offset. If none, then add one */
6828 if (type == R_386_GOT32)
6829 reloc_type = R_386_GLOB_DAT;
6830 else
6831 reloc_type = R_386_JMP_SLOT;
6832 put_got_entry(reloc_type, sym->st_size, sym->st_info,
6833 sym_index);
6835 break;
6836 default:
6837 break;
6843 static Section *new_section_hash(const char *name, int sh_flags,
6844 int nb_buckets, Section *symtab)
6846 Section *hash;
6847 hash = new_section(name, SHT_HASH, sh_flags);
6848 ((int *)hash->data)[0] = nb_buckets;
6849 ((int *)hash->data)[1] = 1;
6850 hash->sh_entsize = sizeof(int);
6851 hash->data_ptr += (2 + nb_buckets + 1) * sizeof(int);
6852 symtab->hash = hash;
6853 hash->link = symtab;
6854 return hash;
6857 /* put dynamic tag */
6858 static void put_dt(Section *dynamic, int dt, unsigned long val)
6860 Elf32_Dyn *dyn;
6861 dyn = (Elf32_Dyn *)dynamic->data_ptr;
6862 dyn->d_tag = dt;
6863 dyn->d_un.d_val = val;
6864 dynamic->data_ptr += sizeof(Elf32_Dyn);
6867 /* add tcc runtime libraries */
6868 static void tcc_add_runtime(TCCState *s1)
6870 tcc_add_file(s1, CONFIG_TCC_PREFIX "/lib/tcc/libtcc1.o");
6873 /* add dynamic sections so that the executable is dynamically linked */
6874 static char elf_interp[] = "/lib/ld-linux.so.2";
6876 #define ELF_START_ADDR 0x08048000
6877 #define ELF_PAGE_SIZE 0x1000
6879 /* output an ELF file */
6880 /* XXX: handle realloc'ed sections (instead of mmaping them) */
6881 /* XXX: suppress unneeded sections */
6882 int tcc_output_file(TCCState *s1, const char *filename)
6884 Elf32_Ehdr ehdr;
6885 FILE *f;
6886 int fd, mode;
6887 int *section_order;
6888 int shnum, i, phnum, file_offset, offset, size, j, tmp, sh_order_index, k;
6889 unsigned long addr;
6890 Section *strsec, *s;
6891 Elf32_Shdr shdr, *sh;
6892 Elf32_Phdr *phdr, *ph;
6893 Section *interp, *plt, *dynamic, *dynstr, *hash;
6894 unsigned char *saved_dynamic_data_ptr;
6895 Elf32_Sym *sym;
6896 int type, file_type;
6897 unsigned long rel_addr, rel_size;
6899 file_type = s1->output_type;
6901 /* add libc crtn object */
6902 if (file_type != TCC_OUTPUT_OBJ) {
6903 tcc_add_runtime(s1);
6904 tcc_add_library(s1, "c");
6905 tcc_add_file(s1, CONFIG_TCC_CRT_PREFIX "/crtn.o");
6908 interp = NULL;
6909 dynamic = NULL;
6910 dynsym = NULL;
6911 got = NULL;
6912 nb_plt_entries = 0;
6913 plt = NULL; /* avoid warning */
6914 hash = NULL; /* avoid warning */
6915 dynstr = NULL; /* avoid warning */
6916 saved_dynamic_data_ptr = NULL; /* avoid warning */
6918 if (file_type != TCC_OUTPUT_OBJ) {
6920 relocate_common_syms();
6922 if (!static_link) {
6923 const char *name;
6924 int sym_index, index;
6925 Elf32_Sym *esym;
6927 if (file_type == TCC_OUTPUT_EXE) {
6928 /* add interpreter section only if executable */
6929 interp = new_section(".interp", SHT_PROGBITS, SHF_ALLOC);
6930 interp->sh_addralign = 1;
6931 strcpy(interp->data_ptr, elf_interp);
6932 interp->data_ptr += sizeof(elf_interp);
6935 /* add dynamic symbol table */
6936 dynsym = new_section(".dynsym", SHT_DYNSYM, SHF_ALLOC);
6937 dynsym->sh_entsize = sizeof(Elf32_Sym);
6938 dynstr = new_section(".dynstr", SHT_STRTAB, SHF_ALLOC);
6939 put_elf_str(dynstr, "");
6940 dynsym->link = dynstr;
6941 put_elf_sym(dynsym, 0, 0, 0, 0, 0, NULL);
6943 /* hash table */
6944 hash = new_section_hash(".hash", SHF_ALLOC,
6945 ELF_DYNSYM_HASH_SIZE, dynsym);
6947 /* add dynamic section */
6948 dynamic = new_section(".dynamic", SHT_DYNAMIC,
6949 SHF_ALLOC | SHF_WRITE);
6950 dynamic->link = dynstr;
6951 dynamic->sh_entsize = sizeof(Elf32_Dyn);
6953 /* add PLT */
6954 plt = new_section(".plt", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
6955 plt->sh_entsize = 4;
6957 /* scan for undefined symbols and see if they are in the
6958 dynamic symbols. If a symbol STT_FUNC is found, then we
6959 add it in the PLT. If a symbol STT_OBJECT is found, we
6960 add it in the .bss section with a suitable relocation */
6961 for(sym = (Elf32_Sym *)symtab_section->data + 1;
6962 sym < (Elf32_Sym *)symtab_section->data_ptr;
6963 sym++) {
6964 if (sym->st_shndx == SHN_UNDEF) {
6965 name = symtab_section->link->data + sym->st_name;
6966 sym_index = find_elf_sym(dynsymtab_section, name);
6967 if (sym_index) {
6968 esym = &((Elf32_Sym *)dynsymtab_section->data)[sym_index];
6969 type = ELF32_ST_TYPE(esym->st_info);
6970 if (type == STT_FUNC) {
6971 put_got_entry(R_386_JMP_SLOT, esym->st_size,
6972 esym->st_info,
6973 sym - (Elf32_Sym *)symtab_section->data);
6974 } else if (type == STT_OBJECT) {
6975 unsigned long offset;
6976 offset = bss_section->data_ptr - bss_section->data;
6977 /* XXX: which alignment ? */
6978 offset = (offset + 8 - 1) & -8;
6979 index = put_elf_sym(dynsym, offset, esym->st_size,
6980 esym->st_info, 0,
6981 bss_section->sh_num, name);
6982 put_elf_reloc(dynsym, bss_section,
6983 offset, R_386_COPY, index);
6984 offset += esym->st_size;
6985 bss_section->data_ptr = bss_section->data + offset;
6987 } else {
6988 /* STT_NOTYPE or STB_WEAK undefined symbols
6989 are accepted */
6990 /* XXX: STT_NOTYPE is only used to exclude the
6991 unreferenced '_fp_hw' symbol. need a better
6992 solution */
6993 if (ELF32_ST_TYPE(sym->st_info) == STT_NOTYPE ||
6994 ELF32_ST_BIND(sym->st_info) == STB_WEAK) {
6995 } else {
6996 error("undefined symbol '%s'", name);
7002 /* now look at unresolved dynamic symbols and export
7003 corresponding symbol */
7004 for(sym = (Elf32_Sym *)dynsymtab_section->data + 1;
7005 sym < (Elf32_Sym *)dynsymtab_section->data_ptr;
7006 sym++) {
7007 if (sym->st_shndx == SHN_UNDEF) {
7008 name = dynsymtab_section->link->data + sym->st_name;
7009 sym_index = find_elf_sym(symtab_section, name);
7010 if (sym_index) {
7011 } else {
7012 if (ELF32_ST_BIND(sym->st_info) == STB_WEAK) {
7013 /* weak symbols can stay undefined */
7014 } else {
7015 warning("undefined dynamic symbol '%s'", name);
7021 build_got_entries();
7023 /* update PLT/GOT sizes so that we can allocate their space */
7024 plt->data_ptr += 16 * (nb_plt_entries + 1);
7026 /* add a list of needed dlls */
7027 for(i = 0; i < nb_loaded_dlls; i++) {
7028 DLLReference *dllref = loaded_dlls[i];
7029 if (dllref->level == 0)
7030 put_dt(dynamic, DT_NEEDED, put_elf_str(dynstr, dllref->name));
7033 /* add necessary space for other entries */
7034 saved_dynamic_data_ptr = dynamic->data_ptr;
7035 dynamic->data_ptr += 8 * 9;
7036 } else {
7037 /* still need to build got entries in case of static link */
7038 build_got_entries();
7042 memset(&ehdr, 0, sizeof(ehdr));
7044 /* we add a section for symbols */
7045 strsec = new_section(".shstrtab", SHT_STRTAB, 0);
7046 put_elf_str(strsec, "");
7048 /* compute number of sections */
7049 shnum = nb_sections;
7051 /* this array is used to reorder sections in the output file */
7052 section_order = malloc(sizeof(int) * shnum);
7053 if (!section_order)
7054 error("memory full");
7055 section_order[0] = 0;
7056 sh_order_index = 1;
7058 /* compute number of program headers */
7059 switch(file_type) {
7060 default:
7061 case TCC_OUTPUT_OBJ:
7062 phnum = 0;
7063 break;
7064 case TCC_OUTPUT_EXE:
7065 if (!static_link)
7066 phnum = 4;
7067 else
7068 phnum = 2;
7069 break;
7070 case TCC_OUTPUT_DLL:
7071 phnum = 3;
7072 break;
7075 /* allocate strings for section names */
7076 for(i = 1; i < nb_sections; i++) {
7077 s = sections[i];
7078 s->sh_name = put_elf_str(strsec, s->name);
7079 s->sh_size = s->data_ptr - s->data;
7082 /* allocate program segment headers */
7083 phdr = malloc(phnum * sizeof(Elf32_Phdr));
7084 if (!phdr)
7085 error("memory full");
7086 memset(phdr, 0, phnum * sizeof(Elf32_Phdr));
7088 file_offset = sizeof(Elf32_Ehdr) + phnum * sizeof(Elf32_Phdr);
7089 if (phnum > 0) {
7090 /* compute section to program header mapping */
7091 if (file_type == TCC_OUTPUT_DLL)
7092 addr = 0;
7093 else
7094 addr = ELF_START_ADDR;
7096 /* dynamic relocation table information, for .dynamic section */
7097 rel_size = 0;
7098 rel_addr = 0;
7100 /* compute address after headers */
7101 addr += (file_offset & (ELF_PAGE_SIZE - 1));
7103 /* leave one program header for the program interpreter */
7104 ph = &phdr[0];
7105 if (interp)
7106 ph++;
7108 for(j = 0; j < 2; j++) {
7109 ph->p_type = PT_LOAD;
7110 if (j == 0)
7111 ph->p_flags = PF_R | PF_X;
7112 else
7113 ph->p_flags = PF_R | PF_W;
7114 ph->p_align = ELF_PAGE_SIZE;
7116 /* we do the following ordering: interp, symbol tables,
7117 relocations, progbits, nobits */
7118 /* XXX: do faster and simpler sorting */
7119 for(k = 0; k < 5; k++) {
7120 for(i = 1; i < nb_sections; i++) {
7121 s = sections[i];
7122 /* compute if section should be included */
7123 if (j == 0) {
7124 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
7125 SHF_ALLOC)
7126 continue;
7127 } else {
7128 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
7129 (SHF_ALLOC | SHF_WRITE))
7130 continue;
7132 if (s == interp) {
7133 if (k != 0)
7134 continue;
7135 } else if (s->sh_type == SHT_DYNSYM ||
7136 s->sh_type == SHT_STRTAB ||
7137 s->sh_type == SHT_HASH) {
7138 if (k != 1)
7139 continue;
7140 } else if (s->sh_type == SHT_REL) {
7141 if (k != 2)
7142 continue;
7143 } else if (s->sh_type == SHT_NOBITS) {
7144 if (k != 4)
7145 continue;
7146 } else {
7147 if (k != 3)
7148 continue;
7150 section_order[sh_order_index++] = i;
7152 /* section matches: we align it and add its size */
7153 tmp = file_offset;
7154 file_offset = (file_offset + s->sh_addralign - 1) &
7155 ~(s->sh_addralign - 1);
7156 s->sh_offset = file_offset;
7157 addr += file_offset - tmp;
7158 s->sh_addr = addr;
7160 /* update program header infos */
7161 if (ph->p_offset == 0) {
7162 ph->p_offset = file_offset;
7163 ph->p_vaddr = addr;
7164 ph->p_paddr = ph->p_vaddr;
7166 /* update dynamic relocation infos */
7167 if (s->sh_type == SHT_REL) {
7168 if (rel_size == 0)
7169 rel_addr = addr;
7170 rel_size += s->sh_size;
7172 addr += s->sh_size;
7173 if (s->sh_type != SHT_NOBITS)
7174 file_offset += s->sh_size;
7177 ph->p_filesz = file_offset - ph->p_offset;
7178 ph->p_memsz = addr - ph->p_vaddr;
7179 ph++;
7182 /* if interpreter, then add corresponing program header */
7183 if (interp) {
7184 ph = &phdr[0];
7186 ph->p_type = PT_INTERP;
7187 ph->p_offset = interp->sh_offset;
7188 ph->p_vaddr = interp->sh_addr;
7189 ph->p_paddr = ph->p_vaddr;
7190 ph->p_filesz = interp->sh_size;
7191 ph->p_memsz = interp->sh_size;
7192 ph->p_flags = PF_R;
7193 ph->p_align = interp->sh_addralign;
7196 /* if dynamic section, then add corresponing program header */
7197 if (dynamic) {
7198 int plt_offset;
7199 unsigned char *p;
7201 ph = &phdr[phnum - 1];
7203 ph->p_type = PT_DYNAMIC;
7204 ph->p_offset = dynamic->sh_offset;
7205 ph->p_vaddr = dynamic->sh_addr;
7206 ph->p_paddr = ph->p_vaddr;
7207 ph->p_filesz = dynamic->sh_size;
7208 ph->p_memsz = dynamic->sh_size;
7209 ph->p_flags = PF_R | PF_W;
7210 ph->p_align = dynamic->sh_addralign;
7212 /* put GOT dynamic section address */
7213 put32(got->data, dynamic->sh_addr);
7215 /* compute the PLT */
7216 plt->data_ptr = plt->data;
7218 /* first plt entry */
7219 p = plt->data_ptr;
7220 p[0] = 0xff; /* pushl got + 4 */
7221 p[1] = 0x35;
7222 put32(p + 2, got->sh_addr + 4);
7223 p[6] = 0xff; /* jmp *(got + 8) */
7224 p[7] = 0x25;
7225 put32(p + 8, got->sh_addr + 8);
7226 plt->data_ptr += 16;
7228 /* relocation symbols in .dynsym and build PLT. */
7229 plt_offset = 0;
7230 for(sym = (Elf32_Sym *)dynsym->data + 1;
7231 sym < (Elf32_Sym *)dynsym->data_ptr;
7232 sym++) {
7233 type = ELF32_ST_TYPE(sym->st_info);
7234 if (sym->st_shndx == SHN_UNDEF) {
7235 if (type == STT_FUNC) {
7236 /* one more entry in PLT */
7237 p = plt->data_ptr;
7238 p[0] = 0xff; /* jmp *(got + x) */
7239 p[1] = 0x25;
7240 put32(p + 2, got->sh_addr + sym->st_value);
7241 p[6] = 0x68; /* push $xxx */
7242 put32(p + 7, plt_offset);
7243 p[11] = 0xe9; /* jmp plt_start */
7244 put32(p + 12, -(plt->data_ptr + 16 - plt->data));
7246 /* patch symbol value to point to plt */
7247 sym->st_value = plt->sh_addr + p - plt->data;
7249 plt_offset += 8;
7250 plt->data_ptr += 16;
7252 } else if (sym->st_shndx < SHN_LORESERVE) {
7253 /* do symbol relocation */
7254 sym->st_value += sections[sym->st_shndx]->sh_addr;
7257 /* put dynamic section entries */
7259 dynamic->data_ptr = saved_dynamic_data_ptr;
7260 put_dt(dynamic, DT_HASH, hash->sh_addr);
7261 put_dt(dynamic, DT_STRTAB, dynstr->sh_addr);
7262 put_dt(dynamic, DT_SYMTAB, dynsym->sh_addr);
7263 put_dt(dynamic, DT_STRSZ, dynstr->data_ptr - dynstr->data);
7264 put_dt(dynamic, DT_SYMENT, sizeof(Elf32_Sym));
7265 put_dt(dynamic, DT_REL, rel_addr);
7266 put_dt(dynamic, DT_RELSZ, rel_size);
7267 put_dt(dynamic, DT_RELENT, sizeof(Elf32_Rel));
7268 put_dt(dynamic, DT_NULL, 0);
7271 ehdr.e_phentsize = sizeof(Elf32_Phdr);
7272 ehdr.e_phnum = phnum;
7273 ehdr.e_phoff = sizeof(Elf32_Ehdr);
7276 /* all other sections come after */
7277 for(i = 1; i < nb_sections; i++) {
7278 s = sections[i];
7279 if (phnum > 0 && (s->sh_flags & SHF_ALLOC))
7280 continue;
7281 section_order[sh_order_index++] = i;
7283 file_offset = (file_offset + s->sh_addralign - 1) &
7284 ~(s->sh_addralign - 1);
7285 s->sh_offset = file_offset;
7286 if (s->sh_type != SHT_NOBITS)
7287 file_offset += s->sh_size;
7290 /* if building executable or DLL, then relocate each section
7291 except the GOT which is already relocated */
7292 if (file_type != TCC_OUTPUT_OBJ) {
7293 relocate_syms(0);
7295 /* relocate sections */
7296 /* XXX: ignore sections with allocated relocations ? */
7297 for(i = 1; i < nb_sections; i++) {
7298 s = sections[i];
7299 if ((s->sh_flags & SHF_ALLOC)
7300 && s->reloc && s != got)
7301 relocate_section(s);
7304 /* relocate relocation entries */
7305 for(i = 1; i < nb_sections; i++) {
7306 s = sections[i];
7307 if ((s->sh_flags & SHF_ALLOC) &&
7308 s->sh_type == SHT_REL) {
7309 relocate_rel(s);
7313 /* get entry point address */
7314 ehdr.e_entry = get_elf_sym_val("_start");
7317 sort_syms(symtab_section);
7319 /* align to 4 */
7320 file_offset = (file_offset + 3) & -4;
7322 /* fill header */
7323 ehdr.e_ident[0] = ELFMAG0;
7324 ehdr.e_ident[1] = ELFMAG1;
7325 ehdr.e_ident[2] = ELFMAG2;
7326 ehdr.e_ident[3] = ELFMAG3;
7327 ehdr.e_ident[4] = ELFCLASS32;
7328 ehdr.e_ident[5] = ELFDATA2LSB;
7329 ehdr.e_ident[6] = EV_CURRENT;
7330 switch(file_type) {
7331 default:
7332 case TCC_OUTPUT_EXE:
7333 ehdr.e_type = ET_EXEC;
7334 break;
7335 case TCC_OUTPUT_DLL:
7336 ehdr.e_type = ET_DYN;
7337 break;
7338 case TCC_OUTPUT_OBJ:
7339 ehdr.e_type = ET_REL;
7340 break;
7342 ehdr.e_machine = EM_386;
7343 ehdr.e_version = EV_CURRENT;
7344 ehdr.e_shoff = file_offset;
7345 ehdr.e_ehsize = sizeof(Elf32_Ehdr);
7346 ehdr.e_shentsize = sizeof(Elf32_Shdr);
7347 ehdr.e_shnum = shnum;
7348 ehdr.e_shstrndx = shnum - 1;
7350 /* write elf file */
7351 if (file_type == TCC_OUTPUT_OBJ)
7352 mode = 0666;
7353 else
7354 mode = 0777;
7355 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, mode);
7356 if (fd < 0)
7357 error("could not write '%s'", filename);
7359 f = fdopen(fd, "w");
7360 fwrite(&ehdr, 1, sizeof(Elf32_Ehdr), f);
7361 fwrite(phdr, 1, phnum * sizeof(Elf32_Phdr), f);
7362 offset = sizeof(Elf32_Ehdr) + phnum * sizeof(Elf32_Phdr);
7363 for(i=1;i<nb_sections;i++) {
7364 s = sections[section_order[i]];
7365 if (s->sh_type != SHT_NOBITS) {
7366 while (offset < s->sh_offset) {
7367 fputc(0, f);
7368 offset++;
7370 size = s->data_ptr - s->data;
7371 fwrite(s->data, 1, size, f);
7372 offset += size;
7375 while (offset < ehdr.e_shoff) {
7376 fputc(0, f);
7377 offset++;
7380 /* output section headers */
7381 for(i=0;i<nb_sections;i++) {
7382 sh = &shdr;
7383 memset(sh, 0, sizeof(Elf32_Shdr));
7384 s = sections[i];
7385 if (s) {
7386 sh->sh_name = s->sh_name;
7387 sh->sh_type = s->sh_type;
7388 sh->sh_flags = s->sh_flags;
7389 sh->sh_entsize = s->sh_entsize;
7390 sh->sh_info = s->sh_info;
7391 if (s->link)
7392 sh->sh_link = s->link->sh_num;
7393 sh->sh_addralign = s->sh_addralign;
7394 sh->sh_addr = s->sh_addr;
7395 sh->sh_offset = s->sh_offset;
7396 sh->sh_size = s->sh_size;
7398 fwrite(sh, 1, sizeof(Elf32_Shdr), f);
7400 fclose(f);
7402 free(section_order);
7403 free(phdr);
7404 return 0;
7407 static void *load_data(int fd, unsigned long file_offset, unsigned long size)
7409 void *data;
7411 data = malloc(size);
7412 if (!data)
7413 error("memory full");
7414 lseek(fd, file_offset, SEEK_SET);
7415 read(fd, data, size);
7416 return data;
7419 typedef struct SectionMergeInfo {
7420 Section *s; /* corresponding existing section */
7421 unsigned long offset; /* offset of the new section in the existing section */
7422 int new_section; /* true if section 's' was added */
7423 } SectionMergeInfo;
7425 /* load an object file and merge it with current files */
7426 /* XXX: handle correctly stab (debug) info */
7427 static int tcc_load_object_file(TCCState *s1,
7428 int fd, unsigned long file_offset)
7430 Elf32_Ehdr ehdr;
7431 Elf32_Shdr *shdr, *sh;
7432 int size, i, j, offset, offseti, nb_syms, sym_index;
7433 unsigned char *strsec, *strtab;
7434 int *old_to_new_syms;
7435 char *sh_name, *name;
7436 SectionMergeInfo *sm_table, *sm;
7437 Elf32_Sym *sym, *symtab;
7438 Elf32_Rel *rel;
7439 Section *s;
7441 if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
7442 goto fail;
7443 if (ehdr.e_ident[0] != ELFMAG0 ||
7444 ehdr.e_ident[1] != ELFMAG1 ||
7445 ehdr.e_ident[2] != ELFMAG2 ||
7446 ehdr.e_ident[3] != ELFMAG3)
7447 goto fail;
7448 /* test if object file */
7449 if (ehdr.e_type != ET_REL)
7450 goto fail;
7451 /* test CPU specific stuff */
7452 if (ehdr.e_ident[5] != ELFDATA2LSB ||
7453 ehdr.e_machine != EM_386) {
7454 fail:
7455 error("invalid object file");
7457 /* read sections */
7458 shdr = load_data(fd, file_offset + ehdr.e_shoff,
7459 sizeof(Elf32_Shdr) * ehdr.e_shnum);
7460 sm_table = malloc(sizeof(SectionMergeInfo) * ehdr.e_shnum);
7461 if (!sm_table)
7462 error("memory full");
7463 memset(sm_table, 0, sizeof(SectionMergeInfo) * ehdr.e_shnum);
7465 /* load section names */
7466 sh = &shdr[ehdr.e_shstrndx];
7467 strsec = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
7469 /* load symtab and strtab */
7470 symtab = NULL;
7471 strtab = NULL;
7472 nb_syms = 0;
7473 for(i = 1; i < ehdr.e_shnum; i++) {
7474 sh = &shdr[i];
7475 if (sh->sh_type == SHT_SYMTAB) {
7476 if (symtab)
7477 error("object must contain only one symtab");
7478 nb_syms = sh->sh_size / sizeof(Elf32_Sym);
7479 symtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
7480 sm_table[i].s = symtab_section;
7482 /* now load strtab */
7483 sh = &shdr[sh->sh_link];
7484 strtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
7488 /* now examine each section and try to merge its content with the
7489 ones in memory */
7490 for(i = 1; i < ehdr.e_shnum; i++) {
7491 /* no need to examine section name strtab */
7492 if (i == ehdr.e_shstrndx)
7493 continue;
7494 sh = &shdr[i];
7495 sh_name = strsec + sh->sh_name;
7496 /* ignore sections types we do not handle */
7497 if (sh->sh_type != SHT_PROGBITS &&
7498 sh->sh_type != SHT_REL &&
7499 sh->sh_type != SHT_NOBITS)
7500 continue;
7501 if (sh->sh_addralign < 1)
7502 sh->sh_addralign = 1;
7503 /* find corresponding section, if any */
7504 for(j = 1; j < nb_sections;j++) {
7505 s = sections[j];
7506 if (!strcmp(s->name, sh_name))
7507 goto found;
7509 /* not found: create new section */
7510 s = new_section(sh_name, sh->sh_type, sh->sh_flags);
7511 /* take as much info as possible from the section. sh_link and
7512 sh_info will be updated later */
7513 s->sh_addralign = sh->sh_addralign;
7514 s->sh_entsize = sh->sh_entsize;
7515 sm_table[i].new_section = 1;
7516 found:
7517 if (sh->sh_type != s->sh_type)
7518 goto fail;
7520 /* align start of section */
7521 offset = s->data_ptr - s->data;
7522 size = sh->sh_addralign - 1;
7523 offset = (offset + size) & ~size;
7524 if (sh->sh_addralign > s->sh_addralign)
7525 s->sh_addralign = sh->sh_addralign;
7526 s->data_ptr = s->data + offset;
7527 sm_table[i].offset = offset;
7528 sm_table[i].s = s;
7529 /* concatenate sections */
7530 size = sh->sh_size;
7531 if (sh->sh_type != SHT_NOBITS) {
7532 lseek(fd, file_offset + sh->sh_offset, SEEK_SET);
7533 read(fd, s->data_ptr, size);
7535 s->data_ptr += size;
7538 /* second short pass to update sh_link and sh_info fields of new
7539 sections */
7540 sm = sm_table;
7541 for(i = 1; i < ehdr.e_shnum; i++) {
7542 s = sm_table[i].s;
7543 if (!s || !sm_table[i].new_section)
7544 continue;
7545 sh = &shdr[i];
7546 if (sh->sh_link > 0)
7547 s->link = sm_table[sh->sh_link].s;
7548 if (sh->sh_type == SHT_REL) {
7549 s->sh_info = sm_table[sh->sh_info].s->sh_num;
7550 /* update backward link */
7551 sections[s->sh_info]->reloc = s;
7555 /* resolve symbols */
7556 old_to_new_syms = malloc(nb_syms * sizeof(int));
7557 if (!old_to_new_syms)
7558 error("memory full");
7559 memset(old_to_new_syms, 0, nb_syms * sizeof(int));
7560 sym = symtab + 1;
7561 for(i = 1; i < nb_syms; i++, sym++) {
7562 if (sym->st_shndx != SHN_UNDEF &&
7563 sym->st_shndx < SHN_LORESERVE) {
7564 sm = &sm_table[sym->st_shndx];
7565 /* if no corresponding section added, no need to add symbol */
7566 if (!sm->s)
7567 continue;
7568 /* convert section number */
7569 sym->st_shndx = sm->s->sh_num;
7570 /* offset value */
7571 sym->st_value += sm->offset;
7573 /* add symbol */
7574 name = strtab + sym->st_name;
7575 sym_index = add_elf_sym(symtab_section, sym->st_value, sym->st_size,
7576 sym->st_info, sym->st_shndx, name);
7577 old_to_new_syms[i] = sym_index;
7580 /* third pass to patch relocation entries */
7581 for(i = 1; i < ehdr.e_shnum; i++) {
7582 s = sm_table[i].s;
7583 if (!s)
7584 continue;
7585 sh = &shdr[i];
7586 offset = sm_table[i].offset;
7587 switch(s->sh_type) {
7588 case SHT_REL:
7589 /* take relocation offset information */
7590 offseti = sm_table[sh->sh_info].offset;
7591 for(rel = (Elf32_Rel *)(s->data + offset);
7592 rel < (Elf32_Rel *)s->data_ptr;
7593 rel++) {
7594 int type;
7595 unsigned sym_index;
7596 /* convert symbol index */
7597 type = ELF32_R_TYPE(rel->r_info);
7598 sym_index = ELF32_R_SYM(rel->r_info);
7599 /* NOTE: only one symtab assumed */
7600 if (sym_index >= nb_syms)
7601 goto invalid_reloc;
7602 sym_index = old_to_new_syms[sym_index];
7603 if (!sym_index) {
7604 invalid_reloc:
7605 error("Invalid relocation entry");
7607 rel->r_info = ELF32_R_INFO(sym_index, type);
7608 /* offset the relocation offset */
7609 rel->r_offset += offseti;
7611 break;
7612 default:
7613 break;
7616 free(symtab);
7617 free(strtab);
7618 free(old_to_new_syms);
7619 free(sm_table);
7620 free(shdr);
7621 return 0;
7624 #define ARMAG "!<arch>\012" /* For COFF and a.out archives */
7626 typedef struct ArchiveHeader {
7627 char ar_name[16]; /* name of this member */
7628 char ar_date[12]; /* file mtime */
7629 char ar_uid[6]; /* owner uid; printed as decimal */
7630 char ar_gid[6]; /* owner gid; printed as decimal */
7631 char ar_mode[8]; /* file mode, printed as octal */
7632 char ar_size[10]; /* file size, printed as decimal */
7633 char ar_fmag[2]; /* should contain ARFMAG */
7634 } ArchiveHeader;
7636 /* load a '.a' file */
7637 static int tcc_load_archive(TCCState *s1, int fd)
7639 ArchiveHeader hdr;
7640 char ar_size[11];
7641 char ar_name[17];
7642 char magic[8];
7643 int size, len, i;
7644 unsigned long file_offset;
7646 /* skip magic which was already checked */
7647 read(fd, magic, sizeof(magic));
7649 for(;;) {
7650 len = read(fd, &hdr, sizeof(hdr));
7651 if (len == 0)
7652 break;
7653 if (len != sizeof(hdr))
7654 error("invalid archive");
7655 memcpy(ar_size, hdr.ar_size, sizeof(hdr.ar_size));
7656 ar_size[sizeof(hdr.ar_size)] = '\0';
7657 size = strtol(ar_size, NULL, 0);
7658 memcpy(ar_name, hdr.ar_name, sizeof(hdr.ar_name));
7659 for(i = sizeof(hdr.ar_name) - 1; i >= 0; i--) {
7660 if (ar_name[i] != ' ')
7661 break;
7663 ar_name[i + 1] = '\0';
7664 // printf("name='%s' size=%d %s\n", ar_name, size, ar_size);
7665 file_offset = lseek(fd, 0, SEEK_CUR);
7666 if (!strcmp(ar_name, "/") ||
7667 !strcmp(ar_name, "//") ||
7668 !strcmp(ar_name, "__.SYMDEF") ||
7669 !strcmp(ar_name, "__.SYMDEF/") ||
7670 !strcmp(ar_name, "ARFILENAMES/")) {
7671 /* skip symbol table or archive names */
7672 } else {
7673 tcc_load_object_file(s1, fd, file_offset);
7675 /* align to even */
7676 size = (size + 1) & ~1;
7677 lseek(fd, file_offset + size, SEEK_SET);
7679 return 0;
7682 /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL
7683 is referenced by the user (so it should be added as DT_NEEDED in
7684 the generated ELF file) */
7685 static int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level)
7687 Elf32_Ehdr ehdr;
7688 Elf32_Shdr *shdr, *sh, *sh1;
7689 int i, nb_syms, nb_dts, sym_bind;
7690 Elf32_Sym *sym, *dynsym;
7691 Elf32_Dyn *dt, *dynamic;
7692 unsigned char *dynstr;
7693 const char *name, *soname, *p;
7694 DLLReference *dllref;
7696 read(fd, &ehdr, sizeof(ehdr));
7698 /* test CPU specific stuff */
7699 if (ehdr.e_ident[5] != ELFDATA2LSB ||
7700 ehdr.e_machine != EM_386)
7701 error("bad architecture");
7703 /* read sections */
7704 shdr = load_data(fd, ehdr.e_shoff, sizeof(Elf32_Shdr) * ehdr.e_shnum);
7706 /* load dynamic section and dynamic symbols */
7707 nb_syms = 0;
7708 nb_dts = 0;
7709 dynamic = NULL;
7710 dynsym = NULL; /* avoid warning */
7711 dynstr = NULL; /* avoid warning */
7712 for(i = 0, sh = shdr; i < ehdr.e_shnum; i++, sh++) {
7713 switch(sh->sh_type) {
7714 case SHT_DYNAMIC:
7715 nb_dts = sh->sh_size / sizeof(Elf32_Dyn);
7716 dynamic = load_data(fd, sh->sh_offset, sh->sh_size);
7717 break;
7718 case SHT_DYNSYM:
7719 nb_syms = sh->sh_size / sizeof(Elf32_Sym);
7720 dynsym = load_data(fd, sh->sh_offset, sh->sh_size);
7721 sh1 = &shdr[sh->sh_link];
7722 dynstr = load_data(fd, sh1->sh_offset, sh1->sh_size);
7723 break;
7724 default:
7725 break;
7729 /* compute the real library name */
7730 soname = filename;
7731 p = strrchr(soname, '/');
7732 if (p)
7733 soname = p + 1;
7735 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
7736 if (dt->d_tag == DT_SONAME) {
7737 soname = dynstr + dt->d_un.d_val;
7741 /* if the dll is already loaded, do not load it */
7742 for(i = 0; i < nb_loaded_dlls; i++) {
7743 dllref = loaded_dlls[i];
7744 if (!strcmp(soname, dllref->name)) {
7745 /* but update level if needed */
7746 if (level < dllref->level)
7747 dllref->level = level;
7748 goto the_end;
7752 // printf("loading dll '%s'\n", soname);
7754 /* add the dll and its level */
7755 dllref = malloc(sizeof(DLLReference) + strlen(soname));
7756 dllref->level = level;
7757 strcpy(dllref->name, soname);
7758 dynarray_add((void ***)&loaded_dlls, &nb_loaded_dlls, dllref);
7760 /* add dynamic symbols in dynsym_section */
7761 for(i = 1, sym = dynsym + 1; i < nb_syms; i++, sym++) {
7762 sym_bind = ELF32_ST_BIND(sym->st_info);
7763 if (sym_bind == STB_LOCAL)
7764 continue;
7765 name = dynstr + sym->st_name;
7766 add_elf_sym(dynsymtab_section, sym->st_value, sym->st_size,
7767 sym->st_info, sym->st_shndx, name);
7770 /* load all referenced DLLs */
7771 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
7772 switch(dt->d_tag) {
7773 case DT_NEEDED:
7774 name = dynstr + dt->d_un.d_val;
7775 for(i = 0; i < nb_loaded_dlls; i++) {
7776 dllref = loaded_dlls[i];
7777 if (!strcmp(name, dllref->name))
7778 goto already_loaded;
7780 if (tcc_add_dll(s1, name, AFF_REFERENCED_DLL) < 0)
7781 error("referenced dll '%s' not found", name);
7782 already_loaded:
7783 break;
7786 the_end:
7787 free(shdr);
7788 return 0;
7791 /* return -2 if error and CH_EOF if eof */
7792 static void ld_skipspaces(void)
7794 while (ch == ' ' || ch == '\t' || ch == '\n')
7795 cinp();
7798 static int ld_get_cmd(char *cmd, int cmd_size)
7800 char *q;
7802 ld_skipspaces();
7803 if (ch == CH_EOF)
7804 return -1;
7805 q = cmd;
7806 for(;;) {
7807 if (!((ch >= 'a' && ch <= 'z') ||
7808 (ch >= 'A' && ch <= 'Z') ||
7809 (ch >= '0' && ch <= '9') ||
7810 strchr("/.-_+=$:\\,~?*", ch)))
7811 break;
7812 if ((q - cmd) >= (cmd_size - 1))
7813 return -2;
7814 *q++ = ch;
7815 cinp();
7817 *q = '\0';
7818 return 0;
7821 /* interpret a subset of GNU ldscripts to handle the dummy libc.so
7822 files */
7823 static int tcc_load_ldscript(TCCState *s1)
7825 char cmd[64];
7826 char filename[1024];
7827 int ret;
7829 inp();
7830 cinp();
7831 for(;;) {
7832 ret = ld_get_cmd(cmd, sizeof(cmd));
7833 if (ret == CH_EOF)
7834 return 0;
7835 else if (ret < 0)
7836 return -1;
7837 // printf("cmd='%s'\n", cmd);
7838 if (!strcmp(cmd, "INPUT") ||
7839 !strcmp(cmd, "GROUP")) {
7840 ld_skipspaces();
7841 if (ch != '(')
7842 expect("(");
7843 cinp();
7844 for(;;) {
7845 ld_get_cmd(filename, sizeof(filename));
7846 tcc_add_file(s1, filename);
7847 ld_skipspaces();
7848 if (ch == ',') {
7849 cinp();
7850 } else if (ch == ')') {
7851 cinp();
7852 break;
7853 } else if (ch == CH_EOF) {
7854 error("unexpected end of file");
7857 } else {
7858 return -1;
7861 return 0;
7864 /* print the position in the source file of PC value 'pc' by reading
7865 the stabs debug information */
7866 static void rt_printline(unsigned long wanted_pc)
7868 Stab_Sym *sym, *sym_end;
7869 char func_name[128];
7870 unsigned long func_addr, last_pc, pc;
7871 const char *incl_files[INCLUDE_STACK_SIZE];
7872 int incl_index, len, last_line_num, i;
7873 const char *str, *p;
7875 func_name[0] = '\0';
7876 func_addr = 0;
7877 incl_index = 0;
7878 last_pc = 0xffffffff;
7879 last_line_num = 1;
7880 sym = (Stab_Sym *)stab_section->data + 1;
7881 sym_end = (Stab_Sym *)stab_section->data_ptr;
7882 while (sym < sym_end) {
7883 switch(sym->n_type) {
7884 /* function start or end */
7885 case N_FUN:
7886 if (sym->n_strx == 0) {
7887 func_name[0] = '\0';
7888 func_addr = 0;
7889 } else {
7890 str = stabstr_section->data + sym->n_strx;
7891 p = strchr(str, ':');
7892 if (!p) {
7893 pstrcpy(func_name, sizeof(func_name), str);
7894 } else {
7895 len = p - str;
7896 if (len > sizeof(func_name) - 1)
7897 len = sizeof(func_name) - 1;
7898 memcpy(func_name, str, len);
7899 func_name[len] = '\0';
7901 func_addr = sym->n_value;
7903 break;
7904 /* line number info */
7905 case N_SLINE:
7906 pc = sym->n_value + func_addr;
7907 if (wanted_pc >= last_pc && wanted_pc < pc)
7908 goto found;
7909 last_pc = pc;
7910 last_line_num = sym->n_desc;
7911 break;
7912 /* include files */
7913 case N_BINCL:
7914 str = stabstr_section->data + sym->n_strx;
7915 add_incl:
7916 if (incl_index < INCLUDE_STACK_SIZE) {
7917 incl_files[incl_index++] = str;
7919 break;
7920 case N_EINCL:
7921 if (incl_index > 1)
7922 incl_index--;
7923 break;
7924 case N_SO:
7925 if (sym->n_strx == 0) {
7926 incl_index = 0; /* end of translation unit */
7927 } else {
7928 str = stabstr_section->data + sym->n_strx;
7929 /* do not add path */
7930 len = strlen(str);
7931 if (len > 0 && str[len - 1] != '/')
7932 goto add_incl;
7934 break;
7936 sym++;
7938 /* did not find line number info: */
7939 fprintf(stderr, "(no debug info, pc=0x%08lx): ", wanted_pc);
7940 return;
7941 found:
7942 for(i = 0; i < incl_index - 1; i++)
7943 fprintf(stderr, "In file included from %s\n",
7944 incl_files[i]);
7945 if (incl_index > 0) {
7946 fprintf(stderr, "%s:%d: ",
7947 incl_files[incl_index - 1], last_line_num);
7949 if (func_name[0] != '\0') {
7950 fprintf(stderr, "in function '%s()': ", func_name);
7954 /* emit a run time error at position 'pc' */
7955 void rt_error(unsigned long pc, const char *fmt, ...)
7957 va_list ap;
7958 va_start(ap, fmt);
7960 rt_printline(pc);
7961 vfprintf(stderr, fmt, ap);
7962 fprintf(stderr, "\n");
7963 exit(255);
7964 va_end(ap);
7967 #ifndef WIN32
7968 /* signal handler for fatal errors */
7969 static void sig_error(int signum, siginfo_t *siginf, void *puc)
7971 struct ucontext *uc = puc;
7972 unsigned long pc;
7974 #ifdef __i386__
7975 pc = uc->uc_mcontext.gregs[14];
7976 #else
7977 #error please put the right sigcontext field
7978 #endif
7980 switch(signum) {
7981 case SIGFPE:
7982 switch(siginf->si_code) {
7983 case FPE_INTDIV:
7984 case FPE_FLTDIV:
7985 rt_error(pc, "division by zero");
7986 break;
7987 default:
7988 rt_error(pc, "floating point exception");
7989 break;
7991 break;
7992 case SIGBUS:
7993 case SIGSEGV:
7994 rt_error(pc, "dereferencing invalid pointer");
7995 break;
7996 case SIGILL:
7997 rt_error(pc, "illegal instruction");
7998 break;
7999 case SIGABRT:
8000 rt_error(pc, "abort() called");
8001 break;
8002 default:
8003 rt_error(pc, "caught signal %d", signum);
8004 break;
8006 exit(255);
8008 #endif
8010 /* launch the compiled program with the given arguments */
8011 int tcc_run(TCCState *s1, int argc, char **argv)
8013 Section *s;
8014 int (*prog_main)(int, char **);
8015 int i;
8017 tcc_add_runtime(s1);
8019 relocate_common_syms();
8021 /* compute relocation address : section are relocated in place */
8022 for(i = 1; i < nb_sections; i++) {
8023 s = sections[i];
8024 if (s->sh_flags & SHF_ALLOC)
8025 s->sh_addr = (unsigned long)s->data;
8028 relocate_syms(1);
8030 /* relocate each section */
8031 for(i = 1; i < nb_sections; i++) {
8032 s = sections[i];
8033 if ((s->sh_flags & SHF_ALLOC) && s->reloc)
8034 relocate_section(s);
8037 prog_main = (void *)get_elf_sym_val("main");
8039 if (do_debug) {
8040 #ifdef WIN32
8041 error("debug mode currently not available for Windows");
8042 #else
8043 struct sigaction sigact;
8044 /* install TCC signal handlers to print debug info on fatal
8045 runtime errors */
8046 sigact.sa_flags = SA_SIGINFO | SA_ONESHOT;
8047 sigact.sa_sigaction = sig_error;
8048 sigemptyset(&sigact.sa_mask);
8049 sigaction(SIGFPE, &sigact, NULL);
8050 sigaction(SIGILL, &sigact, NULL);
8051 sigaction(SIGSEGV, &sigact, NULL);
8052 sigaction(SIGBUS, &sigact, NULL);
8053 sigaction(SIGABRT, &sigact, NULL);
8054 #endif
8057 #ifdef CONFIG_TCC_BCHECK
8058 if (do_bounds_check) {
8059 int *p, *p_end;
8060 __bound_init();
8061 /* add all known static regions */
8062 p = (int *)bounds_section->data;
8063 p_end = (int *)bounds_section->data_ptr;
8064 while (p < p_end) {
8065 __bound_new_region((void *)p[0], p[1]);
8066 p += 2;
8069 #endif
8071 return (*prog_main)(argc, argv);
8074 TCCState *tcc_new(void)
8076 char *p, *r;
8077 TCCState *s;
8079 s = malloc(sizeof(TCCState));
8080 if (!s)
8081 return NULL;
8082 s->output_type = TCC_OUTPUT_MEMORY;
8084 /* default include paths */
8085 tcc_add_include_path(s, "/usr/include");
8086 tcc_add_include_path(s, CONFIG_TCC_PREFIX "/lib/tcc/include");
8087 tcc_add_include_path(s, "/usr/local/include");
8089 /* add all tokens */
8090 tok_ident = TOK_IDENT;
8091 p = tcc_keywords;
8092 while (*p) {
8093 r = p;
8094 while (*r++);
8095 tok_alloc(p, r - p - 1);
8096 p = r;
8099 /* standard defines */
8100 tcc_define_symbol(s, "__STDC__", NULL);
8101 #if defined(TCC_TARGET_I386)
8102 tcc_define_symbol(s, "__i386__", NULL);
8103 #endif
8104 /* tiny C specific defines */
8105 tcc_define_symbol(s, "__TINYC__", NULL);
8107 /* default library paths */
8108 tcc_add_library_path(s, "/usr/local/lib");
8109 tcc_add_library_path(s, "/usr/lib");
8110 tcc_add_library_path(s, "/lib");
8112 /* no section zero */
8113 dynarray_add((void ***)&sections, &nb_sections, NULL);
8115 /* create standard sections */
8116 text_section = new_section(".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
8117 data_section = new_section(".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
8118 bss_section = new_section(".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
8120 /* symbols are always generated for linking stage */
8121 symtab_section = new_section(".symtab", SHT_SYMTAB, 0);
8122 symtab_section->sh_entsize = sizeof(Elf32_Sym);
8123 strtab_section = new_section(".strtab", SHT_STRTAB, 0);
8124 put_elf_str(strtab_section, "");
8125 symtab_section->link = strtab_section;
8126 put_elf_sym(symtab_section, 0, 0, 0, 0, 0, NULL);
8127 new_section_hash(".hashtab", SHF_PRIVATE,
8128 ELF_SYM_HASH_SIZE, symtab_section);
8130 /* private symbol table for dynamic symbols */
8131 dynsymtab_section = new_section(".dynsymtab", SHT_SYMTAB, SHF_PRIVATE);
8132 dynsymtab_section->sh_entsize = sizeof(Elf32_Sym);
8133 dynstrtab_section = new_section(".dynstrtab", SHT_STRTAB, SHF_PRIVATE);
8134 put_elf_str(dynstrtab_section, "");
8135 dynsymtab_section->link = dynstrtab_section;
8136 put_elf_sym(dynsymtab_section, 0, 0, 0, 0, 0, NULL);
8137 new_section_hash(".dynhashtab", SHF_PRIVATE,
8138 ELF_SYM_HASH_SIZE, dynsymtab_section);
8139 return s;
8142 void tcc_delete(TCCState *s)
8144 free(s);
8147 int tcc_add_include_path(TCCState *s, const char *pathname)
8149 char *pathname1;
8151 pathname1 = strdup(pathname);
8152 if (!pathname1)
8153 return -1;
8154 dynarray_add((void ***)&include_paths, &nb_include_paths, pathname1);
8155 return 0;
8158 static int tcc_add_file_internal(TCCState *s, const char *filename, int flags)
8160 const char *ext;
8161 Elf32_Ehdr ehdr;
8162 int fd;
8163 BufferedFile *saved_file;
8165 /* find source file type with extension */
8166 ext = strrchr(filename, '.');
8167 if (ext)
8168 ext++;
8170 /* open the file */
8171 saved_file = file;
8172 file = tcc_open(filename);
8173 if (!file) {
8174 if (flags & AFF_PRINT_ERROR) {
8175 error("file '%s' not found", filename);
8176 } else {
8177 file = saved_file;
8178 return -1;
8182 if (!ext || !strcmp(ext, "c")) {
8183 /* C file assumed */
8184 tcc_compile(s);
8185 } else {
8186 fd = file->fd;
8187 /* assume executable format: auto guess file type */
8188 if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
8189 error("could not read header");
8190 lseek(fd, 0, SEEK_SET);
8192 if (ehdr.e_ident[0] == ELFMAG0 &&
8193 ehdr.e_ident[1] == ELFMAG1 &&
8194 ehdr.e_ident[2] == ELFMAG2 &&
8195 ehdr.e_ident[3] == ELFMAG3) {
8196 file->line_num = 0; /* do not display line number if error */
8197 if (ehdr.e_type == ET_REL) {
8198 tcc_load_object_file(s, fd, 0);
8199 } else if (ehdr.e_type == ET_DYN) {
8200 tcc_load_dll(s, fd, filename, (flags & AFF_REFERENCED_DLL) != 0);
8201 } else {
8202 error("unrecognized ELF file");
8204 } else if (memcmp((char *)&ehdr, ARMAG, 8) == 0) {
8205 file->line_num = 0; /* do not display line number if error */
8206 tcc_load_archive(s, fd);
8207 } else {
8208 /* as GNU ld, consider it is an ld script if not recognized */
8209 if (tcc_load_ldscript(s) < 0)
8210 error("unrecognized file type");
8213 tcc_close(file);
8214 file = saved_file;
8215 return 0;
8218 void tcc_add_file(TCCState *s, const char *filename)
8220 tcc_add_file_internal(s, filename, AFF_PRINT_ERROR);
8223 int tcc_add_library_path(TCCState *s, const char *pathname)
8225 char *pathname1;
8227 pathname1 = strdup(pathname);
8228 if (!pathname1)
8229 return -1;
8230 dynarray_add((void ***)&library_paths, &nb_library_paths, pathname1);
8231 return 0;
8234 /* find and load a dll. Return non zero if not found */
8235 /* XXX: add '-rpath' option support ? */
8236 static int tcc_add_dll(TCCState *s, const char *filename, int flags)
8238 char buf[1024];
8239 int i;
8241 for(i = 0; i < nb_library_paths; i++) {
8242 snprintf(buf, sizeof(buf), "%s/%s",
8243 library_paths[i], filename);
8244 if (tcc_add_file_internal(s, buf, flags) == 0)
8245 return 0;
8247 return -1;
8250 /* the library name is the same as the argument of the '-l' option */
8251 int tcc_add_library(TCCState *s, const char *libraryname)
8253 char buf[1024];
8254 int i;
8255 void *h;
8257 /* if we output to memory, then we simply we dlopen(). */
8258 if (s->output_type == TCC_OUTPUT_MEMORY) {
8259 /* Since the libc is already loaded, we don't need to load it again */
8260 if (!strcmp(libraryname, "c"))
8261 return 0;
8262 snprintf(buf, sizeof(buf), "lib%s.so", libraryname);
8263 h = dlopen(buf, RTLD_GLOBAL | RTLD_LAZY);
8264 if (!h)
8265 return -1;
8266 return 0;
8269 /* first we look for the dynamic library if not static linking */
8270 if (!static_link) {
8271 snprintf(buf, sizeof(buf), "lib%s.so", libraryname);
8272 if (tcc_add_dll(s, buf, 0) == 0)
8273 return 0;
8276 /* then we look for the static library */
8277 for(i = 0; i < nb_library_paths; i++) {
8278 snprintf(buf, sizeof(buf), "%s/lib%s.a",
8279 library_paths[i], libraryname);
8280 if (tcc_add_file_internal(s, buf, 0) == 0)
8281 return 0;
8283 return -1;
8286 int tcc_set_output_type(TCCState *s, int output_type)
8288 s->output_type = output_type;
8290 /* add libc crt1/crti objects */
8291 if (output_type == TCC_OUTPUT_EXE ||
8292 output_type == TCC_OUTPUT_DLL) {
8293 if (output_type != TCC_OUTPUT_DLL)
8294 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crt1.o");
8295 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crti.o");
8297 return 0;
8300 #if !defined(LIBTCC)
8302 void help(void)
8304 printf("tcc version 0.9.8 - Tiny C Compiler - Copyright (C) 2001, 2002 Fabrice Bellard\n"
8305 "usage: tcc [-c] [-o outfile] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
8306 " [-g] [-b] [-Ldir] [-llib] [-shared] [-static]\n"
8307 " [--] infile1 [infile2... --] [infile_args...]\n"
8308 "\n"
8309 "General options:\n"
8310 " -c compile only - generate an object file\n"
8311 " -o outfile set output filename (NOT WORKING YET)\n"
8312 " -bench output compilation statistics\n"
8313 " -- allows multiples input files if no -o option given. Also\n"
8314 " separate input files from runtime arguments\n"
8315 "Preprocessor options:\n"
8316 " -Idir add include path 'dir'\n"
8317 " -Dsym[=val] define 'sym' with value 'val'\n"
8318 " -Usym undefine 'sym'\n"
8319 "C compiler options:\n"
8320 " -g generate runtime debug info\n"
8321 #ifdef CONFIG_TCC_BCHECK
8322 " -b compile with built-in memory and bounds checker (implies -g)\n"
8323 #endif
8324 "Linker options:\n"
8325 " -Ldir add library path 'dir'\n"
8326 " -llib link with dynamic library 'lib'\n"
8327 " -shared generate a shared library (NOT WORKING YET)\n"
8328 " -static static linking (NOT WORKING YET)\n"
8332 int main(int argc, char **argv)
8334 char *r, *outfile;
8335 int optind, output_type, multiple_files, i;
8336 TCCState *s;
8337 char **libraries;
8338 int nb_libraries;
8340 s = tcc_new();
8341 output_type = TCC_OUTPUT_MEMORY;
8343 optind = 1;
8344 outfile = NULL;
8345 multiple_files = 0;
8346 libraries = NULL;
8347 nb_libraries = 0;
8348 while (1) {
8349 if (optind >= argc) {
8350 show_help:
8351 help();
8352 return 1;
8354 r = argv[optind];
8355 if (r[0] != '-')
8356 break;
8357 optind++;
8358 if (r[1] == '-') {
8359 /* '--' enables multiple files input */
8360 multiple_files = 1;
8361 } else if (r[1] == 'h' || r[1] == '?') {
8362 goto show_help;
8363 } else if (r[1] == 'I') {
8364 if (tcc_add_include_path(s, r + 2) < 0)
8365 error("too many include paths");
8366 } else if (r[1] == 'D') {
8367 char *sym, *value;
8368 sym = r + 2;
8369 value = strchr(sym, '=');
8370 if (value) {
8371 *value = '\0';
8372 value++;
8374 tcc_define_symbol(s, sym, value);
8375 } else if (r[1] == 'U') {
8376 tcc_undefine_symbol(s, r + 2);
8377 } else if (r[1] == 'L') {
8378 tcc_add_library_path(s, r + 2);
8379 } else if (r[1] == 'l') {
8380 dynarray_add((void ***)&libraries, &nb_libraries, r + 2);
8381 } else if (!strcmp(r + 1, "bench")) {
8382 do_bench = 1;
8383 #ifdef CONFIG_TCC_BCHECK
8384 } else if (r[1] == 'b') {
8385 if (!do_bounds_check) {
8386 do_bounds_check = 1;
8387 /* define symbol */
8388 tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL);
8389 /* create bounds sections */
8390 bounds_section = new_section(".bounds",
8391 SHT_PROGBITS, SHF_ALLOC);
8392 lbounds_section = new_section(".lbounds",
8393 SHT_PROGBITS, SHF_ALLOC);
8394 /* debug is implied */
8395 goto debug_opt;
8397 #endif
8398 } else if (r[1] == 'g') {
8399 #ifdef CONFIG_TCC_BCHECK
8400 debug_opt:
8401 #endif
8402 if (!do_debug) {
8403 do_debug = 1;
8405 /* stab symbols */
8406 stab_section = new_section(".stab", SHT_PROGBITS, 0);
8407 stab_section->sh_entsize = sizeof(Stab_Sym);
8408 stabstr_section = new_section(".stabstr", SHT_STRTAB, 0);
8409 put_elf_str(stabstr_section, "");
8410 stab_section->link = stabstr_section;
8411 /* put first entry */
8412 put_stabs("", 0, 0, 0, 0);
8414 } else
8415 /* the following options are only for testing, so not
8416 documented */
8417 if (r[1] == 'c') {
8418 multiple_files = 1;
8419 output_type = TCC_OUTPUT_OBJ;
8420 } else if (!strcmp(r + 1, "static")) {
8421 static_link = 1;
8422 } else if (!strcmp(r + 1, "shared")) {
8423 output_type = TCC_OUTPUT_DLL;
8424 } else if (r[1] == 'o') {
8425 if (optind >= argc)
8426 goto show_help;
8427 multiple_files = 1;
8428 outfile = argv[optind++];
8429 } else {
8430 error("invalid option -- '%s'", r);
8434 /* if outfile provided without other options, we output an
8435 executable */
8436 if (outfile && output_type == TCC_OUTPUT_MEMORY)
8437 output_type = TCC_OUTPUT_EXE;
8439 tcc_set_output_type(s, output_type);
8441 tcc_add_file(s, argv[optind]);
8442 if (multiple_files) {
8443 while ((optind + 1) < argc) {
8444 optind++;
8445 r = argv[optind];
8446 if (r[0] == '-') {
8447 if (r[1] != '-')
8448 error("'--' expected");
8449 break;
8451 tcc_add_file(s, r);
8455 /* add specified libraries */
8456 for(i = 0; i < nb_libraries;i++) {
8457 if (tcc_add_library(s, libraries[i]) < 0)
8458 error("cannot find -l%s", libraries[i]);
8461 if (do_bench) {
8462 printf("total: %d idents, %d lines, %d bytes\n",
8463 tok_ident - TOK_IDENT, total_lines, total_bytes);
8466 if (s->output_type != TCC_OUTPUT_MEMORY) {
8467 tcc_output_file(s, outfile);
8468 return 0;
8469 } else {
8470 return tcc_run(s, argc - optind, argv + optind);
8474 #endif