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>
32 #ifndef CONFIG_TCC_STATIC
37 /* preprocessor debug */
40 /* amount of virtual memory associate to a section (currently, we do
42 #define SECTION_VSIZE (1024 * 1024)
44 #define INCLUDE_STACK_SIZE 32
45 #define IFDEF_STACK_SIZE 64
46 #define VSTACK_SIZE 64
47 #define STRING_MAX_SIZE 1024
48 #define INCLUDE_PATHS_MAX 32
50 #define TOK_HASH_SIZE 521
51 #define TOK_ALLOC_INCR 256 /* must be a power of two */
52 #define SYM_HASH_SIZE 263
54 /* token symbol management */
55 typedef struct TokenSym
{
56 struct TokenSym
*hash_next
;
57 int tok
; /* token number */
63 typedef union CValue
{
69 unsigned int ul
; /* address (should be unsigned long on 64 bit cpu) */
71 unsigned long long ull
;
78 typedef struct SValue
{
80 unsigned short r
; /* register + flags */
81 unsigned short r2
; /* second register, used for 'long long'
82 type. If not used, set to VT_CONST */
83 CValue c
; /* constant */
86 /* symbol management */
88 int v
; /* symbol token */
89 int t
; /* associated type */
90 int r
; /* associated register */
91 int c
; /* associated number */
92 struct Sym
*next
; /* next related symbol */
93 struct Sym
*prev
; /* prev symbol in stack */
94 struct Sym
*hash_next
; /* next symbol in hash table */
97 typedef struct SymStack
{
99 struct Sym
*hash
[SYM_HASH_SIZE
];
102 /* relocation entry (currently only used for functions or variables */
103 typedef struct Reloc
{
104 int type
; /* type of relocation */
105 int addr
; /* address of relocation */
106 struct Reloc
*next
; /* next relocation */
109 #define RELOC_ADDR32 1 /* 32 bits relocation */
110 #define RELOC_REL32 2 /* 32 bits relative relocation */
112 /* section definition */
113 typedef struct Section
{
114 char name
[64]; /* section name */
115 unsigned char *data
; /* section data */
116 unsigned char *data_ptr
; /* current data pointer */
117 int sh_num
; /* elf section number */
118 int sh_type
; /* elf section type */
119 int sh_flags
; /* elf section flags */
120 int sh_entsize
; /* elf entry size */
121 struct Section
*link
; /* link to another section */
122 struct Section
*next
;
125 /* GNUC attribute definition */
126 typedef struct AttributeDef
{
131 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
132 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
133 #define SYM_FIRST_ANOM (1 << (31 - VT_STRUCT_SHIFT)) /* first anonymous sym */
135 #define FUNC_NEW 1 /* ansi function prototype */
136 #define FUNC_OLD 2 /* old function prototype */
137 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
139 /* field 'Sym.t' for macros */
140 #define MACRO_OBJ 0 /* object like macro */
141 #define MACRO_FUNC 1 /* function like macro */
143 /* type_decl() types */
144 #define TYPE_ABSTRACT 1 /* type without variable */
145 #define TYPE_DIRECT 2 /* type with variable */
156 int ch
, ch1
, tok
, tok1
;
160 Section
*first_section
;
162 Section
*text_section
, *data_section
, *bss_section
; /* predefined sections */
163 Section
*cur_text_section
; /* current section where function code is
165 Section
*bounds_section
; /* contains global data bound description */
167 Section
*stab_section
, *stabstr_section
, *symtab_section
, *strtab_section
;
169 /* loc : local variable index
170 ind : output code index
172 anon_sym: anonymous symbol index
175 prog
, ind
, loc
, const_wanted
;
176 int global_expr
; /* true if compound literals must be allocated
177 globally (used during initializers parsing */
178 int func_vt
, func_vc
; /* current function return type (used by
179 return instruction) */
180 int last_line_num
, last_ind
, func_ind
; /* debug last line number and pc */
182 TokenSym
**table_ident
;
183 TokenSym
*hash_ident
[TOK_HASH_SIZE
];
184 char token_buf
[STRING_MAX_SIZE
+ 1];
185 char *filename
, *funcname
;
186 /* contains global symbols which remain between each translation unit */
187 SymStack extern_stack
;
188 SymStack define_stack
, global_stack
, local_stack
, label_stack
;
190 SValue vstack
[VSTACK_SIZE
], *vtop
;
191 int *macro_ptr
, *macro_ptr_allocated
;
192 IncludeFile include_stack
[INCLUDE_STACK_SIZE
], *include_stack_ptr
;
193 int ifdef_stack
[IFDEF_STACK_SIZE
], *ifdef_stack_ptr
;
194 char *include_paths
[INCLUDE_PATHS_MAX
];
195 int nb_include_paths
;
196 int char_pointer_type
;
198 /* compile with debug symbol (and use them if error during execution) */
201 /* compile with built-in memory and bounds checker */
202 int do_bounds_check
= 0;
204 /* use GNU C extensions */
207 /* use Tiny C extensions */
210 /* The current value can be: */
211 #define VT_VALMASK 0x00ff
212 #define VT_CONST 0x00f0 /* constant in vc
213 (must be first non register value) */
214 #define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */
215 #define VT_LOCAL 0x00f2 /* offset on stack */
216 #define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */
217 #define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */
218 #define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */
219 #define VT_LVAL 0x0100 /* var is an lvalue */
220 #define VT_FORWARD 0x0200 /* value is forward reference */
221 #define VT_MUSTCAST 0x0400 /* value must be casted to be correct (user for
222 bool/char/short stored in int registers) */
225 #define VT_STRUCT_SHIFT 16 /* structure/enum name shift (16 bits left) */
227 #define VT_INT 0 /* integer type */
228 #define VT_BYTE 1 /* signed byte type */
229 #define VT_SHORT 2 /* short type */
230 #define VT_VOID 3 /* void type */
231 #define VT_PTR 4 /* pointer increment */
232 #define VT_ENUM 5 /* enum definition */
233 #define VT_FUNC 6 /* function type */
234 #define VT_STRUCT 7 /* struct/union definition */
235 #define VT_FLOAT 8 /* IEEE float */
236 #define VT_DOUBLE 9 /* IEEE double */
237 #define VT_LDOUBLE 10 /* IEEE long double */
238 #define VT_BOOL 11 /* ISOC99 boolean type */
239 #define VT_LLONG 12 /* 64 bit integer */
240 #define VT_LONG 13 /* long integer (NEVER USED as type, only
242 #define VT_BTYPE 0x000f /* mask for basic type */
243 #define VT_UNSIGNED 0x0010 /* unsigned type */
244 #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
245 #define VT_BITFIELD 0x0040 /* bitfield modifier */
248 #define VT_EXTERN 0x00000080 /* extern definition */
249 #define VT_STATIC 0x00000100 /* static variable */
250 #define VT_TYPEDEF 0x00000200 /* typedef definition */
252 /* type mask (except storage) */
253 #define VT_TYPE (~(VT_EXTERN | VT_STATIC | VT_TYPEDEF))
257 /* warning: the following compare tokens depend on i386 asm code */
269 #define TOK_LAND 0xa0
273 #define TOK_MID 0xa3 /* inc/dec, to void constant */
275 #define TOK_UDIV 0xb0 /* unsigned division */
276 #define TOK_UMOD 0xb1 /* unsigned modulo */
277 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
278 #define TOK_CINT 0xb3 /* number in tokc */
279 #define TOK_CCHAR 0xb4 /* char constant in tokc */
280 #define TOK_STR 0xb5 /* pointer to string in tokc */
281 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
282 #define TOK_LCHAR 0xb7
283 #define TOK_LSTR 0xb8
284 #define TOK_CFLOAT 0xb9 /* float constant */
285 #define TOK_CDOUBLE 0xc0 /* double constant */
286 #define TOK_CLDOUBLE 0xc1 /* long double constant */
287 #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
288 #define TOK_ADDC1 0xc3 /* add with carry generation */
289 #define TOK_ADDC2 0xc4 /* add with carry use */
290 #define TOK_SUBC1 0xc5 /* add with carry generation */
291 #define TOK_SUBC2 0xc6 /* add with carry use */
292 #define TOK_CUINT 0xc8 /* unsigned int constant */
293 #define TOK_CLLONG 0xc9 /* long long constant */
294 #define TOK_CULLONG 0xca /* unsigned long long constant */
295 #define TOK_ARROW 0xcb
296 #define TOK_DOTS 0xcc /* three dots */
297 #define TOK_SHR 0xcd /* unsigned shift right */
299 #define TOK_SHL 0x01 /* shift left */
300 #define TOK_SAR 0x02 /* signed shift right */
302 /* assignement operators : normal operator or 0x80 */
303 #define TOK_A_MOD 0xa5
304 #define TOK_A_AND 0xa6
305 #define TOK_A_MUL 0xaa
306 #define TOK_A_ADD 0xab
307 #define TOK_A_SUB 0xad
308 #define TOK_A_DIV 0xaf
309 #define TOK_A_XOR 0xde
310 #define TOK_A_OR 0xfc
311 #define TOK_A_SHL 0x81
312 #define TOK_A_SAR 0x82
314 /* all identificators and strings have token above that */
315 #define TOK_IDENT 256
336 /* ignored types Must have contiguous values */
346 /* unsupported type */
360 /* preprocessor only */
361 TOK_UIDENT
, /* first "user" ident (not keyword) */
362 TOK_DEFINE
= TOK_UIDENT
,
378 /* special identifiers */
381 /* attribute identifiers */
390 /* XXX: need to define this to use them in non ISOC99 context */
391 extern float strtof (const char *__nptr
, char **__endptr
);
392 extern long double strtold (const char *__nptr
, char **__endptr
);
396 void next_nomacro(void);
397 int expr_const(void);
401 void decl_initializer(int t
, int r
, int c
, int first
, int size_only
);
402 int decl_initializer_alloc(int t
, AttributeDef
*ad
, int r
, int has_init
);
404 void move_reg(int r
, int s
);
405 void save_regs(void);
406 void save_reg(int r
);
412 void macro_subst(int **tok_str
, int *tok_len
,
413 Sym
**nested_list
, int *macro_str
);
414 int save_reg_forced(int r
);
416 void force_charshort_cast(int t
);
417 void gen_cast(int t
);
419 Sym
*sym_find(int v
);
420 Sym
*sym_push(int v
, int t
, int r
, int c
);
423 int type_size(int t
, int *a
);
424 int pointed_type(int t
);
425 int pointed_size(int t
);
426 int is_compatible_types(int t1
, int t2
);
427 int parse_btype(int *type_ptr
, AttributeDef
*ad
);
428 int type_decl(int *v
, int t
, int td
);
430 void error(const char *fmt
, ...);
432 void vset(int t
, int r
, int v
);
433 void type_to_str(char *buf
, int buf_size
,
434 int t
, const char *varstr
);
436 /* section generation */
437 void greloc(Sym
*s
, int addr
, int type
);
438 static int put_elf_str(Section
*s
, const char *sym
);
439 static void put_elf_sym(Section
*s
,
440 unsigned long value
, unsigned long size
,
441 int info
, int other
, int shndx
, const char *name
);
442 static void put_stabs(const char *str
, int type
, int other
, int desc
, int value
);
443 static void put_stabn(int type
, int other
, int desc
, int value
);
444 static void put_stabd(int type
, int other
, int desc
);
446 /* true if float/double/long double type */
447 static inline int is_float(int t
)
451 return bt
== VT_LDOUBLE
|| bt
== VT_DOUBLE
|| bt
== VT_FLOAT
;
456 #include "i386-gen.c"
458 #ifdef CONFIG_TCC_STATIC
460 #define RTLD_LAZY 0x001
461 #define RTLD_NOW 0x002
462 #define RTLD_GLOBAL 0x100
464 /* dummy function for profiling */
465 void *dlopen(const char *filename
, int flag
)
470 const char *dlerror(void)
475 typedef struct TCCSyms
{
480 #define TCCSYM(a) { #a, &a, },
482 /* add the symbol you want here if no dynamic linking is done */
483 static TCCSyms tcc_syms
[] = {
491 void *dlsym(void *handle
, char *symbol
)
495 while (p
->str
!= NULL
) {
496 if (!strcmp(p
->str
, symbol
))
505 /********************************************************/
506 /* runtime library is there */
507 /* XXX: we suppose that the host compiler handles 'long long'. It
508 would not be difficult to suppress this assumption */
510 /* XXX: these functions are defined in libgcc. Should provide a
511 portable code too. */
512 long long __divll(long long a
, long long b
)
517 long long __modll(long long a
, long long b
)
522 unsigned long long __divull(unsigned long long a
, unsigned long long b
)
527 unsigned long long __modull(unsigned long long a
, unsigned long long b
)
532 long long __sardi3(long long a
, int b
)
537 unsigned long long __shrdi3(unsigned long long a
, int b
)
542 long long __shldi3(long long a
, int b
)
547 float __ulltof(unsigned long long a
)
552 double __ulltod(unsigned long long a
)
557 long double __ulltold(unsigned long long a
)
559 return (long double)a
;
562 unsigned long long __ftoull(float a
)
564 return (unsigned long long)a
;
567 unsigned long long __dtoull(double a
)
569 return (unsigned long long)a
;
572 unsigned long long __ldtoull(long double a
)
574 return (unsigned long long)a
;
578 /********************************************************/
580 /* copy a string and truncate it */
581 char *pstrcpy(char *buf
, int buf_size
, const char *s
)
587 q_end
= buf
+ buf_size
- 1;
598 /* strcat and truncate */
599 char *pstrcat(char *buf
, int buf_size
, const char *s
)
604 pstrcpy(buf
+ len
, buf_size
- len
, s
);
608 Section
*new_section(const char *name
, int sh_type
, int sh_flags
)
610 Section
*sec
, **psec
;
613 sec
= malloc(sizeof(Section
));
615 error("memory full");
616 memset(sec
, 0, sizeof(Section
));
617 pstrcpy(sec
->name
, sizeof(sec
->name
), name
);
619 sec
->sh_num
= ++section_num
;
620 sec
->sh_type
= sh_type
;
621 sec
->sh_flags
= sh_flags
;
622 data
= mmap(NULL
, SECTION_VSIZE
,
623 PROT_EXEC
| PROT_READ
| PROT_WRITE
,
624 MAP_PRIVATE
| MAP_ANONYMOUS
,
626 if (data
== (void *)(-1))
627 error("could not mmap section '%s'", name
);
629 sec
->data_ptr
= data
;
630 psec
= &first_section
;
631 while (*psec
!= NULL
)
632 psec
= &(*psec
)->next
;
638 /* return a reference to a section, and create it if it does not
640 Section
*find_section(const char *name
)
644 for(sec
= first_section
; sec
!= NULL
; sec
= sec
->next
) {
645 if (!strcmp(name
, sec
->name
))
648 /* sections are created as PROGBITS */
649 return new_section(name
, SHT_PROGBITS
, SHF_ALLOC
);
652 /* add a new relocation entry to symbol 's' */
653 void greloc(Sym
*s
, int addr
, int type
)
656 p
= malloc(sizeof(Reloc
));
658 error("memory full");
661 p
->next
= (Reloc
*)s
->c
;
665 /* patch each relocation entry with value 'val' */
666 void greloc_patch(Sym
*s
, int val
)
673 greloc_patch1(p
, val
);
682 static inline int isid(int c
)
684 return (c
>= 'a' && c
<= 'z') ||
685 (c
>= 'A' && c
<= 'Z') ||
689 static inline int isnum(int c
)
691 return c
>= '0' && c
<= '9';
694 static inline int toup(int c
)
696 if (ch
>= 'a' && ch
<= 'z')
697 return ch
- 'a' + 'A';
705 for(f
= include_stack
; f
< include_stack_ptr
; f
++)
706 fprintf(stderr
, "In file included from %s:%d:\n",
707 f
->filename
, f
->line_num
);
708 fprintf(stderr
, "%s:%d: ", filename
, line_num
);
711 void error(const char *fmt
, ...)
716 vfprintf(stderr
, fmt
, ap
);
717 fprintf(stderr
, "\n");
722 void expect(const char *msg
)
724 error("%s expected", msg
);
727 void warning(const char *fmt
, ...)
733 fprintf(stderr
, "warning: ");
734 vfprintf(stderr
, fmt
, ap
);
735 fprintf(stderr
, "\n");
742 error("'%c' expected", c
);
746 void test_lvalue(void)
748 if (!(vtop
->r
& VT_LVAL
))
752 TokenSym
*tok_alloc(const char *str
, int len
)
754 TokenSym
*ts
, **pts
, **ptable
;
761 h
= ((h
<< 8) | (str
[i
] & 0xff)) % TOK_HASH_SIZE
;
763 pts
= &hash_ident
[h
];
768 if (ts
->len
== len
&& !memcmp(ts
->str
, str
, len
))
770 pts
= &(ts
->hash_next
);
773 if (tok_ident
>= SYM_FIRST_ANOM
)
774 error("memory full");
776 /* expand token table if needed */
777 i
= tok_ident
- TOK_IDENT
;
778 if ((i
% TOK_ALLOC_INCR
) == 0) {
779 ptable
= realloc(table_ident
, (i
+ TOK_ALLOC_INCR
) * sizeof(TokenSym
*));
781 error("memory full");
782 table_ident
= ptable
;
785 ts
= malloc(sizeof(TokenSym
) + len
);
787 error("memory full");
789 ts
->tok
= tok_ident
++;
791 ts
->hash_next
= NULL
;
792 memcpy(ts
->str
, str
, len
+ 1);
797 void add_char(char **pp
, int c
)
801 if (c
== '\'' || c
== '\"' || c
== '\\') {
802 /* XXX: could be more precise if char or string */
805 if (c
>= 32 && c
<= 126) {
812 *p
++ = '0' + ((c
>> 6) & 7);
813 *p
++ = '0' + ((c
>> 3) & 7);
814 *p
++ = '0' + (c
& 7);
820 /* XXX: buffer overflow */
821 char *get_tok_str(int v
, CValue
*cv
)
823 static char buf
[STRING_MAX_SIZE
+ 1];
828 if (v
== TOK_CINT
|| v
== TOK_CUINT
) {
829 sprintf(buf
, "%u", cv
->ui
);
831 } else if (v
== TOK_CCHAR
|| v
== TOK_LCHAR
) {
838 } else if (v
== TOK_STR
|| v
== TOK_LSTR
) {
842 for(i
=0;i
<ts
->len
;i
++)
843 add_char(&p
, ts
->str
[i
]);
847 } else if (v
< TOK_IDENT
) {
852 } else if (v
< tok_ident
) {
853 return table_ident
[v
- TOK_IDENT
]->str
;
855 /* should never happen */
860 /* push, without hashing */
861 Sym
*sym_push2(Sym
**ps
, int v
, int t
, int c
)
864 s
= malloc(sizeof(Sym
));
866 error("memory full");
877 /* find a symbol and return its associated structure. 's' is the top
878 of the symbol stack */
879 Sym
*sym_find2(Sym
*s
, int v
)
889 #define HASH_SYM(v) ((unsigned)(v) % SYM_HASH_SIZE)
891 /* find a symbol and return its associated structure. 'st' is the
893 Sym
*sym_find1(SymStack
*st
, int v
)
897 s
= st
->hash
[HASH_SYM(v
)];
906 Sym
*sym_push1(SymStack
*st
, int v
, int t
, int c
)
909 s
= sym_push2(&st
->top
, v
, t
, c
);
910 /* add in hash table */
912 ps
= &st
->hash
[HASH_SYM(v
)];
919 /* find a symbol in the right symbol space */
923 s
= sym_find1(&local_stack
, v
);
925 s
= sym_find1(&global_stack
, v
);
929 /* push a given symbol on the symbol stack */
930 Sym
*sym_push(int v
, int t
, int r
, int c
)
934 s
= sym_push1(&local_stack
, v
, t
, c
);
936 s
= sym_push1(&global_stack
, v
, t
, c
);
941 /* pop symbols until top reaches 'b' */
942 void sym_pop(SymStack
*st
, Sym
*b
)
949 /* free hash table entry, except if symbol was freed (only
950 used for #undef symbols) */
952 st
->hash
[HASH_SYM(s
->v
)] = s
->hash_next
;
959 /* undefined a hashed symbol (used for #undef). Its name is set to
961 void sym_undef(SymStack
*st
, Sym
*s
)
964 ss
= &st
->hash
[HASH_SYM(s
->v
)];
965 while (*ss
!= NULL
) {
968 ss
= &(*ss
)->hash_next
;
974 /* no need to put that inline */
977 if (include_stack_ptr
== include_stack
)
979 /* add end of include file debug info */
981 put_stabd(N_EINCL
, 0, 0);
983 /* pop include stack */
987 file
= include_stack_ptr
->file
;
988 filename
= include_stack_ptr
->filename
;
989 line_num
= include_stack_ptr
->line_num
;
993 /* read next char from current input file */
994 static inline void inp(void)
997 /* faster than fgetc */
998 ch1
= getc_unlocked(file
);
1000 if (handle_eof() < 0)
1007 // printf("ch1=%c 0x%x\n", ch1, ch1);
1010 /* input with '\\n' handling */
1011 static inline void minp(void)
1016 if (ch
== '\\' && ch1
== '\n') {
1020 //printf("ch=%c 0x%x\n", ch, ch);
1024 /* same as minp, but also skip comments */
1032 /* single line C++ comments */
1034 while (ch1
!= '\n' && ch1
!= -1)
1037 ch
= ' '; /* return space */
1038 } else if (ch1
== '*') {
1044 if (c
== '*' && ch1
== '/') {
1046 ch
= ' '; /* return space */
1058 void skip_spaces(void)
1060 while (ch
== ' ' || ch
== '\t')
1064 /* skip block of text until #else, #elif or #endif. skip also pairs of
1066 void preprocess_skip()
1071 while (ch
!= '\n') {
1082 (tok
== TOK_ELSE
|| tok
== TOK_ELIF
|| tok
== TOK_ENDIF
))
1084 if (tok
== TOK_IF
|| tok
== TOK_IFDEF
|| tok
== TOK_IFNDEF
)
1086 else if (tok
== TOK_ENDIF
)
1092 /* return the number of additionnal 'ints' necessary to store the
1094 static inline int tok_ext_size(int t
)
1111 return LDOUBLE_SIZE
/ 4;
1117 void tok_add(int **tok_str
, int *tok_len
, int t
)
1122 if ((len
& 63) == 0) {
1123 str
= realloc(str
, (len
+ 64) * sizeof(int));
1132 void tok_add2(int **tok_str
, int *tok_len
, int t
, CValue
*cv
)
1136 tok_add(tok_str
, tok_len
, t
);
1137 n
= tok_ext_size(t
);
1139 tok_add(tok_str
, tok_len
, cv
->tab
[i
]);
1142 /* get a token from an integer array and increment pointer accordingly */
1143 int tok_get(int **tok_str
, CValue
*cv
)
1149 n
= tok_ext_size(t
);
1156 /* eval an expression for #if/#elif */
1157 int expr_preprocess(void)
1159 int *str
, len
, c
, t
;
1167 next(); /* do macro subst */
1168 if (tok
== TOK_DEFINED
) {
1173 c
= sym_find1(&define_stack
, tok
) != 0;
1178 } else if (tok
>= TOK_IDENT
) {
1179 /* if undefined macro */
1183 tok_add2(&str
, &len
, tok
, &tokc
);
1185 tok_add(&str
, &len
, -1); /* simulate end of file */
1186 tok_add(&str
, &len
, 0);
1187 /* now evaluate C constant expression */
1197 void tok_print(int *str
)
1203 t
= tok_get(&str
, &cval
);
1206 printf(" %s", get_tok_str(t
, &cval
));
1212 void preprocess(void)
1214 int size
, i
, c
, v
, t
, *str
, len
;
1215 char buf
[1024], *q
, *p
;
1218 Sym
**ps
, *first
, *s
;
1223 if (tok
== TOK_DEFINE
) {
1226 /* XXX: should check if same macro (ANSI) */
1229 /* '(' must be just after macro definition for MACRO_FUNC */
1234 while (tok
!= ')') {
1235 if (tok
== TOK_DOTS
)
1236 tok
= TOK___VA_ARGS__
;
1237 s
= sym_push1(&define_stack
, tok
| SYM_FIELD
, 0, 0);
1251 if (ch
== '\n' || ch
== -1)
1254 tok_add2(&str
, &len
, tok
, &tokc
);
1256 tok_add(&str
, &len
, 0);
1258 printf("define %s %d: ", get_tok_str(v
, NULL
), t
);
1261 s
= sym_push1(&define_stack
, v
, t
, (int)str
);
1263 } else if (tok
== TOK_UNDEF
) {
1265 s
= sym_find1(&define_stack
, tok
);
1266 /* undefine symbol by putting an invalid name */
1268 sym_undef(&define_stack
, s
);
1269 } else if (tok
== TOK_INCLUDE
) {
1274 } else if (ch
== '\"') {
1279 while (ch
!= c
&& ch
!= '\n' && ch
!= -1) {
1280 if ((q
- buf
) < sizeof(buf
) - 1)
1288 error("#include syntax error");
1289 pstrcpy(buf
, sizeof(buf
), get_tok_str(tok
, &tokc
));
1292 /* eat all spaces and comments after include */
1293 /* XXX: slightly incorrect */
1294 while (ch1
!= '\n' && ch1
!= -1)
1297 if (include_stack_ptr
>= include_stack
+ INCLUDE_STACK_SIZE
)
1298 error("memory full");
1300 /* first search in current dir if "header.h" */
1302 p
= strrchr(filename
, '/');
1304 size
= p
+ 1 - filename
;
1305 if (size
> sizeof(buf1
) - 1)
1306 size
= sizeof(buf1
) - 1;
1307 memcpy(buf1
, filename
, size
);
1309 pstrcat(buf1
, sizeof(buf1
), buf
);
1310 f
= fopen(buf1
, "r");
1314 /* now search in standard include path */
1315 for(i
=nb_include_paths
- 1;i
>=0;i
--) {
1316 strcpy(buf1
, include_paths
[i
]);
1319 f
= fopen(buf1
, "r");
1323 error("include file '%s' not found", buf1
);
1326 /* push current file in stack */
1327 /* XXX: fix current line init */
1328 include_stack_ptr
->file
= file
;
1329 include_stack_ptr
->filename
= filename
;
1330 include_stack_ptr
->line_num
= line_num
;
1331 include_stack_ptr
++;
1333 filename
= strdup(buf1
);
1335 /* add include file debug info */
1337 put_stabs(filename
, N_BINCL
, 0, 0, 0);
1339 } else if (tok
== TOK_IFNDEF
) {
1342 } else if (tok
== TOK_IF
) {
1343 c
= expr_preprocess();
1345 } else if (tok
== TOK_IFDEF
) {
1349 c
= (sym_find1(&define_stack
, tok
) != 0) ^ c
;
1351 if (ifdef_stack_ptr
>= ifdef_stack
+ IFDEF_STACK_SIZE
)
1352 error("memory full");
1353 *ifdef_stack_ptr
++ = c
;
1355 } else if (tok
== TOK_ELSE
) {
1356 if (ifdef_stack_ptr
== ifdef_stack
||
1357 (ifdef_stack_ptr
[-1] & 2))
1358 error("#else after #else");
1359 c
= (ifdef_stack_ptr
[-1] ^= 3);
1361 } else if (tok
== TOK_ELIF
) {
1362 if (ifdef_stack_ptr
== ifdef_stack
||
1363 ifdef_stack_ptr
[-1] > 1)
1364 error("#elif after #else");
1365 c
= expr_preprocess();
1366 ifdef_stack_ptr
[-1] = c
;
1372 } else if (tok
== TOK_ENDIF
) {
1373 if (ifdef_stack_ptr
== ifdef_stack
)
1376 } else if (tok
== TOK_LINE
) {
1378 if (tok
!= TOK_CINT
)
1386 /* XXX: potential memory leak */
1387 filename
= strdup(get_tok_str(tok
, &tokc
));
1389 } else if (tok
== TOK_ERROR
) {
1392 /* ignore other preprocess commands or #! for C scripts */
1393 while (ch
!= '\n' && ch
!= -1)
1397 /* read a number in base b */
1403 if (ch
>= 'a' && ch
<= 'f')
1405 else if (ch
>= 'A' && ch
<= 'F')
1411 if (t
< 0 || t
>= b
)
1419 /* read a character for string or char constant and eval escape codes */
1428 /* at most three octal digits */
1432 c
= c
* 8 + ch
- '0';
1435 c
= c
* 8 + ch
- '0';
1440 } else if (ch
== 'x') {
1458 else if (ch
== 'e' && gnu_ext
)
1460 else if (ch
== '\'' || ch
== '\"' || ch
== '\\' || ch
== '?')
1463 error("invalid escaped char");
1470 /* we use 64 bit numbers */
1473 /* bn = (bn << shift) | or_val */
1474 void bn_lshift(unsigned int *bn
, int shift
, int or_val
)
1478 for(i
=0;i
<BN_SIZE
;i
++) {
1480 bn
[i
] = (v
<< shift
) | or_val
;
1481 or_val
= v
>> (32 - shift
);
1485 void bn_zero(unsigned int *bn
)
1488 for(i
=0;i
<BN_SIZE
;i
++) {
1493 void parse_number(void)
1495 int b
, t
, shift
, frac_bits
, s
, exp_val
;
1497 unsigned int bn
[BN_SIZE
];
1507 /* special dot handling */
1508 if (ch
>= '0' && ch
<= '9') {
1509 goto float_frac_parse
;
1510 } else if (ch
== '.') {
1521 } else if (t
== '0') {
1522 if (ch
== 'x' || ch
== 'X') {
1526 } else if (tcc_ext
&& (ch
== 'b' || ch
== 'B')) {
1532 /* parse all digits. cannot check octal numbers at this stage
1533 because of floating point constants */
1535 if (ch
>= 'a' && ch
<= 'f')
1537 else if (ch
>= 'A' && ch
<= 'F')
1545 if (q
>= token_buf
+ STRING_MAX_SIZE
) {
1547 error("number too long");
1553 ((ch
== 'e' || ch
== 'E') && b
== 10) ||
1554 ((ch
== 'p' || ch
== 'P') && (b
== 16 || b
== 2))) {
1556 /* NOTE: strtox should support that for hexa numbers, but
1557 non ISOC99 libcs do not support it, so we prefer to do
1559 /* hexadecimal or binary floats */
1560 /* XXX: handle overflows */
1572 } else if (t
>= 'a') {
1574 } else if (t
>= 'A') {
1579 bn_lshift(bn
, shift
, t
);
1586 if (t
>= 'a' && t
<= 'f') {
1588 } else if (t
>= 'A' && t
<= 'F') {
1590 } else if (t
>= '0' && t
<= '9') {
1596 error("invalid digit");
1597 bn_lshift(bn
, shift
, t
);
1602 if (ch
!= 'p' && ch
!= 'P')
1603 error("exponent expected");
1609 } else if (ch
== '-') {
1613 if (ch
< '0' || ch
> '9')
1614 error("exponent digits expected");
1615 while (ch
>= '0' && ch
<= '9') {
1616 exp_val
= exp_val
* 10 + ch
- '0';
1619 exp_val
= exp_val
* s
;
1621 /* now we can generate the number */
1622 /* XXX: should patch directly float number */
1623 d
= (double)bn
[1] * 4294967296.0 + (double)bn
[0];
1624 d
= ldexp(d
, exp_val
- frac_bits
);
1629 /* float : should handle overflow */
1631 } else if (t
== 'L') {
1634 /* XXX: not large enough */
1635 tokc
.ld
= (long double)d
;
1641 /* decimal floats */
1643 if (q
>= token_buf
+ STRING_MAX_SIZE
)
1648 while (ch
>= '0' && ch
<= '9') {
1649 if (q
>= token_buf
+ STRING_MAX_SIZE
)
1655 if (ch
== 'e' || ch
== 'E') {
1656 if (q
>= token_buf
+ STRING_MAX_SIZE
)
1660 if (ch
== '-' || ch
== '+') {
1661 if (q
>= token_buf
+ STRING_MAX_SIZE
)
1666 if (ch
< '0' || ch
> '9')
1667 error("exponent digits expected");
1668 while (ch
>= '0' && ch
<= '9') {
1669 if (q
>= token_buf
+ STRING_MAX_SIZE
)
1681 tokc
.f
= strtof(token_buf
, NULL
);
1682 } else if (t
== 'L') {
1685 tokc
.ld
= strtold(token_buf
, NULL
);
1688 tokc
.d
= strtod(token_buf
, NULL
);
1692 unsigned long long n
, n1
;
1695 /* integer number */
1698 if (b
== 10 && *q
== '0') {
1705 /* no need for checks except for base 10 / 8 errors */
1708 } else if (t
>= 'a') {
1710 } else if (t
>= 'A') {
1715 error("invalid digit");
1719 /* detect overflow */
1721 error("integer constant overflow");
1724 /* XXX: not exactly ANSI compliant */
1725 if ((n
& 0xffffffff00000000LL
) != 0) {
1730 } else if (n
> 0x7fffffff) {
1740 error("three 'l' in integer constant");
1743 if (tok
== TOK_CINT
)
1745 else if (tok
== TOK_CUINT
)
1749 } else if (t
== 'U') {
1750 if (tok
== TOK_CINT
)
1752 else if (tok
== TOK_CLLONG
)
1759 if (tok
== TOK_CINT
|| tok
== TOK_CUINT
)
1767 /* return next token without macro substitution */
1768 void next_nomacro1(void)
1776 while (ch
== '\n') {
1778 while (ch
== ' ' || ch
== 9)
1781 /* preprocessor command if # at start of line after
1786 if (ch
!= ' ' && ch
!= '\t' && ch
!= '\f')
1804 while (isid(ch
) || isnum(ch
)) {
1805 if (q
>= token_buf
+ STRING_MAX_SIZE
)
1806 error("ident too long");
1811 ts
= tok_alloc(token_buf
, q
- token_buf
);
1813 } else if (isnum(ch
) || ch
== '.') {
1815 } else if (ch
== '\'') {
1823 } else if (ch
== '\"') {
1828 while (ch
!= '\"') {
1831 error("unterminated string");
1832 if (q
>= token_buf
+ STRING_MAX_SIZE
)
1833 error("string too long");
1837 tokc
.ts
= tok_alloc(token_buf
, q
- token_buf
);
1840 q
= "<=\236>=\235!=\225&&\240||\241++\244--\242==\224<<\1>>\2+=\253-=\255*=\252/=\257%=\245&=\246^=\336|=\374->\313..\250##\266";
1845 if (*q
== tok
&& q
[1] == ch
) {
1848 /* three chars tests */
1849 if (tok
== TOK_SHL
|| tok
== TOK_SAR
) {
1854 } else if (tok
== TOK_DOTS
) {
1856 error("parse error");
1863 /* single char substitutions */
1866 else if (tok
== '>')
1871 /* return next token without macro substitution. Can read input from
1878 tok
= tok_get(¯o_ptr
, &tokc
);
1884 /* substitute args in macro_str and return allocated string */
1885 int *macro_arg_subst(Sym
**nested_list
, int *macro_str
, Sym
*args
)
1887 int *st
, last_tok
, t
, notfirst
, *str
, len
;
1896 t
= tok_get(¯o_str
, &cval
);
1901 t
= tok_get(¯o_str
, &cval
);
1904 s
= sym_find2(args
, t
);
1906 token_buf
[0] = '\0';
1911 pstrcat(token_buf
, sizeof(token_buf
), " ");
1912 t
= tok_get(&st
, &cval
);
1913 pstrcat(token_buf
, sizeof(token_buf
), get_tok_str(t
, &cval
));
1917 printf("stringize: %s\n", token_buf
);
1920 ts
= tok_alloc(token_buf
, 0);
1922 tok_add2(&str
, &len
, TOK_STR
, &cval
);
1924 tok_add2(&str
, &len
, t
, &cval
);
1926 } else if (t
>= TOK_IDENT
) {
1927 s
= sym_find2(args
, t
);
1930 /* if '##' is present before or after , no arg substitution */
1931 if (*macro_str
== TOK_TWOSHARPS
|| last_tok
== TOK_TWOSHARPS
) {
1933 tok_add(&str
, &len
, *st
++);
1935 macro_subst(&str
, &len
, nested_list
, st
);
1938 tok_add(&str
, &len
, t
);
1941 tok_add2(&str
, &len
, t
, &cval
);
1945 tok_add(&str
, &len
, 0);
1949 /* handle the '##' operator */
1950 int *macro_twosharps(int *macro_str
)
1953 int *macro_str1
, macro_str1_len
, *macro_ptr1
;
1965 while (*macro_ptr
== TOK_TWOSHARPS
) {
1967 macro_ptr1
= macro_ptr
;
1970 t
= tok_get(¯o_ptr
, &cval
);
1971 /* XXX: we handle only most common cases:
1972 ident + ident or ident + number */
1973 if (tok
>= TOK_IDENT
&&
1974 (t
>= TOK_IDENT
|| t
== TOK_CINT
)) {
1975 p
= get_tok_str(tok
, &tokc
);
1976 pstrcpy(token_buf
, sizeof(token_buf
), p
);
1977 p
= get_tok_str(t
, &cval
);
1978 pstrcat(token_buf
, sizeof(token_buf
), p
);
1979 ts
= tok_alloc(token_buf
, 0);
1980 tok
= ts
->tok
; /* modify current token */
1982 /* cannot merge tokens: skip '##' */
1983 macro_ptr
= macro_ptr1
;
1988 tok_add2(¯o_str1
, ¯o_str1_len
, tok
, &tokc
);
1990 tok_add(¯o_str1
, ¯o_str1_len
, 0);
1996 /* do macro substitution of macro_str and add result to
1997 (tok_str,tok_len). If macro_str is NULL, then input stream token is
1998 substituted. 'nested_list' is the list of all macros we got inside
1999 to avoid recursing. */
2000 void macro_subst(int **tok_str
, int *tok_len
,
2001 Sym
**nested_list
, int *macro_str
)
2003 Sym
*s
, *args
, *sa
, *sa1
;
2004 int *str
, parlevel
, len
, *mstr
, t
, *saved_macro_ptr
;
2005 int mstr_allocated
, *macro_str1
;
2008 saved_macro_ptr
= macro_ptr
;
2009 macro_ptr
= macro_str
;
2012 /* first scan for '##' operator handling */
2013 macro_str1
= macro_twosharps(macro_str
);
2014 macro_ptr
= macro_str1
;
2021 /* special macros */
2022 if (tok
== TOK___LINE__
) {
2024 tok_add2(tok_str
, tok_len
, TOK_CINT
, &cval
);
2025 } else if (tok
== TOK___FILE__
) {
2026 cval
.ts
= tok_alloc(filename
, 0);
2027 tok_add2(tok_str
, tok_len
, TOK_STR
, &cval
);
2028 } else if (tok
== TOK___DATE__
) {
2029 cval
.ts
= tok_alloc("Jan 1 1970", 0);
2030 tok_add2(tok_str
, tok_len
, TOK_STR
, &cval
);
2031 } else if (tok
== TOK___TIME__
) {
2032 cval
.ts
= tok_alloc("00:00:00", 0);
2033 tok_add2(tok_str
, tok_len
, TOK_STR
, &cval
);
2034 } else if ((s
= sym_find1(&define_stack
, tok
)) != NULL
) {
2035 /* if symbol is a macro, prepare substitution */
2036 /* if nested substitution, do nothing */
2037 if (sym_find2(*nested_list
, tok
))
2041 if (s
->t
== MACRO_FUNC
) {
2042 /* NOTE: we do not use next_nomacro to avoid eating the
2043 next token. XXX: find better solution */
2047 while (ch
== ' ' || ch
== '\t' || ch
== '\n')
2051 if (t
!= '(') /* no macro subst */
2054 /* argument macro */
2059 while (tok
!= ')' && sa
) {
2063 while ((parlevel
> 0 ||
2066 sa
->v
== (TOK___VA_ARGS__
| SYM_FIELD
)))) &&
2070 else if (tok
== ')')
2072 tok_add2(&str
, &len
, tok
, &tokc
);
2075 tok_add(&str
, &len
, 0);
2076 sym_push2(&args
, sa
->v
& ~SYM_FIELD
, 0, (int)str
);
2084 /* now subst each arg */
2085 mstr
= macro_arg_subst(nested_list
, mstr
, args
);
2096 sym_push2(nested_list
, s
->v
, 0, 0);
2097 macro_subst(tok_str
, tok_len
, nested_list
, mstr
);
2098 /* pop nested defined symbol */
2100 *nested_list
= sa1
->prev
;
2106 /* no need to add if reading input stream */
2109 tok_add2(tok_str
, tok_len
, tok
, &tokc
);
2111 /* only replace one macro while parsing input stream */
2115 macro_ptr
= saved_macro_ptr
;
2120 /* return next token with macro substitution */
2126 /* special 'ungettok' case for label parsing */
2134 /* if not reading from macro substuted string, then try to substitute */
2138 macro_subst(&ptr
, &len
, &nested_list
, NULL
);
2140 tok_add(&ptr
, &len
, 0);
2142 macro_ptr_allocated
= ptr
;
2150 /* end of macro string: free it */
2151 free(macro_ptr_allocated
);
2158 printf("token = %s\n", get_tok_str(tok
, tokc
));
2162 void swap(int *p
, int *q
)
2170 void vsetc(int t
, int r
, CValue
*vc
)
2172 if (vtop
>= vstack
+ VSTACK_SIZE
)
2173 error("memory full");
2174 /* cannot let cpu flags if other instruction are generated */
2175 /* XXX: VT_JMP test too ? */
2176 if ((vtop
->r
& VT_VALMASK
) == VT_CMP
)
2181 vtop
->r2
= VT_CONST
;
2185 /* push integer constant */
2190 vsetc(VT_INT
, VT_CONST
, &cval
);
2193 void vset(int t
, int r
, int v
)
2210 void vpushv(SValue
*v
)
2212 if (vtop
>= vstack
+ VSTACK_SIZE
)
2213 error("memory full");
2223 /* save r to the memory stack, and mark it as being free */
2224 void save_reg(int r
)
2226 int l
, i
, saved
, t
, size
, align
;
2229 /* modify all stack values */
2232 for(p
=vstack
;p
<=vtop
;p
++) {
2233 i
= p
->r
& VT_VALMASK
;
2234 if ((p
->r
& VT_VALMASK
) == r
||
2235 (p
->r2
& VT_VALMASK
) == r
) {
2236 /* must save value on stack if not already done */
2238 /* store register in the stack */
2240 if (!is_float(t
) && (t
& VT_BTYPE
) != VT_LLONG
)
2242 size
= type_size(t
, &align
);
2243 loc
= (loc
- size
) & -align
;
2245 sv
.r
= VT_LOCAL
| VT_LVAL
;
2248 /* XXX: x86 specific: need to pop fp register ST0 if saved */
2250 o(0xd9dd); /* fstp %st(1) */
2252 /* special long long case */
2253 if ((p
->t
& VT_BTYPE
) == VT_LLONG
) {
2260 /* mark that stack entry as being saved on the stack */
2272 /* find a free register of class 'rc'. If none, save one register */
2278 /* find a free register */
2279 for(r
=0;r
<NB_REGS
;r
++) {
2280 if (reg_classes
[r
] & rc
) {
2281 for(p
=vstack
;p
<=vtop
;p
++) {
2282 if ((p
->r
& VT_VALMASK
) == r
||
2283 (p
->r2
& VT_VALMASK
) == r
)
2291 /* no register left : free the first one on the stack (VERY
2292 IMPORTANT to start from the bottom to ensure that we don't
2293 spill registers used in gen_opi()) */
2294 for(p
=vstack
;p
<=vtop
;p
++) {
2295 r
= p
->r
& VT_VALMASK
;
2296 if (r
< VT_CONST
&& (reg_classes
[r
] & rc
)) {
2304 void save_regs(void)
2309 for(p
=vstack
;p
<=vtop
;p
++) {
2310 r
= p
->r
& VT_VALMASK
;
2317 /* move register 's' to 'r', and flush previous value of r to memory
2319 void move_reg(int r
, int s
)
2332 /* store vtop a register belonging to class 'rc'. lvalues are
2333 converted to values. Cannot be used if cannot be converted to
2334 register value (such as structures). */
2337 int r
, r2
, rc2
, bit_pos
, bit_size
, size
, align
, i
, data_offset
;
2338 unsigned long long ll
;
2340 /* NOTE: get_reg can modify vstack[] */
2341 if (vtop
->t
& VT_BITFIELD
) {
2342 bit_pos
= (vtop
->t
>> VT_STRUCT_SHIFT
) & 0x3f;
2343 bit_size
= (vtop
->t
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f;
2344 /* remove bit field info to avoid loops */
2345 vtop
->t
&= ~(VT_BITFIELD
| (-1 << VT_STRUCT_SHIFT
));
2346 /* generate shifts */
2347 vpushi(32 - (bit_pos
+ bit_size
));
2349 vpushi(32 - bit_size
);
2350 /* NOTE: transformed to SHR if unsigned */
2354 if (is_float(vtop
->t
) &&
2355 (vtop
->r
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
) {
2356 /* CPUs usually cannot use float constants, so we store them
2357 generically in data segment */
2358 size
= type_size(vtop
->t
, &align
);
2359 data_offset
= (int)data_section
->data_ptr
;
2360 data_offset
= (data_offset
+ align
- 1) & -align
;
2361 /* XXX: not portable yet */
2364 ((int *)data_offset
)[i
] = vtop
->c
.tab
[i
];
2366 vtop
->c
.ul
= data_offset
;
2367 data_offset
+= size
<< 2;
2368 data_section
->data_ptr
= (unsigned char *)data_offset
;
2370 r
= vtop
->r
& VT_VALMASK
;
2371 /* need to reload if:
2373 - lvalue (need to dereference pointer)
2374 - already a register, but not in the right class */
2375 if (r
>= VT_CONST
||
2376 (vtop
->r
& VT_LVAL
) ||
2377 !(reg_classes
[r
] & rc
) ||
2378 ((vtop
->t
& VT_BTYPE
) == VT_LLONG
&&
2379 !(reg_classes
[vtop
->r2
] & rc
))) {
2381 if ((vtop
->t
& VT_BTYPE
) == VT_LLONG
) {
2382 /* two register type load : expand to two words
2384 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
) {
2387 vtop
->c
.ui
= ll
; /* first word */
2389 vtop
->r
= r
; /* save register value */
2390 vpushi(ll
>> 32); /* second word */
2391 } else if (r
>= VT_CONST
||
2392 (vtop
->r
& VT_LVAL
)) {
2393 /* load from memory */
2396 vtop
[-1].r
= r
; /* save register value */
2397 /* increment pointer to get second word */
2399 vtop
->r
&= ~VT_LVAL
;
2404 /* move registers */
2407 vtop
[-1].r
= r
; /* save register value */
2408 vtop
->r
= vtop
[-1].r2
;
2410 /* allocate second register */
2417 /* write second register */
2420 /* one register type load */
2429 /* expand long long on stack in two int registers */
2434 u
= vtop
->t
& VT_UNSIGNED
;
2437 vtop
[0].r
= vtop
[-1].r2
;
2438 vtop
[0].r2
= VT_CONST
;
2439 vtop
[-1].r2
= VT_CONST
;
2440 vtop
[0].t
= VT_INT
| u
;
2441 vtop
[-1].t
= VT_INT
| u
;
2444 /* build a long long from two ints */
2451 vtop
[-1].r2
= vtop
[0].r
;
2456 /* rotate n first stack elements to the bottom */
2463 for(i
=-n
+1;i
!=0;i
++)
2464 vtop
[i
] = vtop
[i
+1];
2468 /* pop stack value */
2471 /* for x86, we need to pop the FP stack */
2472 if ((vtop
->r
& VT_VALMASK
) == REG_ST0
) {
2473 o(0xd9dd); /* fstp %st(1) */
2478 /* convert stack entry to register and duplicate its value in another
2486 if ((t
& VT_BTYPE
) == VT_LLONG
) {
2493 /* stack: H L L1 H1 */
2501 /* duplicate value */
2512 load(r1
, &sv
); /* move r to r1 */
2514 /* duplicates value */
2519 /* generate CPU independent (unsigned) long long operations */
2520 void gen_opl(int op
)
2522 int t
, a
, b
, op1
, c
, i
;
2541 /* call generic long long function */
2549 vtop
->r2
= REG_LRET
;
2562 /* stack: L1 H1 L2 H2 */
2567 vtop
[-2] = vtop
[-3];
2570 /* stack: H1 H2 L1 L2 */
2576 /* stack: H1 H2 L1 L2 ML MH */
2579 /* stack: ML MH H1 H2 L1 L2 */
2583 /* stack: ML MH H1 L2 H2 L1 */
2588 /* stack: ML MH M1 M2 */
2591 } else if (op
== '+' || op
== '-') {
2592 /* XXX: add non carry method too (for MIPS ?) */
2598 /* stack: H1 H2 (L1 op L2) */
2601 gen_op(op1
+ 1); /* TOK_xxxC2 */
2604 /* stack: H1 H2 (L1 op L2) */
2607 /* stack: (L1 op L2) H1 H2 */
2609 /* stack: (L1 op L2) (H1 op H2) */
2617 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_FORWARD
)) == VT_CONST
) {
2622 /* stack: L H shift */
2624 /* constant: simpler */
2625 /* NOTE: all comments are for SHL. the other cases are
2626 done by swaping words */
2637 if (op
!= TOK_SAR
) {
2667 /* XXX: should provide a faster fallback on x86 ? */
2682 /* compare operations */
2688 /* stack: L1 H1 L2 H2 */
2690 vtop
[-1] = vtop
[-2];
2692 /* stack: L1 L2 H1 H2 */
2695 /* when values are equal, we need to compare low words. since
2696 the jump is inverted, we invert the test too. */
2699 else if (op1
== TOK_GT
)
2701 else if (op1
== TOK_ULT
)
2703 else if (op1
== TOK_UGT
)
2708 if (op1
!= TOK_NE
) {
2712 /* generate non equal test */
2713 /* XXX: NOT PORTABLE yet */
2717 b
= psym(0x850f, 0);
2723 vset(VT_INT
, VT_JMPI
, a
);
2728 /* handle constant optimizations and various machine independant opt */
2729 void gen_opc(int op
)
2736 /* currently, we cannot do computations with forward symbols */
2737 c1
= (v1
->r
& (VT_VALMASK
| VT_LVAL
| VT_FORWARD
)) == VT_CONST
;
2738 c2
= (v2
->r
& (VT_VALMASK
| VT_LVAL
| VT_FORWARD
)) == VT_CONST
;
2742 case '+': v1
->c
.i
+= fc
; break;
2743 case '-': v1
->c
.i
-= fc
; break;
2744 case '&': v1
->c
.i
&= fc
; break;
2745 case '^': v1
->c
.i
^= fc
; break;
2746 case '|': v1
->c
.i
|= fc
; break;
2747 case '*': v1
->c
.i
*= fc
; break;
2749 case '/': v1
->c
.i
/= fc
; break; /* XXX: zero case ? */
2750 case '%': v1
->c
.i
%= fc
; break; /* XXX: zero case ? */
2751 case TOK_UDIV
: v1
->c
.i
= (unsigned)v1
->c
.i
/ fc
; break; /* XXX: zero case ? */
2752 case TOK_UMOD
: v1
->c
.i
= (unsigned)v1
->c
.i
% fc
; break; /* XXX: zero case ? */
2753 case TOK_SHL
: v1
->c
.i
<<= fc
; break;
2754 case TOK_SHR
: v1
->c
.i
= (unsigned)v1
->c
.i
>> fc
; break;
2755 case TOK_SAR
: v1
->c
.i
>>= fc
; break;
2757 case TOK_ULT
: v1
->c
.i
= (unsigned)v1
->c
.i
< (unsigned)fc
; break;
2758 case TOK_UGE
: v1
->c
.i
= (unsigned)v1
->c
.i
>= (unsigned)fc
; break;
2759 case TOK_EQ
: v1
->c
.i
= v1
->c
.i
== fc
; break;
2760 case TOK_NE
: v1
->c
.i
= v1
->c
.i
!= fc
; break;
2761 case TOK_ULE
: v1
->c
.i
= (unsigned)v1
->c
.i
<= (unsigned)fc
; break;
2762 case TOK_UGT
: v1
->c
.i
= (unsigned)v1
->c
.i
> (unsigned)fc
; break;
2763 case TOK_LT
: v1
->c
.i
= v1
->c
.i
< fc
; break;
2764 case TOK_GE
: v1
->c
.i
= v1
->c
.i
>= fc
; break;
2765 case TOK_LE
: v1
->c
.i
= v1
->c
.i
<= fc
; break;
2766 case TOK_GT
: v1
->c
.i
= v1
->c
.i
> fc
; break;
2768 case TOK_LAND
: v1
->c
.i
= v1
->c
.i
&& fc
; break;
2769 case TOK_LOR
: v1
->c
.i
= v1
->c
.i
|| fc
; break;
2775 /* if commutative ops, put c2 as constant */
2776 if (c1
&& (op
== '+' || op
== '&' || op
== '^' ||
2777 op
== '|' || op
== '*')) {
2782 if (c2
&& (((op
== '*' || op
== '/' || op
== TOK_UDIV
||
2785 ((op
== '+' || op
== '-' || op
== '|' || op
== '^' ||
2786 op
== TOK_SHL
|| op
== TOK_SHR
|| op
== TOK_SAR
) &&
2792 } else if (c2
&& (op
== '*' || op
== TOK_PDIV
|| op
== TOK_UDIV
)) {
2793 /* try to use shifts instead of muls or divs */
2794 if (fc
> 0 && (fc
& (fc
- 1)) == 0) {
2803 else if (op
== TOK_PDIV
)
2811 /* call low level op generator */
2812 /* XXX: remove explicit registers */
2818 int pointed_size(int t
)
2820 return type_size(pointed_type(t
), &t
);
2824 void check_pointer_types(SValue
*p1
, SValue
*p2
)
2826 char buf1
[256], buf2
[256];
2830 if (!is_compatible_types(t1
, t2
)) {
2831 type_to_str(buf1
, sizeof(buf1
), t1
, NULL
);
2832 type_to_str(buf2
, sizeof(buf2
), t2
, NULL
);
2833 error("incompatible pointers '%s' and '%s'", buf1
, buf2
);
2838 /* generic gen_op: handles types problems */
2841 int u
, t1
, t2
, bt1
, bt2
, t
;
2845 bt1
= t1
& VT_BTYPE
;
2846 bt2
= t2
& VT_BTYPE
;
2848 if (bt1
== VT_PTR
|| bt2
== VT_PTR
) {
2849 /* at least one operand is a pointer */
2850 /* relationnal op: must be both pointers */
2851 if (op
>= TOK_ULT
&& op
<= TOK_GT
) {
2852 // check_pointer_types(vtop, vtop - 1);
2853 /* pointers are handled are unsigned */
2854 t
= VT_INT
| VT_UNSIGNED
;
2857 /* if both pointers, then it must be the '-' op */
2858 if ((t1
& VT_BTYPE
) == VT_PTR
&&
2859 (t2
& VT_BTYPE
) == VT_PTR
) {
2861 error("cannot use pointers here");
2862 // check_pointer_types(vtop - 1, vtop);
2863 /* XXX: check that types are compatible */
2864 u
= pointed_size(t1
);
2866 /* set to integer type */
2871 /* exactly one pointer : must be '+' or '-'. */
2872 if (op
!= '-' && op
!= '+')
2873 error("cannot use pointers here");
2874 /* Put pointer as first operand */
2875 if ((t2
& VT_BTYPE
) == VT_PTR
) {
2879 /* XXX: cast to int ? (long long case) */
2880 vpushi(pointed_size(vtop
[-1].t
));
2882 if (do_bounds_check
) {
2883 /* if bounded pointers, we generate a special code to test bounds */
2889 gen_bounded_ptr_add();
2893 /* put again type if gen_opc() swaped operands */
2896 } else if (is_float(bt1
) || is_float(bt2
)) {
2897 /* compute bigger type and do implicit casts */
2898 if (bt1
== VT_LDOUBLE
|| bt2
== VT_LDOUBLE
) {
2900 } else if (bt1
== VT_DOUBLE
|| bt2
== VT_DOUBLE
) {
2905 /* floats can only be used for a few operations */
2906 if (op
!= '+' && op
!= '-' && op
!= '*' && op
!= '/' &&
2907 (op
< TOK_ULT
|| op
> TOK_GT
))
2908 error("invalid operands for binary operation");
2910 } else if (bt1
== VT_LLONG
|| bt2
== VT_LLONG
) {
2911 /* cast to biggest op */
2913 /* convert to unsigned if it does not fit in a long long */
2914 if ((t1
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_LLONG
| VT_UNSIGNED
) ||
2915 (t2
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_LLONG
| VT_UNSIGNED
))
2919 /* integer operations */
2921 /* convert to unsigned if it does not fit in an integer */
2922 if ((t1
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
) ||
2923 (t2
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
))
2926 /* XXX: currently, some unsigned operations are explicit, so
2927 we modify them here */
2928 if (t
& VT_UNSIGNED
) {
2935 else if (op
== TOK_LT
)
2937 else if (op
== TOK_GT
)
2939 else if (op
== TOK_LE
)
2941 else if (op
== TOK_GE
)
2947 /* special case for shifts and long long: we keep the shift as
2949 if (op
== TOK_SHR
|| op
== TOK_SAR
|| op
== TOK_SHL
)
2955 else if ((t
& VT_BTYPE
) == VT_LLONG
)
2959 if (op
>= TOK_ULT
&& op
<= TOK_GT
) {
2960 /* relationnal op: the result is an int */
2968 /* generic itof for unsigned long long case */
2969 void gen_cvt_itof1(int t
)
2973 if ((vtop
->t
& (VT_BTYPE
| VT_UNSIGNED
)) ==
2974 (VT_LLONG
| VT_UNSIGNED
)) {
2979 vpushi((int)&__ulltof
);
2980 else if (t
== VT_DOUBLE
)
2981 vpushi((int)&__ulltod
);
2983 vpushi((int)&__ulltold
);
2992 /* generic ftoi for unsigned long long case */
2993 void gen_cvt_ftoi1(int t
)
2998 if (t
== (VT_LLONG
| VT_UNSIGNED
)) {
2999 /* not handled natively */
3001 st
= vtop
->t
& VT_BTYPE
;
3004 vpushi((int)&__ftoull
);
3005 else if (st
== VT_DOUBLE
)
3006 vpushi((int)&__dtoull
);
3008 vpushi((int)&__ldtoull
);
3012 vtop
->r2
= REG_LRET
;
3018 /* force char or short cast */
3019 void force_charshort_cast(int t
)
3023 /* XXX: add optimization if lvalue : just change type and offset */
3028 if (t
& VT_UNSIGNED
) {
3029 vpushi((1 << bits
) - 1);
3040 /* cast 'vtop' to 't' type */
3041 void gen_cast(int t
)
3043 int sbt
, dbt
, sf
, df
, c
, st1
, dt1
;
3045 /* special delayed cast for char/short */
3046 /* XXX: in some cases (multiple cascaded casts), it may still
3048 if (vtop
->r
& VT_MUSTCAST
) {
3049 vtop
->r
&= ~VT_MUSTCAST
;
3050 force_charshort_cast(vtop
->t
);
3054 sbt
= vtop
->t
& VT_BTYPE
;
3059 c
= (vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_FORWARD
)) == VT_CONST
;
3061 /* convert from fp to fp */
3063 /* constant case: we can do it now */
3064 /* XXX: in ISOC, cannot do it if error in convert */
3065 if (dbt
== VT_FLOAT
&& sbt
== VT_DOUBLE
)
3066 vtop
->c
.f
= (float)vtop
->c
.d
;
3067 else if (dbt
== VT_FLOAT
&& sbt
== VT_LDOUBLE
)
3068 vtop
->c
.f
= (float)vtop
->c
.ld
;
3069 else if (dbt
== VT_DOUBLE
&& sbt
== VT_FLOAT
)
3070 vtop
->c
.d
= (double)vtop
->c
.f
;
3071 else if (dbt
== VT_DOUBLE
&& sbt
== VT_LDOUBLE
)
3072 vtop
->c
.d
= (double)vtop
->c
.ld
;
3073 else if (dbt
== VT_LDOUBLE
&& sbt
== VT_FLOAT
)
3074 vtop
->c
.ld
= (long double)vtop
->c
.f
;
3075 else if (dbt
== VT_LDOUBLE
&& sbt
== VT_DOUBLE
)
3076 vtop
->c
.ld
= (long double)vtop
->c
.d
;
3078 /* non constant case: generate code */
3082 /* convert int to fp */
3083 st1
= vtop
->t
& (VT_BTYPE
| VT_UNSIGNED
);
3086 case VT_LLONG
| VT_UNSIGNED
:
3088 /* XXX: add const cases for long long */
3090 case VT_INT
| VT_UNSIGNED
:
3092 case VT_FLOAT
: vtop
->c
.f
= (float)vtop
->c
.ui
; break;
3093 case VT_DOUBLE
: vtop
->c
.d
= (double)vtop
->c
.ui
; break;
3094 case VT_LDOUBLE
: vtop
->c
.ld
= (long double)vtop
->c
.ui
; break;
3099 case VT_FLOAT
: vtop
->c
.f
= (float)vtop
->c
.i
; break;
3100 case VT_DOUBLE
: vtop
->c
.d
= (double)vtop
->c
.i
; break;
3101 case VT_LDOUBLE
: vtop
->c
.ld
= (long double)vtop
->c
.i
; break;
3110 /* convert fp to int */
3111 dt1
= t
& (VT_BTYPE
| VT_UNSIGNED
);
3112 /* we handle char/short/etc... with generic code */
3113 if (dt1
!= (VT_INT
| VT_UNSIGNED
) &&
3114 dt1
!= (VT_LLONG
| VT_UNSIGNED
) &&
3119 case VT_LLONG
| VT_UNSIGNED
:
3121 /* XXX: add const cases for long long */
3123 case VT_INT
| VT_UNSIGNED
:
3125 case VT_FLOAT
: vtop
->c
.ui
= (unsigned int)vtop
->c
.d
; break;
3126 case VT_DOUBLE
: vtop
->c
.ui
= (unsigned int)vtop
->c
.d
; break;
3127 case VT_LDOUBLE
: vtop
->c
.ui
= (unsigned int)vtop
->c
.d
; break;
3133 case VT_FLOAT
: vtop
->c
.i
= (int)vtop
->c
.d
; break;
3134 case VT_DOUBLE
: vtop
->c
.i
= (int)vtop
->c
.d
; break;
3135 case VT_LDOUBLE
: vtop
->c
.i
= (int)vtop
->c
.d
; break;
3143 if (dt1
== VT_INT
&& (t
& (VT_BTYPE
| VT_UNSIGNED
)) != dt1
) {
3144 /* additionnal cast for char/short/bool... */
3148 } else if (dbt
== VT_LLONG
) {
3149 /* scalar to long long */
3151 if ((vtop
->t
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
))
3152 vtop
->c
.ll
= vtop
->c
.ui
;
3154 vtop
->c
.ll
= vtop
->c
.i
;
3156 /* machine independant conversion */
3158 /* generate high word */
3159 if ((vtop
->t
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
)) {
3167 /* patch second register */
3168 vtop
[-1].r2
= vtop
->r
;
3171 } else if (dbt
== VT_BOOL
) {
3172 /* scalar to bool */
3175 } else if (dbt
== VT_BYTE
|| dbt
== VT_SHORT
) {
3176 force_charshort_cast(t
);
3177 } else if (dbt
== VT_INT
) {
3179 if (sbt
== VT_LLONG
) {
3180 /* from long long: just take low order word */
3183 } else if (vtop
->r
& VT_LVAL
) {
3184 /* if lvalue and single word type, nothing to do (XXX:
3185 maybe incorrect for sizeof op) */
3194 /* return type size. Put alignment at 'a' */
3195 int type_size(int t
, int *a
)
3201 if (bt
== VT_STRUCT
) {
3203 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
) | SYM_STRUCT
);
3204 *a
= 4; /* XXX: cannot store it yet. Doing that is safe */
3206 } else if (bt
== VT_PTR
) {
3208 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
));
3209 return type_size(s
->t
, a
) * s
->c
;
3214 } else if (bt
== VT_LDOUBLE
) {
3216 return LDOUBLE_SIZE
;
3217 } else if (bt
== VT_DOUBLE
|| bt
== VT_LLONG
) {
3220 } else if (bt
== VT_INT
|| bt
== VT_ENUM
|| bt
== VT_FLOAT
) {
3223 } else if (bt
== VT_SHORT
) {
3227 /* char, void, function, _Bool */
3233 /* return the pointed type of t */
3234 int pointed_type(int t
)
3237 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
));
3238 return s
->t
| (t
& ~VT_TYPE
);
3241 int mk_pointer(int t
)
3245 sym_push(p
, t
, 0, -1);
3246 return VT_PTR
| (p
<< VT_STRUCT_SHIFT
) | (t
& ~VT_TYPE
);
3249 int is_compatible_types(int t1
, int t2
)
3256 bt1
= t1
& VT_BTYPE
;
3257 bt2
= t2
& VT_BTYPE
;
3258 if (bt1
== VT_PTR
) {
3259 t1
= pointed_type(t1
);
3260 /* if function, then convert implicitely to function pointer */
3261 if (bt2
!= VT_FUNC
) {
3264 t2
= pointed_type(t2
);
3266 /* void matches everything */
3269 if (t1
== VT_VOID
|| t2
== VT_VOID
)
3271 return is_compatible_types(t1
, t2
);
3272 } else if (bt1
== VT_STRUCT
) {
3274 } else if (bt1
== VT_FUNC
) {
3277 s1
= sym_find(((unsigned)t1
>> VT_STRUCT_SHIFT
));
3278 s2
= sym_find(((unsigned)t2
>> VT_STRUCT_SHIFT
));
3279 if (!is_compatible_types(s1
->t
, s2
->t
))
3281 /* XXX: not complete */
3282 if (s1
->c
== FUNC_OLD
|| s2
->c
== FUNC_OLD
)
3286 while (s1
!= NULL
) {
3289 if (!is_compatible_types(s1
->t
, s2
->t
))
3298 /* XXX: not complete */
3303 /* print a type. If 'varstr' is not NULL, then the variable is also
3304 printed in the type */
3306 /* XXX: add array and function pointers */
3307 void type_to_str(char *buf
, int buf_size
,
3308 int t
, const char *varstr
)
3318 if (t
& VT_UNSIGNED
)
3319 pstrcat(buf
, buf_size
, "unsigned ");
3349 tstr
= "long double";
3351 pstrcat(buf
, buf_size
, tstr
);
3355 if (bt
== VT_STRUCT
)
3359 pstrcat(buf
, buf_size
, tstr
);
3360 v
= (unsigned)t
>> VT_STRUCT_SHIFT
;
3361 if (v
>= SYM_FIRST_ANOM
)
3362 pstrcat(buf
, buf_size
, "<anonymous>");
3364 pstrcat(buf
, buf_size
, get_tok_str(v
, NULL
));
3367 s
= sym_find((unsigned)t
>> VT_STRUCT_SHIFT
);
3368 type_to_str(buf
, buf_size
, s
->t
, varstr
);
3369 pstrcat(buf
, buf_size
, "(");
3371 while (sa
!= NULL
) {
3372 type_to_str(buf1
, sizeof(buf1
), sa
->t
, NULL
);
3373 pstrcat(buf
, buf_size
, buf1
);
3376 pstrcat(buf
, buf_size
, ", ");
3378 pstrcat(buf
, buf_size
, ")");
3381 s
= sym_find((unsigned)t
>> VT_STRUCT_SHIFT
);
3382 pstrcpy(buf1
, sizeof(buf1
), "*");
3384 pstrcat(buf1
, sizeof(buf1
), varstr
);
3385 type_to_str(buf
, buf_size
, s
->t
, buf1
);
3389 pstrcat(buf
, buf_size
, " ");
3390 pstrcat(buf
, buf_size
, varstr
);
3395 /* verify type compatibility to store vtop in 'dt' type, and generate
3397 void gen_assign_cast(int dt
)
3400 char buf1
[256], buf2
[256];
3402 st
= vtop
->t
; /* source type */
3403 if ((dt
& VT_BTYPE
) == VT_PTR
) {
3404 /* special cases for pointers */
3405 /* a function is implicitely a function pointer */
3406 if ((st
& VT_BTYPE
) == VT_FUNC
) {
3407 if (!is_compatible_types(pointed_type(dt
), st
))
3412 /* '0' can also be a pointer */
3413 if ((st
& VT_BTYPE
) == VT_INT
&&
3414 ((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_FORWARD
)) == VT_CONST
) &&
3418 if (!is_compatible_types(dt
, st
)) {
3420 type_to_str(buf1
, sizeof(buf1
), st
, NULL
);
3421 type_to_str(buf2
, sizeof(buf2
), dt
, NULL
);
3422 error("cannot cast '%s' to '%s'", buf1
, buf2
);
3428 /* store vtop in lvalue pushed on stack */
3431 int sbt
, dbt
, ft
, r
, t
, size
, align
, bit_size
, bit_pos
, rc
, delayed_cast
;
3435 sbt
= vtop
->t
& VT_BTYPE
;
3436 dbt
= ft
& VT_BTYPE
;
3437 if (((sbt
== VT_INT
|| sbt
== VT_SHORT
) && dbt
== VT_BYTE
) ||
3438 (sbt
== VT_INT
&& dbt
== VT_SHORT
)) {
3439 /* optimize char/short casts */
3440 delayed_cast
= VT_MUSTCAST
;
3441 vtop
->t
= ft
& VT_TYPE
;
3444 gen_assign_cast(ft
& VT_TYPE
);
3447 if (sbt
== VT_STRUCT
) {
3448 /* if structure, only generate pointer */
3449 /* structure assignment : generate memcpy */
3450 /* XXX: optimize if small size */
3455 size
= type_size(vtop
->t
, &align
);
3460 vtop
->r
&= ~VT_LVAL
;
3465 vtop
->r
&= ~VT_LVAL
;
3469 vpushi((int)&memcpy
);
3471 /* leave source on stack */
3472 } else if (ft
& VT_BITFIELD
) {
3473 /* bitfield store handling */
3474 bit_pos
= (ft
>> VT_STRUCT_SHIFT
) & 0x3f;
3475 bit_size
= (ft
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f;
3476 /* remove bit field info to avoid loops */
3477 vtop
[-1].t
= ft
& ~(VT_BITFIELD
| (-1 << VT_STRUCT_SHIFT
));
3479 /* duplicate destination */
3481 vtop
[-1] = vtop
[-2];
3483 /* mask and shift source */
3484 vpushi((1 << bit_size
) - 1);
3488 /* load destination, mask and or with source */
3490 vpushi(~(((1 << bit_size
) - 1) << bit_pos
));
3499 r
= gv(rc
); /* generate value (XXX: move that to store code) */
3500 /* if lvalue was saved on stack, must read it */
3501 if ((vtop
[-1].r
& VT_VALMASK
) == VT_LLOCAL
) {
3503 t
= get_reg(RC_INT
);
3505 sv
.r
= VT_LOCAL
| VT_LVAL
;
3506 sv
.c
.ul
= vtop
[-1].c
.ul
;
3508 vtop
[-1].r
= t
| VT_LVAL
;
3511 /* two word case handling : store second register at word + 4 */
3512 if ((ft
& VT_BTYPE
) == VT_LLONG
) {
3514 /* convert to int to increment easily */
3516 vtop
->r
&= ~VT_LVAL
;
3521 /* XXX: it works because r2 is spilled last ! */
3522 store(vtop
->r2
, vtop
- 1);
3525 vtop
--; /* NOT vpop() because on x86 it would flush the fp stack */
3526 vtop
->r
|= delayed_cast
;
3530 /* post defines POST/PRE add. c is the token ++ or -- */
3531 void inc(int post
, int c
)
3534 vdup(); /* save lvalue */
3536 gv_dup(); /* duplicate value */
3541 vpushi(c
- TOK_MID
);
3543 vstore(); /* store value */
3545 vpop(); /* if post op, return saved value */
3548 /* Parse GNUC __attribute__ extension. Currently, the following
3549 extensions are recognized:
3550 - aligned(n) : set data/function alignment.
3551 - section(x) : generate data/code in this section.
3552 - unused : currently ignored, but may be used someday.
3554 void parse_attribute(AttributeDef
*ad
)
3561 while (tok
!= ')') {
3562 if (tok
< TOK_IDENT
)
3563 expect("attribute name");
3568 case TOK___SECTION__
:
3571 expect("section name");
3572 ad
->section
= find_section(tokc
.ts
->str
);
3577 case TOK___ALIGNED__
:
3580 if (n
<= 0 || (n
& (n
- 1)) != 0)
3581 error("alignment must be a positive power of two");
3586 case TOK___UNUSED__
:
3587 /* currently, no need to handle it because tcc does not
3588 track unused objects */
3591 warning("'%s' attribute ignored", get_tok_str(t
, NULL
));
3592 /* skip parameters */
3593 /* XXX: skip parenthesis too */
3596 while (tok
!= ')' && tok
!= -1)
3610 /* enum/struct/union declaration */
3611 int struct_decl(int u
)
3613 int a
, t
, b
, v
, size
, align
, maxalign
, c
, offset
;
3614 int bit_size
, bit_pos
, bsize
, bt
, lbit_pos
;
3618 a
= tok
; /* save decl type */
3623 /* struct already defined ? return it */
3624 /* XXX: check consistency */
3625 s
= sym_find(v
| SYM_STRUCT
);
3628 error("invalid type");
3634 s
= sym_push(v
| SYM_STRUCT
, a
, 0, 0);
3635 /* put struct/union/enum name in type */
3637 u
= u
| (v
<< VT_STRUCT_SHIFT
);
3642 error("struct/union/enum already defined");
3643 /* cannot be empty */
3650 if (a
== TOK_ENUM
) {
3657 /* enum symbols have static storage */
3658 sym_push(v
, VT_STATIC
| VT_INT
, VT_CONST
, c
);
3663 parse_btype(&b
, &ad
);
3668 t
= type_decl(&v
, b
, TYPE_DIRECT
);
3669 if ((t
& VT_BTYPE
) == VT_FUNC
||
3670 (t
& (VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
)))
3671 error("invalid type for '%s'",
3672 get_tok_str(v
, NULL
));
3678 bit_size
= expr_const();
3679 /* XXX: handle v = 0 case for messages */
3681 error("negative width in bit-field '%s'",
3682 get_tok_str(v
, NULL
));
3683 if (v
&& bit_size
== 0)
3684 error("zero width for bit-field '%s'",
3685 get_tok_str(v
, NULL
));
3687 size
= type_size(t
, &align
);
3689 if (bit_size
>= 0) {
3694 error("bitfields must have scalar type");
3696 if (bit_size
> bsize
) {
3697 error("width of '%s' exceeds its type",
3698 get_tok_str(v
, NULL
));
3699 } else if (bit_size
== bsize
) {
3700 /* no need for bit fields */
3702 } else if (bit_size
== 0) {
3703 /* XXX: what to do if only padding in a
3705 /* zero size: means to pad */
3709 /* we do not have enough room ? */
3710 if ((bit_pos
+ bit_size
) > bsize
)
3713 /* XXX: handle LSB first */
3715 (bit_pos
<< VT_STRUCT_SHIFT
) |
3716 (bit_size
<< (VT_STRUCT_SHIFT
+ 6));
3717 bit_pos
+= bit_size
;
3723 /* add new memory data only if starting
3725 if (lbit_pos
== 0) {
3726 if (a
== TOK_STRUCT
) {
3727 c
= (c
+ align
- 1) & -align
;
3735 if (align
> maxalign
)
3739 printf("add field %s offset=%d",
3740 get_tok_str(v
, NULL
), offset
);
3741 if (t
& VT_BITFIELD
) {
3742 printf(" pos=%d size=%d",
3743 (t
>> VT_STRUCT_SHIFT
) & 0x3f,
3744 (t
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f);
3748 ss
= sym_push(v
| SYM_FIELD
, t
, 0, offset
);
3752 if (tok
== ';' || tok
== -1)
3762 /* size for struct/union, dummy for enum */
3763 s
->c
= (c
+ maxalign
- 1) & -maxalign
;
3768 /* return 0 if no type declaration. otherwise, return the basic type
3771 int parse_btype(int *type_ptr
, AttributeDef
*ad
)
3773 int t
, u
, type_found
;
3776 memset(ad
, 0, sizeof(AttributeDef
));
3787 if ((t
& VT_BTYPE
) != 0)
3788 error("too many basic types");
3802 if ((t
& VT_BTYPE
) == VT_DOUBLE
) {
3803 t
= (t
& ~VT_BTYPE
) | VT_LDOUBLE
;
3804 } else if ((t
& VT_BTYPE
) == VT_LONG
) {
3805 t
= (t
& ~VT_BTYPE
) | VT_LLONG
;
3819 if ((t
& VT_BTYPE
) == VT_LONG
) {
3820 t
= (t
& ~VT_BTYPE
) | VT_LDOUBLE
;
3827 u
= struct_decl(VT_ENUM
);
3831 u
= struct_decl(VT_STRUCT
);
3834 /* type modifiers */
3862 /* GNUC attribute */
3863 case TOK___ATTRIBUTE__
:
3864 parse_attribute(ad
);
3868 if (!s
|| !(s
->t
& VT_TYPEDEF
))
3870 t
|= (s
->t
& ~VT_TYPEDEF
);
3877 /* long is never used as type */
3878 if ((t
& VT_BTYPE
) == VT_LONG
)
3879 t
= (t
& ~VT_BTYPE
) | VT_INT
;
3884 int post_type(int t
)
3886 int p
, n
, pt
, l
, t1
;
3887 Sym
**plast
, *s
, *first
;
3891 /* function declaration */
3896 while (tok
!= ')') {
3897 /* read param name and compute offset */
3898 if (l
!= FUNC_OLD
) {
3899 if (!parse_btype(&pt
, &ad
)) {
3901 error("invalid type");
3908 if ((pt
& VT_BTYPE
) == VT_VOID
&& tok
== ')')
3910 pt
= type_decl(&n
, pt
, TYPE_DIRECT
| TYPE_ABSTRACT
);
3911 if ((pt
& VT_BTYPE
) == VT_VOID
)
3912 error("parameter declared as void");
3919 /* array must be transformed to pointer according to ANSI C */
3921 s
= sym_push(n
| SYM_FIELD
, pt
, 0, 0);
3926 if (l
== FUNC_NEW
&& tok
== TOK_DOTS
) {
3933 /* if no parameters, then old type prototype */
3937 t1
= t
& (VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
);
3938 t
= post_type(t
& ~(VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
));
3939 /* we push a anonymous symbol which will contain the function prototype */
3941 s
= sym_push(p
, t
, 0, l
);
3943 t
= t1
| VT_FUNC
| (p
<< VT_STRUCT_SHIFT
);
3944 } else if (tok
== '[') {
3945 /* array definition */
3951 error("invalid array size");
3954 /* parse next post type */
3955 t1
= t
& (VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
);
3956 t
= post_type(t
& ~(VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
));
3958 /* we push a anonymous symbol which will contain the array
3961 sym_push(p
, t
, 0, n
);
3962 t
= t1
| VT_ARRAY
| VT_PTR
| (p
<< VT_STRUCT_SHIFT
);
3967 /* Read a type declaration (except basic type), and return the
3968 type. If v is true, then also put variable name in 'vtop->c' */
3969 int type_decl(int *v
, int t
, int td
)
3974 while (tok
== '*') {
3976 while (tok
== TOK_CONST
|| tok
== TOK_VOLATILE
|| tok
== TOK_RESTRICT
)
3981 /* recursive type */
3982 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
3985 u
= type_decl(v
, 0, td
);
3989 /* type identifier */
3990 if (tok
>= TOK_IDENT
&& (td
& TYPE_DIRECT
)) {
3994 if (!(td
& TYPE_ABSTRACT
))
3995 expect("identifier");
3999 /* append t at the end of u */
4005 s
= sym_find((unsigned)p
>> VT_STRUCT_SHIFT
);
4015 /* define a new external reference to a function 'v' of type 'u' */
4016 Sym
*external_sym(int v
, int u
, int r
)
4021 /* push forward reference */
4022 s
= sym_push1(&global_stack
,
4024 s
->r
= r
| VT_CONST
| VT_FORWARD
;
4031 if ((vtop
->t
& VT_BTYPE
) != VT_PTR
)
4033 if (vtop
->r
& VT_LVAL
)
4035 vtop
->t
= pointed_type(vtop
->t
);
4036 if (!(vtop
->t
& VT_ARRAY
)) /* an array is never an lvalue */
4040 /* pass a parameter to a function and do type checking and casting */
4041 void gfunc_param_typed(GFuncContext
*gf
, Sym
*func
, Sym
*arg
)
4044 func_type
= func
->c
;
4045 if (func_type
== FUNC_OLD
||
4046 (func_type
== FUNC_ELLIPSIS
&& arg
== NULL
)) {
4047 /* default casting : only need to convert float to double */
4048 if ((vtop
->t
& VT_BTYPE
) == VT_FLOAT
)
4049 gen_cast(VT_DOUBLE
);
4050 } else if (arg
== NULL
) {
4051 error("too many arguments to function");
4053 gen_assign_cast(arg
->t
);
4060 int n
, t
, ft
, fc
, p
, align
, size
, r
, data_offset
;
4065 if (tok
== TOK_CINT
|| tok
== TOK_CCHAR
|| tok
== TOK_LCHAR
) {
4068 } else if (tok
== TOK_CUINT
) {
4069 vsetc(VT_INT
| VT_UNSIGNED
, VT_CONST
, &tokc
);
4071 } else if (tok
== TOK_CLLONG
) {
4072 vsetc(VT_LLONG
, VT_CONST
, &tokc
);
4074 } else if (tok
== TOK_CULLONG
) {
4075 vsetc(VT_LLONG
| VT_UNSIGNED
, VT_CONST
, &tokc
);
4077 } else if (tok
== TOK_CFLOAT
) {
4078 vsetc(VT_FLOAT
, VT_CONST
, &tokc
);
4080 } else if (tok
== TOK_CDOUBLE
) {
4081 vsetc(VT_DOUBLE
, VT_CONST
, &tokc
);
4083 } else if (tok
== TOK_CLDOUBLE
) {
4084 vsetc(VT_LDOUBLE
, VT_CONST
, &tokc
);
4086 } else if (tok
== TOK___FUNC__
) {
4087 /* special function name identifier */
4088 /* generate (char *) type */
4089 data_offset
= (int)data_section
->data_ptr
;
4090 vset(mk_pointer(VT_BYTE
), VT_CONST
, data_offset
);
4091 strcpy((void *)data_offset
, funcname
);
4092 data_offset
+= strlen(funcname
) + 1;
4093 data_section
->data_ptr
= (unsigned char *)data_offset
;
4095 } else if (tok
== TOK_LSTR
) {
4098 } else if (tok
== TOK_STR
) {
4099 /* string parsing */
4102 type_size(t
, &align
);
4103 data_offset
= (int)data_section
->data_ptr
;
4104 data_offset
= (data_offset
+ align
- 1) & -align
;
4106 /* we must declare it as an array first to use initializer parser */
4107 t
= VT_ARRAY
| mk_pointer(t
);
4108 decl_initializer(t
, VT_CONST
, data_offset
, 1, 0);
4109 data_offset
+= type_size(t
, &align
);
4110 /* put it as pointer */
4111 vset(t
& ~VT_ARRAY
, VT_CONST
, fc
);
4112 data_section
->data_ptr
= (unsigned char *)data_offset
;
4118 if (parse_btype(&t
, &ad
)) {
4119 ft
= type_decl(&n
, t
, TYPE_ABSTRACT
);
4121 /* check ISOC99 compound literal */
4123 /* data is allocated locally by default */
4128 /* all except arrays are lvalues */
4129 if (!(ft
& VT_ARRAY
))
4131 memset(&ad
, 0, sizeof(AttributeDef
));
4132 fc
= decl_initializer_alloc(ft
, &ad
, r
, 1);
4142 } else if (t
== '*') {
4145 } else if (t
== '&') {
4147 /* functions names must be treated as function pointers,
4148 except for unary '&' and sizeof. Since we consider that
4149 functions are not lvalues, we only have to handle it
4150 there and in function calls. */
4151 if ((vtop
->t
& VT_BTYPE
) != VT_FUNC
)
4153 vtop
->t
= mk_pointer(vtop
->t
);
4154 vtop
->r
&= ~VT_LVAL
;
4158 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
)
4159 vtop
->c
.i
= !vtop
->c
.i
;
4160 else if ((vtop
->r
& VT_VALMASK
) == VT_CMP
)
4161 vtop
->c
.i
= vtop
->c
.i
^ 1;
4163 vset(VT_INT
, VT_JMP
, gtst(1, 0));
4173 if (t
== TOK_SIZEOF
) {
4176 if (parse_btype(&t
, &ad
)) {
4177 t
= type_decl(&n
, t
, TYPE_ABSTRACT
);
4179 /* XXX: some code could be generated: add eval
4191 vpushi(type_size(t
, &t
));
4193 if (t
== TOK_INC
|| t
== TOK_DEC
) {
4196 } else if (t
== '-') {
4205 error("'%s' undeclared", get_tok_str(t
, NULL
));
4206 /* for simple function calls, we tolerate undeclared
4207 external reference */
4209 sym_push1(&global_stack
, p
, 0, FUNC_OLD
);
4210 /* int() function */
4211 s
= external_sym(t
, VT_FUNC
| (p
<< VT_STRUCT_SHIFT
), 0);
4213 vset(s
->t
, s
->r
, s
->c
);
4214 /* if forward reference, we must point to s */
4215 if (vtop
->r
& VT_FORWARD
)
4220 /* post operations */
4222 if (tok
== TOK_INC
|| tok
== TOK_DEC
) {
4225 } else if (tok
== '.' || tok
== TOK_ARROW
) {
4227 if (tok
== TOK_ARROW
)
4230 vtop
->r
&= ~VT_LVAL
;
4232 /* expect pointer on structure */
4233 if ((vtop
->t
& VT_BTYPE
) != VT_STRUCT
)
4234 expect("struct or union");
4235 s
= sym_find(((unsigned)vtop
->t
>> VT_STRUCT_SHIFT
) | SYM_STRUCT
);
4238 while ((s
= s
->next
) != NULL
) {
4243 error("field not found");
4244 /* add field offset to pointer */
4245 vtop
->t
= char_pointer_type
; /* change type to 'char *' */
4248 /* change type to field type, and set to lvalue */
4250 /* an array is never an lvalue */
4251 if (!(vtop
->t
& VT_ARRAY
))
4254 } else if (tok
== '[') {
4260 } else if (tok
== '(') {
4265 if ((vtop
->t
& VT_BTYPE
) != VT_FUNC
) {
4266 /* pointer test (no array accepted) */
4267 if ((vtop
->t
& (VT_BTYPE
| VT_ARRAY
)) == VT_PTR
) {
4268 vtop
->t
= pointed_type(vtop
->t
);
4269 if ((vtop
->t
& VT_BTYPE
) != VT_FUNC
)
4273 expect("function pointer");
4276 vtop
->r
&= ~VT_LVAL
; /* no lvalue */
4278 /* get return type */
4279 s
= sym_find((unsigned)vtop
->t
>> VT_STRUCT_SHIFT
);
4280 save_regs(); /* save used temporary registers */
4283 sa
= s
->next
; /* first parameter */
4284 #ifdef INVERT_FUNC_PARAMS
4286 int *str
, len
, parlevel
, *saved_macro_ptr
;
4289 /* read each argument and store it on a stack */
4290 /* XXX: merge it with macro args ? */
4292 while (tok
!= ')') {
4296 while ((parlevel
> 0 || (tok
!= ')' && tok
!= ',')) &&
4300 else if (tok
== ')')
4302 tok_add2(&str
, &len
, tok
, &tokc
);
4305 tok_add(&str
, &len
, -1); /* end of file added */
4306 tok_add(&str
, &len
, 0);
4307 s1
= sym_push2(&args
, 0, 0, (int)str
);
4308 s1
->next
= sa
; /* add reference to argument */
4318 /* now generate code in reverse order by reading the stack */
4319 saved_macro_ptr
= macro_ptr
;
4321 macro_ptr
= (int *)args
->c
;
4325 expect("',' or ')'");
4326 gfunc_param_typed(&gf
, s
, args
->next
);
4328 free((int *)args
->c
);
4332 macro_ptr
= saved_macro_ptr
;
4337 /* compute first implicit argument if a structure is returned */
4338 if ((s
->t
& VT_BTYPE
) == VT_STRUCT
) {
4339 /* get some space for the returned structure */
4340 size
= type_size(s
->t
, &align
);
4341 loc
= (loc
- size
) & -align
;
4343 ret
.r
= VT_LOCAL
| VT_LVAL
;
4344 /* pass it as 'int' to avoid structure arg passing
4346 vset(VT_INT
, VT_LOCAL
, loc
);
4352 /* return in register */
4353 if (is_float(ret
.t
)) {
4356 if ((ret
.t
& VT_BTYPE
) == VT_LLONG
)
4362 #ifndef INVERT_FUNC_PARAMS
4363 while (tok
!= ')') {
4365 gfunc_param_typed(&gf
, s
, sa
);
4373 error("too few arguments to function");
4377 vsetc(ret
.t
, ret
.r
, &ret
.c
);
4391 (tok
>= TOK_A_MOD
&& tok
<= TOK_A_DIV
) ||
4392 tok
== TOK_A_XOR
|| tok
== TOK_A_OR
||
4393 tok
== TOK_A_SHL
|| tok
== TOK_A_SAR
) {
4416 while ((l
== 0 && (tok
== '*' || tok
== '/' || tok
== '%')) ||
4417 (l
== 1 && (tok
== '+' || tok
== '-')) ||
4418 (l
== 2 && (tok
== TOK_SHL
|| tok
== TOK_SAR
)) ||
4419 (l
== 3 && ((tok
>= TOK_ULE
&& tok
<= TOK_GT
) ||
4420 tok
== TOK_ULT
|| tok
== TOK_UGE
)) ||
4421 (l
== 4 && (tok
== TOK_EQ
|| tok
== TOK_NE
)) ||
4422 (l
== 5 && tok
== '&') ||
4423 (l
== 6 && tok
== '^') ||
4424 (l
== 7 && tok
== '|') ||
4425 (l
== 8 && tok
== TOK_LAND
) ||
4426 (l
== 9 && tok
== TOK_LOR
)) {
4435 /* only used if non constant */
4443 if (tok
!= TOK_LAND
) {
4446 vset(VT_INT
, VT_JMPI
, t
);
4463 if (tok
!= TOK_LOR
) {
4466 vset(VT_INT
, VT_JMP
, t
);
4476 /* XXX: better constant handling */
4479 int t
, u
, c
, r1
, r2
, rc
;
4501 /* XXX: long long handling ? */
4503 if (is_float(vtop
->t
))
4531 /* parse a constant expression and return value in vtop */
4532 void expr_const1(void)
4538 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
)) != VT_CONST
)
4543 /* parse an integer constant and return its value */
4544 int expr_const(void)
4553 /* return the label token if current token is a label, otherwise
4560 /* fast test first */
4561 if (tok
< TOK_UIDENT
)
4563 /* no need to save tokc since we expect an identifier */
4571 /* XXX: may not work in all cases (macros ?) */
4580 void block(int *bsym
, int *csym
, int *case_sym
, int *def_sym
, int case_reg
)
4585 /* generate line number info */
4587 (last_line_num
!= line_num
|| last_ind
!= ind
)) {
4588 put_stabn(N_SLINE
, 0, line_num
, ind
- func_ind
);
4590 last_line_num
= line_num
;
4593 if (tok
== TOK_IF
) {
4600 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
4602 if (c
== TOK_ELSE
) {
4606 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
4607 gsym(d
); /* patch else jmp */
4610 } else if (tok
== TOK_WHILE
) {
4618 block(&a
, &b
, case_sym
, def_sym
, case_reg
);
4619 oad(0xe9, d
- ind
- 5); /* jmp */
4622 } else if (tok
== '{') {
4625 s
= local_stack
.top
;
4626 while (tok
!= '}') {
4629 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
4631 /* pop locally defined symbols */
4632 sym_pop(&local_stack
, s
);
4634 } else if (tok
== TOK_RETURN
) {
4638 gen_assign_cast(func_vt
);
4639 if ((func_vt
& VT_BTYPE
) == VT_STRUCT
) {
4640 /* if returning structure, must copy it to implicit
4641 first pointer arg location */
4642 vset(mk_pointer(func_vt
), VT_LOCAL
| VT_LVAL
, func_vc
);
4645 /* copy structure value to pointer */
4647 } else if (is_float(func_vt
)) {
4655 rsym
= gjmp(rsym
); /* jmp */
4656 } else if (tok
== TOK_BREAK
) {
4659 error("cannot break");
4660 *bsym
= gjmp(*bsym
);
4663 } else if (tok
== TOK_CONTINUE
) {
4666 error("cannot continue");
4667 *csym
= gjmp(*csym
);
4670 } else if (tok
== TOK_FOR
) {
4693 oad(0xe9, d
- ind
- 5); /* jmp */
4697 block(&a
, &b
, case_sym
, def_sym
, case_reg
);
4698 oad(0xe9, c
- ind
- 5); /* jmp */
4702 if (tok
== TOK_DO
) {
4707 block(&a
, &b
, case_sym
, def_sym
, case_reg
);
4718 if (tok
== TOK_SWITCH
) {
4722 /* XXX: other types than integer */
4723 case_reg
= gv(RC_INT
);
4727 b
= gjmp(0); /* jump to first case */
4729 block(&a
, csym
, &b
, &c
, case_reg
);
4730 /* if no default, jmp after switch */
4738 if (tok
== TOK_CASE
) {
4745 if (gnu_ext
&& tok
== TOK_DOTS
) {
4749 warning("empty case range");
4751 /* since a case is like a label, we must skip it with a jmp */
4754 vset(VT_INT
, case_reg
, 0);
4758 *case_sym
= gtst(1, 0);
4761 *case_sym
= gtst(1, 0);
4762 vset(VT_INT
, case_reg
, 0);
4765 *case_sym
= gtst(1, *case_sym
);
4769 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
4771 if (tok
== TOK_DEFAULT
) {
4777 error("too many 'default'");
4779 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
4781 if (tok
== TOK_GOTO
) {
4783 s
= sym_find1(&label_stack
, tok
);
4784 /* put forward definition if needed */
4786 s
= sym_push1(&label_stack
, tok
, VT_FORWARD
, 0);
4787 /* label already defined */
4788 if (s
->t
& VT_FORWARD
)
4789 s
->c
= gjmp(s
->c
); /* jmp xxx */
4791 oad(0xe9, s
->c
- ind
- 5); /* jmp xxx */
4798 s
= sym_find1(&label_stack
, b
);
4800 if (!(s
->t
& VT_FORWARD
))
4801 error("multiple defined label");
4806 sym_push1(&label_stack
, b
, 0, ind
);
4808 /* we accept this, but it is a mistake */
4810 warning("deprecated use of label at end of compound statement");
4812 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
4814 /* expression case */
4824 /* t is the array or struct type. c is the array or struct
4825 address. cur_index/cur_field is the pointer to the current
4826 value. 'size_only' is true if only size info is needed (only used
4828 void decl_designator(int t
, int r
, int c
,
4829 int *cur_index
, Sym
**cur_field
,
4833 int notfirst
, index
, align
, l
;
4836 if (gnu_ext
&& (l
= is_label()) != 0)
4839 while (tok
== '[' || tok
== '.') {
4841 if (!(t
& VT_ARRAY
))
4842 expect("array type");
4843 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
));
4845 index
= expr_const();
4846 if (index
< 0 || (s
->c
>= 0 && index
>= s
->c
))
4847 expect("invalid index");
4851 t
= pointed_type(t
);
4852 c
+= index
* type_size(t
, &align
);
4858 if ((t
& VT_BTYPE
) != VT_STRUCT
)
4859 expect("struct/union type");
4860 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
) | SYM_STRUCT
);
4872 t
= f
->t
| (t
& ~VT_TYPE
);
4887 t
= pointed_type(t
);
4888 c
+= index
* type_size(t
, &align
);
4892 error("too many field init");
4893 t
= f
->t
| (t
& ~VT_TYPE
);
4897 decl_initializer(t
, r
, c
, 0, size_only
);
4901 #define EXPR_CONST 1
4904 /* store a value or an expression directly in global data or in local array */
4905 void init_putv(int t
, int r
, int c
,
4906 int v
, int expr_type
)
4908 int saved_global_expr
, bt
;
4915 /* compound literals must be allocated globally in this case */
4916 saved_global_expr
= global_expr
;
4919 global_expr
= saved_global_expr
;
4926 if ((r
& VT_VALMASK
) == VT_CONST
) {
4927 /* XXX: do casting */
4928 /* XXX: not portable */
4929 bt
= vtop
->t
& VT_BTYPE
;
4932 *(char *)c
= vtop
->c
.i
;
4935 *(short *)c
= vtop
->c
.i
;
4938 *(double *)c
= vtop
->c
.d
;
4941 *(long double *)c
= vtop
->c
.ld
;
4945 *(long long *)c
= vtop
->c
.ll
;
4949 *(int *)c
= vtop
->c
.i
;
4961 /* put zeros for variable based init */
4962 void init_putz(int t
, int r
, int c
, int size
)
4966 if ((r
& VT_VALMASK
) == VT_CONST
) {
4967 /* nothing to do because global are already set to zero */
4974 vset(VT_INT
, VT_LOCAL
, c
);
4976 vpushi((int)&memset
);
4981 /* 't' contains the type and storage info. c is the address of the
4982 object. 'first' is true if array '{' must be read (multi dimension
4983 implicit array init handling). 'size_only' is true if size only
4984 evaluation is wanted (only for arrays). */
4985 void decl_initializer(int t
, int r
, int c
, int first
, int size_only
)
4987 int index
, array_length
, n
, no_oblock
, nb
, parlevel
, i
;
4988 int t1
, size1
, align1
, expr_type
;
4993 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
));
4996 t1
= pointed_type(t
);
4997 size1
= type_size(t1
, &align1
);
5000 if ((first
&& tok
!= TOK_LSTR
&& tok
!= TOK_STR
) ||
5006 /* only parse strings here if correct type (otherwise: handle
5007 them as ((w)char *) expressions */
5008 if ((tok
== TOK_LSTR
&&
5009 (t1
& VT_BTYPE
) == VT_INT
) ||
5011 (t1
& VT_BTYPE
) == VT_BYTE
)) {
5012 /* XXX: move multiple string parsing in parser ? */
5013 while (tok
== TOK_STR
|| tok
== TOK_LSTR
) {
5015 /* compute maximum number of chars wanted */
5017 if (n
>= 0 && nb
> (n
- array_length
))
5018 nb
= n
- array_length
;
5021 warning("initializer-string for array is too long");
5023 init_putv(t1
, r
, c
+ (array_length
+ i
) * size1
,
5024 ts
->str
[i
], EXPR_VAL
);
5030 /* only add trailing zero if enough storage (no
5031 warning in this case since it is standard) */
5032 if (n
< 0 || array_length
< n
) {
5034 init_putv(t1
, r
, c
+ (array_length
* size1
), 0, EXPR_VAL
);
5040 while (tok
!= '}') {
5041 decl_designator(t
, r
, c
, &index
, NULL
, size_only
);
5042 if (n
>= 0 && index
>= n
)
5043 error("index too large");
5044 /* must put zero in holes (note that doing it that way
5045 ensures that it even works with designators) */
5046 if (!size_only
&& array_length
< index
) {
5047 init_putz(t1
, r
, c
+ array_length
* size1
,
5048 (index
- array_length
) * size1
);
5051 if (index
> array_length
)
5052 array_length
= index
;
5053 /* special test for multi dimensional arrays (may not
5054 be strictly correct if designators are used at the
5056 if (index
>= n
&& no_oblock
)
5065 /* put zeros at the end */
5066 if (!size_only
&& n
>= 0 && array_length
< n
) {
5067 init_putz(t1
, r
, c
+ array_length
* size1
,
5068 (n
- array_length
) * size1
);
5070 /* patch type size if needed */
5072 s
->c
= array_length
;
5073 } else if ((t
& VT_BTYPE
) == VT_STRUCT
&& tok
== '{') {
5074 /* XXX: union needs only one init */
5076 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
) | SYM_STRUCT
);
5081 while (tok
!= '}') {
5082 decl_designator(t
, r
, c
, NULL
, &f
, size_only
);
5083 /* fill with zero between fields */
5085 if (!size_only
&& array_length
< index
) {
5086 init_putz(t
, r
, c
+ array_length
,
5087 index
- array_length
);
5089 index
= index
+ type_size(f
->t
, &align1
);
5090 if (index
> array_length
)
5091 array_length
= index
;
5097 /* put zeros at the end */
5098 if (!size_only
&& array_length
< n
) {
5099 init_putz(t
, r
, c
+ array_length
,
5103 } else if (tok
== '{') {
5105 decl_initializer(t
, r
, c
, first
, size_only
);
5107 } else if (size_only
) {
5108 /* just skip expression */
5110 while ((parlevel
> 0 || (tok
!= '}' && tok
!= ',')) &&
5114 else if (tok
== ')')
5119 /* currently, we always use constant expression for globals
5120 (may change for scripting case) */
5121 expr_type
= EXPR_CONST
;
5122 if ((r
& VT_VALMASK
) == VT_LOCAL
)
5123 expr_type
= EXPR_ANY
;
5124 init_putv(t
, r
, c
, 0, expr_type
);
5128 /* parse an initializer for type 't' if 'has_init' is true, and
5129 allocate space in local or global data space ('r' is either
5130 VT_LOCAL or VT_CONST). The allocated address in returned */
5131 int decl_initializer_alloc(int t
, AttributeDef
*ad
, int r
, int has_init
)
5133 int size
, align
, addr
, tok1
, data_offset
;
5134 int *init_str
, init_len
, level
, *saved_macro_ptr
;
5137 size
= type_size(t
, &align
);
5138 /* If unknown size, we must evaluate it before
5139 evaluating initializers because
5140 initializers can generate global data too
5141 (e.g. string pointers or ISOC99 compound
5142 literals). It also simplifies local
5143 initializers handling */
5146 saved_macro_ptr
= NULL
; /* avoid warning */
5150 error("unknown type size");
5151 /* get all init string */
5153 while (level
> 0 || (tok
!= ',' && tok
!= ';')) {
5155 error("unexpected end of file in initializer");
5156 tok_add2(&init_str
, &init_len
, tok
, &tokc
);
5159 else if (tok
== '}') {
5167 tok_add(&init_str
, &init_len
, -1);
5168 tok_add(&init_str
, &init_len
, 0);
5171 saved_macro_ptr
= macro_ptr
;
5172 macro_ptr
= init_str
;
5174 decl_initializer(t
, r
, 0, 1, 1);
5175 /* prepare second initializer parsing */
5176 macro_ptr
= init_str
;
5179 /* if still unknown size, error */
5180 size
= type_size(t
, &align
);
5182 error("unknown type size");
5184 /* take into account specified alignment if bigger */
5185 if (ad
->aligned
> align
)
5186 align
= ad
->aligned
;
5187 if ((r
& VT_VALMASK
) == VT_LOCAL
) {
5188 loc
= (loc
- size
) & -align
;
5191 /* compute section */
5199 data_offset
= (int)sec
->data_ptr
;
5200 data_offset
= (data_offset
+ align
- 1) & -align
;
5202 /* very important to increment global
5203 pointer at this time because
5204 initializers themselves can create new
5206 data_offset
+= size
;
5207 /* handles bounds */
5208 if (do_bounds_check
) {
5210 /* first, we need to add at least one byte between each region */
5212 /* then add global data info */
5213 bounds_ptr
= (int *)bounds_section
->data_ptr
;
5214 *bounds_ptr
++ = addr
;
5215 *bounds_ptr
++ = size
;
5216 bounds_section
->data_ptr
= (unsigned char *)bounds_ptr
;
5218 sec
->data_ptr
= (unsigned char *)data_offset
;
5221 decl_initializer(t
, r
, addr
, 1, 0);
5222 /* restore parse state if needed */
5225 macro_ptr
= saved_macro_ptr
;
5232 void put_func_debug(int t
)
5241 put_elf_sym(symtab_section
, ind
, 0,
5242 ELF32_ST_INFO(bind
, STT_FUNC
), 0,
5243 cur_text_section
->sh_num
, funcname
);
5245 /* XXX: we put here a dummy type */
5246 snprintf(buf
, sizeof(buf
), "%s:%c1",
5247 funcname
, t
& VT_STATIC
? 'f' : 'F');
5248 put_stabs(buf
, N_FUN
, 0, line_num
, ind
);
5254 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
5257 int t
, b
, v
, addr
, has_init
, r
;
5262 if (!parse_btype(&b
, &ad
)) {
5263 /* skip redundant ';' */
5264 /* XXX: find more elegant solution */
5269 /* special test for old K&R protos without explicit int
5270 type. Only accepted when defining global data */
5271 if (l
== VT_LOCAL
|| tok
< TOK_DEFINE
)
5275 if (((b
& VT_BTYPE
) == VT_ENUM
||
5276 (b
& VT_BTYPE
) == VT_STRUCT
) &&
5278 /* we accept no variable after */
5282 while (1) { /* iterate thru each declaration */
5283 t
= type_decl(&v
, b
, TYPE_DIRECT
);
5284 /* currently, we do not parse attribute in
5285 type_decl(). May change if needed */
5286 if (tok
== TOK___ATTRIBUTE__
)
5287 parse_attribute(&ad
);
5291 type_to_str(buf
, sizeof(buf
), t
, get_tok_str(v
, NULL
));
5292 printf("type = '%s'\n", buf
);
5297 error("cannot use local functions");
5299 expect("function definition");
5300 /* compute text section */
5301 cur_text_section
= ad
.section
;
5302 if (!cur_text_section
)
5303 cur_text_section
= text_section
;
5304 ind
= (int)cur_text_section
->data_ptr
;
5305 /* patch forward references */
5306 if ((sym
= sym_find(v
)) && (sym
->r
& VT_FORWARD
)) {
5307 greloc_patch(sym
, ind
);
5310 /* put function address */
5311 sym
= sym_push1(&global_stack
, v
, t
, ind
);
5314 funcname
= get_tok_str(v
, NULL
);
5315 /* put debug symbol */
5318 /* push a dummy symbol to enable local sym storage */
5319 sym_push1(&local_stack
, 0, 0, 0);
5323 block(NULL
, NULL
, NULL
, NULL
, 0);
5326 cur_text_section
->data_ptr
= (unsigned char *)ind
;
5327 sym_pop(&label_stack
, NULL
); /* reset label stack */
5328 sym_pop(&local_stack
, NULL
); /* reset local stack */
5329 /* end of function */
5331 put_stabn(N_FUN
, 0, 0, ind
- func_ind
);
5333 funcname
= ""; /* for safety */
5334 func_vt
= VT_VOID
; /* for safety */
5337 if (b
& VT_TYPEDEF
) {
5338 /* save typedefed type */
5339 /* XXX: test storage specifiers ? */
5340 sym_push(v
, t
| VT_TYPEDEF
, 0, 0);
5341 } else if ((t
& VT_BTYPE
) == VT_FUNC
) {
5342 /* external function definition */
5343 external_sym(v
, t
, 0);
5345 /* not lvalue if array */
5347 if (!(t
& VT_ARRAY
))
5349 if (b
& VT_EXTERN
) {
5350 /* external variable */
5351 external_sym(v
, t
, r
);
5357 has_init
= (tok
== '=');
5360 addr
= decl_initializer_alloc(t
, &ad
, r
,
5362 if (l
== VT_CONST
) {
5363 /* global scope: see if already defined */
5367 if (!is_compatible_types(sym
->t
, t
))
5368 error("incompatible types for redefinition of '%s'",
5369 get_tok_str(v
, NULL
));
5370 if (!(sym
->r
& VT_FORWARD
))
5371 error("redefinition of '%s'", get_tok_str(v
, NULL
));
5372 greloc_patch(sym
, addr
);
5375 sym_push(v
, t
, r
, addr
);
5389 /* put all global symbols in the extern stack and do all the
5390 resolving which can be done without using external symbols from DLLs */
5391 /* XXX: could try to verify types, but would not to save them in
5393 void resolve_global_syms(void)
5395 Sym
*s
, *s1
, *ext_sym
;
5398 s
= global_stack
.top
;
5401 /* do not save static or typedefed symbols or types */
5402 if (!(s
->t
& (VT_STATIC
| VT_TYPEDEF
)) &&
5403 !(s
->v
& (SYM_FIELD
| SYM_STRUCT
)) &&
5404 (s
->v
< SYM_FIRST_ANOM
)) {
5405 ext_sym
= sym_find1(&extern_stack
, s
->v
);
5407 /* if the symbol do not exist, we simply save it */
5408 ext_sym
= sym_push1(&extern_stack
, s
->v
, s
->t
, s
->c
);
5410 } else if (ext_sym
->r
& VT_FORWARD
) {
5411 /* external symbol already exists, but only as forward
5413 if (!(s
->r
& VT_FORWARD
)) {
5414 /* s is not forward, so we can relocate all symbols */
5415 greloc_patch(ext_sym
, s
->c
);
5417 /* the two symbols are forward: merge them */
5418 p
= (Reloc
**)&ext_sym
->c
;
5424 /* external symbol already exists and is defined :
5425 patch all references to it */
5426 if (!(s
->r
& VT_FORWARD
))
5427 error("'%s' defined twice", get_tok_str(s
->v
, NULL
));
5428 greloc_patch(s
, ext_sym
->c
);
5435 /* compile a C file. Return non zero if errors. */
5436 int tcc_compile_file(const char *filename1
)
5443 filename
= (char *)filename1
;
5445 file
= fopen(filename
, "r");
5447 error("file '%s' not found", filename
);
5448 include_stack_ptr
= include_stack
;
5449 ifdef_stack_ptr
= ifdef_stack
;
5452 anon_sym
= SYM_FIRST_ANOM
;
5454 /* file info: full path + filename */
5456 getcwd(buf
, sizeof(buf
));
5457 pstrcat(buf
, sizeof(buf
), "/");
5458 put_stabs(buf
, N_SO
, 0, 0, (unsigned long)text_section
->data_ptr
);
5459 put_stabs(filename
, N_SO
, 0, 0, (unsigned long)text_section
->data_ptr
);
5461 /* define common 'char *' type because it is often used internally
5462 for arrays and struct dereference */
5463 char_pointer_type
= mk_pointer(VT_BYTE
);
5465 define_start
= define_stack
.top
;
5467 ch
= '\n'; /* needed to parse correctly first preprocessor command */
5471 expect("declaration");
5474 /* end of translation unit info */
5476 put_stabn(N_SO
, 0, 0, (unsigned long)text_section
->data_ptr
);
5479 /* reset define stack, but leave -Dsymbols (may be incorrect if
5480 they are undefined) */
5481 sym_pop(&define_stack
, define_start
);
5483 resolve_global_syms();
5485 sym_pop(&global_stack
, NULL
);
5490 /* define a symbol. A value can also be provided with the '=' operator */
5491 /* XXX: currently only handles integers and string defines. should use
5492 tcc parser, but would need a custom 'FILE *' */
5493 void define_symbol(const char *sym
)
5501 p
= strchr(sym
, '=');
5503 pstrcpy(buf
, sizeof(buf
), sym
);
5507 if (len
> sizeof(buf
) - 1)
5508 len
= sizeof(buf
) - 1;
5509 memcpy(buf
, sym
, len
);
5514 ts
= tok_alloc(buf
, 0);
5520 tok_add2(&str
, &len
, TOK_CINT
, &cval
);
5523 cval
.ts
= tok_alloc(p
, 0);
5524 tok_add2(&str
, &len
, TOK_STR
, &cval
);
5526 tok_add(&str
, &len
, 0);
5527 sym_push1(&define_stack
, ts
->tok
, MACRO_OBJ
, (int)str
);
5530 void undef_symbol(const char *sym
)
5534 printf("undef %s\n", sym
);
5535 ts
= tok_alloc(sym
, 0);
5536 s
= sym_find1(&define_stack
, tok
);
5537 /* undefine symbol by putting an invalid name */
5539 sym_undef(&define_stack
, s
);
5542 /* open a dynamic library so that its symbol are available for
5543 compiled programs */
5544 void open_dll(char *libname
)
5549 snprintf(buf
, sizeof(buf
), "lib%s.so", libname
);
5550 h
= dlopen(buf
, RTLD_GLOBAL
| RTLD_LAZY
);
5552 error((char *)dlerror());
5555 static void *resolve_sym(const char *sym
)
5558 if (do_bounds_check
) {
5559 ptr
= bound_resolve_sym(sym
);
5563 return dlsym(NULL
, sym
);
5566 void resolve_extern_syms(void)
5572 s
= extern_stack
.top
;
5575 if (s
->r
& VT_FORWARD
) {
5576 /* if there is at least one relocation to do, then find it
5579 str
= get_tok_str(s
->v
, NULL
);
5580 addr
= (int)resolve_sym(str
);
5582 error("unresolved external reference '%s'", str
);
5583 greloc_patch(s
, addr
);
5590 static int put_elf_str(Section
*s
, const char *sym
)
5593 offset
= s
->data_ptr
- s
->data
;
5603 static void put_elf_sym(Section
*s
,
5604 unsigned long value
, unsigned long size
,
5605 int info
, int other
, int shndx
, const char *name
)
5610 sym
= (Elf32_Sym
*)s
->data_ptr
;
5612 name_offset
= put_elf_str(s
->link
, name
);
5615 sym
->st_name
= name_offset
;
5616 sym
->st_value
= value
;
5617 sym
->st_size
= size
;
5618 sym
->st_info
= info
;
5619 sym
->st_other
= other
;
5620 sym
->st_shndx
= shndx
;
5621 s
->data_ptr
+= sizeof(Elf32_Sym
);
5624 /* put stab debug information */
5627 unsigned long n_strx
; /* index into string table of name */
5628 unsigned char n_type
; /* type of symbol */
5629 unsigned char n_other
; /* misc info (usually empty) */
5630 unsigned short n_desc
; /* description field */
5631 unsigned long n_value
; /* value of symbol */
5634 static void put_stabs(const char *str
, int type
, int other
, int desc
, int value
)
5638 sym
= (Stab_Sym
*)stab_section
->data_ptr
;
5640 sym
->n_strx
= put_elf_str(stabstr_section
, str
);
5645 sym
->n_other
= other
;
5647 sym
->n_value
= value
;
5649 stab_section
->data_ptr
+= sizeof(Stab_Sym
);
5652 static void put_stabn(int type
, int other
, int desc
, int value
)
5654 put_stabs(NULL
, type
, other
, desc
, value
);
5657 static void put_stabd(int type
, int other
, int desc
)
5659 put_stabs(NULL
, type
, other
, desc
, 0);
5662 /* output an ELF file (currently, only for testing) */
5663 void build_exe(char *filename
)
5667 int shnum
, i
, phnum
, file_offset
, offset
, size
, j
;
5668 Section
*sec
, *strsec
;
5669 Elf32_Shdr
*shdr
, *sh
;
5670 Elf32_Phdr
*phdr
, *ph
;
5672 memset(&ehdr
, 0, sizeof(ehdr
));
5674 /* we add a section for symbols */
5675 strsec
= new_section(".shstrtab", SHT_STRTAB
, 0);
5676 put_elf_str(strsec
, "");
5678 /* count number of sections and compute number of program segments */
5679 shnum
= 1; /* section index zero is reserved */
5681 for(sec
= first_section
; sec
!= NULL
; sec
= sec
->next
) {
5683 if (sec
->sh_flags
& SHF_ALLOC
)
5686 /* allocate section headers */
5687 shdr
= malloc(shnum
* sizeof(Elf32_Shdr
));
5689 error("memory full");
5690 memset(shdr
, 0, shnum
* sizeof(Elf32_Shdr
));
5691 /* allocate program segment headers */
5692 phdr
= malloc(phnum
* sizeof(Elf32_Phdr
));
5694 error("memory full");
5695 memset(phdr
, 0, phnum
* sizeof(Elf32_Phdr
));
5697 /* XXX: find correct load order */
5698 file_offset
= sizeof(Elf32_Ehdr
) + phnum
* sizeof(Elf32_Phdr
);
5699 for(sec
= first_section
, i
= 1; sec
!= NULL
; sec
= sec
->next
, i
++) {
5701 sh
->sh_name
= put_elf_str(strsec
, sec
->name
);
5702 sh
->sh_type
= sec
->sh_type
;
5703 sh
->sh_flags
= sec
->sh_flags
;
5704 sh
->sh_entsize
= sec
->sh_entsize
;
5706 sh
->sh_link
= sec
->link
->sh_num
;
5707 if (sh
->sh_type
== SHT_STRTAB
) {
5708 sh
->sh_addralign
= 1;
5709 } else if (sh
->sh_type
== SHT_SYMTAB
||
5710 (sh
->sh_flags
& SHF_ALLOC
) == 0) {
5711 sh
->sh_addralign
= 4;
5713 sh
->sh_addr
= (Elf32_Word
)sec
->data
;
5714 sh
->sh_addralign
= 4096;
5716 sh
->sh_size
= (Elf32_Word
)sec
->data_ptr
- (Elf32_Word
)sec
->data
;
5717 /* align to section start */
5718 file_offset
= (file_offset
+ sh
->sh_addralign
- 1) &
5719 ~(sh
->sh_addralign
- 1);
5720 sh
->sh_offset
= file_offset
;
5721 file_offset
+= sh
->sh_size
;
5723 /* build program headers (simplistic - not fully correct) */
5725 for(i
=1;i
<shnum
;i
++) {
5727 if (sh
->sh_type
== SHT_PROGBITS
&&
5728 (sh
->sh_flags
& SHF_ALLOC
) != 0) {
5730 ph
->p_type
= PT_LOAD
;
5731 ph
->p_offset
= sh
->sh_offset
;
5732 ph
->p_vaddr
= sh
->sh_addr
;
5733 ph
->p_paddr
= ph
->p_vaddr
;
5734 ph
->p_filesz
= sh
->sh_size
;
5735 ph
->p_memsz
= sh
->sh_size
;
5737 if (sh
->sh_flags
& SHF_WRITE
)
5738 ph
->p_flags
|= PF_W
;
5739 if (sh
->sh_flags
& SHF_EXECINSTR
)
5740 ph
->p_flags
|= PF_X
;
5741 ph
->p_align
= sh
->sh_addralign
;
5746 file_offset
= (file_offset
+ 3) & -4;
5749 ehdr
.e_ident
[0] = ELFMAG0
;
5750 ehdr
.e_ident
[1] = ELFMAG1
;
5751 ehdr
.e_ident
[2] = ELFMAG2
;
5752 ehdr
.e_ident
[3] = ELFMAG3
;
5753 ehdr
.e_ident
[4] = ELFCLASS32
;
5754 ehdr
.e_ident
[5] = ELFDATA2LSB
;
5755 ehdr
.e_ident
[6] = EV_CURRENT
;
5756 ehdr
.e_type
= ET_EXEC
;
5757 ehdr
.e_machine
= EM_386
;
5758 ehdr
.e_version
= EV_CURRENT
;
5759 ehdr
.e_entry
= 0; /* XXX: patch it */
5760 ehdr
.e_phoff
= sizeof(Elf32_Ehdr
);
5761 ehdr
.e_shoff
= file_offset
;
5762 ehdr
.e_ehsize
= sizeof(Elf32_Ehdr
);
5763 ehdr
.e_phentsize
= sizeof(Elf32_Phdr
);
5764 ehdr
.e_phnum
= phnum
;
5765 ehdr
.e_shentsize
= sizeof(Elf32_Shdr
);
5766 ehdr
.e_shnum
= shnum
;
5767 ehdr
.e_shstrndx
= shnum
- 1;
5769 /* write elf file */
5770 f
= fopen(filename
, "w");
5772 error("could not write '%s'", filename
);
5773 fwrite(&ehdr
, 1, sizeof(Elf32_Ehdr
), f
);
5774 fwrite(phdr
, 1, phnum
* sizeof(Elf32_Phdr
), f
);
5775 offset
= sizeof(Elf32_Ehdr
) + phnum
* sizeof(Elf32_Phdr
);
5776 for(sec
= first_section
, i
= 1; sec
!= NULL
; sec
= sec
->next
, i
++) {
5778 while (offset
< sh
->sh_offset
) {
5782 size
= sec
->data_ptr
- sec
->data
;
5783 fwrite(sec
->data
, 1, size
, f
);
5786 while (offset
< ehdr
.e_shoff
) {
5790 fwrite(shdr
, 1, shnum
* sizeof(Elf32_Shdr
), f
);
5794 /* print the position in the source file of PC value 'pc' by reading
5795 the stabs debug information */
5796 static void rt_printline(unsigned long wanted_pc
)
5798 Stab_Sym
*sym
, *sym_end
;
5799 char func_name
[128];
5800 unsigned long func_addr
, last_pc
, pc
;
5801 const char *incl_files
[INCLUDE_STACK_SIZE
];
5802 int incl_index
, len
, last_line_num
, i
;
5803 const char *str
, *p
;
5805 func_name
[0] = '\0';
5808 last_pc
= 0xffffffff;
5810 sym
= (Stab_Sym
*)stab_section
->data
+ 1;
5811 sym_end
= (Stab_Sym
*)stab_section
->data_ptr
;
5812 while (sym
< sym_end
) {
5813 switch(sym
->n_type
) {
5814 /* function start or end */
5816 if (sym
->n_strx
== 0) {
5817 func_name
[0] = '\0';
5820 str
= stabstr_section
->data
+ sym
->n_strx
;
5821 p
= strchr(str
, ':');
5823 pstrcpy(func_name
, sizeof(func_name
), str
);
5826 if (len
> sizeof(func_name
) - 1)
5827 len
= sizeof(func_name
) - 1;
5828 memcpy(func_name
, str
, len
);
5829 func_name
[len
] = '\0';
5831 func_addr
= sym
->n_value
;
5834 /* line number info */
5836 pc
= sym
->n_value
+ func_addr
;
5837 if (wanted_pc
>= last_pc
&& wanted_pc
< pc
)
5840 last_line_num
= sym
->n_desc
;
5844 str
= stabstr_section
->data
+ sym
->n_strx
;
5846 if (incl_index
< INCLUDE_STACK_SIZE
) {
5847 incl_files
[incl_index
++] = str
;
5855 if (sym
->n_strx
== 0) {
5856 incl_index
= 0; /* end of translation unit */
5858 str
= stabstr_section
->data
+ sym
->n_strx
;
5859 /* do not add path */
5861 if (len
> 0 && str
[len
- 1] != '/')
5868 /* did not find line number info: */
5869 fprintf(stderr
, "(no debug info, pc=0x%08lx) ", wanted_pc
);
5872 for(i
= 0; i
< incl_index
- 1; i
++)
5873 fprintf(stderr
, "In file included from %s\n",
5875 if (incl_index
> 0) {
5876 fprintf(stderr
, "%s:%d: ",
5877 incl_files
[incl_index
- 1], last_line_num
);
5879 if (func_name
[0] != '\0') {
5880 fprintf(stderr
, "in function '%s()': ", func_name
);
5885 /* signal handler for fatal errors */
5886 static void sig_error(int signum
, siginfo_t
*siginf
, void *puc
)
5888 struct ucontext
*uc
= puc
;
5892 pc
= uc
->uc_mcontext
.gregs
[14];
5894 #error please put the right sigcontext field
5901 switch(siginf
->si_code
) {
5904 fprintf(stderr
, "division by zero\n");
5907 fprintf(stderr
, "floating point exception\n");
5913 fprintf(stderr
, "dereferencing invalid pointer\n");
5916 fprintf(stderr
, "illegal instruction\n");
5919 fprintf(stderr
, "abort() called\n");
5922 fprintf(stderr
, "signal %d\n", signum
);
5928 /* launch the compiled program with the given arguments */
5929 int launch_exe(int argc
, char **argv
)
5933 struct sigaction sigact
;
5935 s
= sym_find1(&extern_stack
, TOK_MAIN
);
5936 if (!s
|| (s
->r
& VT_FORWARD
))
5937 error("main() not defined");
5940 /* install TCC signal handlers to print debug info on fatal
5942 sigact
.sa_flags
= SA_SIGINFO
| SA_ONESHOT
;
5943 sigact
.sa_sigaction
= sig_error
;
5944 sigemptyset(&sigact
.sa_mask
);
5945 sigaction(SIGFPE
, &sigact
, NULL
);
5946 sigaction(SIGILL
, &sigact
, NULL
);
5947 sigaction(SIGSEGV
, &sigact
, NULL
);
5948 sigaction(SIGBUS
, &sigact
, NULL
);
5949 sigaction(SIGABRT
, &sigact
, NULL
);
5952 if (do_bounds_check
) {
5955 /* add all known static regions */
5956 p
= (int *)bounds_section
->data
;
5957 p_end
= (int *)bounds_section
->data_ptr
;
5959 __bound_new_region((void *)p
[0], p
[1]);
5964 t
= (int (*)())s
->c
;
5965 return (*t
)(argc
, argv
);
5971 printf("tcc version 0.9.3 - Tiny C Compiler - Copyright (C) 2001, 2002 Fabrice Bellard\n"
5972 "usage: tcc [-Idir] [-Dsym[=val]] [-Usym] [-llib] [-g] [-b]\n"
5973 " [-i infile] infile [infile_args...]\n"
5975 "-Idir : add include path 'dir'\n"
5976 "-Dsym[=val] : define 'sym' with value 'val'\n"
5977 "-Usym : undefine 'sym'\n"
5978 "-llib : link with dynamic library 'lib'\n"
5979 "-g : generate debug info\n"
5980 "-b : compile with built-in memory and bounds checker (implies -g)\n"
5981 "-i infile : compile infile\n"
5985 int main(int argc
, char **argv
)
5987 char *p
, *r
, *outfile
;
5990 include_paths
[0] = "/usr/include";
5991 include_paths
[1] = "/usr/lib/tcc";
5992 include_paths
[2] = "/usr/local/lib/tcc";
5993 nb_include_paths
= 3;
5995 /* add all tokens */
5996 tok_ident
= TOK_IDENT
;
5997 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";
6001 tok_alloc(p
, r
- p
- 1);
6005 /* standard defines */
6006 define_symbol("__STDC__");
6008 define_symbol("__i386__");
6010 /* tiny C specific defines */
6011 define_symbol("__TINYC__");
6013 /* create standard sections */
6014 text_section
= new_section(".text", SHT_PROGBITS
, SHF_ALLOC
| SHF_EXECINSTR
);
6015 data_section
= new_section(".data", SHT_PROGBITS
, SHF_ALLOC
| SHF_WRITE
);
6016 /* XXX: should change type to SHT_NOBITS */
6017 bss_section
= new_section(".bss", SHT_PROGBITS
, SHF_ALLOC
| SHF_WRITE
);
6022 if (optind
>= argc
) {
6032 if (nb_include_paths
>= INCLUDE_PATHS_MAX
)
6033 error("too many include paths");
6034 include_paths
[nb_include_paths
++] = r
+ 2;
6035 } else if (r
[1] == 'D') {
6036 define_symbol(r
+ 2);
6037 } else if (r
[1] == 'U') {
6038 undef_symbol(r
+ 2);
6039 } else if (r
[1] == 'l') {
6041 } else if (r
[1] == 'i') {
6044 tcc_compile_file(argv
[optind
++]);
6045 } else if (r
[1] == 'b') {
6046 if (!do_bounds_check
) {
6047 do_bounds_check
= 1;
6048 /* create bounds section for global data */
6049 bounds_section
= new_section(".bounds",
6050 SHT_PROGBITS
, SHF_ALLOC
);
6051 /* debug is implied */
6054 } else if (r
[1] == 'g') {
6060 stab_section
= new_section(".stab", SHT_PROGBITS
, 0);
6061 stab_section
->sh_entsize
= sizeof(Stab_Sym
);
6062 stabstr_section
= new_section(".stabstr", SHT_STRTAB
, 0);
6063 put_elf_str(stabstr_section
, "");
6064 stab_section
->link
= stabstr_section
;
6065 /* put first entry */
6066 put_stabs("", 0, 0, 0, 0);
6069 symtab_section
= new_section(".symtab", SHT_SYMTAB
, 0);
6070 symtab_section
->sh_entsize
= sizeof(Elf32_Sym
);
6071 strtab_section
= new_section(".strtab", SHT_STRTAB
, 0);
6072 put_elf_str(strtab_section
, "");
6073 symtab_section
->link
= strtab_section
;
6074 put_elf_sym(symtab_section
, 0, 0, 0, 0, 0, NULL
);
6076 } else if (r
[1] == 'o') {
6077 /* currently, only for testing, so not documented */
6080 outfile
= argv
[optind
++];
6082 fprintf(stderr
, "invalid option -- '%s'\n", r
);
6087 tcc_compile_file(argv
[optind
]);
6089 resolve_extern_syms();
6095 return launch_exe(argc
- optind
, argv
+ optind
);