2 * TCC - Tiny C Compiler
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.
28 #include <sys/ucontext.h>
33 #ifndef CONFIG_TCC_STATIC
38 /* preprocessor debug */
41 /* amount of virtual memory associate to a section (currently, we do
43 #define SECTION_VSIZE (1024 * 1024)
45 #define INCLUDE_STACK_SIZE 32
46 #define IFDEF_STACK_SIZE 64
47 #define VSTACK_SIZE 64
48 #define STRING_MAX_SIZE 1024
49 #define INCLUDE_PATHS_MAX 32
51 #define TOK_HASH_SIZE 521
52 #define TOK_ALLOC_INCR 256 /* must be a power of two */
53 #define SYM_HASH_SIZE 263
55 /* token symbol management */
56 typedef struct TokenSym
{
57 struct TokenSym
*hash_next
;
58 int tok
; /* token number */
64 typedef union CValue
{
70 unsigned int ul
; /* address (should be unsigned long on 64 bit cpu) */
72 unsigned long long ull
;
79 typedef struct SValue
{
81 unsigned short r
; /* register + flags */
82 unsigned short r2
; /* second register, used for 'long long'
83 type. If not used, set to VT_CONST */
84 CValue c
; /* constant */
87 /* symbol management */
89 int v
; /* symbol token */
90 int t
; /* associated type */
91 int r
; /* associated register */
92 int c
; /* associated number */
93 struct Sym
*next
; /* next related symbol */
94 struct Sym
*prev
; /* prev symbol in stack */
95 struct Sym
*hash_next
; /* next symbol in hash table */
98 typedef struct SymStack
{
100 struct Sym
*hash
[SYM_HASH_SIZE
];
103 /* relocation entry (currently only used for functions or variables */
104 typedef struct Reloc
{
105 int type
; /* type of relocation */
106 int addr
; /* address of relocation */
107 struct Reloc
*next
; /* next relocation */
110 #define RELOC_ADDR32 1 /* 32 bits relocation */
111 #define RELOC_REL32 2 /* 32 bits relative relocation */
113 /* section definition */
114 typedef struct Section
{
115 char name
[64]; /* section name */
116 unsigned char *data
; /* section data */
117 unsigned char *data_ptr
; /* current data pointer */
118 int sh_num
; /* elf section number */
119 int sh_type
; /* elf section type */
120 int sh_flags
; /* elf section flags */
121 int sh_entsize
; /* elf entry size */
122 struct Section
*link
; /* link to another section */
123 struct Section
*next
;
126 /* GNUC attribute definition */
127 typedef struct AttributeDef
{
132 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
133 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
134 #define SYM_FIRST_ANOM (1 << (31 - VT_STRUCT_SHIFT)) /* first anonymous sym */
136 #define FUNC_NEW 1 /* ansi function prototype */
137 #define FUNC_OLD 2 /* old function prototype */
138 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
140 /* field 'Sym.t' for macros */
141 #define MACRO_OBJ 0 /* object like macro */
142 #define MACRO_FUNC 1 /* function like macro */
144 /* type_decl() types */
145 #define TYPE_ABSTRACT 1 /* type without variable */
146 #define TYPE_DIRECT 2 /* type with variable */
157 int ch
, ch1
, tok
, tok1
;
161 Section
*first_section
;
163 Section
*text_section
, *data_section
, *bss_section
; /* predefined sections */
164 Section
*cur_text_section
; /* current section where function code is
166 Section
*bounds_section
; /* contains global data bound description */
168 Section
*stab_section
, *stabstr_section
, *symtab_section
, *strtab_section
;
170 /* loc : local variable index
171 ind : output code index
173 anon_sym: anonymous symbol index
176 prog
, ind
, loc
, const_wanted
;
177 int global_expr
; /* true if compound literals must be allocated
178 globally (used during initializers parsing */
179 int func_vt
, func_vc
; /* current function return type (used by
180 return instruction) */
181 int last_line_num
, last_ind
, func_ind
; /* debug last line number and pc */
183 TokenSym
**table_ident
;
184 TokenSym
*hash_ident
[TOK_HASH_SIZE
];
185 char token_buf
[STRING_MAX_SIZE
+ 1];
186 char *filename
, *funcname
;
187 /* contains global symbols which remain between each translation unit */
188 SymStack extern_stack
;
189 SymStack define_stack
, global_stack
, local_stack
, label_stack
;
191 SValue vstack
[VSTACK_SIZE
], *vtop
;
192 int *macro_ptr
, *macro_ptr_allocated
;
193 IncludeFile include_stack
[INCLUDE_STACK_SIZE
], *include_stack_ptr
;
194 int ifdef_stack
[IFDEF_STACK_SIZE
], *ifdef_stack_ptr
;
195 char *include_paths
[INCLUDE_PATHS_MAX
];
196 int nb_include_paths
;
197 int char_pointer_type
;
199 /* compile with debug symbol (and use them if error during execution) */
202 /* compile with built-in memory and bounds checker */
203 int do_bounds_check
= 0;
205 /* use GNU C extensions */
208 /* use Tiny C extensions */
211 /* The current value can be: */
212 #define VT_VALMASK 0x00ff
213 #define VT_CONST 0x00f0 /* constant in vc
214 (must be first non register value) */
215 #define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */
216 #define VT_LOCAL 0x00f2 /* offset on stack */
217 #define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */
218 #define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */
219 #define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */
220 #define VT_LVAL 0x0100 /* var is an lvalue */
221 #define VT_FORWARD 0x0200 /* value is forward reference */
222 #define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for
223 char/short stored in integer registers) */
226 #define VT_STRUCT_SHIFT 16 /* structure/enum name shift (16 bits left) */
228 #define VT_INT 0 /* integer type */
229 #define VT_BYTE 1 /* signed byte type */
230 #define VT_SHORT 2 /* short type */
231 #define VT_VOID 3 /* void type */
232 #define VT_PTR 4 /* pointer increment */
233 #define VT_ENUM 5 /* enum definition */
234 #define VT_FUNC 6 /* function type */
235 #define VT_STRUCT 7 /* struct/union definition */
236 #define VT_FLOAT 8 /* IEEE float */
237 #define VT_DOUBLE 9 /* IEEE double */
238 #define VT_LDOUBLE 10 /* IEEE long double */
239 #define VT_BOOL 11 /* ISOC99 boolean type */
240 #define VT_LLONG 12 /* 64 bit integer */
241 #define VT_LONG 13 /* long integer (NEVER USED as type, only
243 #define VT_BTYPE 0x000f /* mask for basic type */
244 #define VT_UNSIGNED 0x0010 /* unsigned type */
245 #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
246 #define VT_BITFIELD 0x0040 /* bitfield modifier */
249 #define VT_EXTERN 0x00000080 /* extern definition */
250 #define VT_STATIC 0x00000100 /* static variable */
251 #define VT_TYPEDEF 0x00000200 /* typedef definition */
253 /* type mask (except storage) */
254 #define VT_TYPE (~(VT_EXTERN | VT_STATIC | VT_TYPEDEF))
258 /* warning: the following compare tokens depend on i386 asm code */
270 #define TOK_LAND 0xa0
274 #define TOK_MID 0xa3 /* inc/dec, to void constant */
276 #define TOK_UDIV 0xb0 /* unsigned division */
277 #define TOK_UMOD 0xb1 /* unsigned modulo */
278 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
279 #define TOK_CINT 0xb3 /* number in tokc */
280 #define TOK_CCHAR 0xb4 /* char constant in tokc */
281 #define TOK_STR 0xb5 /* pointer to string in tokc */
282 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
283 #define TOK_LCHAR 0xb7
284 #define TOK_LSTR 0xb8
285 #define TOK_CFLOAT 0xb9 /* float constant */
286 #define TOK_CDOUBLE 0xc0 /* double constant */
287 #define TOK_CLDOUBLE 0xc1 /* long double constant */
288 #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
289 #define TOK_ADDC1 0xc3 /* add with carry generation */
290 #define TOK_ADDC2 0xc4 /* add with carry use */
291 #define TOK_SUBC1 0xc5 /* add with carry generation */
292 #define TOK_SUBC2 0xc6 /* add with carry use */
293 #define TOK_CUINT 0xc8 /* unsigned int constant */
294 #define TOK_CLLONG 0xc9 /* long long constant */
295 #define TOK_CULLONG 0xca /* unsigned long long constant */
296 #define TOK_ARROW 0xcb
297 #define TOK_DOTS 0xcc /* three dots */
298 #define TOK_SHR 0xcd /* unsigned shift right */
300 #define TOK_SHL 0x01 /* shift left */
301 #define TOK_SAR 0x02 /* signed shift right */
303 /* assignement operators : normal operator or 0x80 */
304 #define TOK_A_MOD 0xa5
305 #define TOK_A_AND 0xa6
306 #define TOK_A_MUL 0xaa
307 #define TOK_A_ADD 0xab
308 #define TOK_A_SUB 0xad
309 #define TOK_A_DIV 0xaf
310 #define TOK_A_XOR 0xde
311 #define TOK_A_OR 0xfc
312 #define TOK_A_SHL 0x81
313 #define TOK_A_SAR 0x82
315 /* all identificators and strings have token above that */
316 #define TOK_IDENT 256
337 /* ignored types Must have contiguous values */
347 /* unsupported type */
361 /* preprocessor only */
362 TOK_UIDENT
, /* first "user" ident (not keyword) */
363 TOK_DEFINE
= TOK_UIDENT
,
379 /* special identifiers */
382 /* attribute identifiers */
391 /* XXX: need to define this to use them in non ISOC99 context */
392 extern float strtof (const char *__nptr
, char **__endptr
);
393 extern long double strtold (const char *__nptr
, char **__endptr
);
397 void next_nomacro(void);
398 int expr_const(void);
402 void decl_initializer(int t
, int r
, int c
, int first
, int size_only
);
403 int decl_initializer_alloc(int t
, AttributeDef
*ad
, int r
, int has_init
);
405 void move_reg(int r
, int s
);
406 void save_regs(void);
407 void save_reg(int r
);
413 void macro_subst(int **tok_str
, int *tok_len
,
414 Sym
**nested_list
, int *macro_str
);
415 int save_reg_forced(int r
);
417 void force_charshort_cast(int t
);
418 void gen_cast(int t
);
420 Sym
*sym_find(int v
);
421 Sym
*sym_push(int v
, int t
, int r
, int c
);
424 int type_size(int t
, int *a
);
425 int pointed_type(int t
);
426 int pointed_size(int t
);
427 int is_compatible_types(int t1
, int t2
);
428 int parse_btype(int *type_ptr
, AttributeDef
*ad
);
429 int type_decl(int *v
, int t
, int td
);
431 void error(const char *fmt
, ...);
433 void vset(int t
, int r
, int v
);
434 void type_to_str(char *buf
, int buf_size
,
435 int t
, const char *varstr
);
437 /* section generation */
438 void greloc(Sym
*s
, int addr
, int type
);
439 static int put_elf_str(Section
*s
, const char *sym
);
440 static void put_elf_sym(Section
*s
,
441 unsigned long value
, unsigned long size
,
442 int info
, int other
, int shndx
, const char *name
);
443 static void put_stabs(const char *str
, int type
, int other
, int desc
, int value
);
444 static void put_stabn(int type
, int other
, int desc
, int value
);
445 static void put_stabd(int type
, int other
, int desc
);
447 /* true if float/double/long double type */
448 static inline int is_float(int t
)
452 return bt
== VT_LDOUBLE
|| bt
== VT_DOUBLE
|| bt
== VT_FLOAT
;
457 #include "i386-gen.c"
459 #ifdef CONFIG_TCC_STATIC
461 #define RTLD_LAZY 0x001
462 #define RTLD_NOW 0x002
463 #define RTLD_GLOBAL 0x100
465 /* dummy function for profiling */
466 void *dlopen(const char *filename
, int flag
)
471 const char *dlerror(void)
476 typedef struct TCCSyms
{
481 #define TCCSYM(a) { #a, &a, },
483 /* add the symbol you want here if no dynamic linking is done */
484 static TCCSyms tcc_syms
[] = {
492 void *dlsym(void *handle
, char *symbol
)
496 while (p
->str
!= NULL
) {
497 if (!strcmp(p
->str
, symbol
))
506 /********************************************************/
507 /* runtime library is there */
508 /* XXX: we suppose that the host compiler handles 'long long'. It
509 would not be difficult to suppress this assumption */
511 /* XXX: these functions are defined in libgcc. Should provide a
512 portable code too. */
513 long long __divll(long long a
, long long b
)
518 long long __modll(long long a
, long long b
)
523 unsigned long long __divull(unsigned long long a
, unsigned long long b
)
528 unsigned long long __modull(unsigned long long a
, unsigned long long b
)
533 long long __sardi3(long long a
, int b
)
538 unsigned long long __shrdi3(unsigned long long a
, int b
)
543 long long __shldi3(long long a
, int b
)
548 float __ulltof(unsigned long long a
)
553 double __ulltod(unsigned long long a
)
558 long double __ulltold(unsigned long long a
)
560 return (long double)a
;
563 unsigned long long __ftoull(float a
)
565 return (unsigned long long)a
;
568 unsigned long long __dtoull(double a
)
570 return (unsigned long long)a
;
573 unsigned long long __ldtoull(long double a
)
575 return (unsigned long long)a
;
579 /********************************************************/
581 /* copy a string and truncate it */
582 char *pstrcpy(char *buf
, int buf_size
, const char *s
)
588 q_end
= buf
+ buf_size
- 1;
599 /* strcat and truncate */
600 char *pstrcat(char *buf
, int buf_size
, const char *s
)
605 pstrcpy(buf
+ len
, buf_size
- len
, s
);
609 Section
*new_section(const char *name
, int sh_type
, int sh_flags
)
611 Section
*sec
, **psec
;
614 sec
= malloc(sizeof(Section
));
616 error("memory full");
617 memset(sec
, 0, sizeof(Section
));
618 pstrcpy(sec
->name
, sizeof(sec
->name
), name
);
620 sec
->sh_num
= ++section_num
;
621 sec
->sh_type
= sh_type
;
622 sec
->sh_flags
= sh_flags
;
623 data
= mmap(NULL
, SECTION_VSIZE
,
624 PROT_EXEC
| PROT_READ
| PROT_WRITE
,
625 MAP_PRIVATE
| MAP_ANONYMOUS
,
627 if (data
== (void *)(-1))
628 error("could not mmap section '%s'", name
);
630 sec
->data_ptr
= data
;
631 psec
= &first_section
;
632 while (*psec
!= NULL
)
633 psec
= &(*psec
)->next
;
639 /* return a reference to a section, and create it if it does not
641 Section
*find_section(const char *name
)
645 for(sec
= first_section
; sec
!= NULL
; sec
= sec
->next
) {
646 if (!strcmp(name
, sec
->name
))
649 /* sections are created as PROGBITS */
650 return new_section(name
, SHT_PROGBITS
, SHF_ALLOC
);
653 /* add a new relocation entry to symbol 's' */
654 void greloc(Sym
*s
, int addr
, int type
)
657 p
= malloc(sizeof(Reloc
));
659 error("memory full");
662 p
->next
= (Reloc
*)s
->c
;
666 /* patch each relocation entry with value 'val' */
667 void greloc_patch(Sym
*s
, int val
)
674 greloc_patch1(p
, val
);
683 static inline int isid(int c
)
685 return (c
>= 'a' && c
<= 'z') ||
686 (c
>= 'A' && c
<= 'Z') ||
690 static inline int isnum(int c
)
692 return c
>= '0' && c
<= '9';
695 static inline int toup(int c
)
697 if (ch
>= 'a' && ch
<= 'z')
698 return ch
- 'a' + 'A';
706 for(f
= include_stack
; f
< include_stack_ptr
; f
++)
707 fprintf(stderr
, "In file included from %s:%d:\n",
708 f
->filename
, f
->line_num
);
709 fprintf(stderr
, "%s:%d: ", filename
, line_num
);
712 void error(const char *fmt
, ...)
717 vfprintf(stderr
, fmt
, ap
);
718 fprintf(stderr
, "\n");
723 void expect(const char *msg
)
725 error("%s expected", msg
);
728 void warning(const char *fmt
, ...)
734 fprintf(stderr
, "warning: ");
735 vfprintf(stderr
, fmt
, ap
);
736 fprintf(stderr
, "\n");
743 error("'%c' expected", c
);
747 void test_lvalue(void)
749 if (!(vtop
->r
& VT_LVAL
))
753 TokenSym
*tok_alloc(const char *str
, int len
)
755 TokenSym
*ts
, **pts
, **ptable
;
762 h
= ((h
<< 8) | (str
[i
] & 0xff)) % TOK_HASH_SIZE
;
764 pts
= &hash_ident
[h
];
769 if (ts
->len
== len
&& !memcmp(ts
->str
, str
, len
))
771 pts
= &(ts
->hash_next
);
774 if (tok_ident
>= SYM_FIRST_ANOM
)
775 error("memory full");
777 /* expand token table if needed */
778 i
= tok_ident
- TOK_IDENT
;
779 if ((i
% TOK_ALLOC_INCR
) == 0) {
780 ptable
= realloc(table_ident
, (i
+ TOK_ALLOC_INCR
) * sizeof(TokenSym
*));
782 error("memory full");
783 table_ident
= ptable
;
786 ts
= malloc(sizeof(TokenSym
) + len
);
788 error("memory full");
790 ts
->tok
= tok_ident
++;
792 ts
->hash_next
= NULL
;
793 memcpy(ts
->str
, str
, len
+ 1);
798 void add_char(char **pp
, int c
)
802 if (c
== '\'' || c
== '\"' || c
== '\\') {
803 /* XXX: could be more precise if char or string */
806 if (c
>= 32 && c
<= 126) {
813 *p
++ = '0' + ((c
>> 6) & 7);
814 *p
++ = '0' + ((c
>> 3) & 7);
815 *p
++ = '0' + (c
& 7);
821 /* XXX: buffer overflow */
822 char *get_tok_str(int v
, CValue
*cv
)
824 static char buf
[STRING_MAX_SIZE
+ 1];
829 if (v
== TOK_CINT
|| v
== TOK_CUINT
) {
830 sprintf(buf
, "%u", cv
->ui
);
832 } else if (v
== TOK_CCHAR
|| v
== TOK_LCHAR
) {
839 } else if (v
== TOK_STR
|| v
== TOK_LSTR
) {
843 for(i
=0;i
<ts
->len
;i
++)
844 add_char(&p
, ts
->str
[i
]);
848 } else if (v
< TOK_IDENT
) {
853 } else if (v
< tok_ident
) {
854 return table_ident
[v
- TOK_IDENT
]->str
;
856 /* should never happen */
861 /* push, without hashing */
862 Sym
*sym_push2(Sym
**ps
, int v
, int t
, int c
)
865 s
= malloc(sizeof(Sym
));
867 error("memory full");
878 /* find a symbol and return its associated structure. 's' is the top
879 of the symbol stack */
880 Sym
*sym_find2(Sym
*s
, int v
)
890 #define HASH_SYM(v) ((unsigned)(v) % SYM_HASH_SIZE)
892 /* find a symbol and return its associated structure. 'st' is the
894 Sym
*sym_find1(SymStack
*st
, int v
)
898 s
= st
->hash
[HASH_SYM(v
)];
907 Sym
*sym_push1(SymStack
*st
, int v
, int t
, int c
)
910 s
= sym_push2(&st
->top
, v
, t
, c
);
911 /* add in hash table */
913 ps
= &st
->hash
[HASH_SYM(v
)];
920 /* find a symbol in the right symbol space */
924 s
= sym_find1(&local_stack
, v
);
926 s
= sym_find1(&global_stack
, v
);
930 /* push a given symbol on the symbol stack */
931 Sym
*sym_push(int v
, int t
, int r
, int c
)
935 s
= sym_push1(&local_stack
, v
, t
, c
);
937 s
= sym_push1(&global_stack
, v
, t
, c
);
942 /* pop symbols until top reaches 'b' */
943 void sym_pop(SymStack
*st
, Sym
*b
)
950 /* free hash table entry, except if symbol was freed (only
951 used for #undef symbols) */
953 st
->hash
[HASH_SYM(s
->v
)] = s
->hash_next
;
960 /* undefined a hashed symbol (used for #undef). Its name is set to
962 void sym_undef(SymStack
*st
, Sym
*s
)
965 ss
= &st
->hash
[HASH_SYM(s
->v
)];
966 while (*ss
!= NULL
) {
969 ss
= &(*ss
)->hash_next
;
975 /* no need to put that inline */
978 if (include_stack_ptr
== include_stack
)
980 /* add end of include file debug info */
982 put_stabd(N_EINCL
, 0, 0);
984 /* pop include stack */
988 file
= include_stack_ptr
->file
;
989 filename
= include_stack_ptr
->filename
;
990 line_num
= include_stack_ptr
->line_num
;
994 /* read next char from current input file */
995 static inline void inp(void)
998 /* faster than fgetc */
999 ch1
= getc_unlocked(file
);
1001 if (handle_eof() < 0)
1008 // printf("ch1=%c 0x%x\n", ch1, ch1);
1011 /* input with '\\n' handling */
1012 static inline void minp(void)
1017 if (ch
== '\\' && ch1
== '\n') {
1021 //printf("ch=%c 0x%x\n", ch, ch);
1025 /* same as minp, but also skip comments */
1033 /* single line C++ comments */
1035 while (ch1
!= '\n' && ch1
!= -1)
1038 ch
= ' '; /* return space */
1039 } else if (ch1
== '*') {
1045 if (c
== '*' && ch1
== '/') {
1047 ch
= ' '; /* return space */
1059 void skip_spaces(void)
1061 while (ch
== ' ' || ch
== '\t')
1065 /* skip block of text until #else, #elif or #endif. skip also pairs of
1067 void preprocess_skip()
1072 while (ch
!= '\n') {
1083 (tok
== TOK_ELSE
|| tok
== TOK_ELIF
|| tok
== TOK_ENDIF
))
1085 if (tok
== TOK_IF
|| tok
== TOK_IFDEF
|| tok
== TOK_IFNDEF
)
1087 else if (tok
== TOK_ENDIF
)
1093 /* return the number of additionnal 'ints' necessary to store the
1095 static inline int tok_ext_size(int t
)
1112 return LDOUBLE_SIZE
/ 4;
1118 void tok_add(int **tok_str
, int *tok_len
, int t
)
1123 if ((len
& 63) == 0) {
1124 str
= realloc(str
, (len
+ 64) * sizeof(int));
1133 void tok_add2(int **tok_str
, int *tok_len
, int t
, CValue
*cv
)
1137 tok_add(tok_str
, tok_len
, t
);
1138 n
= tok_ext_size(t
);
1140 tok_add(tok_str
, tok_len
, cv
->tab
[i
]);
1143 /* get a token from an integer array and increment pointer accordingly */
1144 int tok_get(int **tok_str
, CValue
*cv
)
1150 n
= tok_ext_size(t
);
1157 /* eval an expression for #if/#elif */
1158 int expr_preprocess(void)
1160 int *str
, len
, c
, t
;
1168 next(); /* do macro subst */
1169 if (tok
== TOK_DEFINED
) {
1174 c
= sym_find1(&define_stack
, tok
) != 0;
1179 } else if (tok
>= TOK_IDENT
) {
1180 /* if undefined macro */
1184 tok_add2(&str
, &len
, tok
, &tokc
);
1186 tok_add(&str
, &len
, -1); /* simulate end of file */
1187 tok_add(&str
, &len
, 0);
1188 /* now evaluate C constant expression */
1198 void tok_print(int *str
)
1204 t
= tok_get(&str
, &cval
);
1207 printf(" %s", get_tok_str(t
, &cval
));
1213 void preprocess(void)
1215 int size
, i
, c
, v
, t
, *str
, len
;
1216 char buf
[1024], *q
, *p
;
1219 Sym
**ps
, *first
, *s
;
1224 if (tok
== TOK_DEFINE
) {
1227 /* XXX: should check if same macro (ANSI) */
1230 /* '(' must be just after macro definition for MACRO_FUNC */
1235 while (tok
!= ')') {
1236 if (tok
== TOK_DOTS
)
1237 tok
= TOK___VA_ARGS__
;
1238 s
= sym_push1(&define_stack
, tok
| SYM_FIELD
, 0, 0);
1252 if (ch
== '\n' || ch
== -1)
1255 tok_add2(&str
, &len
, tok
, &tokc
);
1257 tok_add(&str
, &len
, 0);
1259 printf("define %s %d: ", get_tok_str(v
, NULL
), t
);
1262 s
= sym_push1(&define_stack
, v
, t
, (int)str
);
1264 } else if (tok
== TOK_UNDEF
) {
1266 s
= sym_find1(&define_stack
, tok
);
1267 /* undefine symbol by putting an invalid name */
1269 sym_undef(&define_stack
, s
);
1270 } else if (tok
== TOK_INCLUDE
) {
1275 } else if (ch
== '\"') {
1280 while (ch
!= c
&& ch
!= '\n' && ch
!= -1) {
1281 if ((q
- buf
) < sizeof(buf
) - 1)
1289 error("#include syntax error");
1290 pstrcpy(buf
, sizeof(buf
), get_tok_str(tok
, &tokc
));
1293 /* eat all spaces and comments after include */
1294 /* XXX: slightly incorrect */
1295 while (ch1
!= '\n' && ch1
!= -1)
1298 if (include_stack_ptr
>= include_stack
+ INCLUDE_STACK_SIZE
)
1299 error("memory full");
1301 /* first search in current dir if "header.h" */
1303 p
= strrchr(filename
, '/');
1305 size
= p
+ 1 - filename
;
1306 if (size
> sizeof(buf1
) - 1)
1307 size
= sizeof(buf1
) - 1;
1308 memcpy(buf1
, filename
, size
);
1310 pstrcat(buf1
, sizeof(buf1
), buf
);
1311 f
= fopen(buf1
, "r");
1315 /* now search in standard include path */
1316 for(i
=nb_include_paths
- 1;i
>=0;i
--) {
1317 strcpy(buf1
, include_paths
[i
]);
1320 f
= fopen(buf1
, "r");
1324 error("include file '%s' not found", buf1
);
1327 /* push current file in stack */
1328 /* XXX: fix current line init */
1329 include_stack_ptr
->file
= file
;
1330 include_stack_ptr
->filename
= filename
;
1331 include_stack_ptr
->line_num
= line_num
;
1332 include_stack_ptr
++;
1334 filename
= strdup(buf1
);
1336 /* add include file debug info */
1338 put_stabs(filename
, N_BINCL
, 0, 0, 0);
1340 } else if (tok
== TOK_IFNDEF
) {
1343 } else if (tok
== TOK_IF
) {
1344 c
= expr_preprocess();
1346 } else if (tok
== TOK_IFDEF
) {
1350 c
= (sym_find1(&define_stack
, tok
) != 0) ^ c
;
1352 if (ifdef_stack_ptr
>= ifdef_stack
+ IFDEF_STACK_SIZE
)
1353 error("memory full");
1354 *ifdef_stack_ptr
++ = c
;
1356 } else if (tok
== TOK_ELSE
) {
1357 if (ifdef_stack_ptr
== ifdef_stack
||
1358 (ifdef_stack_ptr
[-1] & 2))
1359 error("#else after #else");
1360 c
= (ifdef_stack_ptr
[-1] ^= 3);
1362 } else if (tok
== TOK_ELIF
) {
1363 if (ifdef_stack_ptr
== ifdef_stack
||
1364 ifdef_stack_ptr
[-1] > 1)
1365 error("#elif after #else");
1366 c
= expr_preprocess();
1367 ifdef_stack_ptr
[-1] = c
;
1373 } else if (tok
== TOK_ENDIF
) {
1374 if (ifdef_stack_ptr
== ifdef_stack
)
1377 } else if (tok
== TOK_LINE
) {
1379 if (tok
!= TOK_CINT
)
1387 /* XXX: potential memory leak */
1388 filename
= strdup(get_tok_str(tok
, &tokc
));
1390 } else if (tok
== TOK_ERROR
) {
1393 /* ignore other preprocess commands or #! for C scripts */
1394 while (ch
!= '\n' && ch
!= -1)
1398 /* read a number in base b */
1404 if (ch
>= 'a' && ch
<= 'f')
1406 else if (ch
>= 'A' && ch
<= 'F')
1412 if (t
< 0 || t
>= b
)
1420 /* read a character for string or char constant and eval escape codes */
1429 /* at most three octal digits */
1433 c
= c
* 8 + ch
- '0';
1436 c
= c
* 8 + ch
- '0';
1441 } else if (ch
== 'x') {
1459 else if (ch
== 'e' && gnu_ext
)
1461 else if (ch
== '\'' || ch
== '\"' || ch
== '\\' || ch
== '?')
1464 error("invalid escaped char");
1471 /* we use 64 bit numbers */
1474 /* bn = (bn << shift) | or_val */
1475 void bn_lshift(unsigned int *bn
, int shift
, int or_val
)
1479 for(i
=0;i
<BN_SIZE
;i
++) {
1481 bn
[i
] = (v
<< shift
) | or_val
;
1482 or_val
= v
>> (32 - shift
);
1486 void bn_zero(unsigned int *bn
)
1489 for(i
=0;i
<BN_SIZE
;i
++) {
1494 void parse_number(void)
1496 int b
, t
, shift
, frac_bits
, s
, exp_val
;
1498 unsigned int bn
[BN_SIZE
];
1508 /* special dot handling */
1509 if (ch
>= '0' && ch
<= '9') {
1510 goto float_frac_parse
;
1511 } else if (ch
== '.') {
1522 } else if (t
== '0') {
1523 if (ch
== 'x' || ch
== 'X') {
1527 } else if (tcc_ext
&& (ch
== 'b' || ch
== 'B')) {
1533 /* parse all digits. cannot check octal numbers at this stage
1534 because of floating point constants */
1536 if (ch
>= 'a' && ch
<= 'f')
1538 else if (ch
>= 'A' && ch
<= 'F')
1546 if (q
>= token_buf
+ STRING_MAX_SIZE
) {
1548 error("number too long");
1554 ((ch
== 'e' || ch
== 'E') && b
== 10) ||
1555 ((ch
== 'p' || ch
== 'P') && (b
== 16 || b
== 2))) {
1557 /* NOTE: strtox should support that for hexa numbers, but
1558 non ISOC99 libcs do not support it, so we prefer to do
1560 /* hexadecimal or binary floats */
1561 /* XXX: handle overflows */
1573 } else if (t
>= 'a') {
1575 } else if (t
>= 'A') {
1580 bn_lshift(bn
, shift
, t
);
1587 if (t
>= 'a' && t
<= 'f') {
1589 } else if (t
>= 'A' && t
<= 'F') {
1591 } else if (t
>= '0' && t
<= '9') {
1597 error("invalid digit");
1598 bn_lshift(bn
, shift
, t
);
1603 if (ch
!= 'p' && ch
!= 'P')
1604 error("exponent expected");
1610 } else if (ch
== '-') {
1614 if (ch
< '0' || ch
> '9')
1615 error("exponent digits expected");
1616 while (ch
>= '0' && ch
<= '9') {
1617 exp_val
= exp_val
* 10 + ch
- '0';
1620 exp_val
= exp_val
* s
;
1622 /* now we can generate the number */
1623 /* XXX: should patch directly float number */
1624 d
= (double)bn
[1] * 4294967296.0 + (double)bn
[0];
1625 d
= ldexp(d
, exp_val
- frac_bits
);
1630 /* float : should handle overflow */
1632 } else if (t
== 'L') {
1635 /* XXX: not large enough */
1636 tokc
.ld
= (long double)d
;
1642 /* decimal floats */
1644 if (q
>= token_buf
+ STRING_MAX_SIZE
)
1649 while (ch
>= '0' && ch
<= '9') {
1650 if (q
>= token_buf
+ STRING_MAX_SIZE
)
1656 if (ch
== 'e' || ch
== 'E') {
1657 if (q
>= token_buf
+ STRING_MAX_SIZE
)
1661 if (ch
== '-' || ch
== '+') {
1662 if (q
>= token_buf
+ STRING_MAX_SIZE
)
1667 if (ch
< '0' || ch
> '9')
1668 error("exponent digits expected");
1669 while (ch
>= '0' && ch
<= '9') {
1670 if (q
>= token_buf
+ STRING_MAX_SIZE
)
1682 tokc
.f
= strtof(token_buf
, NULL
);
1683 } else if (t
== 'L') {
1686 tokc
.ld
= strtold(token_buf
, NULL
);
1689 tokc
.d
= strtod(token_buf
, NULL
);
1693 unsigned long long n
, n1
;
1696 /* integer number */
1699 if (b
== 10 && *q
== '0') {
1706 /* no need for checks except for base 10 / 8 errors */
1709 } else if (t
>= 'a') {
1711 } else if (t
>= 'A') {
1716 error("invalid digit");
1720 /* detect overflow */
1722 error("integer constant overflow");
1725 /* XXX: not exactly ANSI compliant */
1726 if ((n
& 0xffffffff00000000LL
) != 0) {
1731 } else if (n
> 0x7fffffff) {
1741 error("three 'l' in integer constant");
1744 if (tok
== TOK_CINT
)
1746 else if (tok
== TOK_CUINT
)
1750 } else if (t
== 'U') {
1751 if (tok
== TOK_CINT
)
1753 else if (tok
== TOK_CLLONG
)
1760 if (tok
== TOK_CINT
|| tok
== TOK_CUINT
)
1768 /* return next token without macro substitution */
1769 void next_nomacro1(void)
1777 while (ch
== '\n') {
1779 while (ch
== ' ' || ch
== 9)
1782 /* preprocessor command if # at start of line after
1787 if (ch
!= ' ' && ch
!= '\t' && ch
!= '\f')
1805 while (isid(ch
) || isnum(ch
)) {
1806 if (q
>= token_buf
+ STRING_MAX_SIZE
)
1807 error("ident too long");
1812 ts
= tok_alloc(token_buf
, q
- token_buf
);
1814 } else if (isnum(ch
) || ch
== '.') {
1816 } else if (ch
== '\'') {
1824 } else if (ch
== '\"') {
1829 while (ch
!= '\"') {
1832 error("unterminated string");
1833 if (q
>= token_buf
+ STRING_MAX_SIZE
)
1834 error("string too long");
1838 tokc
.ts
= tok_alloc(token_buf
, q
- token_buf
);
1841 q
= "<=\236>=\235!=\225&&\240||\241++\244--\242==\224<<\1>>\2+=\253-=\255*=\252/=\257%=\245&=\246^=\336|=\374->\313..\250##\266";
1846 if (*q
== tok
&& q
[1] == ch
) {
1849 /* three chars tests */
1850 if (tok
== TOK_SHL
|| tok
== TOK_SAR
) {
1855 } else if (tok
== TOK_DOTS
) {
1857 error("parse error");
1864 /* single char substitutions */
1867 else if (tok
== '>')
1872 /* return next token without macro substitution. Can read input from
1879 tok
= tok_get(¯o_ptr
, &tokc
);
1885 /* substitute args in macro_str and return allocated string */
1886 int *macro_arg_subst(Sym
**nested_list
, int *macro_str
, Sym
*args
)
1888 int *st
, last_tok
, t
, notfirst
, *str
, len
;
1897 t
= tok_get(¯o_str
, &cval
);
1902 t
= tok_get(¯o_str
, &cval
);
1905 s
= sym_find2(args
, t
);
1907 token_buf
[0] = '\0';
1912 pstrcat(token_buf
, sizeof(token_buf
), " ");
1913 t
= tok_get(&st
, &cval
);
1914 pstrcat(token_buf
, sizeof(token_buf
), get_tok_str(t
, &cval
));
1918 printf("stringize: %s\n", token_buf
);
1921 ts
= tok_alloc(token_buf
, 0);
1923 tok_add2(&str
, &len
, TOK_STR
, &cval
);
1925 tok_add2(&str
, &len
, t
, &cval
);
1927 } else if (t
>= TOK_IDENT
) {
1928 s
= sym_find2(args
, t
);
1931 /* if '##' is present before or after , no arg substitution */
1932 if (*macro_str
== TOK_TWOSHARPS
|| last_tok
== TOK_TWOSHARPS
) {
1934 tok_add(&str
, &len
, *st
++);
1936 macro_subst(&str
, &len
, nested_list
, st
);
1939 tok_add(&str
, &len
, t
);
1942 tok_add2(&str
, &len
, t
, &cval
);
1946 tok_add(&str
, &len
, 0);
1950 /* handle the '##' operator */
1951 int *macro_twosharps(int *macro_str
)
1954 int *macro_str1
, macro_str1_len
, *macro_ptr1
;
1966 while (*macro_ptr
== TOK_TWOSHARPS
) {
1968 macro_ptr1
= macro_ptr
;
1971 t
= tok_get(¯o_ptr
, &cval
);
1972 /* XXX: we handle only most common cases:
1973 ident + ident or ident + number */
1974 if (tok
>= TOK_IDENT
&&
1975 (t
>= TOK_IDENT
|| t
== TOK_CINT
)) {
1976 p
= get_tok_str(tok
, &tokc
);
1977 pstrcpy(token_buf
, sizeof(token_buf
), p
);
1978 p
= get_tok_str(t
, &cval
);
1979 pstrcat(token_buf
, sizeof(token_buf
), p
);
1980 ts
= tok_alloc(token_buf
, 0);
1981 tok
= ts
->tok
; /* modify current token */
1983 /* cannot merge tokens: skip '##' */
1984 macro_ptr
= macro_ptr1
;
1989 tok_add2(¯o_str1
, ¯o_str1_len
, tok
, &tokc
);
1991 tok_add(¯o_str1
, ¯o_str1_len
, 0);
1997 /* do macro substitution of macro_str and add result to
1998 (tok_str,tok_len). If macro_str is NULL, then input stream token is
1999 substituted. 'nested_list' is the list of all macros we got inside
2000 to avoid recursing. */
2001 void macro_subst(int **tok_str
, int *tok_len
,
2002 Sym
**nested_list
, int *macro_str
)
2004 Sym
*s
, *args
, *sa
, *sa1
;
2005 int *str
, parlevel
, len
, *mstr
, t
, *saved_macro_ptr
;
2006 int mstr_allocated
, *macro_str1
;
2009 saved_macro_ptr
= macro_ptr
;
2010 macro_ptr
= macro_str
;
2013 /* first scan for '##' operator handling */
2014 macro_str1
= macro_twosharps(macro_str
);
2015 macro_ptr
= macro_str1
;
2022 /* special macros */
2023 if (tok
== TOK___LINE__
) {
2025 tok_add2(tok_str
, tok_len
, TOK_CINT
, &cval
);
2026 } else if (tok
== TOK___FILE__
) {
2027 cval
.ts
= tok_alloc(filename
, 0);
2028 tok_add2(tok_str
, tok_len
, TOK_STR
, &cval
);
2029 } else if (tok
== TOK___DATE__
) {
2030 cval
.ts
= tok_alloc("Jan 1 1970", 0);
2031 tok_add2(tok_str
, tok_len
, TOK_STR
, &cval
);
2032 } else if (tok
== TOK___TIME__
) {
2033 cval
.ts
= tok_alloc("00:00:00", 0);
2034 tok_add2(tok_str
, tok_len
, TOK_STR
, &cval
);
2035 } else if ((s
= sym_find1(&define_stack
, tok
)) != NULL
) {
2036 /* if symbol is a macro, prepare substitution */
2037 /* if nested substitution, do nothing */
2038 if (sym_find2(*nested_list
, tok
))
2042 if (s
->t
== MACRO_FUNC
) {
2043 /* NOTE: we do not use next_nomacro to avoid eating the
2044 next token. XXX: find better solution */
2048 while (ch
== ' ' || ch
== '\t' || ch
== '\n')
2052 if (t
!= '(') /* no macro subst */
2055 /* argument macro */
2060 while (tok
!= ')' && sa
) {
2064 while ((parlevel
> 0 ||
2067 sa
->v
== (TOK___VA_ARGS__
| SYM_FIELD
)))) &&
2071 else if (tok
== ')')
2073 tok_add2(&str
, &len
, tok
, &tokc
);
2076 tok_add(&str
, &len
, 0);
2077 sym_push2(&args
, sa
->v
& ~SYM_FIELD
, 0, (int)str
);
2085 /* now subst each arg */
2086 mstr
= macro_arg_subst(nested_list
, mstr
, args
);
2097 sym_push2(nested_list
, s
->v
, 0, 0);
2098 macro_subst(tok_str
, tok_len
, nested_list
, mstr
);
2099 /* pop nested defined symbol */
2101 *nested_list
= sa1
->prev
;
2107 /* no need to add if reading input stream */
2110 tok_add2(tok_str
, tok_len
, tok
, &tokc
);
2112 /* only replace one macro while parsing input stream */
2116 macro_ptr
= saved_macro_ptr
;
2121 /* return next token with macro substitution */
2127 /* special 'ungettok' case for label parsing */
2135 /* if not reading from macro substuted string, then try to substitute */
2139 macro_subst(&ptr
, &len
, &nested_list
, NULL
);
2141 tok_add(&ptr
, &len
, 0);
2143 macro_ptr_allocated
= ptr
;
2151 /* end of macro string: free it */
2152 free(macro_ptr_allocated
);
2159 printf("token = %s\n", get_tok_str(tok
, tokc
));
2163 void swap(int *p
, int *q
)
2171 void vsetc(int t
, int r
, CValue
*vc
)
2173 if (vtop
>= vstack
+ VSTACK_SIZE
)
2174 error("memory full");
2175 /* cannot let cpu flags if other instruction are generated */
2176 /* XXX: VT_JMP test too ? */
2177 if ((vtop
->r
& VT_VALMASK
) == VT_CMP
)
2182 vtop
->r2
= VT_CONST
;
2186 /* push integer constant */
2191 vsetc(VT_INT
, VT_CONST
, &cval
);
2194 void vset(int t
, int r
, int v
)
2211 void vpushv(SValue
*v
)
2213 if (vtop
>= vstack
+ VSTACK_SIZE
)
2214 error("memory full");
2224 /* save r to the memory stack, and mark it as being free */
2225 void save_reg(int r
)
2227 int l
, i
, saved
, t
, size
, align
;
2230 /* modify all stack values */
2233 for(p
=vstack
;p
<=vtop
;p
++) {
2234 i
= p
->r
& VT_VALMASK
;
2235 if ((p
->r
& VT_VALMASK
) == r
||
2236 (p
->r2
& VT_VALMASK
) == r
) {
2237 /* must save value on stack if not already done */
2239 /* store register in the stack */
2241 if (!is_float(t
) && (t
& VT_BTYPE
) != VT_LLONG
)
2243 size
= type_size(t
, &align
);
2244 loc
= (loc
- size
) & -align
;
2246 sv
.r
= VT_LOCAL
| VT_LVAL
;
2249 /* XXX: x86 specific: need to pop fp register ST0 if saved */
2251 o(0xd9dd); /* fstp %st(1) */
2253 /* special long long case */
2254 if ((p
->t
& VT_BTYPE
) == VT_LLONG
) {
2261 /* mark that stack entry as being saved on the stack */
2273 /* find a free register of class 'rc'. If none, save one register */
2279 /* find a free register */
2280 for(r
=0;r
<NB_REGS
;r
++) {
2281 if (reg_classes
[r
] & rc
) {
2282 for(p
=vstack
;p
<=vtop
;p
++) {
2283 if ((p
->r
& VT_VALMASK
) == r
||
2284 (p
->r2
& VT_VALMASK
) == r
)
2292 /* no register left : free the first one on the stack (VERY
2293 IMPORTANT to start from the bottom to ensure that we don't
2294 spill registers used in gen_opi()) */
2295 for(p
=vstack
;p
<=vtop
;p
++) {
2296 r
= p
->r
& VT_VALMASK
;
2297 if (r
< VT_CONST
&& (reg_classes
[r
] & rc
)) {
2305 void save_regs(void)
2310 for(p
=vstack
;p
<=vtop
;p
++) {
2311 r
= p
->r
& VT_VALMASK
;
2318 /* move register 's' to 'r', and flush previous value of r to memory
2320 void move_reg(int r
, int s
)
2333 /* get address of vtop (vtop MUST BE an lvalue) */
2336 vtop
->r
&= ~VT_LVAL
;
2337 /* tricky: if saved lvalue, then we can go back to lvalue */
2338 if ((vtop
->r
& VT_VALMASK
) == VT_LLOCAL
)
2339 vtop
->r
= (vtop
->r
& ~VT_VALMASK
) | VT_LOCAL
| VT_LVAL
;
2342 /* store vtop a register belonging to class 'rc'. lvalues are
2343 converted to values. Cannot be used if cannot be converted to
2344 register value (such as structures). */
2347 int r
, r2
, rc2
, bit_pos
, bit_size
, size
, align
, i
, data_offset
;
2348 unsigned long long ll
;
2350 /* NOTE: get_reg can modify vstack[] */
2351 if (vtop
->t
& VT_BITFIELD
) {
2352 bit_pos
= (vtop
->t
>> VT_STRUCT_SHIFT
) & 0x3f;
2353 bit_size
= (vtop
->t
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f;
2354 /* remove bit field info to avoid loops */
2355 vtop
->t
&= ~(VT_BITFIELD
| (-1 << VT_STRUCT_SHIFT
));
2356 /* generate shifts */
2357 vpushi(32 - (bit_pos
+ bit_size
));
2359 vpushi(32 - bit_size
);
2360 /* NOTE: transformed to SHR if unsigned */
2364 if (is_float(vtop
->t
) &&
2365 (vtop
->r
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
) {
2366 /* CPUs usually cannot use float constants, so we store them
2367 generically in data segment */
2368 size
= type_size(vtop
->t
, &align
);
2369 data_offset
= (int)data_section
->data_ptr
;
2370 data_offset
= (data_offset
+ align
- 1) & -align
;
2371 /* XXX: not portable yet */
2374 ((int *)data_offset
)[i
] = vtop
->c
.tab
[i
];
2376 vtop
->c
.ul
= data_offset
;
2377 data_offset
+= size
<< 2;
2378 data_section
->data_ptr
= (unsigned char *)data_offset
;
2380 r
= vtop
->r
& VT_VALMASK
;
2381 /* need to reload if:
2383 - lvalue (need to dereference pointer)
2384 - already a register, but not in the right class */
2385 if (r
>= VT_CONST
||
2386 (vtop
->r
& VT_LVAL
) ||
2387 !(reg_classes
[r
] & rc
) ||
2388 ((vtop
->t
& VT_BTYPE
) == VT_LLONG
&&
2389 !(reg_classes
[vtop
->r2
] & rc
))) {
2391 if ((vtop
->t
& VT_BTYPE
) == VT_LLONG
) {
2392 /* two register type load : expand to two words
2394 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
) {
2397 vtop
->c
.ui
= ll
; /* first word */
2399 vtop
->r
= r
; /* save register value */
2400 vpushi(ll
>> 32); /* second word */
2401 } else if (r
>= VT_CONST
||
2402 (vtop
->r
& VT_LVAL
)) {
2403 /* load from memory */
2406 vtop
[-1].r
= r
; /* save register value */
2407 /* increment pointer to get second word */
2414 /* move registers */
2417 vtop
[-1].r
= r
; /* save register value */
2418 vtop
->r
= vtop
[-1].r2
;
2420 /* allocate second register */
2427 /* write second register */
2430 /* one register type load */
2439 /* expand long long on stack in two int registers */
2444 u
= vtop
->t
& VT_UNSIGNED
;
2447 vtop
[0].r
= vtop
[-1].r2
;
2448 vtop
[0].r2
= VT_CONST
;
2449 vtop
[-1].r2
= VT_CONST
;
2450 vtop
[0].t
= VT_INT
| u
;
2451 vtop
[-1].t
= VT_INT
| u
;
2454 /* build a long long from two ints */
2461 vtop
[-1].r2
= vtop
[0].r
;
2466 /* rotate n first stack elements to the bottom */
2473 for(i
=-n
+1;i
!=0;i
++)
2474 vtop
[i
] = vtop
[i
+1];
2478 /* pop stack value */
2481 /* for x86, we need to pop the FP stack */
2482 if ((vtop
->r
& VT_VALMASK
) == REG_ST0
) {
2483 o(0xd9dd); /* fstp %st(1) */
2488 /* convert stack entry to register and duplicate its value in another
2496 if ((t
& VT_BTYPE
) == VT_LLONG
) {
2503 /* stack: H L L1 H1 */
2511 /* duplicate value */
2522 load(r1
, &sv
); /* move r to r1 */
2524 /* duplicates value */
2529 /* generate CPU independent (unsigned) long long operations */
2530 void gen_opl(int op
)
2532 int t
, a
, b
, op1
, c
, i
;
2551 /* call generic long long function */
2559 vtop
->r2
= REG_LRET
;
2572 /* stack: L1 H1 L2 H2 */
2577 vtop
[-2] = vtop
[-3];
2580 /* stack: H1 H2 L1 L2 */
2586 /* stack: H1 H2 L1 L2 ML MH */
2589 /* stack: ML MH H1 H2 L1 L2 */
2593 /* stack: ML MH H1 L2 H2 L1 */
2598 /* stack: ML MH M1 M2 */
2601 } else if (op
== '+' || op
== '-') {
2602 /* XXX: add non carry method too (for MIPS ?) */
2608 /* stack: H1 H2 (L1 op L2) */
2611 gen_op(op1
+ 1); /* TOK_xxxC2 */
2614 /* stack: H1 H2 (L1 op L2) */
2617 /* stack: (L1 op L2) H1 H2 */
2619 /* stack: (L1 op L2) (H1 op H2) */
2627 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_FORWARD
)) == VT_CONST
) {
2632 /* stack: L H shift */
2634 /* constant: simpler */
2635 /* NOTE: all comments are for SHL. the other cases are
2636 done by swaping words */
2647 if (op
!= TOK_SAR
) {
2677 /* XXX: should provide a faster fallback on x86 ? */
2692 /* compare operations */
2698 /* stack: L1 H1 L2 H2 */
2700 vtop
[-1] = vtop
[-2];
2702 /* stack: L1 L2 H1 H2 */
2705 /* when values are equal, we need to compare low words. since
2706 the jump is inverted, we invert the test too. */
2709 else if (op1
== TOK_GT
)
2711 else if (op1
== TOK_ULT
)
2713 else if (op1
== TOK_UGT
)
2718 if (op1
!= TOK_NE
) {
2722 /* generate non equal test */
2723 /* XXX: NOT PORTABLE yet */
2727 b
= psym(0x850f, 0);
2733 vset(VT_INT
, VT_JMPI
, a
);
2738 /* handle constant optimizations and various machine independant opt */
2739 void gen_opc(int op
)
2746 /* currently, we cannot do computations with forward symbols */
2747 c1
= (v1
->r
& (VT_VALMASK
| VT_LVAL
| VT_FORWARD
)) == VT_CONST
;
2748 c2
= (v2
->r
& (VT_VALMASK
| VT_LVAL
| VT_FORWARD
)) == VT_CONST
;
2752 case '+': v1
->c
.i
+= fc
; break;
2753 case '-': v1
->c
.i
-= fc
; break;
2754 case '&': v1
->c
.i
&= fc
; break;
2755 case '^': v1
->c
.i
^= fc
; break;
2756 case '|': v1
->c
.i
|= fc
; break;
2757 case '*': v1
->c
.i
*= fc
; break;
2759 case '/': v1
->c
.i
/= fc
; break; /* XXX: zero case ? */
2760 case '%': v1
->c
.i
%= fc
; break; /* XXX: zero case ? */
2761 case TOK_UDIV
: v1
->c
.i
= (unsigned)v1
->c
.i
/ fc
; break; /* XXX: zero case ? */
2762 case TOK_UMOD
: v1
->c
.i
= (unsigned)v1
->c
.i
% fc
; break; /* XXX: zero case ? */
2763 case TOK_SHL
: v1
->c
.i
<<= fc
; break;
2764 case TOK_SHR
: v1
->c
.i
= (unsigned)v1
->c
.i
>> fc
; break;
2765 case TOK_SAR
: v1
->c
.i
>>= fc
; break;
2767 case TOK_ULT
: v1
->c
.i
= (unsigned)v1
->c
.i
< (unsigned)fc
; break;
2768 case TOK_UGE
: v1
->c
.i
= (unsigned)v1
->c
.i
>= (unsigned)fc
; break;
2769 case TOK_EQ
: v1
->c
.i
= v1
->c
.i
== fc
; break;
2770 case TOK_NE
: v1
->c
.i
= v1
->c
.i
!= fc
; break;
2771 case TOK_ULE
: v1
->c
.i
= (unsigned)v1
->c
.i
<= (unsigned)fc
; break;
2772 case TOK_UGT
: v1
->c
.i
= (unsigned)v1
->c
.i
> (unsigned)fc
; break;
2773 case TOK_LT
: v1
->c
.i
= v1
->c
.i
< fc
; break;
2774 case TOK_GE
: v1
->c
.i
= v1
->c
.i
>= fc
; break;
2775 case TOK_LE
: v1
->c
.i
= v1
->c
.i
<= fc
; break;
2776 case TOK_GT
: v1
->c
.i
= v1
->c
.i
> fc
; break;
2778 case TOK_LAND
: v1
->c
.i
= v1
->c
.i
&& fc
; break;
2779 case TOK_LOR
: v1
->c
.i
= v1
->c
.i
|| fc
; break;
2785 /* if commutative ops, put c2 as constant */
2786 if (c1
&& (op
== '+' || op
== '&' || op
== '^' ||
2787 op
== '|' || op
== '*')) {
2792 if (c2
&& (((op
== '*' || op
== '/' || op
== TOK_UDIV
||
2795 ((op
== '+' || op
== '-' || op
== '|' || op
== '^' ||
2796 op
== TOK_SHL
|| op
== TOK_SHR
|| op
== TOK_SAR
) &&
2802 } else if (c2
&& (op
== '*' || op
== TOK_PDIV
|| op
== TOK_UDIV
)) {
2803 /* try to use shifts instead of muls or divs */
2804 if (fc
> 0 && (fc
& (fc
- 1)) == 0) {
2813 else if (op
== TOK_PDIV
)
2821 /* call low level op generator */
2822 /* XXX: remove explicit registers */
2828 int pointed_size(int t
)
2830 return type_size(pointed_type(t
), &t
);
2834 void check_pointer_types(SValue
*p1
, SValue
*p2
)
2836 char buf1
[256], buf2
[256];
2840 if (!is_compatible_types(t1
, t2
)) {
2841 type_to_str(buf1
, sizeof(buf1
), t1
, NULL
);
2842 type_to_str(buf2
, sizeof(buf2
), t2
, NULL
);
2843 error("incompatible pointers '%s' and '%s'", buf1
, buf2
);
2848 /* generic gen_op: handles types problems */
2851 int u
, t1
, t2
, bt1
, bt2
, t
;
2855 bt1
= t1
& VT_BTYPE
;
2856 bt2
= t2
& VT_BTYPE
;
2858 if (bt1
== VT_PTR
|| bt2
== VT_PTR
) {
2859 /* at least one operand is a pointer */
2860 /* relationnal op: must be both pointers */
2861 if (op
>= TOK_ULT
&& op
<= TOK_GT
) {
2862 // check_pointer_types(vtop, vtop - 1);
2863 /* pointers are handled are unsigned */
2864 t
= VT_INT
| VT_UNSIGNED
;
2867 /* if both pointers, then it must be the '-' op */
2868 if ((t1
& VT_BTYPE
) == VT_PTR
&&
2869 (t2
& VT_BTYPE
) == VT_PTR
) {
2871 error("cannot use pointers here");
2872 // check_pointer_types(vtop - 1, vtop);
2873 /* XXX: check that types are compatible */
2874 u
= pointed_size(t1
);
2876 /* set to integer type */
2881 /* exactly one pointer : must be '+' or '-'. */
2882 if (op
!= '-' && op
!= '+')
2883 error("cannot use pointers here");
2884 /* Put pointer as first operand */
2885 if ((t2
& VT_BTYPE
) == VT_PTR
) {
2889 /* XXX: cast to int ? (long long case) */
2890 vpushi(pointed_size(vtop
[-1].t
));
2892 if (do_bounds_check
) {
2893 /* if bounded pointers, we generate a special code to test bounds */
2899 gen_bounded_ptr_add();
2903 /* put again type if gen_opc() swaped operands */
2906 } else if (is_float(bt1
) || is_float(bt2
)) {
2907 /* compute bigger type and do implicit casts */
2908 if (bt1
== VT_LDOUBLE
|| bt2
== VT_LDOUBLE
) {
2910 } else if (bt1
== VT_DOUBLE
|| bt2
== VT_DOUBLE
) {
2915 /* floats can only be used for a few operations */
2916 if (op
!= '+' && op
!= '-' && op
!= '*' && op
!= '/' &&
2917 (op
< TOK_ULT
|| op
> TOK_GT
))
2918 error("invalid operands for binary operation");
2920 } else if (bt1
== VT_LLONG
|| bt2
== VT_LLONG
) {
2921 /* cast to biggest op */
2923 /* convert to unsigned if it does not fit in a long long */
2924 if ((t1
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_LLONG
| VT_UNSIGNED
) ||
2925 (t2
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_LLONG
| VT_UNSIGNED
))
2929 /* integer operations */
2931 /* convert to unsigned if it does not fit in an integer */
2932 if ((t1
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
) ||
2933 (t2
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
))
2936 /* XXX: currently, some unsigned operations are explicit, so
2937 we modify them here */
2938 if (t
& VT_UNSIGNED
) {
2945 else if (op
== TOK_LT
)
2947 else if (op
== TOK_GT
)
2949 else if (op
== TOK_LE
)
2951 else if (op
== TOK_GE
)
2957 /* special case for shifts and long long: we keep the shift as
2959 if (op
== TOK_SHR
|| op
== TOK_SAR
|| op
== TOK_SHL
)
2965 else if ((t
& VT_BTYPE
) == VT_LLONG
)
2969 if (op
>= TOK_ULT
&& op
<= TOK_GT
) {
2970 /* relationnal op: the result is an int */
2978 /* generic itof for unsigned long long case */
2979 void gen_cvt_itof1(int t
)
2983 if ((vtop
->t
& (VT_BTYPE
| VT_UNSIGNED
)) ==
2984 (VT_LLONG
| VT_UNSIGNED
)) {
2989 vpushi((int)&__ulltof
);
2990 else if (t
== VT_DOUBLE
)
2991 vpushi((int)&__ulltod
);
2993 vpushi((int)&__ulltold
);
3002 /* generic ftoi for unsigned long long case */
3003 void gen_cvt_ftoi1(int t
)
3008 if (t
== (VT_LLONG
| VT_UNSIGNED
)) {
3009 /* not handled natively */
3011 st
= vtop
->t
& VT_BTYPE
;
3014 vpushi((int)&__ftoull
);
3015 else if (st
== VT_DOUBLE
)
3016 vpushi((int)&__dtoull
);
3018 vpushi((int)&__ldtoull
);
3022 vtop
->r2
= REG_LRET
;
3028 /* force char or short cast */
3029 void force_charshort_cast(int t
)
3033 /* XXX: add optimization if lvalue : just change type and offset */
3038 if (t
& VT_UNSIGNED
) {
3039 vpushi((1 << bits
) - 1);
3050 /* cast 'vtop' to 't' type */
3051 void gen_cast(int t
)
3053 int sbt
, dbt
, sf
, df
, c
, st1
, dt1
;
3055 /* special delayed cast for char/short */
3056 /* XXX: in some cases (multiple cascaded casts), it may still
3058 if (vtop
->r
& VT_MUSTCAST
) {
3059 vtop
->r
&= ~VT_MUSTCAST
;
3060 force_charshort_cast(vtop
->t
);
3064 sbt
= vtop
->t
& VT_BTYPE
;
3069 c
= (vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_FORWARD
)) == VT_CONST
;
3071 /* convert from fp to fp */
3073 /* constant case: we can do it now */
3074 /* XXX: in ISOC, cannot do it if error in convert */
3075 if (dbt
== VT_FLOAT
&& sbt
== VT_DOUBLE
)
3076 vtop
->c
.f
= (float)vtop
->c
.d
;
3077 else if (dbt
== VT_FLOAT
&& sbt
== VT_LDOUBLE
)
3078 vtop
->c
.f
= (float)vtop
->c
.ld
;
3079 else if (dbt
== VT_DOUBLE
&& sbt
== VT_FLOAT
)
3080 vtop
->c
.d
= (double)vtop
->c
.f
;
3081 else if (dbt
== VT_DOUBLE
&& sbt
== VT_LDOUBLE
)
3082 vtop
->c
.d
= (double)vtop
->c
.ld
;
3083 else if (dbt
== VT_LDOUBLE
&& sbt
== VT_FLOAT
)
3084 vtop
->c
.ld
= (long double)vtop
->c
.f
;
3085 else if (dbt
== VT_LDOUBLE
&& sbt
== VT_DOUBLE
)
3086 vtop
->c
.ld
= (long double)vtop
->c
.d
;
3088 /* non constant case: generate code */
3092 /* convert int to fp */
3093 st1
= vtop
->t
& (VT_BTYPE
| VT_UNSIGNED
);
3096 case VT_LLONG
| VT_UNSIGNED
:
3098 /* XXX: add const cases for long long */
3100 case VT_INT
| VT_UNSIGNED
:
3102 case VT_FLOAT
: vtop
->c
.f
= (float)vtop
->c
.ui
; break;
3103 case VT_DOUBLE
: vtop
->c
.d
= (double)vtop
->c
.ui
; break;
3104 case VT_LDOUBLE
: vtop
->c
.ld
= (long double)vtop
->c
.ui
; break;
3109 case VT_FLOAT
: vtop
->c
.f
= (float)vtop
->c
.i
; break;
3110 case VT_DOUBLE
: vtop
->c
.d
= (double)vtop
->c
.i
; break;
3111 case VT_LDOUBLE
: vtop
->c
.ld
= (long double)vtop
->c
.i
; break;
3120 /* convert fp to int */
3121 dt1
= t
& (VT_BTYPE
| VT_UNSIGNED
);
3122 /* we handle char/short/etc... with generic code */
3123 if (dt1
!= (VT_INT
| VT_UNSIGNED
) &&
3124 dt1
!= (VT_LLONG
| VT_UNSIGNED
) &&
3129 case VT_LLONG
| VT_UNSIGNED
:
3131 /* XXX: add const cases for long long */
3133 case VT_INT
| VT_UNSIGNED
:
3135 case VT_FLOAT
: vtop
->c
.ui
= (unsigned int)vtop
->c
.d
; break;
3136 case VT_DOUBLE
: vtop
->c
.ui
= (unsigned int)vtop
->c
.d
; break;
3137 case VT_LDOUBLE
: vtop
->c
.ui
= (unsigned int)vtop
->c
.d
; break;
3143 case VT_FLOAT
: vtop
->c
.i
= (int)vtop
->c
.d
; break;
3144 case VT_DOUBLE
: vtop
->c
.i
= (int)vtop
->c
.d
; break;
3145 case VT_LDOUBLE
: vtop
->c
.i
= (int)vtop
->c
.d
; break;
3153 if (dt1
== VT_INT
&& (t
& (VT_BTYPE
| VT_UNSIGNED
)) != dt1
) {
3154 /* additionnal cast for char/short/bool... */
3158 } else if (dbt
== VT_LLONG
) {
3159 /* scalar to long long */
3161 if ((vtop
->t
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
))
3162 vtop
->c
.ll
= vtop
->c
.ui
;
3164 vtop
->c
.ll
= vtop
->c
.i
;
3166 /* machine independant conversion */
3168 /* generate high word */
3169 if ((vtop
->t
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
)) {
3177 /* patch second register */
3178 vtop
[-1].r2
= vtop
->r
;
3181 } else if (dbt
== VT_BOOL
) {
3182 /* scalar to bool */
3185 } else if (dbt
== VT_BYTE
|| dbt
== VT_SHORT
) {
3186 force_charshort_cast(t
);
3187 } else if (dbt
== VT_INT
) {
3189 if (sbt
== VT_LLONG
) {
3190 /* from long long: just take low order word */
3193 } else if (vtop
->r
& VT_LVAL
) {
3194 /* if lvalue and single word type, nothing to do (XXX:
3195 maybe incorrect for sizeof op) */
3204 /* return type size. Put alignment at 'a' */
3205 int type_size(int t
, int *a
)
3211 if (bt
== VT_STRUCT
) {
3213 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
) | SYM_STRUCT
);
3214 *a
= 4; /* XXX: cannot store it yet. Doing that is safe */
3216 } else if (bt
== VT_PTR
) {
3218 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
));
3219 return type_size(s
->t
, a
) * s
->c
;
3224 } else if (bt
== VT_LDOUBLE
) {
3226 return LDOUBLE_SIZE
;
3227 } else if (bt
== VT_DOUBLE
|| bt
== VT_LLONG
) {
3230 } else if (bt
== VT_INT
|| bt
== VT_ENUM
|| bt
== VT_FLOAT
) {
3233 } else if (bt
== VT_SHORT
) {
3237 /* char, void, function, _Bool */
3243 /* return the pointed type of t */
3244 int pointed_type(int t
)
3247 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
));
3248 return s
->t
| (t
& ~VT_TYPE
);
3251 int mk_pointer(int t
)
3255 sym_push(p
, t
, 0, -1);
3256 return VT_PTR
| (p
<< VT_STRUCT_SHIFT
) | (t
& ~VT_TYPE
);
3259 int is_compatible_types(int t1
, int t2
)
3266 bt1
= t1
& VT_BTYPE
;
3267 bt2
= t2
& VT_BTYPE
;
3268 if (bt1
== VT_PTR
) {
3269 t1
= pointed_type(t1
);
3270 /* if function, then convert implicitely to function pointer */
3271 if (bt2
!= VT_FUNC
) {
3274 t2
= pointed_type(t2
);
3276 /* void matches everything */
3279 if (t1
== VT_VOID
|| t2
== VT_VOID
)
3281 return is_compatible_types(t1
, t2
);
3282 } else if (bt1
== VT_STRUCT
) {
3284 } else if (bt1
== VT_FUNC
) {
3287 s1
= sym_find(((unsigned)t1
>> VT_STRUCT_SHIFT
));
3288 s2
= sym_find(((unsigned)t2
>> VT_STRUCT_SHIFT
));
3289 if (!is_compatible_types(s1
->t
, s2
->t
))
3291 /* XXX: not complete */
3292 if (s1
->c
== FUNC_OLD
|| s2
->c
== FUNC_OLD
)
3296 while (s1
!= NULL
) {
3299 if (!is_compatible_types(s1
->t
, s2
->t
))
3308 /* XXX: not complete */
3313 /* print a type. If 'varstr' is not NULL, then the variable is also
3314 printed in the type */
3316 /* XXX: add array and function pointers */
3317 void type_to_str(char *buf
, int buf_size
,
3318 int t
, const char *varstr
)
3328 if (t
& VT_UNSIGNED
)
3329 pstrcat(buf
, buf_size
, "unsigned ");
3359 tstr
= "long double";
3361 pstrcat(buf
, buf_size
, tstr
);
3365 if (bt
== VT_STRUCT
)
3369 pstrcat(buf
, buf_size
, tstr
);
3370 v
= (unsigned)t
>> VT_STRUCT_SHIFT
;
3371 if (v
>= SYM_FIRST_ANOM
)
3372 pstrcat(buf
, buf_size
, "<anonymous>");
3374 pstrcat(buf
, buf_size
, get_tok_str(v
, NULL
));
3377 s
= sym_find((unsigned)t
>> VT_STRUCT_SHIFT
);
3378 type_to_str(buf
, buf_size
, s
->t
, varstr
);
3379 pstrcat(buf
, buf_size
, "(");
3381 while (sa
!= NULL
) {
3382 type_to_str(buf1
, sizeof(buf1
), sa
->t
, NULL
);
3383 pstrcat(buf
, buf_size
, buf1
);
3386 pstrcat(buf
, buf_size
, ", ");
3388 pstrcat(buf
, buf_size
, ")");
3391 s
= sym_find((unsigned)t
>> VT_STRUCT_SHIFT
);
3392 pstrcpy(buf1
, sizeof(buf1
), "*");
3394 pstrcat(buf1
, sizeof(buf1
), varstr
);
3395 type_to_str(buf
, buf_size
, s
->t
, buf1
);
3399 pstrcat(buf
, buf_size
, " ");
3400 pstrcat(buf
, buf_size
, varstr
);
3405 /* verify type compatibility to store vtop in 'dt' type, and generate
3407 void gen_assign_cast(int dt
)
3410 char buf1
[256], buf2
[256];
3412 st
= vtop
->t
; /* source type */
3413 if ((dt
& VT_BTYPE
) == VT_PTR
) {
3414 /* special cases for pointers */
3415 /* a function is implicitely a function pointer */
3416 if ((st
& VT_BTYPE
) == VT_FUNC
) {
3417 if (!is_compatible_types(pointed_type(dt
), st
))
3422 /* '0' can also be a pointer */
3423 if ((st
& VT_BTYPE
) == VT_INT
&&
3424 ((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_FORWARD
)) == VT_CONST
) &&
3428 if (!is_compatible_types(dt
, st
)) {
3430 type_to_str(buf1
, sizeof(buf1
), st
, NULL
);
3431 type_to_str(buf2
, sizeof(buf2
), dt
, NULL
);
3432 error("cannot cast '%s' to '%s'", buf1
, buf2
);
3438 /* store vtop in lvalue pushed on stack */
3441 int sbt
, dbt
, ft
, r
, t
, size
, align
, bit_size
, bit_pos
, rc
, delayed_cast
;
3445 sbt
= vtop
->t
& VT_BTYPE
;
3446 dbt
= ft
& VT_BTYPE
;
3447 if (((sbt
== VT_INT
|| sbt
== VT_SHORT
) && dbt
== VT_BYTE
) ||
3448 (sbt
== VT_INT
&& dbt
== VT_SHORT
)) {
3449 /* optimize char/short casts */
3450 delayed_cast
= VT_MUSTCAST
;
3451 vtop
->t
= ft
& VT_TYPE
;
3454 gen_assign_cast(ft
& VT_TYPE
);
3457 if (sbt
== VT_STRUCT
) {
3458 /* if structure, only generate pointer */
3459 /* structure assignment : generate memcpy */
3460 /* XXX: optimize if small size */
3465 size
= type_size(vtop
->t
, &align
);
3479 vpushi((int)&memcpy
);
3481 /* leave source on stack */
3482 } else if (ft
& VT_BITFIELD
) {
3483 /* bitfield store handling */
3484 bit_pos
= (ft
>> VT_STRUCT_SHIFT
) & 0x3f;
3485 bit_size
= (ft
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f;
3486 /* remove bit field info to avoid loops */
3487 vtop
[-1].t
= ft
& ~(VT_BITFIELD
| (-1 << VT_STRUCT_SHIFT
));
3489 /* duplicate destination */
3491 vtop
[-1] = vtop
[-2];
3493 /* mask and shift source */
3494 vpushi((1 << bit_size
) - 1);
3498 /* load destination, mask and or with source */
3500 vpushi(~(((1 << bit_size
) - 1) << bit_pos
));
3509 r
= gv(rc
); /* generate value (XXX: move that to store code) */
3510 /* if lvalue was saved on stack, must read it */
3511 if ((vtop
[-1].r
& VT_VALMASK
) == VT_LLOCAL
) {
3513 t
= get_reg(RC_INT
);
3515 sv
.r
= VT_LOCAL
| VT_LVAL
;
3516 sv
.c
.ul
= vtop
[-1].c
.ul
;
3518 vtop
[-1].r
= t
| VT_LVAL
;
3521 /* two word case handling : store second register at word + 4 */
3522 if ((ft
& VT_BTYPE
) == VT_LLONG
) {
3524 /* convert to int to increment easily */
3531 /* XXX: it works because r2 is spilled last ! */
3532 store(vtop
->r2
, vtop
- 1);
3535 vtop
--; /* NOT vpop() because on x86 it would flush the fp stack */
3536 vtop
->r
|= delayed_cast
;
3540 /* post defines POST/PRE add. c is the token ++ or -- */
3541 void inc(int post
, int c
)
3544 vdup(); /* save lvalue */
3546 gv_dup(); /* duplicate value */
3551 vpushi(c
- TOK_MID
);
3553 vstore(); /* store value */
3555 vpop(); /* if post op, return saved value */
3558 /* Parse GNUC __attribute__ extension. Currently, the following
3559 extensions are recognized:
3560 - aligned(n) : set data/function alignment.
3561 - section(x) : generate data/code in this section.
3562 - unused : currently ignored, but may be used someday.
3564 void parse_attribute(AttributeDef
*ad
)
3571 while (tok
!= ')') {
3572 if (tok
< TOK_IDENT
)
3573 expect("attribute name");
3578 case TOK___SECTION__
:
3581 expect("section name");
3582 ad
->section
= find_section(tokc
.ts
->str
);
3587 case TOK___ALIGNED__
:
3590 if (n
<= 0 || (n
& (n
- 1)) != 0)
3591 error("alignment must be a positive power of two");
3596 case TOK___UNUSED__
:
3597 /* currently, no need to handle it because tcc does not
3598 track unused objects */
3601 warning("'%s' attribute ignored", get_tok_str(t
, NULL
));
3602 /* skip parameters */
3603 /* XXX: skip parenthesis too */
3606 while (tok
!= ')' && tok
!= -1)
3620 /* enum/struct/union declaration */
3621 int struct_decl(int u
)
3623 int a
, t
, b
, v
, size
, align
, maxalign
, c
, offset
;
3624 int bit_size
, bit_pos
, bsize
, bt
, lbit_pos
;
3628 a
= tok
; /* save decl type */
3633 /* struct already defined ? return it */
3634 /* XXX: check consistency */
3635 s
= sym_find(v
| SYM_STRUCT
);
3638 error("invalid type");
3644 s
= sym_push(v
| SYM_STRUCT
, a
, 0, 0);
3645 /* put struct/union/enum name in type */
3647 u
= u
| (v
<< VT_STRUCT_SHIFT
);
3652 error("struct/union/enum already defined");
3653 /* cannot be empty */
3660 if (a
== TOK_ENUM
) {
3667 /* enum symbols have static storage */
3668 sym_push(v
, VT_STATIC
| VT_INT
, VT_CONST
, c
);
3673 parse_btype(&b
, &ad
);
3678 t
= type_decl(&v
, b
, TYPE_DIRECT
);
3679 if ((t
& VT_BTYPE
) == VT_FUNC
||
3680 (t
& (VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
)))
3681 error("invalid type for '%s'",
3682 get_tok_str(v
, NULL
));
3688 bit_size
= expr_const();
3689 /* XXX: handle v = 0 case for messages */
3691 error("negative width in bit-field '%s'",
3692 get_tok_str(v
, NULL
));
3693 if (v
&& bit_size
== 0)
3694 error("zero width for bit-field '%s'",
3695 get_tok_str(v
, NULL
));
3697 size
= type_size(t
, &align
);
3699 if (bit_size
>= 0) {
3704 error("bitfields must have scalar type");
3706 if (bit_size
> bsize
) {
3707 error("width of '%s' exceeds its type",
3708 get_tok_str(v
, NULL
));
3709 } else if (bit_size
== bsize
) {
3710 /* no need for bit fields */
3712 } else if (bit_size
== 0) {
3713 /* XXX: what to do if only padding in a
3715 /* zero size: means to pad */
3719 /* we do not have enough room ? */
3720 if ((bit_pos
+ bit_size
) > bsize
)
3723 /* XXX: handle LSB first */
3725 (bit_pos
<< VT_STRUCT_SHIFT
) |
3726 (bit_size
<< (VT_STRUCT_SHIFT
+ 6));
3727 bit_pos
+= bit_size
;
3733 /* add new memory data only if starting
3735 if (lbit_pos
== 0) {
3736 if (a
== TOK_STRUCT
) {
3737 c
= (c
+ align
- 1) & -align
;
3745 if (align
> maxalign
)
3749 printf("add field %s offset=%d",
3750 get_tok_str(v
, NULL
), offset
);
3751 if (t
& VT_BITFIELD
) {
3752 printf(" pos=%d size=%d",
3753 (t
>> VT_STRUCT_SHIFT
) & 0x3f,
3754 (t
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f);
3758 ss
= sym_push(v
| SYM_FIELD
, t
, 0, offset
);
3762 if (tok
== ';' || tok
== -1)
3772 /* size for struct/union, dummy for enum */
3773 s
->c
= (c
+ maxalign
- 1) & -maxalign
;
3778 /* return 0 if no type declaration. otherwise, return the basic type
3781 int parse_btype(int *type_ptr
, AttributeDef
*ad
)
3783 int t
, u
, type_found
;
3786 memset(ad
, 0, sizeof(AttributeDef
));
3797 if ((t
& VT_BTYPE
) != 0)
3798 error("too many basic types");
3812 if ((t
& VT_BTYPE
) == VT_DOUBLE
) {
3813 t
= (t
& ~VT_BTYPE
) | VT_LDOUBLE
;
3814 } else if ((t
& VT_BTYPE
) == VT_LONG
) {
3815 t
= (t
& ~VT_BTYPE
) | VT_LLONG
;
3829 if ((t
& VT_BTYPE
) == VT_LONG
) {
3830 t
= (t
& ~VT_BTYPE
) | VT_LDOUBLE
;
3837 u
= struct_decl(VT_ENUM
);
3841 u
= struct_decl(VT_STRUCT
);
3844 /* type modifiers */
3872 /* GNUC attribute */
3873 case TOK___ATTRIBUTE__
:
3874 parse_attribute(ad
);
3878 if (!s
|| !(s
->t
& VT_TYPEDEF
))
3880 t
|= (s
->t
& ~VT_TYPEDEF
);
3887 /* long is never used as type */
3888 if ((t
& VT_BTYPE
) == VT_LONG
)
3889 t
= (t
& ~VT_BTYPE
) | VT_INT
;
3894 int post_type(int t
)
3896 int p
, n
, pt
, l
, t1
;
3897 Sym
**plast
, *s
, *first
;
3901 /* function declaration */
3906 while (tok
!= ')') {
3907 /* read param name and compute offset */
3908 if (l
!= FUNC_OLD
) {
3909 if (!parse_btype(&pt
, &ad
)) {
3911 error("invalid type");
3918 if ((pt
& VT_BTYPE
) == VT_VOID
&& tok
== ')')
3920 pt
= type_decl(&n
, pt
, TYPE_DIRECT
| TYPE_ABSTRACT
);
3921 if ((pt
& VT_BTYPE
) == VT_VOID
)
3922 error("parameter declared as void");
3929 /* array must be transformed to pointer according to ANSI C */
3931 s
= sym_push(n
| SYM_FIELD
, pt
, 0, 0);
3936 if (l
== FUNC_NEW
&& tok
== TOK_DOTS
) {
3943 /* if no parameters, then old type prototype */
3947 t1
= t
& (VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
);
3948 t
= post_type(t
& ~(VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
));
3949 /* we push a anonymous symbol which will contain the function prototype */
3951 s
= sym_push(p
, t
, 0, l
);
3953 t
= t1
| VT_FUNC
| (p
<< VT_STRUCT_SHIFT
);
3954 } else if (tok
== '[') {
3955 /* array definition */
3961 error("invalid array size");
3964 /* parse next post type */
3965 t1
= t
& (VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
);
3966 t
= post_type(t
& ~(VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
));
3968 /* we push a anonymous symbol which will contain the array
3971 sym_push(p
, t
, 0, n
);
3972 t
= t1
| VT_ARRAY
| VT_PTR
| (p
<< VT_STRUCT_SHIFT
);
3977 /* Read a type declaration (except basic type), and return the
3978 type. If v is true, then also put variable name in 'vtop->c' */
3979 int type_decl(int *v
, int t
, int td
)
3984 while (tok
== '*') {
3986 while (tok
== TOK_CONST
|| tok
== TOK_VOLATILE
|| tok
== TOK_RESTRICT
)
3991 /* recursive type */
3992 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
3995 u
= type_decl(v
, 0, td
);
3999 /* type identifier */
4000 if (tok
>= TOK_IDENT
&& (td
& TYPE_DIRECT
)) {
4004 if (!(td
& TYPE_ABSTRACT
))
4005 expect("identifier");
4009 /* append t at the end of u */
4015 s
= sym_find((unsigned)p
>> VT_STRUCT_SHIFT
);
4025 /* define a new external reference to a function 'v' of type 'u' */
4026 Sym
*external_sym(int v
, int u
, int r
)
4031 /* push forward reference */
4032 s
= sym_push1(&global_stack
,
4034 s
->r
= r
| VT_CONST
| VT_FORWARD
;
4041 if ((vtop
->t
& VT_BTYPE
) != VT_PTR
)
4043 if (vtop
->r
& VT_LVAL
)
4045 vtop
->t
= pointed_type(vtop
->t
);
4046 if (!(vtop
->t
& VT_ARRAY
)) /* an array is never an lvalue */
4050 /* pass a parameter to a function and do type checking and casting */
4051 void gfunc_param_typed(GFuncContext
*gf
, Sym
*func
, Sym
*arg
)
4054 func_type
= func
->c
;
4055 if (func_type
== FUNC_OLD
||
4056 (func_type
== FUNC_ELLIPSIS
&& arg
== NULL
)) {
4057 /* default casting : only need to convert float to double */
4058 if ((vtop
->t
& VT_BTYPE
) == VT_FLOAT
)
4059 gen_cast(VT_DOUBLE
);
4060 } else if (arg
== NULL
) {
4061 error("too many arguments to function");
4063 gen_assign_cast(arg
->t
);
4070 int n
, t
, ft
, fc
, p
, align
, size
, r
, data_offset
;
4075 if (tok
== TOK_CINT
|| tok
== TOK_CCHAR
|| tok
== TOK_LCHAR
) {
4078 } else if (tok
== TOK_CUINT
) {
4079 vsetc(VT_INT
| VT_UNSIGNED
, VT_CONST
, &tokc
);
4081 } else if (tok
== TOK_CLLONG
) {
4082 vsetc(VT_LLONG
, VT_CONST
, &tokc
);
4084 } else if (tok
== TOK_CULLONG
) {
4085 vsetc(VT_LLONG
| VT_UNSIGNED
, VT_CONST
, &tokc
);
4087 } else if (tok
== TOK_CFLOAT
) {
4088 vsetc(VT_FLOAT
, VT_CONST
, &tokc
);
4090 } else if (tok
== TOK_CDOUBLE
) {
4091 vsetc(VT_DOUBLE
, VT_CONST
, &tokc
);
4093 } else if (tok
== TOK_CLDOUBLE
) {
4094 vsetc(VT_LDOUBLE
, VT_CONST
, &tokc
);
4096 } else if (tok
== TOK___FUNC__
) {
4097 /* special function name identifier */
4098 /* generate (char *) type */
4099 data_offset
= (int)data_section
->data_ptr
;
4100 vset(mk_pointer(VT_BYTE
), VT_CONST
, data_offset
);
4101 strcpy((void *)data_offset
, funcname
);
4102 data_offset
+= strlen(funcname
) + 1;
4103 data_section
->data_ptr
= (unsigned char *)data_offset
;
4105 } else if (tok
== TOK_LSTR
) {
4108 } else if (tok
== TOK_STR
) {
4109 /* string parsing */
4112 type_size(t
, &align
);
4113 data_offset
= (int)data_section
->data_ptr
;
4114 data_offset
= (data_offset
+ align
- 1) & -align
;
4116 /* we must declare it as an array first to use initializer parser */
4117 t
= VT_ARRAY
| mk_pointer(t
);
4118 decl_initializer(t
, VT_CONST
, data_offset
, 1, 0);
4119 data_offset
+= type_size(t
, &align
);
4120 /* put it as pointer */
4121 vset(t
& ~VT_ARRAY
, VT_CONST
, fc
);
4122 data_section
->data_ptr
= (unsigned char *)data_offset
;
4128 if (parse_btype(&t
, &ad
)) {
4129 ft
= type_decl(&n
, t
, TYPE_ABSTRACT
);
4131 /* check ISOC99 compound literal */
4133 /* data is allocated locally by default */
4138 /* all except arrays are lvalues */
4139 if (!(ft
& VT_ARRAY
))
4141 memset(&ad
, 0, sizeof(AttributeDef
));
4142 fc
= decl_initializer_alloc(ft
, &ad
, r
, 1);
4152 } else if (t
== '*') {
4155 } else if (t
== '&') {
4157 /* functions names must be treated as function pointers,
4158 except for unary '&' and sizeof. Since we consider that
4159 functions are not lvalues, we only have to handle it
4160 there and in function calls. */
4161 if ((vtop
->t
& VT_BTYPE
) != VT_FUNC
)
4163 vtop
->t
= mk_pointer(vtop
->t
);
4168 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
)
4169 vtop
->c
.i
= !vtop
->c
.i
;
4170 else if ((vtop
->r
& VT_VALMASK
) == VT_CMP
)
4171 vtop
->c
.i
= vtop
->c
.i
^ 1;
4173 vset(VT_INT
, VT_JMP
, gtst(1, 0));
4183 if (t
== TOK_SIZEOF
) {
4186 if (parse_btype(&t
, &ad
)) {
4187 t
= type_decl(&n
, t
, TYPE_ABSTRACT
);
4189 /* XXX: some code could be generated: add eval
4201 vpushi(type_size(t
, &t
));
4203 if (t
== TOK_INC
|| t
== TOK_DEC
) {
4206 } else if (t
== '-') {
4215 error("'%s' undeclared", get_tok_str(t
, NULL
));
4216 /* for simple function calls, we tolerate undeclared
4217 external reference */
4219 sym_push1(&global_stack
, p
, 0, FUNC_OLD
);
4220 /* int() function */
4221 s
= external_sym(t
, VT_FUNC
| (p
<< VT_STRUCT_SHIFT
), 0);
4223 vset(s
->t
, s
->r
, s
->c
);
4224 /* if forward reference, we must point to s */
4225 if (vtop
->r
& VT_FORWARD
)
4230 /* post operations */
4232 if (tok
== TOK_INC
|| tok
== TOK_DEC
) {
4235 } else if (tok
== '.' || tok
== TOK_ARROW
) {
4237 if (tok
== TOK_ARROW
)
4242 /* expect pointer on structure */
4243 if ((vtop
->t
& VT_BTYPE
) != VT_STRUCT
)
4244 expect("struct or union");
4245 s
= sym_find(((unsigned)vtop
->t
>> VT_STRUCT_SHIFT
) | SYM_STRUCT
);
4248 while ((s
= s
->next
) != NULL
) {
4253 error("field not found");
4254 /* add field offset to pointer */
4255 vtop
->t
= char_pointer_type
; /* change type to 'char *' */
4258 /* change type to field type, and set to lvalue */
4260 /* an array is never an lvalue */
4261 if (!(vtop
->t
& VT_ARRAY
))
4264 } else if (tok
== '[') {
4270 } else if (tok
== '(') {
4275 if ((vtop
->t
& VT_BTYPE
) != VT_FUNC
) {
4276 /* pointer test (no array accepted) */
4277 if ((vtop
->t
& (VT_BTYPE
| VT_ARRAY
)) == VT_PTR
) {
4278 vtop
->t
= pointed_type(vtop
->t
);
4279 if ((vtop
->t
& VT_BTYPE
) != VT_FUNC
)
4283 expect("function pointer");
4286 vtop
->r
&= ~VT_LVAL
; /* no lvalue */
4288 /* get return type */
4289 s
= sym_find((unsigned)vtop
->t
>> VT_STRUCT_SHIFT
);
4290 save_regs(); /* save used temporary registers */
4293 sa
= s
->next
; /* first parameter */
4294 #ifdef INVERT_FUNC_PARAMS
4296 int *str
, len
, parlevel
, *saved_macro_ptr
;
4299 /* read each argument and store it on a stack */
4300 /* XXX: merge it with macro args ? */
4302 while (tok
!= ')') {
4306 while ((parlevel
> 0 || (tok
!= ')' && tok
!= ',')) &&
4310 else if (tok
== ')')
4312 tok_add2(&str
, &len
, tok
, &tokc
);
4315 tok_add(&str
, &len
, -1); /* end of file added */
4316 tok_add(&str
, &len
, 0);
4317 s1
= sym_push2(&args
, 0, 0, (int)str
);
4318 s1
->next
= sa
; /* add reference to argument */
4328 /* now generate code in reverse order by reading the stack */
4329 saved_macro_ptr
= macro_ptr
;
4331 macro_ptr
= (int *)args
->c
;
4335 expect("',' or ')'");
4336 gfunc_param_typed(&gf
, s
, args
->next
);
4338 free((int *)args
->c
);
4342 macro_ptr
= saved_macro_ptr
;
4347 /* compute first implicit argument if a structure is returned */
4348 if ((s
->t
& VT_BTYPE
) == VT_STRUCT
) {
4349 /* get some space for the returned structure */
4350 size
= type_size(s
->t
, &align
);
4351 loc
= (loc
- size
) & -align
;
4353 ret
.r
= VT_LOCAL
| VT_LVAL
;
4354 /* pass it as 'int' to avoid structure arg passing
4356 vset(VT_INT
, VT_LOCAL
, loc
);
4362 /* return in register */
4363 if (is_float(ret
.t
)) {
4366 if ((ret
.t
& VT_BTYPE
) == VT_LLONG
)
4372 #ifndef INVERT_FUNC_PARAMS
4373 while (tok
!= ')') {
4375 gfunc_param_typed(&gf
, s
, sa
);
4383 error("too few arguments to function");
4387 vsetc(ret
.t
, ret
.r
, &ret
.c
);
4401 (tok
>= TOK_A_MOD
&& tok
<= TOK_A_DIV
) ||
4402 tok
== TOK_A_XOR
|| tok
== TOK_A_OR
||
4403 tok
== TOK_A_SHL
|| tok
== TOK_A_SAR
) {
4426 while ((l
== 0 && (tok
== '*' || tok
== '/' || tok
== '%')) ||
4427 (l
== 1 && (tok
== '+' || tok
== '-')) ||
4428 (l
== 2 && (tok
== TOK_SHL
|| tok
== TOK_SAR
)) ||
4429 (l
== 3 && ((tok
>= TOK_ULE
&& tok
<= TOK_GT
) ||
4430 tok
== TOK_ULT
|| tok
== TOK_UGE
)) ||
4431 (l
== 4 && (tok
== TOK_EQ
|| tok
== TOK_NE
)) ||
4432 (l
== 5 && tok
== '&') ||
4433 (l
== 6 && tok
== '^') ||
4434 (l
== 7 && tok
== '|') ||
4435 (l
== 8 && tok
== TOK_LAND
) ||
4436 (l
== 9 && tok
== TOK_LOR
)) {
4445 /* only used if non constant */
4453 if (tok
!= TOK_LAND
) {
4456 vset(VT_INT
, VT_JMPI
, t
);
4473 if (tok
!= TOK_LOR
) {
4476 vset(VT_INT
, VT_JMP
, t
);
4486 /* XXX: better constant handling */
4489 int t
, u
, c
, r1
, r2
, rc
;
4511 /* XXX: long long handling ? */
4513 if (is_float(vtop
->t
))
4541 /* parse a constant expression and return value in vtop */
4542 void expr_const1(void)
4548 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
)) != VT_CONST
)
4553 /* parse an integer constant and return its value */
4554 int expr_const(void)
4563 /* return the label token if current token is a label, otherwise
4570 /* fast test first */
4571 if (tok
< TOK_UIDENT
)
4573 /* no need to save tokc since we expect an identifier */
4581 /* XXX: may not work in all cases (macros ?) */
4590 void block(int *bsym
, int *csym
, int *case_sym
, int *def_sym
, int case_reg
)
4595 /* generate line number info */
4597 (last_line_num
!= line_num
|| last_ind
!= ind
)) {
4598 put_stabn(N_SLINE
, 0, line_num
, ind
- func_ind
);
4600 last_line_num
= line_num
;
4603 if (tok
== TOK_IF
) {
4610 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
4612 if (c
== TOK_ELSE
) {
4616 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
4617 gsym(d
); /* patch else jmp */
4620 } else if (tok
== TOK_WHILE
) {
4628 block(&a
, &b
, case_sym
, def_sym
, case_reg
);
4629 oad(0xe9, d
- ind
- 5); /* jmp */
4632 } else if (tok
== '{') {
4635 s
= local_stack
.top
;
4636 while (tok
!= '}') {
4639 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
4641 /* pop locally defined symbols */
4642 sym_pop(&local_stack
, s
);
4644 } else if (tok
== TOK_RETURN
) {
4648 gen_assign_cast(func_vt
);
4649 if ((func_vt
& VT_BTYPE
) == VT_STRUCT
) {
4650 /* if returning structure, must copy it to implicit
4651 first pointer arg location */
4652 vset(mk_pointer(func_vt
), VT_LOCAL
| VT_LVAL
, func_vc
);
4655 /* copy structure value to pointer */
4657 } else if (is_float(func_vt
)) {
4665 rsym
= gjmp(rsym
); /* jmp */
4666 } else if (tok
== TOK_BREAK
) {
4669 error("cannot break");
4670 *bsym
= gjmp(*bsym
);
4673 } else if (tok
== TOK_CONTINUE
) {
4676 error("cannot continue");
4677 *csym
= gjmp(*csym
);
4680 } else if (tok
== TOK_FOR
) {
4703 oad(0xe9, d
- ind
- 5); /* jmp */
4707 block(&a
, &b
, case_sym
, def_sym
, case_reg
);
4708 oad(0xe9, c
- ind
- 5); /* jmp */
4712 if (tok
== TOK_DO
) {
4717 block(&a
, &b
, case_sym
, def_sym
, case_reg
);
4728 if (tok
== TOK_SWITCH
) {
4732 /* XXX: other types than integer */
4733 case_reg
= gv(RC_INT
);
4737 b
= gjmp(0); /* jump to first case */
4739 block(&a
, csym
, &b
, &c
, case_reg
);
4740 /* if no default, jmp after switch */
4748 if (tok
== TOK_CASE
) {
4755 if (gnu_ext
&& tok
== TOK_DOTS
) {
4759 warning("empty case range");
4761 /* since a case is like a label, we must skip it with a jmp */
4764 vset(VT_INT
, case_reg
, 0);
4768 *case_sym
= gtst(1, 0);
4771 *case_sym
= gtst(1, 0);
4772 vset(VT_INT
, case_reg
, 0);
4775 *case_sym
= gtst(1, *case_sym
);
4779 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
4781 if (tok
== TOK_DEFAULT
) {
4787 error("too many 'default'");
4789 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
4791 if (tok
== TOK_GOTO
) {
4793 s
= sym_find1(&label_stack
, tok
);
4794 /* put forward definition if needed */
4796 s
= sym_push1(&label_stack
, tok
, VT_FORWARD
, 0);
4797 /* label already defined */
4798 if (s
->t
& VT_FORWARD
)
4799 s
->c
= gjmp(s
->c
); /* jmp xxx */
4801 oad(0xe9, s
->c
- ind
- 5); /* jmp xxx */
4808 s
= sym_find1(&label_stack
, b
);
4810 if (!(s
->t
& VT_FORWARD
))
4811 error("multiple defined label");
4816 sym_push1(&label_stack
, b
, 0, ind
);
4818 /* we accept this, but it is a mistake */
4820 warning("deprecated use of label at end of compound statement");
4822 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
4824 /* expression case */
4834 /* t is the array or struct type. c is the array or struct
4835 address. cur_index/cur_field is the pointer to the current
4836 value. 'size_only' is true if only size info is needed (only used
4838 void decl_designator(int t
, int r
, int c
,
4839 int *cur_index
, Sym
**cur_field
,
4843 int notfirst
, index
, align
, l
;
4846 if (gnu_ext
&& (l
= is_label()) != 0)
4849 while (tok
== '[' || tok
== '.') {
4851 if (!(t
& VT_ARRAY
))
4852 expect("array type");
4853 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
));
4855 index
= expr_const();
4856 if (index
< 0 || (s
->c
>= 0 && index
>= s
->c
))
4857 expect("invalid index");
4861 t
= pointed_type(t
);
4862 c
+= index
* type_size(t
, &align
);
4868 if ((t
& VT_BTYPE
) != VT_STRUCT
)
4869 expect("struct/union type");
4870 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
) | SYM_STRUCT
);
4882 t
= f
->t
| (t
& ~VT_TYPE
);
4897 t
= pointed_type(t
);
4898 c
+= index
* type_size(t
, &align
);
4902 error("too many field init");
4903 t
= f
->t
| (t
& ~VT_TYPE
);
4907 decl_initializer(t
, r
, c
, 0, size_only
);
4911 #define EXPR_CONST 1
4914 /* store a value or an expression directly in global data or in local array */
4915 void init_putv(int t
, int r
, int c
,
4916 int v
, int expr_type
)
4918 int saved_global_expr
, bt
;
4925 /* compound literals must be allocated globally in this case */
4926 saved_global_expr
= global_expr
;
4929 global_expr
= saved_global_expr
;
4936 if ((r
& VT_VALMASK
) == VT_CONST
) {
4937 /* XXX: do casting */
4938 /* XXX: not portable */
4939 bt
= vtop
->t
& VT_BTYPE
;
4942 *(char *)c
= vtop
->c
.i
;
4945 *(short *)c
= vtop
->c
.i
;
4948 *(double *)c
= vtop
->c
.d
;
4951 *(long double *)c
= vtop
->c
.ld
;
4955 *(long long *)c
= vtop
->c
.ll
;
4959 *(int *)c
= vtop
->c
.i
;
4971 /* put zeros for variable based init */
4972 void init_putz(int t
, int r
, int c
, int size
)
4976 if ((r
& VT_VALMASK
) == VT_CONST
) {
4977 /* nothing to do because global are already set to zero */
4984 vset(VT_INT
, VT_LOCAL
, c
);
4986 vpushi((int)&memset
);
4991 /* 't' contains the type and storage info. c is the address of the
4992 object. 'first' is true if array '{' must be read (multi dimension
4993 implicit array init handling). 'size_only' is true if size only
4994 evaluation is wanted (only for arrays). */
4995 void decl_initializer(int t
, int r
, int c
, int first
, int size_only
)
4997 int index
, array_length
, n
, no_oblock
, nb
, parlevel
, i
;
4998 int t1
, size1
, align1
, expr_type
;
5003 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
));
5006 t1
= pointed_type(t
);
5007 size1
= type_size(t1
, &align1
);
5010 if ((first
&& tok
!= TOK_LSTR
&& tok
!= TOK_STR
) ||
5016 /* only parse strings here if correct type (otherwise: handle
5017 them as ((w)char *) expressions */
5018 if ((tok
== TOK_LSTR
&&
5019 (t1
& VT_BTYPE
) == VT_INT
) ||
5021 (t1
& VT_BTYPE
) == VT_BYTE
)) {
5022 /* XXX: move multiple string parsing in parser ? */
5023 while (tok
== TOK_STR
|| tok
== TOK_LSTR
) {
5025 /* compute maximum number of chars wanted */
5027 if (n
>= 0 && nb
> (n
- array_length
))
5028 nb
= n
- array_length
;
5031 warning("initializer-string for array is too long");
5033 init_putv(t1
, r
, c
+ (array_length
+ i
) * size1
,
5034 ts
->str
[i
], EXPR_VAL
);
5040 /* only add trailing zero if enough storage (no
5041 warning in this case since it is standard) */
5042 if (n
< 0 || array_length
< n
) {
5044 init_putv(t1
, r
, c
+ (array_length
* size1
), 0, EXPR_VAL
);
5050 while (tok
!= '}') {
5051 decl_designator(t
, r
, c
, &index
, NULL
, size_only
);
5052 if (n
>= 0 && index
>= n
)
5053 error("index too large");
5054 /* must put zero in holes (note that doing it that way
5055 ensures that it even works with designators) */
5056 if (!size_only
&& array_length
< index
) {
5057 init_putz(t1
, r
, c
+ array_length
* size1
,
5058 (index
- array_length
) * size1
);
5061 if (index
> array_length
)
5062 array_length
= index
;
5063 /* special test for multi dimensional arrays (may not
5064 be strictly correct if designators are used at the
5066 if (index
>= n
&& no_oblock
)
5075 /* put zeros at the end */
5076 if (!size_only
&& n
>= 0 && array_length
< n
) {
5077 init_putz(t1
, r
, c
+ array_length
* size1
,
5078 (n
- array_length
) * size1
);
5080 /* patch type size if needed */
5082 s
->c
= array_length
;
5083 } else if ((t
& VT_BTYPE
) == VT_STRUCT
&& tok
== '{') {
5084 /* XXX: union needs only one init */
5086 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
) | SYM_STRUCT
);
5091 while (tok
!= '}') {
5092 decl_designator(t
, r
, c
, NULL
, &f
, size_only
);
5093 /* fill with zero between fields */
5095 if (!size_only
&& array_length
< index
) {
5096 init_putz(t
, r
, c
+ array_length
,
5097 index
- array_length
);
5099 index
= index
+ type_size(f
->t
, &align1
);
5100 if (index
> array_length
)
5101 array_length
= index
;
5107 /* put zeros at the end */
5108 if (!size_only
&& array_length
< n
) {
5109 init_putz(t
, r
, c
+ array_length
,
5113 } else if (tok
== '{') {
5115 decl_initializer(t
, r
, c
, first
, size_only
);
5117 } else if (size_only
) {
5118 /* just skip expression */
5120 while ((parlevel
> 0 || (tok
!= '}' && tok
!= ',')) &&
5124 else if (tok
== ')')
5129 /* currently, we always use constant expression for globals
5130 (may change for scripting case) */
5131 expr_type
= EXPR_CONST
;
5132 if ((r
& VT_VALMASK
) == VT_LOCAL
)
5133 expr_type
= EXPR_ANY
;
5134 init_putv(t
, r
, c
, 0, expr_type
);
5138 /* parse an initializer for type 't' if 'has_init' is true, and
5139 allocate space in local or global data space ('r' is either
5140 VT_LOCAL or VT_CONST). The allocated address in returned */
5141 int decl_initializer_alloc(int t
, AttributeDef
*ad
, int r
, int has_init
)
5143 int size
, align
, addr
, tok1
, data_offset
;
5144 int *init_str
, init_len
, level
, *saved_macro_ptr
;
5147 size
= type_size(t
, &align
);
5148 /* If unknown size, we must evaluate it before
5149 evaluating initializers because
5150 initializers can generate global data too
5151 (e.g. string pointers or ISOC99 compound
5152 literals). It also simplifies local
5153 initializers handling */
5156 saved_macro_ptr
= NULL
; /* avoid warning */
5160 error("unknown type size");
5161 /* get all init string */
5163 while (level
> 0 || (tok
!= ',' && tok
!= ';')) {
5165 error("unexpected end of file in initializer");
5166 tok_add2(&init_str
, &init_len
, tok
, &tokc
);
5169 else if (tok
== '}') {
5177 tok_add(&init_str
, &init_len
, -1);
5178 tok_add(&init_str
, &init_len
, 0);
5181 saved_macro_ptr
= macro_ptr
;
5182 macro_ptr
= init_str
;
5184 decl_initializer(t
, r
, 0, 1, 1);
5185 /* prepare second initializer parsing */
5186 macro_ptr
= init_str
;
5189 /* if still unknown size, error */
5190 size
= type_size(t
, &align
);
5192 error("unknown type size");
5194 /* take into account specified alignment if bigger */
5195 if (ad
->aligned
> align
)
5196 align
= ad
->aligned
;
5197 if ((r
& VT_VALMASK
) == VT_LOCAL
) {
5198 loc
= (loc
- size
) & -align
;
5201 /* compute section */
5209 data_offset
= (int)sec
->data_ptr
;
5210 data_offset
= (data_offset
+ align
- 1) & -align
;
5212 /* very important to increment global
5213 pointer at this time because
5214 initializers themselves can create new
5216 data_offset
+= size
;
5217 /* handles bounds */
5218 if (do_bounds_check
) {
5220 /* first, we need to add at least one byte between each region */
5222 /* then add global data info */
5223 bounds_ptr
= (int *)bounds_section
->data_ptr
;
5224 *bounds_ptr
++ = addr
;
5225 *bounds_ptr
++ = size
;
5226 bounds_section
->data_ptr
= (unsigned char *)bounds_ptr
;
5228 sec
->data_ptr
= (unsigned char *)data_offset
;
5231 decl_initializer(t
, r
, addr
, 1, 0);
5232 /* restore parse state if needed */
5235 macro_ptr
= saved_macro_ptr
;
5242 void put_func_debug(int t
)
5251 put_elf_sym(symtab_section
, ind
, 0,
5252 ELF32_ST_INFO(bind
, STT_FUNC
), 0,
5253 cur_text_section
->sh_num
, funcname
);
5255 /* XXX: we put here a dummy type */
5256 snprintf(buf
, sizeof(buf
), "%s:%c1",
5257 funcname
, t
& VT_STATIC
? 'f' : 'F');
5258 put_stabs(buf
, N_FUN
, 0, line_num
, ind
);
5264 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
5267 int t
, b
, v
, addr
, has_init
, r
;
5272 if (!parse_btype(&b
, &ad
)) {
5273 /* skip redundant ';' */
5274 /* XXX: find more elegant solution */
5279 /* special test for old K&R protos without explicit int
5280 type. Only accepted when defining global data */
5281 if (l
== VT_LOCAL
|| tok
< TOK_DEFINE
)
5285 if (((b
& VT_BTYPE
) == VT_ENUM
||
5286 (b
& VT_BTYPE
) == VT_STRUCT
) &&
5288 /* we accept no variable after */
5292 while (1) { /* iterate thru each declaration */
5293 t
= type_decl(&v
, b
, TYPE_DIRECT
);
5294 /* currently, we do not parse attribute in
5295 type_decl(). May change if needed */
5296 if (tok
== TOK___ATTRIBUTE__
)
5297 parse_attribute(&ad
);
5301 type_to_str(buf
, sizeof(buf
), t
, get_tok_str(v
, NULL
));
5302 printf("type = '%s'\n", buf
);
5307 error("cannot use local functions");
5309 expect("function definition");
5310 /* compute text section */
5311 cur_text_section
= ad
.section
;
5312 if (!cur_text_section
)
5313 cur_text_section
= text_section
;
5314 ind
= (int)cur_text_section
->data_ptr
;
5315 /* patch forward references */
5316 if ((sym
= sym_find(v
)) && (sym
->r
& VT_FORWARD
)) {
5317 greloc_patch(sym
, ind
);
5320 /* put function address */
5321 sym
= sym_push1(&global_stack
, v
, t
, ind
);
5324 funcname
= get_tok_str(v
, NULL
);
5325 /* put debug symbol */
5328 /* push a dummy symbol to enable local sym storage */
5329 sym_push1(&local_stack
, 0, 0, 0);
5333 block(NULL
, NULL
, NULL
, NULL
, 0);
5336 cur_text_section
->data_ptr
= (unsigned char *)ind
;
5337 sym_pop(&label_stack
, NULL
); /* reset label stack */
5338 sym_pop(&local_stack
, NULL
); /* reset local stack */
5339 /* end of function */
5341 put_stabn(N_FUN
, 0, 0, ind
- func_ind
);
5343 funcname
= ""; /* for safety */
5344 func_vt
= VT_VOID
; /* for safety */
5347 if (b
& VT_TYPEDEF
) {
5348 /* save typedefed type */
5349 /* XXX: test storage specifiers ? */
5350 sym_push(v
, t
| VT_TYPEDEF
, 0, 0);
5351 } else if ((t
& VT_BTYPE
) == VT_FUNC
) {
5352 /* external function definition */
5353 external_sym(v
, t
, 0);
5355 /* not lvalue if array */
5357 if (!(t
& VT_ARRAY
))
5359 if (b
& VT_EXTERN
) {
5360 /* external variable */
5361 external_sym(v
, t
, r
);
5367 has_init
= (tok
== '=');
5370 addr
= decl_initializer_alloc(t
, &ad
, r
,
5372 if (l
== VT_CONST
) {
5373 /* global scope: see if already defined */
5377 if (!is_compatible_types(sym
->t
, t
))
5378 error("incompatible types for redefinition of '%s'",
5379 get_tok_str(v
, NULL
));
5380 if (!(sym
->r
& VT_FORWARD
))
5381 error("redefinition of '%s'", get_tok_str(v
, NULL
));
5382 greloc_patch(sym
, addr
);
5385 sym_push(v
, t
, r
, addr
);
5399 /* put all global symbols in the extern stack and do all the
5400 resolving which can be done without using external symbols from DLLs */
5401 /* XXX: could try to verify types, but would not to save them in
5403 void resolve_global_syms(void)
5405 Sym
*s
, *s1
, *ext_sym
;
5408 s
= global_stack
.top
;
5411 /* do not save static or typedefed symbols or types */
5412 if (!(s
->t
& (VT_STATIC
| VT_TYPEDEF
)) &&
5413 !(s
->v
& (SYM_FIELD
| SYM_STRUCT
)) &&
5414 (s
->v
< SYM_FIRST_ANOM
)) {
5415 ext_sym
= sym_find1(&extern_stack
, s
->v
);
5417 /* if the symbol do not exist, we simply save it */
5418 ext_sym
= sym_push1(&extern_stack
, s
->v
, s
->t
, s
->c
);
5420 } else if (ext_sym
->r
& VT_FORWARD
) {
5421 /* external symbol already exists, but only as forward
5423 if (!(s
->r
& VT_FORWARD
)) {
5424 /* s is not forward, so we can relocate all symbols */
5425 greloc_patch(ext_sym
, s
->c
);
5427 /* the two symbols are forward: merge them */
5428 p
= (Reloc
**)&ext_sym
->c
;
5434 /* external symbol already exists and is defined :
5435 patch all references to it */
5436 if (!(s
->r
& VT_FORWARD
))
5437 error("'%s' defined twice", get_tok_str(s
->v
, NULL
));
5438 greloc_patch(s
, ext_sym
->c
);
5445 /* compile a C file. Return non zero if errors. */
5446 int tcc_compile_file(const char *filename1
)
5453 filename
= (char *)filename1
;
5455 file
= fopen(filename
, "r");
5457 error("file '%s' not found", filename
);
5458 include_stack_ptr
= include_stack
;
5459 ifdef_stack_ptr
= ifdef_stack
;
5462 anon_sym
= SYM_FIRST_ANOM
;
5464 /* file info: full path + filename */
5466 getcwd(buf
, sizeof(buf
));
5467 pstrcat(buf
, sizeof(buf
), "/");
5468 put_stabs(buf
, N_SO
, 0, 0, (unsigned long)text_section
->data_ptr
);
5469 put_stabs(filename
, N_SO
, 0, 0, (unsigned long)text_section
->data_ptr
);
5471 /* define common 'char *' type because it is often used internally
5472 for arrays and struct dereference */
5473 char_pointer_type
= mk_pointer(VT_BYTE
);
5475 define_start
= define_stack
.top
;
5477 ch
= '\n'; /* needed to parse correctly first preprocessor command */
5481 expect("declaration");
5484 /* end of translation unit info */
5486 put_stabn(N_SO
, 0, 0, (unsigned long)text_section
->data_ptr
);
5489 /* reset define stack, but leave -Dsymbols (may be incorrect if
5490 they are undefined) */
5491 sym_pop(&define_stack
, define_start
);
5493 resolve_global_syms();
5495 sym_pop(&global_stack
, NULL
);
5500 /* define a symbol. A value can also be provided with the '=' operator */
5501 /* XXX: currently only handles integers and string defines. should use
5502 tcc parser, but would need a custom 'FILE *' */
5503 void define_symbol(const char *sym
)
5511 p
= strchr(sym
, '=');
5513 pstrcpy(buf
, sizeof(buf
), sym
);
5517 if (len
> sizeof(buf
) - 1)
5518 len
= sizeof(buf
) - 1;
5519 memcpy(buf
, sym
, len
);
5524 ts
= tok_alloc(buf
, 0);
5530 tok_add2(&str
, &len
, TOK_CINT
, &cval
);
5533 cval
.ts
= tok_alloc(p
, 0);
5534 tok_add2(&str
, &len
, TOK_STR
, &cval
);
5536 tok_add(&str
, &len
, 0);
5537 sym_push1(&define_stack
, ts
->tok
, MACRO_OBJ
, (int)str
);
5540 void undef_symbol(const char *sym
)
5544 printf("undef %s\n", sym
);
5545 ts
= tok_alloc(sym
, 0);
5546 s
= sym_find1(&define_stack
, tok
);
5547 /* undefine symbol by putting an invalid name */
5549 sym_undef(&define_stack
, s
);
5552 /* open a dynamic library so that its symbol are available for
5553 compiled programs */
5554 void open_dll(char *libname
)
5559 snprintf(buf
, sizeof(buf
), "lib%s.so", libname
);
5560 h
= dlopen(buf
, RTLD_GLOBAL
| RTLD_LAZY
);
5562 error((char *)dlerror());
5565 static void *resolve_sym(const char *sym
)
5568 if (do_bounds_check
) {
5569 ptr
= bound_resolve_sym(sym
);
5573 return dlsym(NULL
, sym
);
5576 void resolve_extern_syms(void)
5582 s
= extern_stack
.top
;
5585 if (s
->r
& VT_FORWARD
) {
5586 /* if there is at least one relocation to do, then find it
5589 str
= get_tok_str(s
->v
, NULL
);
5590 addr
= (int)resolve_sym(str
);
5592 error("unresolved external reference '%s'", str
);
5593 greloc_patch(s
, addr
);
5600 static int put_elf_str(Section
*s
, const char *sym
)
5603 offset
= s
->data_ptr
- s
->data
;
5613 static void put_elf_sym(Section
*s
,
5614 unsigned long value
, unsigned long size
,
5615 int info
, int other
, int shndx
, const char *name
)
5620 sym
= (Elf32_Sym
*)s
->data_ptr
;
5622 name_offset
= put_elf_str(s
->link
, name
);
5625 sym
->st_name
= name_offset
;
5626 sym
->st_value
= value
;
5627 sym
->st_size
= size
;
5628 sym
->st_info
= info
;
5629 sym
->st_other
= other
;
5630 sym
->st_shndx
= shndx
;
5631 s
->data_ptr
+= sizeof(Elf32_Sym
);
5634 /* put stab debug information */
5637 unsigned long n_strx
; /* index into string table of name */
5638 unsigned char n_type
; /* type of symbol */
5639 unsigned char n_other
; /* misc info (usually empty) */
5640 unsigned short n_desc
; /* description field */
5641 unsigned long n_value
; /* value of symbol */
5644 static void put_stabs(const char *str
, int type
, int other
, int desc
, int value
)
5648 sym
= (Stab_Sym
*)stab_section
->data_ptr
;
5650 sym
->n_strx
= put_elf_str(stabstr_section
, str
);
5655 sym
->n_other
= other
;
5657 sym
->n_value
= value
;
5659 stab_section
->data_ptr
+= sizeof(Stab_Sym
);
5662 static void put_stabn(int type
, int other
, int desc
, int value
)
5664 put_stabs(NULL
, type
, other
, desc
, value
);
5667 static void put_stabd(int type
, int other
, int desc
)
5669 put_stabs(NULL
, type
, other
, desc
, 0);
5672 /* output an ELF file (currently, only for testing) */
5673 /* XXX: better program header generation */
5674 /* XXX: handle realloc'ed sections (instead of mmaping them) */
5675 /* XXX: generate dynamic reloc info + DLL tables */
5676 /* XXX: generate startup code */
5677 void build_exe(char *filename
)
5681 int shnum
, i
, phnum
, file_offset
, offset
, size
, j
;
5682 Section
*sec
, *strsec
;
5683 Elf32_Shdr
*shdr
, *sh
;
5684 Elf32_Phdr
*phdr
, *ph
;
5686 memset(&ehdr
, 0, sizeof(ehdr
));
5688 /* we add a section for symbols */
5689 strsec
= new_section(".shstrtab", SHT_STRTAB
, 0);
5690 put_elf_str(strsec
, "");
5692 /* count number of sections and compute number of program segments */
5693 shnum
= 1; /* section index zero is reserved */
5695 for(sec
= first_section
; sec
!= NULL
; sec
= sec
->next
) {
5697 if (sec
->sh_flags
& SHF_ALLOC
)
5700 /* allocate section headers */
5701 shdr
= malloc(shnum
* sizeof(Elf32_Shdr
));
5703 error("memory full");
5704 memset(shdr
, 0, shnum
* sizeof(Elf32_Shdr
));
5705 /* allocate program segment headers */
5706 phdr
= malloc(phnum
* sizeof(Elf32_Phdr
));
5708 error("memory full");
5709 memset(phdr
, 0, phnum
* sizeof(Elf32_Phdr
));
5711 /* XXX: find correct load order */
5712 file_offset
= sizeof(Elf32_Ehdr
) + phnum
* sizeof(Elf32_Phdr
);
5713 for(sec
= first_section
, i
= 1; sec
!= NULL
; sec
= sec
->next
, i
++) {
5715 sh
->sh_name
= put_elf_str(strsec
, sec
->name
);
5716 sh
->sh_type
= sec
->sh_type
;
5717 sh
->sh_flags
= sec
->sh_flags
;
5718 sh
->sh_entsize
= sec
->sh_entsize
;
5720 sh
->sh_link
= sec
->link
->sh_num
;
5721 if (sh
->sh_type
== SHT_STRTAB
) {
5722 sh
->sh_addralign
= 1;
5723 } else if (sh
->sh_type
== SHT_SYMTAB
||
5724 (sh
->sh_flags
& SHF_ALLOC
) == 0) {
5725 sh
->sh_addralign
= 4;
5727 sh
->sh_addr
= (Elf32_Word
)sec
->data
;
5728 sh
->sh_addralign
= 4096;
5730 sh
->sh_size
= (Elf32_Word
)sec
->data_ptr
- (Elf32_Word
)sec
->data
;
5731 /* align to section start */
5732 file_offset
= (file_offset
+ sh
->sh_addralign
- 1) &
5733 ~(sh
->sh_addralign
- 1);
5734 sh
->sh_offset
= file_offset
;
5735 file_offset
+= sh
->sh_size
;
5737 /* build program headers (simplistic - not fully correct) */
5739 for(i
=1;i
<shnum
;i
++) {
5741 if (sh
->sh_type
== SHT_PROGBITS
&&
5742 (sh
->sh_flags
& SHF_ALLOC
) != 0) {
5744 ph
->p_type
= PT_LOAD
;
5745 ph
->p_offset
= sh
->sh_offset
;
5746 ph
->p_vaddr
= sh
->sh_addr
;
5747 ph
->p_paddr
= ph
->p_vaddr
;
5748 ph
->p_filesz
= sh
->sh_size
;
5749 ph
->p_memsz
= sh
->sh_size
;
5751 if (sh
->sh_flags
& SHF_WRITE
)
5752 ph
->p_flags
|= PF_W
;
5753 if (sh
->sh_flags
& SHF_EXECINSTR
)
5754 ph
->p_flags
|= PF_X
;
5755 ph
->p_align
= sh
->sh_addralign
;
5760 file_offset
= (file_offset
+ 3) & -4;
5763 ehdr
.e_ident
[0] = ELFMAG0
;
5764 ehdr
.e_ident
[1] = ELFMAG1
;
5765 ehdr
.e_ident
[2] = ELFMAG2
;
5766 ehdr
.e_ident
[3] = ELFMAG3
;
5767 ehdr
.e_ident
[4] = ELFCLASS32
;
5768 ehdr
.e_ident
[5] = ELFDATA2LSB
;
5769 ehdr
.e_ident
[6] = EV_CURRENT
;
5770 ehdr
.e_type
= ET_EXEC
;
5771 ehdr
.e_machine
= EM_386
;
5772 ehdr
.e_version
= EV_CURRENT
;
5773 ehdr
.e_entry
= 0; /* XXX: patch it */
5774 ehdr
.e_phoff
= sizeof(Elf32_Ehdr
);
5775 ehdr
.e_shoff
= file_offset
;
5776 ehdr
.e_ehsize
= sizeof(Elf32_Ehdr
);
5777 ehdr
.e_phentsize
= sizeof(Elf32_Phdr
);
5778 ehdr
.e_phnum
= phnum
;
5779 ehdr
.e_shentsize
= sizeof(Elf32_Shdr
);
5780 ehdr
.e_shnum
= shnum
;
5781 ehdr
.e_shstrndx
= shnum
- 1;
5783 /* write elf file */
5784 f
= fopen(filename
, "w");
5786 error("could not write '%s'", filename
);
5787 fwrite(&ehdr
, 1, sizeof(Elf32_Ehdr
), f
);
5788 fwrite(phdr
, 1, phnum
* sizeof(Elf32_Phdr
), f
);
5789 offset
= sizeof(Elf32_Ehdr
) + phnum
* sizeof(Elf32_Phdr
);
5790 for(sec
= first_section
, i
= 1; sec
!= NULL
; sec
= sec
->next
, i
++) {
5792 while (offset
< sh
->sh_offset
) {
5796 size
= sec
->data_ptr
- sec
->data
;
5797 fwrite(sec
->data
, 1, size
, f
);
5800 while (offset
< ehdr
.e_shoff
) {
5804 fwrite(shdr
, 1, shnum
* sizeof(Elf32_Shdr
), f
);
5808 /* print the position in the source file of PC value 'pc' by reading
5809 the stabs debug information */
5810 static void rt_printline(unsigned long wanted_pc
)
5812 Stab_Sym
*sym
, *sym_end
;
5813 char func_name
[128];
5814 unsigned long func_addr
, last_pc
, pc
;
5815 const char *incl_files
[INCLUDE_STACK_SIZE
];
5816 int incl_index
, len
, last_line_num
, i
;
5817 const char *str
, *p
;
5819 func_name
[0] = '\0';
5822 last_pc
= 0xffffffff;
5824 sym
= (Stab_Sym
*)stab_section
->data
+ 1;
5825 sym_end
= (Stab_Sym
*)stab_section
->data_ptr
;
5826 while (sym
< sym_end
) {
5827 switch(sym
->n_type
) {
5828 /* function start or end */
5830 if (sym
->n_strx
== 0) {
5831 func_name
[0] = '\0';
5834 str
= stabstr_section
->data
+ sym
->n_strx
;
5835 p
= strchr(str
, ':');
5837 pstrcpy(func_name
, sizeof(func_name
), str
);
5840 if (len
> sizeof(func_name
) - 1)
5841 len
= sizeof(func_name
) - 1;
5842 memcpy(func_name
, str
, len
);
5843 func_name
[len
] = '\0';
5845 func_addr
= sym
->n_value
;
5848 /* line number info */
5850 pc
= sym
->n_value
+ func_addr
;
5851 if (wanted_pc
>= last_pc
&& wanted_pc
< pc
)
5854 last_line_num
= sym
->n_desc
;
5858 str
= stabstr_section
->data
+ sym
->n_strx
;
5860 if (incl_index
< INCLUDE_STACK_SIZE
) {
5861 incl_files
[incl_index
++] = str
;
5869 if (sym
->n_strx
== 0) {
5870 incl_index
= 0; /* end of translation unit */
5872 str
= stabstr_section
->data
+ sym
->n_strx
;
5873 /* do not add path */
5875 if (len
> 0 && str
[len
- 1] != '/')
5882 /* did not find line number info: */
5883 fprintf(stderr
, "(no debug info, pc=0x%08lx): ", wanted_pc
);
5886 for(i
= 0; i
< incl_index
- 1; i
++)
5887 fprintf(stderr
, "In file included from %s\n",
5889 if (incl_index
> 0) {
5890 fprintf(stderr
, "%s:%d: ",
5891 incl_files
[incl_index
- 1], last_line_num
);
5893 if (func_name
[0] != '\0') {
5894 fprintf(stderr
, "in function '%s()': ", func_name
);
5899 /* signal handler for fatal errors */
5900 static void sig_error(int signum
, siginfo_t
*siginf
, void *puc
)
5902 struct ucontext
*uc
= puc
;
5906 pc
= uc
->uc_mcontext
.gregs
[14];
5908 #error please put the right sigcontext field
5915 switch(siginf
->si_code
) {
5918 fprintf(stderr
, "division by zero\n");
5921 fprintf(stderr
, "floating point exception\n");
5927 fprintf(stderr
, "dereferencing invalid pointer\n");
5930 fprintf(stderr
, "illegal instruction\n");
5933 fprintf(stderr
, "abort() called\n");
5936 fprintf(stderr
, "caught signal %d\n", signum
);
5942 /* launch the compiled program with the given arguments */
5943 int launch_exe(int argc
, char **argv
)
5947 struct sigaction sigact
;
5949 s
= sym_find1(&extern_stack
, TOK_MAIN
);
5950 if (!s
|| (s
->r
& VT_FORWARD
))
5951 error("main() not defined");
5954 /* install TCC signal handlers to print debug info on fatal
5956 sigact
.sa_flags
= SA_SIGINFO
| SA_ONESHOT
;
5957 sigact
.sa_sigaction
= sig_error
;
5958 sigemptyset(&sigact
.sa_mask
);
5959 sigaction(SIGFPE
, &sigact
, NULL
);
5960 sigaction(SIGILL
, &sigact
, NULL
);
5961 sigaction(SIGSEGV
, &sigact
, NULL
);
5962 sigaction(SIGBUS
, &sigact
, NULL
);
5963 sigaction(SIGABRT
, &sigact
, NULL
);
5966 if (do_bounds_check
) {
5969 /* add all known static regions */
5970 p
= (int *)bounds_section
->data
;
5971 p_end
= (int *)bounds_section
->data_ptr
;
5973 __bound_new_region((void *)p
[0], p
[1]);
5978 t
= (int (*)())s
->c
;
5979 return (*t
)(argc
, argv
);
5985 printf("tcc version 0.9.3 - Tiny C Compiler - Copyright (C) 2001, 2002 Fabrice Bellard\n"
5986 "usage: tcc [-Idir] [-Dsym[=val]] [-Usym] [-llib] [-g] [-b]\n"
5987 " [-i infile] infile [infile_args...]\n"
5989 "-Idir : add include path 'dir'\n"
5990 "-Dsym[=val] : define 'sym' with value 'val'\n"
5991 "-Usym : undefine 'sym'\n"
5992 "-llib : link with dynamic library 'lib'\n"
5993 "-g : generate runtime debug info\n"
5994 "-b : compile with built-in memory and bounds checker (implies -g)\n"
5995 "-i infile : compile infile\n"
5999 int main(int argc
, char **argv
)
6001 char *p
, *r
, *outfile
;
6004 include_paths
[0] = "/usr/include";
6005 include_paths
[1] = "/usr/lib/tcc";
6006 include_paths
[2] = "/usr/local/lib/tcc";
6007 nb_include_paths
= 3;
6009 /* add all tokens */
6010 tok_ident
= TOK_IDENT
;
6011 p
= "int\0void\0char\0if\0else\0while\0break\0return\0for\0extern\0static\0unsigned\0goto\0do\0continue\0switch\0case\0const\0volatile\0long\0register\0signed\0auto\0inline\0restrict\0float\0double\0_Bool\0short\0struct\0union\0typedef\0default\0enum\0sizeof\0__attribute__\0define\0include\0ifdef\0ifndef\0elif\0endif\0defined\0undef\0error\0line\0__LINE__\0__FILE__\0__DATE__\0__TIME__\0__VA_ARGS__\0__func__\0main\0section\0__section__\0aligned\0__aligned__\0unused\0__unused__\0";
6015 tok_alloc(p
, r
- p
- 1);
6019 /* standard defines */
6020 define_symbol("__STDC__");
6022 define_symbol("__i386__");
6024 /* tiny C specific defines */
6025 define_symbol("__TINYC__");
6027 /* create standard sections */
6028 text_section
= new_section(".text", SHT_PROGBITS
, SHF_ALLOC
| SHF_EXECINSTR
);
6029 data_section
= new_section(".data", SHT_PROGBITS
, SHF_ALLOC
| SHF_WRITE
);
6030 /* XXX: should change type to SHT_NOBITS */
6031 bss_section
= new_section(".bss", SHT_PROGBITS
, SHF_ALLOC
| SHF_WRITE
);
6036 if (optind
>= argc
) {
6046 if (nb_include_paths
>= INCLUDE_PATHS_MAX
)
6047 error("too many include paths");
6048 include_paths
[nb_include_paths
++] = r
+ 2;
6049 } else if (r
[1] == 'D') {
6050 define_symbol(r
+ 2);
6051 } else if (r
[1] == 'U') {
6052 undef_symbol(r
+ 2);
6053 } else if (r
[1] == 'l') {
6055 } else if (r
[1] == 'i') {
6058 tcc_compile_file(argv
[optind
++]);
6059 } else if (r
[1] == 'b') {
6060 if (!do_bounds_check
) {
6061 do_bounds_check
= 1;
6062 /* create bounds section for global data */
6063 bounds_section
= new_section(".bounds",
6064 SHT_PROGBITS
, SHF_ALLOC
);
6065 /* debug is implied */
6068 } else if (r
[1] == 'g') {
6074 stab_section
= new_section(".stab", SHT_PROGBITS
, 0);
6075 stab_section
->sh_entsize
= sizeof(Stab_Sym
);
6076 stabstr_section
= new_section(".stabstr", SHT_STRTAB
, 0);
6077 put_elf_str(stabstr_section
, "");
6078 stab_section
->link
= stabstr_section
;
6079 /* put first entry */
6080 put_stabs("", 0, 0, 0, 0);
6083 symtab_section
= new_section(".symtab", SHT_SYMTAB
, 0);
6084 symtab_section
->sh_entsize
= sizeof(Elf32_Sym
);
6085 strtab_section
= new_section(".strtab", SHT_STRTAB
, 0);
6086 put_elf_str(strtab_section
, "");
6087 symtab_section
->link
= strtab_section
;
6088 put_elf_sym(symtab_section
, 0, 0, 0, 0, 0, NULL
);
6090 } else if (r
[1] == 'o') {
6091 /* currently, only for testing, so not documented */
6094 outfile
= argv
[optind
++];
6096 fprintf(stderr
, "invalid option -- '%s'\n", r
);
6101 tcc_compile_file(argv
[optind
]);
6103 resolve_extern_syms();
6109 return launch_exe(argc
- optind
, argv
+ optind
);