2 * TCC - Tiny C Compiler
4 * Copyright (c) 2001, 2002 Fabrice Bellard
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 #include <sys/ucontext.h>
33 #ifndef CONFIG_TCC_STATIC
38 /* preprocessor debug */
41 /* amount of virtual memory associate to a section (currently, we do
43 #define SECTION_VSIZE (1024 * 1024)
45 #define INCLUDE_STACK_SIZE 32
46 #define IFDEF_STACK_SIZE 64
47 #define VSTACK_SIZE 64
48 #define STRING_MAX_SIZE 1024
49 #define INCLUDE_PATHS_MAX 32
51 #define TOK_HASH_SIZE 521
52 #define TOK_ALLOC_INCR 256 /* must be a power of two */
53 #define SYM_HASH_SIZE 263
55 /* token symbol management */
56 typedef struct TokenSym
{
57 struct TokenSym
*hash_next
;
58 int tok
; /* token number */
64 typedef union CValue
{
70 unsigned int ul
; /* address (should be unsigned long on 64 bit cpu) */
72 unsigned long long ull
;
79 typedef struct SValue
{
81 unsigned short r
; /* register + flags */
82 unsigned short r2
; /* second register, used for 'long long'
83 type. If not used, set to VT_CONST */
84 CValue c
; /* constant */
87 /* symbol management */
89 int v
; /* symbol token */
90 int t
; /* associated type */
91 int r
; /* associated register */
92 int c
; /* associated number */
93 struct Sym
*next
; /* next related symbol */
94 struct Sym
*prev
; /* prev symbol in stack */
95 struct Sym
*hash_next
; /* next symbol in hash table */
98 typedef struct SymStack
{
100 struct Sym
*hash
[SYM_HASH_SIZE
];
103 /* relocation entry (currently only used for functions or variables */
104 typedef struct Reloc
{
105 int type
; /* type of relocation */
106 int addr
; /* address of relocation */
107 struct Reloc
*next
; /* next relocation */
110 #define RELOC_ADDR32 1 /* 32 bits relocation */
111 #define RELOC_REL32 2 /* 32 bits relative relocation */
113 /* section definition */
114 typedef struct Section
{
115 char name
[64]; /* section name */
116 unsigned char *data
; /* section data */
117 unsigned char *data_ptr
; /* current data pointer */
118 int sh_num
; /* elf section number */
119 int sh_type
; /* elf section type */
120 int sh_flags
; /* elf section flags */
121 int sh_entsize
; /* elf entry size */
122 struct Section
*link
; /* link to another section */
123 struct Section
*next
;
126 /* GNUC attribute definition */
127 typedef struct AttributeDef
{
132 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
133 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
134 #define SYM_FIRST_ANOM (1 << (31 - VT_STRUCT_SHIFT)) /* first anonymous sym */
136 #define FUNC_NEW 1 /* ansi function prototype */
137 #define FUNC_OLD 2 /* old function prototype */
138 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
140 /* field 'Sym.t' for macros */
141 #define MACRO_OBJ 0 /* object like macro */
142 #define MACRO_FUNC 1 /* function like macro */
144 /* type_decl() types */
145 #define TYPE_ABSTRACT 1 /* type without variable */
146 #define TYPE_DIRECT 2 /* type with variable */
157 int ch
, ch1
, tok
, tok1
;
161 Section
*first_section
;
163 Section
*text_section
, *data_section
, *bss_section
; /* predefined sections */
164 Section
*cur_text_section
; /* current section where function code is
166 /* bound check related sections */
167 Section
*bounds_section
; /* contains global data bound description */
168 Section
*lbounds_section
; /* contains local data bound description */
170 Section
*stab_section
, *stabstr_section
, *symtab_section
, *strtab_section
;
172 /* loc : local variable index
173 ind : output code index
175 anon_sym: anonymous symbol index
178 prog
, ind
, loc
, const_wanted
;
179 int global_expr
; /* true if compound literals must be allocated
180 globally (used during initializers parsing */
181 int func_vt
, func_vc
; /* current function return type (used by
182 return instruction) */
183 int last_line_num
, last_ind
, func_ind
; /* debug last line number and pc */
185 TokenSym
**table_ident
;
186 TokenSym
*hash_ident
[TOK_HASH_SIZE
];
187 char token_buf
[STRING_MAX_SIZE
+ 1];
188 char *filename
, *funcname
;
189 /* contains global symbols which remain between each translation unit */
190 SymStack extern_stack
;
191 SymStack define_stack
, global_stack
, local_stack
, label_stack
;
193 SValue vstack
[VSTACK_SIZE
], *vtop
;
194 int *macro_ptr
, *macro_ptr_allocated
;
195 IncludeFile include_stack
[INCLUDE_STACK_SIZE
], *include_stack_ptr
;
196 int ifdef_stack
[IFDEF_STACK_SIZE
], *ifdef_stack_ptr
;
197 char *include_paths
[INCLUDE_PATHS_MAX
];
198 int nb_include_paths
;
199 int char_pointer_type
;
201 /* compile with debug symbol (and use them if error during execution) */
204 /* compile with built-in memory and bounds checker */
205 int do_bounds_check
= 0;
207 /* use GNU C extensions */
210 /* use Tiny C extensions */
213 /* The current value can be: */
214 #define VT_VALMASK 0x00ff
215 #define VT_CONST 0x00f0 /* constant in vc
216 (must be first non register value) */
217 #define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */
218 #define VT_LOCAL 0x00f2 /* offset on stack */
219 #define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */
220 #define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */
221 #define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */
222 #define VT_LVAL 0x0100 /* var is an lvalue */
223 #define VT_FORWARD 0x0200 /* value is forward reference */
224 #define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for
225 char/short stored in integer registers) */
226 #define VT_MUSTBOUND 0x0800 /* bound checking must be done before
227 dereferencing value */
230 #define VT_STRUCT_SHIFT 16 /* structure/enum name shift (16 bits left) */
232 #define VT_INT 0 /* integer type */
233 #define VT_BYTE 1 /* signed byte type */
234 #define VT_SHORT 2 /* short type */
235 #define VT_VOID 3 /* void type */
236 #define VT_PTR 4 /* pointer increment */
237 #define VT_ENUM 5 /* enum definition */
238 #define VT_FUNC 6 /* function type */
239 #define VT_STRUCT 7 /* struct/union definition */
240 #define VT_FLOAT 8 /* IEEE float */
241 #define VT_DOUBLE 9 /* IEEE double */
242 #define VT_LDOUBLE 10 /* IEEE long double */
243 #define VT_BOOL 11 /* ISOC99 boolean type */
244 #define VT_LLONG 12 /* 64 bit integer */
245 #define VT_LONG 13 /* long integer (NEVER USED as type, only
247 #define VT_BTYPE 0x000f /* mask for basic type */
248 #define VT_UNSIGNED 0x0010 /* unsigned type */
249 #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
250 #define VT_BITFIELD 0x0040 /* bitfield modifier */
253 #define VT_EXTERN 0x00000080 /* extern definition */
254 #define VT_STATIC 0x00000100 /* static variable */
255 #define VT_TYPEDEF 0x00000200 /* typedef definition */
257 /* type mask (except storage) */
258 #define VT_TYPE (~(VT_EXTERN | VT_STATIC | VT_TYPEDEF))
262 /* warning: the following compare tokens depend on i386 asm code */
274 #define TOK_LAND 0xa0
278 #define TOK_MID 0xa3 /* inc/dec, to void constant */
280 #define TOK_UDIV 0xb0 /* unsigned division */
281 #define TOK_UMOD 0xb1 /* unsigned modulo */
282 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
283 #define TOK_CINT 0xb3 /* number in tokc */
284 #define TOK_CCHAR 0xb4 /* char constant in tokc */
285 #define TOK_STR 0xb5 /* pointer to string in tokc */
286 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
287 #define TOK_LCHAR 0xb7
288 #define TOK_LSTR 0xb8
289 #define TOK_CFLOAT 0xb9 /* float constant */
290 #define TOK_CDOUBLE 0xc0 /* double constant */
291 #define TOK_CLDOUBLE 0xc1 /* long double constant */
292 #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
293 #define TOK_ADDC1 0xc3 /* add with carry generation */
294 #define TOK_ADDC2 0xc4 /* add with carry use */
295 #define TOK_SUBC1 0xc5 /* add with carry generation */
296 #define TOK_SUBC2 0xc6 /* add with carry use */
297 #define TOK_CUINT 0xc8 /* unsigned int constant */
298 #define TOK_CLLONG 0xc9 /* long long constant */
299 #define TOK_CULLONG 0xca /* unsigned long long constant */
300 #define TOK_ARROW 0xcb
301 #define TOK_DOTS 0xcc /* three dots */
302 #define TOK_SHR 0xcd /* unsigned shift right */
304 #define TOK_SHL 0x01 /* shift left */
305 #define TOK_SAR 0x02 /* signed shift right */
307 /* assignement operators : normal operator or 0x80 */
308 #define TOK_A_MOD 0xa5
309 #define TOK_A_AND 0xa6
310 #define TOK_A_MUL 0xaa
311 #define TOK_A_ADD 0xab
312 #define TOK_A_SUB 0xad
313 #define TOK_A_DIV 0xaf
314 #define TOK_A_XOR 0xde
315 #define TOK_A_OR 0xfc
316 #define TOK_A_SHL 0x81
317 #define TOK_A_SAR 0x82
319 /* all identificators and strings have token above that */
320 #define TOK_IDENT 256
341 /* ignored types Must have contiguous values */
351 /* unsupported type */
365 /* preprocessor only */
366 TOK_UIDENT
, /* first "user" ident (not keyword) */
367 TOK_DEFINE
= TOK_UIDENT
,
383 /* special identifiers */
386 /* attribute identifiers */
395 /* XXX: need to define this to use them in non ISOC99 context */
396 extern float strtof (const char *__nptr
, char **__endptr
);
397 extern long double strtold (const char *__nptr
, char **__endptr
);
401 void next_nomacro(void);
402 int expr_const(void);
406 void decl_initializer(int t
, int r
, int c
, int first
, int size_only
);
407 int decl_initializer_alloc(int t
, AttributeDef
*ad
, int r
, int has_init
);
409 void gv2(int rc1
, int rc2
);
410 void move_reg(int r
, int s
);
411 void save_regs(void);
412 void save_reg(int r
);
418 void macro_subst(int **tok_str
, int *tok_len
,
419 Sym
**nested_list
, int *macro_str
);
420 int save_reg_forced(int r
);
422 void force_charshort_cast(int t
);
423 void gen_cast(int t
);
425 Sym
*sym_find(int v
);
426 Sym
*sym_push(int v
, int t
, int r
, int c
);
429 int type_size(int t
, int *a
);
430 int pointed_type(int t
);
431 int pointed_size(int t
);
432 int is_compatible_types(int t1
, int t2
);
433 int parse_btype(int *type_ptr
, AttributeDef
*ad
);
434 int type_decl(int *v
, int t
, int td
);
436 void error(const char *fmt
, ...);
438 void vset(int t
, int r
, int v
);
439 void type_to_str(char *buf
, int buf_size
,
440 int t
, const char *varstr
);
442 /* section generation */
443 void greloc(Sym
*s
, int addr
, int type
);
444 static int put_elf_str(Section
*s
, const char *sym
);
445 static void put_elf_sym(Section
*s
,
446 unsigned long value
, unsigned long size
,
447 int info
, int other
, int shndx
, const char *name
);
448 static void put_stabs(const char *str
, int type
, int other
, int desc
, int value
);
449 static void put_stabn(int type
, int other
, int desc
, int value
);
450 static void put_stabd(int type
, int other
, int desc
);
452 /* true if float/double/long double type */
453 static inline int is_float(int t
)
457 return bt
== VT_LDOUBLE
|| bt
== VT_DOUBLE
|| bt
== VT_FLOAT
;
462 #include "i386-gen.c"
464 #ifdef CONFIG_TCC_STATIC
466 #define RTLD_LAZY 0x001
467 #define RTLD_NOW 0x002
468 #define RTLD_GLOBAL 0x100
470 /* dummy function for profiling */
471 void *dlopen(const char *filename
, int flag
)
476 const char *dlerror(void)
481 typedef struct TCCSyms
{
486 #define TCCSYM(a) { #a, &a, },
488 /* add the symbol you want here if no dynamic linking is done */
489 static TCCSyms tcc_syms
[] = {
497 void *dlsym(void *handle
, char *symbol
)
501 while (p
->str
!= NULL
) {
502 if (!strcmp(p
->str
, symbol
))
511 /********************************************************/
512 /* runtime library is there */
513 /* XXX: we suppose that the host compiler handles 'long long'. It
514 would not be difficult to suppress this assumption */
516 /* XXX: these functions are defined in libgcc. Should provide a
517 portable code too. */
518 long long __divll(long long a
, long long b
)
523 long long __modll(long long a
, long long b
)
528 unsigned long long __divull(unsigned long long a
, unsigned long long b
)
533 unsigned long long __modull(unsigned long long a
, unsigned long long b
)
538 long long __sardi3(long long a
, int b
)
543 unsigned long long __shrdi3(unsigned long long a
, int b
)
548 long long __shldi3(long long a
, int b
)
553 float __ulltof(unsigned long long a
)
558 double __ulltod(unsigned long long a
)
563 long double __ulltold(unsigned long long a
)
565 return (long double)a
;
568 unsigned long long __ftoull(float a
)
570 return (unsigned long long)a
;
573 unsigned long long __dtoull(double a
)
575 return (unsigned long long)a
;
578 unsigned long long __ldtoull(long double a
)
580 return (unsigned long long)a
;
584 /********************************************************/
586 /* copy a string and truncate it */
587 char *pstrcpy(char *buf
, int buf_size
, const char *s
)
593 q_end
= buf
+ buf_size
- 1;
604 /* strcat and truncate */
605 char *pstrcat(char *buf
, int buf_size
, const char *s
)
610 pstrcpy(buf
+ len
, buf_size
- len
, s
);
614 Section
*new_section(const char *name
, int sh_type
, int sh_flags
)
616 Section
*sec
, **psec
;
619 sec
= malloc(sizeof(Section
));
621 error("memory full");
622 memset(sec
, 0, sizeof(Section
));
623 pstrcpy(sec
->name
, sizeof(sec
->name
), name
);
625 sec
->sh_num
= ++section_num
;
626 sec
->sh_type
= sh_type
;
627 sec
->sh_flags
= sh_flags
;
628 data
= mmap(NULL
, SECTION_VSIZE
,
629 PROT_EXEC
| PROT_READ
| PROT_WRITE
,
630 MAP_PRIVATE
| MAP_ANONYMOUS
,
632 if (data
== (void *)(-1))
633 error("could not mmap section '%s'", name
);
635 sec
->data_ptr
= data
;
636 psec
= &first_section
;
637 while (*psec
!= NULL
)
638 psec
= &(*psec
)->next
;
644 /* return a reference to a section, and create it if it does not
646 Section
*find_section(const char *name
)
650 for(sec
= first_section
; sec
!= NULL
; sec
= sec
->next
) {
651 if (!strcmp(name
, sec
->name
))
654 /* sections are created as PROGBITS */
655 return new_section(name
, SHT_PROGBITS
, SHF_ALLOC
);
658 /* add a new relocation entry to symbol 's' */
659 void greloc(Sym
*s
, int addr
, int type
)
662 p
= malloc(sizeof(Reloc
));
664 error("memory full");
667 p
->next
= (Reloc
*)s
->c
;
671 /* patch each relocation entry with value 'val' */
672 void greloc_patch(Sym
*s
, int val
)
679 greloc_patch1(p
, val
);
688 static inline int isid(int c
)
690 return (c
>= 'a' && c
<= 'z') ||
691 (c
>= 'A' && c
<= 'Z') ||
695 static inline int isnum(int c
)
697 return c
>= '0' && c
<= '9';
700 static inline int toup(int c
)
702 if (ch
>= 'a' && ch
<= 'z')
703 return ch
- 'a' + 'A';
711 for(f
= include_stack
; f
< include_stack_ptr
; f
++)
712 fprintf(stderr
, "In file included from %s:%d:\n",
713 f
->filename
, f
->line_num
);
714 fprintf(stderr
, "%s:%d: ", filename
, line_num
);
717 void error(const char *fmt
, ...)
722 vfprintf(stderr
, fmt
, ap
);
723 fprintf(stderr
, "\n");
728 void expect(const char *msg
)
730 error("%s expected", msg
);
733 void warning(const char *fmt
, ...)
739 fprintf(stderr
, "warning: ");
740 vfprintf(stderr
, fmt
, ap
);
741 fprintf(stderr
, "\n");
748 error("'%c' expected", c
);
752 void test_lvalue(void)
754 if (!(vtop
->r
& VT_LVAL
))
758 TokenSym
*tok_alloc(const char *str
, int len
)
760 TokenSym
*ts
, **pts
, **ptable
;
767 h
= ((h
<< 8) | (str
[i
] & 0xff)) % TOK_HASH_SIZE
;
769 pts
= &hash_ident
[h
];
774 if (ts
->len
== len
&& !memcmp(ts
->str
, str
, len
))
776 pts
= &(ts
->hash_next
);
779 if (tok_ident
>= SYM_FIRST_ANOM
)
780 error("memory full");
782 /* expand token table if needed */
783 i
= tok_ident
- TOK_IDENT
;
784 if ((i
% TOK_ALLOC_INCR
) == 0) {
785 ptable
= realloc(table_ident
, (i
+ TOK_ALLOC_INCR
) * sizeof(TokenSym
*));
787 error("memory full");
788 table_ident
= ptable
;
791 ts
= malloc(sizeof(TokenSym
) + len
);
793 error("memory full");
795 ts
->tok
= tok_ident
++;
797 ts
->hash_next
= NULL
;
798 memcpy(ts
->str
, str
, len
+ 1);
803 void add_char(char **pp
, int c
)
807 if (c
== '\'' || c
== '\"' || c
== '\\') {
808 /* XXX: could be more precise if char or string */
811 if (c
>= 32 && c
<= 126) {
818 *p
++ = '0' + ((c
>> 6) & 7);
819 *p
++ = '0' + ((c
>> 3) & 7);
820 *p
++ = '0' + (c
& 7);
826 /* XXX: buffer overflow */
827 char *get_tok_str(int v
, CValue
*cv
)
829 static char buf
[STRING_MAX_SIZE
+ 1];
834 if (v
== TOK_CINT
|| v
== TOK_CUINT
) {
835 sprintf(buf
, "%u", cv
->ui
);
837 } else if (v
== TOK_CCHAR
|| v
== TOK_LCHAR
) {
844 } else if (v
== TOK_STR
|| v
== TOK_LSTR
) {
848 for(i
=0;i
<ts
->len
;i
++)
849 add_char(&p
, ts
->str
[i
]);
853 } else if (v
< TOK_IDENT
) {
858 } else if (v
< tok_ident
) {
859 return table_ident
[v
- TOK_IDENT
]->str
;
861 /* should never happen */
866 /* push, without hashing */
867 Sym
*sym_push2(Sym
**ps
, int v
, int t
, int c
)
870 s
= malloc(sizeof(Sym
));
872 error("memory full");
883 /* find a symbol and return its associated structure. 's' is the top
884 of the symbol stack */
885 Sym
*sym_find2(Sym
*s
, int v
)
895 #define HASH_SYM(v) ((unsigned)(v) % SYM_HASH_SIZE)
897 /* find a symbol and return its associated structure. 'st' is the
899 Sym
*sym_find1(SymStack
*st
, int v
)
903 s
= st
->hash
[HASH_SYM(v
)];
912 Sym
*sym_push1(SymStack
*st
, int v
, int t
, int c
)
915 s
= sym_push2(&st
->top
, v
, t
, c
);
916 /* add in hash table */
918 ps
= &st
->hash
[HASH_SYM(v
)];
925 /* find a symbol in the right symbol space */
929 s
= sym_find1(&local_stack
, v
);
931 s
= sym_find1(&global_stack
, v
);
935 /* push a given symbol on the symbol stack */
936 Sym
*sym_push(int v
, int t
, int r
, int c
)
940 s
= sym_push1(&local_stack
, v
, t
, c
);
942 s
= sym_push1(&global_stack
, v
, t
, c
);
947 /* pop symbols until top reaches 'b' */
948 void sym_pop(SymStack
*st
, Sym
*b
)
955 /* free hash table entry, except if symbol was freed (only
956 used for #undef symbols) */
958 st
->hash
[HASH_SYM(s
->v
)] = s
->hash_next
;
965 /* undefined a hashed symbol (used for #undef). Its name is set to
967 void sym_undef(SymStack
*st
, Sym
*s
)
970 ss
= &st
->hash
[HASH_SYM(s
->v
)];
971 while (*ss
!= NULL
) {
974 ss
= &(*ss
)->hash_next
;
980 /* no need to put that inline */
983 if (include_stack_ptr
== include_stack
)
985 /* add end of include file debug info */
987 put_stabd(N_EINCL
, 0, 0);
989 /* pop include stack */
993 file
= include_stack_ptr
->file
;
994 filename
= include_stack_ptr
->filename
;
995 line_num
= include_stack_ptr
->line_num
;
999 /* read next char from current input file */
1000 static inline void inp(void)
1003 /* faster than fgetc */
1004 ch1
= getc_unlocked(file
);
1006 if (handle_eof() < 0)
1013 // printf("ch1=%c 0x%x\n", ch1, ch1);
1016 /* input with '\\n' handling */
1017 static inline void minp(void)
1022 if (ch
== '\\' && ch1
== '\n') {
1026 //printf("ch=%c 0x%x\n", ch, ch);
1030 /* same as minp, but also skip comments */
1038 /* single line C++ comments */
1040 while (ch1
!= '\n' && ch1
!= -1)
1043 ch
= ' '; /* return space */
1044 } else if (ch1
== '*') {
1050 if (c
== '*' && ch1
== '/') {
1052 ch
= ' '; /* return space */
1064 void skip_spaces(void)
1066 while (ch
== ' ' || ch
== '\t')
1070 /* skip block of text until #else, #elif or #endif. skip also pairs of
1072 void preprocess_skip()
1077 while (ch
!= '\n') {
1088 (tok
== TOK_ELSE
|| tok
== TOK_ELIF
|| tok
== TOK_ENDIF
))
1090 if (tok
== TOK_IF
|| tok
== TOK_IFDEF
|| tok
== TOK_IFNDEF
)
1092 else if (tok
== TOK_ENDIF
)
1098 /* return the number of additionnal 'ints' necessary to store the
1100 static inline int tok_ext_size(int t
)
1117 return LDOUBLE_SIZE
/ 4;
1123 void tok_add(int **tok_str
, int *tok_len
, int t
)
1128 if ((len
& 63) == 0) {
1129 str
= realloc(str
, (len
+ 64) * sizeof(int));
1138 void tok_add2(int **tok_str
, int *tok_len
, int t
, CValue
*cv
)
1142 tok_add(tok_str
, tok_len
, t
);
1143 n
= tok_ext_size(t
);
1145 tok_add(tok_str
, tok_len
, cv
->tab
[i
]);
1148 /* get a token from an integer array and increment pointer accordingly */
1149 int tok_get(int **tok_str
, CValue
*cv
)
1155 n
= tok_ext_size(t
);
1162 /* eval an expression for #if/#elif */
1163 int expr_preprocess(void)
1165 int *str
, len
, c
, t
;
1173 next(); /* do macro subst */
1174 if (tok
== TOK_DEFINED
) {
1179 c
= sym_find1(&define_stack
, tok
) != 0;
1184 } else if (tok
>= TOK_IDENT
) {
1185 /* if undefined macro */
1189 tok_add2(&str
, &len
, tok
, &tokc
);
1191 tok_add(&str
, &len
, -1); /* simulate end of file */
1192 tok_add(&str
, &len
, 0);
1193 /* now evaluate C constant expression */
1203 void tok_print(int *str
)
1209 t
= tok_get(&str
, &cval
);
1212 printf(" %s", get_tok_str(t
, &cval
));
1218 void preprocess(void)
1220 int size
, i
, c
, v
, t
, *str
, len
;
1221 char buf
[1024], *q
, *p
;
1224 Sym
**ps
, *first
, *s
;
1229 if (tok
== TOK_DEFINE
) {
1232 /* XXX: should check if same macro (ANSI) */
1235 /* '(' must be just after macro definition for MACRO_FUNC */
1240 while (tok
!= ')') {
1241 if (tok
== TOK_DOTS
)
1242 tok
= TOK___VA_ARGS__
;
1243 s
= sym_push1(&define_stack
, tok
| SYM_FIELD
, 0, 0);
1257 if (ch
== '\n' || ch
== -1)
1260 tok_add2(&str
, &len
, tok
, &tokc
);
1262 tok_add(&str
, &len
, 0);
1264 printf("define %s %d: ", get_tok_str(v
, NULL
), t
);
1267 s
= sym_push1(&define_stack
, v
, t
, (int)str
);
1269 } else if (tok
== TOK_UNDEF
) {
1271 s
= sym_find1(&define_stack
, tok
);
1272 /* undefine symbol by putting an invalid name */
1274 sym_undef(&define_stack
, s
);
1275 } else if (tok
== TOK_INCLUDE
) {
1280 } else if (ch
== '\"') {
1285 while (ch
!= c
&& ch
!= '\n' && ch
!= -1) {
1286 if ((q
- buf
) < sizeof(buf
) - 1)
1294 error("#include syntax error");
1295 pstrcpy(buf
, sizeof(buf
), get_tok_str(tok
, &tokc
));
1298 /* eat all spaces and comments after include */
1299 /* XXX: slightly incorrect */
1300 while (ch1
!= '\n' && ch1
!= -1)
1303 if (include_stack_ptr
>= include_stack
+ INCLUDE_STACK_SIZE
)
1304 error("memory full");
1306 /* first search in current dir if "header.h" */
1308 p
= strrchr(filename
, '/');
1310 size
= p
+ 1 - filename
;
1311 if (size
> sizeof(buf1
) - 1)
1312 size
= sizeof(buf1
) - 1;
1313 memcpy(buf1
, filename
, size
);
1315 pstrcat(buf1
, sizeof(buf1
), buf
);
1316 f
= fopen(buf1
, "r");
1320 /* now search in standard include path */
1321 for(i
=nb_include_paths
- 1;i
>=0;i
--) {
1322 strcpy(buf1
, include_paths
[i
]);
1325 f
= fopen(buf1
, "r");
1329 error("include file '%s' not found", buf1
);
1332 /* push current file in stack */
1333 /* XXX: fix current line init */
1334 include_stack_ptr
->file
= file
;
1335 include_stack_ptr
->filename
= filename
;
1336 include_stack_ptr
->line_num
= line_num
;
1337 include_stack_ptr
++;
1339 filename
= strdup(buf1
);
1341 /* add include file debug info */
1343 put_stabs(filename
, N_BINCL
, 0, 0, 0);
1345 } else if (tok
== TOK_IFNDEF
) {
1348 } else if (tok
== TOK_IF
) {
1349 c
= expr_preprocess();
1351 } else if (tok
== TOK_IFDEF
) {
1355 c
= (sym_find1(&define_stack
, tok
) != 0) ^ c
;
1357 if (ifdef_stack_ptr
>= ifdef_stack
+ IFDEF_STACK_SIZE
)
1358 error("memory full");
1359 *ifdef_stack_ptr
++ = c
;
1361 } else if (tok
== TOK_ELSE
) {
1362 if (ifdef_stack_ptr
== ifdef_stack
||
1363 (ifdef_stack_ptr
[-1] & 2))
1364 error("#else after #else");
1365 c
= (ifdef_stack_ptr
[-1] ^= 3);
1367 } else if (tok
== TOK_ELIF
) {
1368 if (ifdef_stack_ptr
== ifdef_stack
||
1369 ifdef_stack_ptr
[-1] > 1)
1370 error("#elif after #else");
1371 c
= expr_preprocess();
1372 ifdef_stack_ptr
[-1] = c
;
1378 } else if (tok
== TOK_ENDIF
) {
1379 if (ifdef_stack_ptr
== ifdef_stack
)
1382 } else if (tok
== TOK_LINE
) {
1384 if (tok
!= TOK_CINT
)
1392 /* XXX: potential memory leak */
1393 filename
= strdup(get_tok_str(tok
, &tokc
));
1395 } else if (tok
== TOK_ERROR
) {
1398 /* ignore other preprocess commands or #! for C scripts */
1399 while (ch
!= '\n' && ch
!= -1)
1403 /* read a number in base b */
1409 if (ch
>= 'a' && ch
<= 'f')
1411 else if (ch
>= 'A' && ch
<= 'F')
1417 if (t
< 0 || t
>= b
)
1425 /* read a character for string or char constant and eval escape codes */
1434 /* at most three octal digits */
1438 c
= c
* 8 + ch
- '0';
1441 c
= c
* 8 + ch
- '0';
1446 } else if (ch
== 'x') {
1464 else if (ch
== 'e' && gnu_ext
)
1466 else if (ch
== '\'' || ch
== '\"' || ch
== '\\' || ch
== '?')
1469 error("invalid escaped char");
1476 /* we use 64 bit numbers */
1479 /* bn = (bn << shift) | or_val */
1480 void bn_lshift(unsigned int *bn
, int shift
, int or_val
)
1484 for(i
=0;i
<BN_SIZE
;i
++) {
1486 bn
[i
] = (v
<< shift
) | or_val
;
1487 or_val
= v
>> (32 - shift
);
1491 void bn_zero(unsigned int *bn
)
1494 for(i
=0;i
<BN_SIZE
;i
++) {
1499 void parse_number(void)
1501 int b
, t
, shift
, frac_bits
, s
, exp_val
;
1503 unsigned int bn
[BN_SIZE
];
1513 /* special dot handling */
1514 if (ch
>= '0' && ch
<= '9') {
1515 goto float_frac_parse
;
1516 } else if (ch
== '.') {
1527 } else if (t
== '0') {
1528 if (ch
== 'x' || ch
== 'X') {
1532 } else if (tcc_ext
&& (ch
== 'b' || ch
== 'B')) {
1538 /* parse all digits. cannot check octal numbers at this stage
1539 because of floating point constants */
1541 if (ch
>= 'a' && ch
<= 'f')
1543 else if (ch
>= 'A' && ch
<= 'F')
1551 if (q
>= token_buf
+ STRING_MAX_SIZE
) {
1553 error("number too long");
1559 ((ch
== 'e' || ch
== 'E') && b
== 10) ||
1560 ((ch
== 'p' || ch
== 'P') && (b
== 16 || b
== 2))) {
1562 /* NOTE: strtox should support that for hexa numbers, but
1563 non ISOC99 libcs do not support it, so we prefer to do
1565 /* hexadecimal or binary floats */
1566 /* XXX: handle overflows */
1578 } else if (t
>= 'a') {
1580 } else if (t
>= 'A') {
1585 bn_lshift(bn
, shift
, t
);
1592 if (t
>= 'a' && t
<= 'f') {
1594 } else if (t
>= 'A' && t
<= 'F') {
1596 } else if (t
>= '0' && t
<= '9') {
1602 error("invalid digit");
1603 bn_lshift(bn
, shift
, t
);
1608 if (ch
!= 'p' && ch
!= 'P')
1609 error("exponent expected");
1615 } else if (ch
== '-') {
1619 if (ch
< '0' || ch
> '9')
1620 error("exponent digits expected");
1621 while (ch
>= '0' && ch
<= '9') {
1622 exp_val
= exp_val
* 10 + ch
- '0';
1625 exp_val
= exp_val
* s
;
1627 /* now we can generate the number */
1628 /* XXX: should patch directly float number */
1629 d
= (double)bn
[1] * 4294967296.0 + (double)bn
[0];
1630 d
= ldexp(d
, exp_val
- frac_bits
);
1635 /* float : should handle overflow */
1637 } else if (t
== 'L') {
1640 /* XXX: not large enough */
1641 tokc
.ld
= (long double)d
;
1647 /* decimal floats */
1649 if (q
>= token_buf
+ STRING_MAX_SIZE
)
1654 while (ch
>= '0' && ch
<= '9') {
1655 if (q
>= token_buf
+ STRING_MAX_SIZE
)
1661 if (ch
== 'e' || ch
== 'E') {
1662 if (q
>= token_buf
+ STRING_MAX_SIZE
)
1666 if (ch
== '-' || ch
== '+') {
1667 if (q
>= token_buf
+ STRING_MAX_SIZE
)
1672 if (ch
< '0' || ch
> '9')
1673 error("exponent digits expected");
1674 while (ch
>= '0' && ch
<= '9') {
1675 if (q
>= token_buf
+ STRING_MAX_SIZE
)
1687 tokc
.f
= strtof(token_buf
, NULL
);
1688 } else if (t
== 'L') {
1691 tokc
.ld
= strtold(token_buf
, NULL
);
1694 tokc
.d
= strtod(token_buf
, NULL
);
1698 unsigned long long n
, n1
;
1701 /* integer number */
1704 if (b
== 10 && *q
== '0') {
1711 /* no need for checks except for base 10 / 8 errors */
1714 } else if (t
>= 'a') {
1716 } else if (t
>= 'A') {
1721 error("invalid digit");
1725 /* detect overflow */
1727 error("integer constant overflow");
1730 /* XXX: not exactly ANSI compliant */
1731 if ((n
& 0xffffffff00000000LL
) != 0) {
1736 } else if (n
> 0x7fffffff) {
1746 error("three 'l' in integer constant");
1749 if (tok
== TOK_CINT
)
1751 else if (tok
== TOK_CUINT
)
1755 } else if (t
== 'U') {
1756 if (tok
== TOK_CINT
)
1758 else if (tok
== TOK_CLLONG
)
1765 if (tok
== TOK_CINT
|| tok
== TOK_CUINT
)
1773 /* return next token without macro substitution */
1774 void next_nomacro1(void)
1782 while (ch
== '\n') {
1784 while (ch
== ' ' || ch
== 9)
1787 /* preprocessor command if # at start of line after
1792 if (ch
!= ' ' && ch
!= '\t' && ch
!= '\f')
1810 while (isid(ch
) || isnum(ch
)) {
1811 if (q
>= token_buf
+ STRING_MAX_SIZE
)
1812 error("ident too long");
1817 ts
= tok_alloc(token_buf
, q
- token_buf
);
1819 } else if (isnum(ch
) || ch
== '.') {
1821 } else if (ch
== '\'') {
1829 } else if (ch
== '\"') {
1834 while (ch
!= '\"') {
1837 error("unterminated string");
1838 if (q
>= token_buf
+ STRING_MAX_SIZE
)
1839 error("string too long");
1843 tokc
.ts
= tok_alloc(token_buf
, q
- token_buf
);
1846 q
= "<=\236>=\235!=\225&&\240||\241++\244--\242==\224<<\1>>\2+=\253-=\255*=\252/=\257%=\245&=\246^=\336|=\374->\313..\250##\266";
1851 if (*q
== tok
&& q
[1] == ch
) {
1854 /* three chars tests */
1855 if (tok
== TOK_SHL
|| tok
== TOK_SAR
) {
1860 } else if (tok
== TOK_DOTS
) {
1862 error("parse error");
1869 /* single char substitutions */
1872 else if (tok
== '>')
1877 /* return next token without macro substitution. Can read input from
1884 tok
= tok_get(¯o_ptr
, &tokc
);
1890 /* substitute args in macro_str and return allocated string */
1891 int *macro_arg_subst(Sym
**nested_list
, int *macro_str
, Sym
*args
)
1893 int *st
, last_tok
, t
, notfirst
, *str
, len
;
1902 t
= tok_get(¯o_str
, &cval
);
1907 t
= tok_get(¯o_str
, &cval
);
1910 s
= sym_find2(args
, t
);
1912 token_buf
[0] = '\0';
1917 pstrcat(token_buf
, sizeof(token_buf
), " ");
1918 t
= tok_get(&st
, &cval
);
1919 pstrcat(token_buf
, sizeof(token_buf
), get_tok_str(t
, &cval
));
1923 printf("stringize: %s\n", token_buf
);
1926 ts
= tok_alloc(token_buf
, 0);
1928 tok_add2(&str
, &len
, TOK_STR
, &cval
);
1930 tok_add2(&str
, &len
, t
, &cval
);
1932 } else if (t
>= TOK_IDENT
) {
1933 s
= sym_find2(args
, t
);
1936 /* if '##' is present before or after , no arg substitution */
1937 if (*macro_str
== TOK_TWOSHARPS
|| last_tok
== TOK_TWOSHARPS
) {
1939 tok_add(&str
, &len
, *st
++);
1941 macro_subst(&str
, &len
, nested_list
, st
);
1944 tok_add(&str
, &len
, t
);
1947 tok_add2(&str
, &len
, t
, &cval
);
1951 tok_add(&str
, &len
, 0);
1955 /* handle the '##' operator */
1956 int *macro_twosharps(int *macro_str
)
1959 int *macro_str1
, macro_str1_len
, *macro_ptr1
;
1971 while (*macro_ptr
== TOK_TWOSHARPS
) {
1973 macro_ptr1
= macro_ptr
;
1976 t
= tok_get(¯o_ptr
, &cval
);
1977 /* XXX: we handle only most common cases:
1978 ident + ident or ident + number */
1979 if (tok
>= TOK_IDENT
&&
1980 (t
>= TOK_IDENT
|| t
== TOK_CINT
)) {
1981 p
= get_tok_str(tok
, &tokc
);
1982 pstrcpy(token_buf
, sizeof(token_buf
), p
);
1983 p
= get_tok_str(t
, &cval
);
1984 pstrcat(token_buf
, sizeof(token_buf
), p
);
1985 ts
= tok_alloc(token_buf
, 0);
1986 tok
= ts
->tok
; /* modify current token */
1988 /* cannot merge tokens: skip '##' */
1989 macro_ptr
= macro_ptr1
;
1994 tok_add2(¯o_str1
, ¯o_str1_len
, tok
, &tokc
);
1996 tok_add(¯o_str1
, ¯o_str1_len
, 0);
2002 /* do macro substitution of macro_str and add result to
2003 (tok_str,tok_len). If macro_str is NULL, then input stream token is
2004 substituted. 'nested_list' is the list of all macros we got inside
2005 to avoid recursing. */
2006 void macro_subst(int **tok_str
, int *tok_len
,
2007 Sym
**nested_list
, int *macro_str
)
2009 Sym
*s
, *args
, *sa
, *sa1
;
2010 int *str
, parlevel
, len
, *mstr
, t
, *saved_macro_ptr
;
2011 int mstr_allocated
, *macro_str1
;
2014 saved_macro_ptr
= macro_ptr
;
2015 macro_ptr
= macro_str
;
2018 /* first scan for '##' operator handling */
2019 macro_str1
= macro_twosharps(macro_str
);
2020 macro_ptr
= macro_str1
;
2027 /* special macros */
2028 if (tok
== TOK___LINE__
) {
2030 tok_add2(tok_str
, tok_len
, TOK_CINT
, &cval
);
2031 } else if (tok
== TOK___FILE__
) {
2032 cval
.ts
= tok_alloc(filename
, 0);
2033 tok_add2(tok_str
, tok_len
, TOK_STR
, &cval
);
2034 } else if (tok
== TOK___DATE__
) {
2035 cval
.ts
= tok_alloc("Jan 1 1970", 0);
2036 tok_add2(tok_str
, tok_len
, TOK_STR
, &cval
);
2037 } else if (tok
== TOK___TIME__
) {
2038 cval
.ts
= tok_alloc("00:00:00", 0);
2039 tok_add2(tok_str
, tok_len
, TOK_STR
, &cval
);
2040 } else if ((s
= sym_find1(&define_stack
, tok
)) != NULL
) {
2041 /* if symbol is a macro, prepare substitution */
2042 /* if nested substitution, do nothing */
2043 if (sym_find2(*nested_list
, tok
))
2047 if (s
->t
== MACRO_FUNC
) {
2048 /* NOTE: we do not use next_nomacro to avoid eating the
2049 next token. XXX: find better solution */
2053 while (ch
== ' ' || ch
== '\t' || ch
== '\n')
2057 if (t
!= '(') /* no macro subst */
2060 /* argument macro */
2065 while (tok
!= ')' && sa
) {
2069 while ((parlevel
> 0 ||
2072 sa
->v
== (TOK___VA_ARGS__
| SYM_FIELD
)))) &&
2076 else if (tok
== ')')
2078 tok_add2(&str
, &len
, tok
, &tokc
);
2081 tok_add(&str
, &len
, 0);
2082 sym_push2(&args
, sa
->v
& ~SYM_FIELD
, 0, (int)str
);
2090 /* now subst each arg */
2091 mstr
= macro_arg_subst(nested_list
, mstr
, args
);
2102 sym_push2(nested_list
, s
->v
, 0, 0);
2103 macro_subst(tok_str
, tok_len
, nested_list
, mstr
);
2104 /* pop nested defined symbol */
2106 *nested_list
= sa1
->prev
;
2112 /* no need to add if reading input stream */
2115 tok_add2(tok_str
, tok_len
, tok
, &tokc
);
2117 /* only replace one macro while parsing input stream */
2121 macro_ptr
= saved_macro_ptr
;
2126 /* return next token with macro substitution */
2132 /* special 'ungettok' case for label parsing */
2140 /* if not reading from macro substuted string, then try to substitute */
2144 macro_subst(&ptr
, &len
, &nested_list
, NULL
);
2146 tok_add(&ptr
, &len
, 0);
2148 macro_ptr_allocated
= ptr
;
2156 /* end of macro string: free it */
2157 free(macro_ptr_allocated
);
2164 printf("token = %s\n", get_tok_str(tok
, tokc
));
2168 void swap(int *p
, int *q
)
2176 void vsetc(int t
, int r
, CValue
*vc
)
2178 if (vtop
>= vstack
+ VSTACK_SIZE
)
2179 error("memory full");
2180 /* cannot let cpu flags if other instruction are generated */
2181 /* XXX: VT_JMP test too ? */
2182 if ((vtop
->r
& VT_VALMASK
) == VT_CMP
)
2187 vtop
->r2
= VT_CONST
;
2191 /* push integer constant */
2196 vsetc(VT_INT
, VT_CONST
, &cval
);
2199 void vset(int t
, int r
, int v
)
2216 void vpushv(SValue
*v
)
2218 if (vtop
>= vstack
+ VSTACK_SIZE
)
2219 error("memory full");
2229 /* save r to the memory stack, and mark it as being free */
2230 void save_reg(int r
)
2232 int l
, i
, saved
, t
, size
, align
;
2235 /* modify all stack values */
2238 for(p
=vstack
;p
<=vtop
;p
++) {
2239 i
= p
->r
& VT_VALMASK
;
2240 if ((p
->r
& VT_VALMASK
) == r
||
2241 (p
->r2
& VT_VALMASK
) == r
) {
2242 /* must save value on stack if not already done */
2244 /* store register in the stack */
2246 if (!is_float(t
) && (t
& VT_BTYPE
) != VT_LLONG
)
2248 size
= type_size(t
, &align
);
2249 loc
= (loc
- size
) & -align
;
2251 sv
.r
= VT_LOCAL
| VT_LVAL
;
2254 /* XXX: x86 specific: need to pop fp register ST0 if saved */
2256 o(0xd9dd); /* fstp %st(1) */
2258 /* special long long case */
2259 if ((p
->t
& VT_BTYPE
) == VT_LLONG
) {
2266 /* mark that stack entry as being saved on the stack */
2278 /* find a free register of class 'rc'. If none, save one register */
2284 /* find a free register */
2285 for(r
=0;r
<NB_REGS
;r
++) {
2286 if (reg_classes
[r
] & rc
) {
2287 for(p
=vstack
;p
<=vtop
;p
++) {
2288 if ((p
->r
& VT_VALMASK
) == r
||
2289 (p
->r2
& VT_VALMASK
) == r
)
2297 /* no register left : free the first one on the stack (VERY
2298 IMPORTANT to start from the bottom to ensure that we don't
2299 spill registers used in gen_opi()) */
2300 for(p
=vstack
;p
<=vtop
;p
++) {
2301 r
= p
->r
& VT_VALMASK
;
2302 if (r
< VT_CONST
&& (reg_classes
[r
] & rc
)) {
2310 void save_regs(void)
2315 for(p
=vstack
;p
<=vtop
;p
++) {
2316 r
= p
->r
& VT_VALMASK
;
2323 /* move register 's' to 'r', and flush previous value of r to memory
2325 void move_reg(int r
, int s
)
2338 /* get address of vtop (vtop MUST BE an lvalue) */
2341 vtop
->r
&= ~VT_LVAL
;
2342 /* tricky: if saved lvalue, then we can go back to lvalue */
2343 if ((vtop
->r
& VT_VALMASK
) == VT_LLOCAL
)
2344 vtop
->r
= (vtop
->r
& ~VT_VALMASK
) | VT_LOCAL
| VT_LVAL
;
2347 /* generate lvalue bound code */
2350 vtop
->r
&= ~VT_MUSTBOUND
;
2351 /* if lvalue, then use checking code before dereferencing */
2352 if (vtop
->r
& VT_LVAL
) {
2355 gen_bounded_ptr_add1();
2356 gen_bounded_ptr_add2(1);
2361 /* store vtop a register belonging to class 'rc'. lvalues are
2362 converted to values. Cannot be used if cannot be converted to
2363 register value (such as structures). */
2366 int r
, r2
, rc2
, bit_pos
, bit_size
, size
, align
, i
, data_offset
;
2367 unsigned long long ll
;
2369 /* NOTE: get_reg can modify vstack[] */
2370 if (vtop
->t
& VT_BITFIELD
) {
2371 bit_pos
= (vtop
->t
>> VT_STRUCT_SHIFT
) & 0x3f;
2372 bit_size
= (vtop
->t
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f;
2373 /* remove bit field info to avoid loops */
2374 vtop
->t
&= ~(VT_BITFIELD
| (-1 << VT_STRUCT_SHIFT
));
2375 /* generate shifts */
2376 vpushi(32 - (bit_pos
+ bit_size
));
2378 vpushi(32 - bit_size
);
2379 /* NOTE: transformed to SHR if unsigned */
2383 if (is_float(vtop
->t
) &&
2384 (vtop
->r
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
) {
2385 /* CPUs usually cannot use float constants, so we store them
2386 generically in data segment */
2387 size
= type_size(vtop
->t
, &align
);
2388 data_offset
= (int)data_section
->data_ptr
;
2389 data_offset
= (data_offset
+ align
- 1) & -align
;
2390 /* XXX: not portable yet */
2393 ((int *)data_offset
)[i
] = vtop
->c
.tab
[i
];
2395 vtop
->c
.ul
= data_offset
;
2396 data_offset
+= size
<< 2;
2397 data_section
->data_ptr
= (unsigned char *)data_offset
;
2399 if (vtop
->r
& VT_MUSTBOUND
)
2402 r
= vtop
->r
& VT_VALMASK
;
2403 /* need to reload if:
2405 - lvalue (need to dereference pointer)
2406 - already a register, but not in the right class */
2407 if (r
>= VT_CONST
||
2408 (vtop
->r
& VT_LVAL
) ||
2409 !(reg_classes
[r
] & rc
) ||
2410 ((vtop
->t
& VT_BTYPE
) == VT_LLONG
&&
2411 !(reg_classes
[vtop
->r2
] & rc
))) {
2413 if ((vtop
->t
& VT_BTYPE
) == VT_LLONG
) {
2414 /* two register type load : expand to two words
2416 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
) {
2419 vtop
->c
.ui
= ll
; /* first word */
2421 vtop
->r
= r
; /* save register value */
2422 vpushi(ll
>> 32); /* second word */
2423 } else if (r
>= VT_CONST
||
2424 (vtop
->r
& VT_LVAL
)) {
2425 /* load from memory */
2428 vtop
[-1].r
= r
; /* save register value */
2429 /* increment pointer to get second word */
2436 /* move registers */
2439 vtop
[-1].r
= r
; /* save register value */
2440 vtop
->r
= vtop
[-1].r2
;
2442 /* allocate second register */
2449 /* write second register */
2452 /* one register type load */
2461 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
2462 void gv2(int rc1
, int rc2
)
2464 /* generate more generic register first */
2470 /* test if reload is needed for first register */
2471 if ((vtop
[-1].r
& VT_VALMASK
) >= VT_CONST
) {
2481 /* test if reload is needed for first register */
2482 if ((vtop
[0].r
& VT_VALMASK
) >= VT_CONST
) {
2488 /* expand long long on stack in two int registers */
2493 u
= vtop
->t
& VT_UNSIGNED
;
2496 vtop
[0].r
= vtop
[-1].r2
;
2497 vtop
[0].r2
= VT_CONST
;
2498 vtop
[-1].r2
= VT_CONST
;
2499 vtop
[0].t
= VT_INT
| u
;
2500 vtop
[-1].t
= VT_INT
| u
;
2503 /* build a long long from two ints */
2506 gv2(RC_INT
, RC_INT
);
2507 vtop
[-1].r2
= vtop
[0].r
;
2512 /* rotate n first stack elements to the bottom */
2519 for(i
=-n
+1;i
!=0;i
++)
2520 vtop
[i
] = vtop
[i
+1];
2524 /* pop stack value */
2527 /* for x86, we need to pop the FP stack */
2528 if ((vtop
->r
& VT_VALMASK
) == REG_ST0
) {
2529 o(0xd9dd); /* fstp %st(1) */
2534 /* convert stack entry to register and duplicate its value in another
2542 if ((t
& VT_BTYPE
) == VT_LLONG
) {
2549 /* stack: H L L1 H1 */
2557 /* duplicate value */
2568 load(r1
, &sv
); /* move r to r1 */
2570 /* duplicates value */
2575 /* generate CPU independent (unsigned) long long operations */
2576 void gen_opl(int op
)
2578 int t
, a
, b
, op1
, c
, i
;
2597 /* call generic long long function */
2605 vtop
->r2
= REG_LRET
;
2618 /* stack: L1 H1 L2 H2 */
2623 vtop
[-2] = vtop
[-3];
2626 /* stack: H1 H2 L1 L2 */
2632 /* stack: H1 H2 L1 L2 ML MH */
2635 /* stack: ML MH H1 H2 L1 L2 */
2639 /* stack: ML MH H1 L2 H2 L1 */
2644 /* stack: ML MH M1 M2 */
2647 } else if (op
== '+' || op
== '-') {
2648 /* XXX: add non carry method too (for MIPS ?) */
2654 /* stack: H1 H2 (L1 op L2) */
2657 gen_op(op1
+ 1); /* TOK_xxxC2 */
2660 /* stack: H1 H2 (L1 op L2) */
2663 /* stack: (L1 op L2) H1 H2 */
2665 /* stack: (L1 op L2) (H1 op H2) */
2673 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_FORWARD
)) == VT_CONST
) {
2678 /* stack: L H shift */
2680 /* constant: simpler */
2681 /* NOTE: all comments are for SHL. the other cases are
2682 done by swaping words */
2693 if (op
!= TOK_SAR
) {
2723 /* XXX: should provide a faster fallback on x86 ? */
2738 /* compare operations */
2744 /* stack: L1 H1 L2 H2 */
2746 vtop
[-1] = vtop
[-2];
2748 /* stack: L1 L2 H1 H2 */
2751 /* when values are equal, we need to compare low words. since
2752 the jump is inverted, we invert the test too. */
2755 else if (op1
== TOK_GT
)
2757 else if (op1
== TOK_ULT
)
2759 else if (op1
== TOK_UGT
)
2764 if (op1
!= TOK_NE
) {
2768 /* generate non equal test */
2769 /* XXX: NOT PORTABLE yet */
2773 b
= psym(0x850f, 0);
2779 vset(VT_INT
, VT_JMPI
, a
);
2784 /* handle constant optimizations and various machine independant opt */
2785 void gen_opc(int op
)
2792 /* currently, we cannot do computations with forward symbols */
2793 c1
= (v1
->r
& (VT_VALMASK
| VT_LVAL
| VT_FORWARD
)) == VT_CONST
;
2794 c2
= (v2
->r
& (VT_VALMASK
| VT_LVAL
| VT_FORWARD
)) == VT_CONST
;
2798 case '+': v1
->c
.i
+= fc
; break;
2799 case '-': v1
->c
.i
-= fc
; break;
2800 case '&': v1
->c
.i
&= fc
; break;
2801 case '^': v1
->c
.i
^= fc
; break;
2802 case '|': v1
->c
.i
|= fc
; break;
2803 case '*': v1
->c
.i
*= fc
; break;
2805 case '/': v1
->c
.i
/= fc
; break; /* XXX: zero case ? */
2806 case '%': v1
->c
.i
%= fc
; break; /* XXX: zero case ? */
2807 case TOK_UDIV
: v1
->c
.i
= (unsigned)v1
->c
.i
/ fc
; break; /* XXX: zero case ? */
2808 case TOK_UMOD
: v1
->c
.i
= (unsigned)v1
->c
.i
% fc
; break; /* XXX: zero case ? */
2809 case TOK_SHL
: v1
->c
.i
<<= fc
; break;
2810 case TOK_SHR
: v1
->c
.i
= (unsigned)v1
->c
.i
>> fc
; break;
2811 case TOK_SAR
: v1
->c
.i
>>= fc
; break;
2813 case TOK_ULT
: v1
->c
.i
= (unsigned)v1
->c
.i
< (unsigned)fc
; break;
2814 case TOK_UGE
: v1
->c
.i
= (unsigned)v1
->c
.i
>= (unsigned)fc
; break;
2815 case TOK_EQ
: v1
->c
.i
= v1
->c
.i
== fc
; break;
2816 case TOK_NE
: v1
->c
.i
= v1
->c
.i
!= fc
; break;
2817 case TOK_ULE
: v1
->c
.i
= (unsigned)v1
->c
.i
<= (unsigned)fc
; break;
2818 case TOK_UGT
: v1
->c
.i
= (unsigned)v1
->c
.i
> (unsigned)fc
; break;
2819 case TOK_LT
: v1
->c
.i
= v1
->c
.i
< fc
; break;
2820 case TOK_GE
: v1
->c
.i
= v1
->c
.i
>= fc
; break;
2821 case TOK_LE
: v1
->c
.i
= v1
->c
.i
<= fc
; break;
2822 case TOK_GT
: v1
->c
.i
= v1
->c
.i
> fc
; break;
2824 case TOK_LAND
: v1
->c
.i
= v1
->c
.i
&& fc
; break;
2825 case TOK_LOR
: v1
->c
.i
= v1
->c
.i
|| fc
; break;
2831 /* if commutative ops, put c2 as constant */
2832 if (c1
&& (op
== '+' || op
== '&' || op
== '^' ||
2833 op
== '|' || op
== '*')) {
2838 if (c2
&& (((op
== '*' || op
== '/' || op
== TOK_UDIV
||
2841 ((op
== '+' || op
== '-' || op
== '|' || op
== '^' ||
2842 op
== TOK_SHL
|| op
== TOK_SHR
|| op
== TOK_SAR
) &&
2848 } else if (c2
&& (op
== '*' || op
== TOK_PDIV
|| op
== TOK_UDIV
)) {
2849 /* try to use shifts instead of muls or divs */
2850 if (fc
> 0 && (fc
& (fc
- 1)) == 0) {
2859 else if (op
== TOK_PDIV
)
2867 /* call low level op generator */
2868 /* XXX: remove explicit registers */
2874 int pointed_size(int t
)
2876 return type_size(pointed_type(t
), &t
);
2880 void check_pointer_types(SValue
*p1
, SValue
*p2
)
2882 char buf1
[256], buf2
[256];
2886 if (!is_compatible_types(t1
, t2
)) {
2887 type_to_str(buf1
, sizeof(buf1
), t1
, NULL
);
2888 type_to_str(buf2
, sizeof(buf2
), t2
, NULL
);
2889 error("incompatible pointers '%s' and '%s'", buf1
, buf2
);
2894 /* generic gen_op: handles types problems */
2897 int u
, t1
, t2
, bt1
, bt2
, t
;
2901 bt1
= t1
& VT_BTYPE
;
2902 bt2
= t2
& VT_BTYPE
;
2904 if (bt1
== VT_PTR
|| bt2
== VT_PTR
) {
2905 /* at least one operand is a pointer */
2906 /* relationnal op: must be both pointers */
2907 if (op
>= TOK_ULT
&& op
<= TOK_GT
) {
2908 // check_pointer_types(vtop, vtop - 1);
2909 /* pointers are handled are unsigned */
2910 t
= VT_INT
| VT_UNSIGNED
;
2913 /* if both pointers, then it must be the '-' op */
2914 if ((t1
& VT_BTYPE
) == VT_PTR
&&
2915 (t2
& VT_BTYPE
) == VT_PTR
) {
2917 error("cannot use pointers here");
2918 // check_pointer_types(vtop - 1, vtop);
2919 /* XXX: check that types are compatible */
2920 u
= pointed_size(t1
);
2922 /* set to integer type */
2927 /* exactly one pointer : must be '+' or '-'. */
2928 if (op
!= '-' && op
!= '+')
2929 error("cannot use pointers here");
2930 /* Put pointer as first operand */
2931 if ((t2
& VT_BTYPE
) == VT_PTR
) {
2935 /* XXX: cast to int ? (long long case) */
2936 vpushi(pointed_size(vtop
[-1].t
));
2938 if (do_bounds_check
) {
2939 /* if bounded pointers, we generate a special code to
2946 gen_bounded_ptr_add1();
2947 gen_bounded_ptr_add2(0);
2951 /* put again type if gen_opc() swaped operands */
2954 } else if (is_float(bt1
) || is_float(bt2
)) {
2955 /* compute bigger type and do implicit casts */
2956 if (bt1
== VT_LDOUBLE
|| bt2
== VT_LDOUBLE
) {
2958 } else if (bt1
== VT_DOUBLE
|| bt2
== VT_DOUBLE
) {
2963 /* floats can only be used for a few operations */
2964 if (op
!= '+' && op
!= '-' && op
!= '*' && op
!= '/' &&
2965 (op
< TOK_ULT
|| op
> TOK_GT
))
2966 error("invalid operands for binary operation");
2968 } else if (bt1
== VT_LLONG
|| bt2
== VT_LLONG
) {
2969 /* cast to biggest op */
2971 /* convert to unsigned if it does not fit in a long long */
2972 if ((t1
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_LLONG
| VT_UNSIGNED
) ||
2973 (t2
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_LLONG
| VT_UNSIGNED
))
2977 /* integer operations */
2979 /* convert to unsigned if it does not fit in an integer */
2980 if ((t1
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
) ||
2981 (t2
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
))
2984 /* XXX: currently, some unsigned operations are explicit, so
2985 we modify them here */
2986 if (t
& VT_UNSIGNED
) {
2993 else if (op
== TOK_LT
)
2995 else if (op
== TOK_GT
)
2997 else if (op
== TOK_LE
)
2999 else if (op
== TOK_GE
)
3005 /* special case for shifts and long long: we keep the shift as
3007 if (op
== TOK_SHR
|| op
== TOK_SAR
|| op
== TOK_SHL
)
3013 else if ((t
& VT_BTYPE
) == VT_LLONG
)
3017 if (op
>= TOK_ULT
&& op
<= TOK_GT
) {
3018 /* relationnal op: the result is an int */
3026 /* generic itof for unsigned long long case */
3027 void gen_cvt_itof1(int t
)
3031 if ((vtop
->t
& (VT_BTYPE
| VT_UNSIGNED
)) ==
3032 (VT_LLONG
| VT_UNSIGNED
)) {
3037 vpushi((int)&__ulltof
);
3038 else if (t
== VT_DOUBLE
)
3039 vpushi((int)&__ulltod
);
3041 vpushi((int)&__ulltold
);
3050 /* generic ftoi for unsigned long long case */
3051 void gen_cvt_ftoi1(int t
)
3056 if (t
== (VT_LLONG
| VT_UNSIGNED
)) {
3057 /* not handled natively */
3059 st
= vtop
->t
& VT_BTYPE
;
3062 vpushi((int)&__ftoull
);
3063 else if (st
== VT_DOUBLE
)
3064 vpushi((int)&__dtoull
);
3066 vpushi((int)&__ldtoull
);
3070 vtop
->r2
= REG_LRET
;
3076 /* force char or short cast */
3077 void force_charshort_cast(int t
)
3081 /* XXX: add optimization if lvalue : just change type and offset */
3086 if (t
& VT_UNSIGNED
) {
3087 vpushi((1 << bits
) - 1);
3098 /* cast 'vtop' to 't' type */
3099 void gen_cast(int t
)
3101 int sbt
, dbt
, sf
, df
, c
, st1
, dt1
;
3103 /* special delayed cast for char/short */
3104 /* XXX: in some cases (multiple cascaded casts), it may still
3106 if (vtop
->r
& VT_MUSTCAST
) {
3107 vtop
->r
&= ~VT_MUSTCAST
;
3108 force_charshort_cast(vtop
->t
);
3112 sbt
= vtop
->t
& VT_BTYPE
;
3117 c
= (vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_FORWARD
)) == VT_CONST
;
3119 /* convert from fp to fp */
3121 /* constant case: we can do it now */
3122 /* XXX: in ISOC, cannot do it if error in convert */
3123 if (dbt
== VT_FLOAT
&& sbt
== VT_DOUBLE
)
3124 vtop
->c
.f
= (float)vtop
->c
.d
;
3125 else if (dbt
== VT_FLOAT
&& sbt
== VT_LDOUBLE
)
3126 vtop
->c
.f
= (float)vtop
->c
.ld
;
3127 else if (dbt
== VT_DOUBLE
&& sbt
== VT_FLOAT
)
3128 vtop
->c
.d
= (double)vtop
->c
.f
;
3129 else if (dbt
== VT_DOUBLE
&& sbt
== VT_LDOUBLE
)
3130 vtop
->c
.d
= (double)vtop
->c
.ld
;
3131 else if (dbt
== VT_LDOUBLE
&& sbt
== VT_FLOAT
)
3132 vtop
->c
.ld
= (long double)vtop
->c
.f
;
3133 else if (dbt
== VT_LDOUBLE
&& sbt
== VT_DOUBLE
)
3134 vtop
->c
.ld
= (long double)vtop
->c
.d
;
3136 /* non constant case: generate code */
3140 /* convert int to fp */
3141 st1
= vtop
->t
& (VT_BTYPE
| VT_UNSIGNED
);
3144 case VT_LLONG
| VT_UNSIGNED
:
3146 /* XXX: add const cases for long long */
3148 case VT_INT
| VT_UNSIGNED
:
3150 case VT_FLOAT
: vtop
->c
.f
= (float)vtop
->c
.ui
; break;
3151 case VT_DOUBLE
: vtop
->c
.d
= (double)vtop
->c
.ui
; break;
3152 case VT_LDOUBLE
: vtop
->c
.ld
= (long double)vtop
->c
.ui
; break;
3157 case VT_FLOAT
: vtop
->c
.f
= (float)vtop
->c
.i
; break;
3158 case VT_DOUBLE
: vtop
->c
.d
= (double)vtop
->c
.i
; break;
3159 case VT_LDOUBLE
: vtop
->c
.ld
= (long double)vtop
->c
.i
; break;
3168 /* convert fp to int */
3169 dt1
= t
& (VT_BTYPE
| VT_UNSIGNED
);
3170 /* we handle char/short/etc... with generic code */
3171 if (dt1
!= (VT_INT
| VT_UNSIGNED
) &&
3172 dt1
!= (VT_LLONG
| VT_UNSIGNED
) &&
3177 case VT_LLONG
| VT_UNSIGNED
:
3179 /* XXX: add const cases for long long */
3181 case VT_INT
| VT_UNSIGNED
:
3183 case VT_FLOAT
: vtop
->c
.ui
= (unsigned int)vtop
->c
.d
; break;
3184 case VT_DOUBLE
: vtop
->c
.ui
= (unsigned int)vtop
->c
.d
; break;
3185 case VT_LDOUBLE
: vtop
->c
.ui
= (unsigned int)vtop
->c
.d
; break;
3191 case VT_FLOAT
: vtop
->c
.i
= (int)vtop
->c
.d
; break;
3192 case VT_DOUBLE
: vtop
->c
.i
= (int)vtop
->c
.d
; break;
3193 case VT_LDOUBLE
: vtop
->c
.i
= (int)vtop
->c
.d
; break;
3201 if (dt1
== VT_INT
&& (t
& (VT_BTYPE
| VT_UNSIGNED
)) != dt1
) {
3202 /* additionnal cast for char/short/bool... */
3206 } else if (dbt
== VT_LLONG
) {
3207 /* scalar to long long */
3209 if ((vtop
->t
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
))
3210 vtop
->c
.ll
= vtop
->c
.ui
;
3212 vtop
->c
.ll
= vtop
->c
.i
;
3214 /* machine independant conversion */
3216 /* generate high word */
3217 if ((vtop
->t
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
)) {
3225 /* patch second register */
3226 vtop
[-1].r2
= vtop
->r
;
3229 } else if (dbt
== VT_BOOL
) {
3230 /* scalar to bool */
3233 } else if (dbt
== VT_BYTE
|| dbt
== VT_SHORT
) {
3234 force_charshort_cast(t
);
3235 } else if (dbt
== VT_INT
) {
3237 if (sbt
== VT_LLONG
) {
3238 /* from long long: just take low order word */
3241 } else if (vtop
->r
& VT_LVAL
) {
3242 /* if lvalue and single word type, nothing to do (XXX:
3243 maybe incorrect for sizeof op) */
3252 /* return type size. Put alignment at 'a' */
3253 int type_size(int t
, int *a
)
3259 if (bt
== VT_STRUCT
) {
3261 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
) | SYM_STRUCT
);
3262 *a
= 4; /* XXX: cannot store it yet. Doing that is safe */
3264 } else if (bt
== VT_PTR
) {
3266 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
));
3267 return type_size(s
->t
, a
) * s
->c
;
3272 } else if (bt
== VT_LDOUBLE
) {
3274 return LDOUBLE_SIZE
;
3275 } else if (bt
== VT_DOUBLE
|| bt
== VT_LLONG
) {
3278 } else if (bt
== VT_INT
|| bt
== VT_ENUM
|| bt
== VT_FLOAT
) {
3281 } else if (bt
== VT_SHORT
) {
3285 /* char, void, function, _Bool */
3291 /* return the pointed type of t */
3292 int pointed_type(int t
)
3295 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
));
3296 return s
->t
| (t
& ~VT_TYPE
);
3299 int mk_pointer(int t
)
3303 sym_push(p
, t
, 0, -1);
3304 return VT_PTR
| (p
<< VT_STRUCT_SHIFT
) | (t
& ~VT_TYPE
);
3307 int is_compatible_types(int t1
, int t2
)
3314 bt1
= t1
& VT_BTYPE
;
3315 bt2
= t2
& VT_BTYPE
;
3316 if (bt1
== VT_PTR
) {
3317 t1
= pointed_type(t1
);
3318 /* if function, then convert implicitely to function pointer */
3319 if (bt2
!= VT_FUNC
) {
3322 t2
= pointed_type(t2
);
3324 /* void matches everything */
3327 if (t1
== VT_VOID
|| t2
== VT_VOID
)
3329 return is_compatible_types(t1
, t2
);
3330 } else if (bt1
== VT_STRUCT
) {
3332 } else if (bt1
== VT_FUNC
) {
3335 s1
= sym_find(((unsigned)t1
>> VT_STRUCT_SHIFT
));
3336 s2
= sym_find(((unsigned)t2
>> VT_STRUCT_SHIFT
));
3337 if (!is_compatible_types(s1
->t
, s2
->t
))
3339 /* XXX: not complete */
3340 if (s1
->c
== FUNC_OLD
|| s2
->c
== FUNC_OLD
)
3344 while (s1
!= NULL
) {
3347 if (!is_compatible_types(s1
->t
, s2
->t
))
3356 /* XXX: not complete */
3361 /* print a type. If 'varstr' is not NULL, then the variable is also
3362 printed in the type */
3364 /* XXX: add array and function pointers */
3365 void type_to_str(char *buf
, int buf_size
,
3366 int t
, const char *varstr
)
3376 if (t
& VT_UNSIGNED
)
3377 pstrcat(buf
, buf_size
, "unsigned ");
3407 tstr
= "long double";
3409 pstrcat(buf
, buf_size
, tstr
);
3413 if (bt
== VT_STRUCT
)
3417 pstrcat(buf
, buf_size
, tstr
);
3418 v
= (unsigned)t
>> VT_STRUCT_SHIFT
;
3419 if (v
>= SYM_FIRST_ANOM
)
3420 pstrcat(buf
, buf_size
, "<anonymous>");
3422 pstrcat(buf
, buf_size
, get_tok_str(v
, NULL
));
3425 s
= sym_find((unsigned)t
>> VT_STRUCT_SHIFT
);
3426 type_to_str(buf
, buf_size
, s
->t
, varstr
);
3427 pstrcat(buf
, buf_size
, "(");
3429 while (sa
!= NULL
) {
3430 type_to_str(buf1
, sizeof(buf1
), sa
->t
, NULL
);
3431 pstrcat(buf
, buf_size
, buf1
);
3434 pstrcat(buf
, buf_size
, ", ");
3436 pstrcat(buf
, buf_size
, ")");
3439 s
= sym_find((unsigned)t
>> VT_STRUCT_SHIFT
);
3440 pstrcpy(buf1
, sizeof(buf1
), "*");
3442 pstrcat(buf1
, sizeof(buf1
), varstr
);
3443 type_to_str(buf
, buf_size
, s
->t
, buf1
);
3447 pstrcat(buf
, buf_size
, " ");
3448 pstrcat(buf
, buf_size
, varstr
);
3453 /* verify type compatibility to store vtop in 'dt' type, and generate
3455 void gen_assign_cast(int dt
)
3458 char buf1
[256], buf2
[256];
3460 st
= vtop
->t
; /* source type */
3461 if ((dt
& VT_BTYPE
) == VT_PTR
) {
3462 /* special cases for pointers */
3463 /* a function is implicitely a function pointer */
3464 if ((st
& VT_BTYPE
) == VT_FUNC
) {
3465 if (!is_compatible_types(pointed_type(dt
), st
))
3470 /* '0' can also be a pointer */
3471 if ((st
& VT_BTYPE
) == VT_INT
&&
3472 ((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_FORWARD
)) == VT_CONST
) &&
3476 if (!is_compatible_types(dt
, st
)) {
3478 type_to_str(buf1
, sizeof(buf1
), st
, NULL
);
3479 type_to_str(buf2
, sizeof(buf2
), dt
, NULL
);
3480 error("cannot cast '%s' to '%s'", buf1
, buf2
);
3486 /* store vtop in lvalue pushed on stack */
3489 int sbt
, dbt
, ft
, r
, t
, size
, align
, bit_size
, bit_pos
, rc
, delayed_cast
;
3493 sbt
= vtop
->t
& VT_BTYPE
;
3494 dbt
= ft
& VT_BTYPE
;
3495 if (((sbt
== VT_INT
|| sbt
== VT_SHORT
) && dbt
== VT_BYTE
) ||
3496 (sbt
== VT_INT
&& dbt
== VT_SHORT
)) {
3497 /* optimize char/short casts */
3498 delayed_cast
= VT_MUSTCAST
;
3499 vtop
->t
= ft
& VT_TYPE
;
3502 gen_assign_cast(ft
& VT_TYPE
);
3505 if (sbt
== VT_STRUCT
) {
3506 /* if structure, only generate pointer */
3507 /* structure assignment : generate memcpy */
3508 /* XXX: optimize if small size */
3513 size
= type_size(vtop
->t
, &align
);
3527 vpushi((int)&memcpy
);
3529 /* leave source on stack */
3530 } else if (ft
& VT_BITFIELD
) {
3531 /* bitfield store handling */
3532 bit_pos
= (ft
>> VT_STRUCT_SHIFT
) & 0x3f;
3533 bit_size
= (ft
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f;
3534 /* remove bit field info to avoid loops */
3535 vtop
[-1].t
= ft
& ~(VT_BITFIELD
| (-1 << VT_STRUCT_SHIFT
));
3537 /* duplicate destination */
3539 vtop
[-1] = vtop
[-2];
3541 /* mask and shift source */
3542 vpushi((1 << bit_size
) - 1);
3546 /* load destination, mask and or with source */
3548 vpushi(~(((1 << bit_size
) - 1) << bit_pos
));
3554 /* bound check case */
3555 if (vtop
[-1].r
& VT_MUSTBOUND
) {
3563 r
= gv(rc
); /* generate value */
3564 /* if lvalue was saved on stack, must read it */
3565 if ((vtop
[-1].r
& VT_VALMASK
) == VT_LLOCAL
) {
3567 t
= get_reg(RC_INT
);
3569 sv
.r
= VT_LOCAL
| VT_LVAL
;
3570 sv
.c
.ul
= vtop
[-1].c
.ul
;
3572 vtop
[-1].r
= t
| VT_LVAL
;
3575 /* two word case handling : store second register at word + 4 */
3576 if ((ft
& VT_BTYPE
) == VT_LLONG
) {
3578 /* convert to int to increment easily */
3585 /* XXX: it works because r2 is spilled last ! */
3586 store(vtop
->r2
, vtop
- 1);
3589 vtop
--; /* NOT vpop() because on x86 it would flush the fp stack */
3590 vtop
->r
|= delayed_cast
;
3594 /* post defines POST/PRE add. c is the token ++ or -- */
3595 void inc(int post
, int c
)
3598 vdup(); /* save lvalue */
3600 gv_dup(); /* duplicate value */
3605 vpushi(c
- TOK_MID
);
3607 vstore(); /* store value */
3609 vpop(); /* if post op, return saved value */
3612 /* Parse GNUC __attribute__ extension. Currently, the following
3613 extensions are recognized:
3614 - aligned(n) : set data/function alignment.
3615 - section(x) : generate data/code in this section.
3616 - unused : currently ignored, but may be used someday.
3618 void parse_attribute(AttributeDef
*ad
)
3625 while (tok
!= ')') {
3626 if (tok
< TOK_IDENT
)
3627 expect("attribute name");
3632 case TOK___SECTION__
:
3635 expect("section name");
3636 ad
->section
= find_section(tokc
.ts
->str
);
3641 case TOK___ALIGNED__
:
3644 if (n
<= 0 || (n
& (n
- 1)) != 0)
3645 error("alignment must be a positive power of two");
3650 case TOK___UNUSED__
:
3651 /* currently, no need to handle it because tcc does not
3652 track unused objects */
3655 warning("'%s' attribute ignored", get_tok_str(t
, NULL
));
3656 /* skip parameters */
3657 /* XXX: skip parenthesis too */
3660 while (tok
!= ')' && tok
!= -1)
3674 /* enum/struct/union declaration */
3675 int struct_decl(int u
)
3677 int a
, t
, b
, v
, size
, align
, maxalign
, c
, offset
;
3678 int bit_size
, bit_pos
, bsize
, bt
, lbit_pos
;
3682 a
= tok
; /* save decl type */
3687 /* struct already defined ? return it */
3688 /* XXX: check consistency */
3689 s
= sym_find(v
| SYM_STRUCT
);
3692 error("invalid type");
3698 s
= sym_push(v
| SYM_STRUCT
, a
, 0, 0);
3699 /* put struct/union/enum name in type */
3701 u
= u
| (v
<< VT_STRUCT_SHIFT
);
3706 error("struct/union/enum already defined");
3707 /* cannot be empty */
3714 if (a
== TOK_ENUM
) {
3721 /* enum symbols have static storage */
3722 sym_push(v
, VT_STATIC
| VT_INT
, VT_CONST
, c
);
3727 parse_btype(&b
, &ad
);
3732 t
= type_decl(&v
, b
, TYPE_DIRECT
);
3733 if ((t
& VT_BTYPE
) == VT_FUNC
||
3734 (t
& (VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
)))
3735 error("invalid type for '%s'",
3736 get_tok_str(v
, NULL
));
3742 bit_size
= expr_const();
3743 /* XXX: handle v = 0 case for messages */
3745 error("negative width in bit-field '%s'",
3746 get_tok_str(v
, NULL
));
3747 if (v
&& bit_size
== 0)
3748 error("zero width for bit-field '%s'",
3749 get_tok_str(v
, NULL
));
3751 size
= type_size(t
, &align
);
3753 if (bit_size
>= 0) {
3758 error("bitfields must have scalar type");
3760 if (bit_size
> bsize
) {
3761 error("width of '%s' exceeds its type",
3762 get_tok_str(v
, NULL
));
3763 } else if (bit_size
== bsize
) {
3764 /* no need for bit fields */
3766 } else if (bit_size
== 0) {
3767 /* XXX: what to do if only padding in a
3769 /* zero size: means to pad */
3773 /* we do not have enough room ? */
3774 if ((bit_pos
+ bit_size
) > bsize
)
3777 /* XXX: handle LSB first */
3779 (bit_pos
<< VT_STRUCT_SHIFT
) |
3780 (bit_size
<< (VT_STRUCT_SHIFT
+ 6));
3781 bit_pos
+= bit_size
;
3787 /* add new memory data only if starting
3789 if (lbit_pos
== 0) {
3790 if (a
== TOK_STRUCT
) {
3791 c
= (c
+ align
- 1) & -align
;
3799 if (align
> maxalign
)
3803 printf("add field %s offset=%d",
3804 get_tok_str(v
, NULL
), offset
);
3805 if (t
& VT_BITFIELD
) {
3806 printf(" pos=%d size=%d",
3807 (t
>> VT_STRUCT_SHIFT
) & 0x3f,
3808 (t
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f);
3812 ss
= sym_push(v
| SYM_FIELD
, t
, 0, offset
);
3816 if (tok
== ';' || tok
== -1)
3826 /* size for struct/union, dummy for enum */
3827 s
->c
= (c
+ maxalign
- 1) & -maxalign
;
3832 /* return 0 if no type declaration. otherwise, return the basic type
3835 int parse_btype(int *type_ptr
, AttributeDef
*ad
)
3837 int t
, u
, type_found
;
3840 memset(ad
, 0, sizeof(AttributeDef
));
3851 if ((t
& VT_BTYPE
) != 0)
3852 error("too many basic types");
3866 if ((t
& VT_BTYPE
) == VT_DOUBLE
) {
3867 t
= (t
& ~VT_BTYPE
) | VT_LDOUBLE
;
3868 } else if ((t
& VT_BTYPE
) == VT_LONG
) {
3869 t
= (t
& ~VT_BTYPE
) | VT_LLONG
;
3883 if ((t
& VT_BTYPE
) == VT_LONG
) {
3884 t
= (t
& ~VT_BTYPE
) | VT_LDOUBLE
;
3891 u
= struct_decl(VT_ENUM
);
3895 u
= struct_decl(VT_STRUCT
);
3898 /* type modifiers */
3926 /* GNUC attribute */
3927 case TOK___ATTRIBUTE__
:
3928 parse_attribute(ad
);
3932 if (!s
|| !(s
->t
& VT_TYPEDEF
))
3934 t
|= (s
->t
& ~VT_TYPEDEF
);
3941 /* long is never used as type */
3942 if ((t
& VT_BTYPE
) == VT_LONG
)
3943 t
= (t
& ~VT_BTYPE
) | VT_INT
;
3948 int post_type(int t
)
3950 int p
, n
, pt
, l
, t1
;
3951 Sym
**plast
, *s
, *first
;
3955 /* function declaration */
3960 while (tok
!= ')') {
3961 /* read param name and compute offset */
3962 if (l
!= FUNC_OLD
) {
3963 if (!parse_btype(&pt
, &ad
)) {
3965 error("invalid type");
3972 if ((pt
& VT_BTYPE
) == VT_VOID
&& tok
== ')')
3974 pt
= type_decl(&n
, pt
, TYPE_DIRECT
| TYPE_ABSTRACT
);
3975 if ((pt
& VT_BTYPE
) == VT_VOID
)
3976 error("parameter declared as void");
3983 /* array must be transformed to pointer according to ANSI C */
3985 s
= sym_push(n
| SYM_FIELD
, pt
, 0, 0);
3990 if (l
== FUNC_NEW
&& tok
== TOK_DOTS
) {
3997 /* if no parameters, then old type prototype */
4001 t1
= t
& (VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
);
4002 t
= post_type(t
& ~(VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
));
4003 /* we push a anonymous symbol which will contain the function prototype */
4005 s
= sym_push(p
, t
, 0, l
);
4007 t
= t1
| VT_FUNC
| (p
<< VT_STRUCT_SHIFT
);
4008 } else if (tok
== '[') {
4009 /* array definition */
4015 error("invalid array size");
4018 /* parse next post type */
4019 t1
= t
& (VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
);
4020 t
= post_type(t
& ~(VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
));
4022 /* we push a anonymous symbol which will contain the array
4025 sym_push(p
, t
, 0, n
);
4026 t
= t1
| VT_ARRAY
| VT_PTR
| (p
<< VT_STRUCT_SHIFT
);
4031 /* Read a type declaration (except basic type), and return the
4032 type. If v is true, then also put variable name in 'vtop->c' */
4033 int type_decl(int *v
, int t
, int td
)
4038 while (tok
== '*') {
4040 while (tok
== TOK_CONST
|| tok
== TOK_VOLATILE
|| tok
== TOK_RESTRICT
)
4045 /* recursive type */
4046 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
4049 u
= type_decl(v
, 0, td
);
4053 /* type identifier */
4054 if (tok
>= TOK_IDENT
&& (td
& TYPE_DIRECT
)) {
4058 if (!(td
& TYPE_ABSTRACT
))
4059 expect("identifier");
4063 /* append t at the end of u */
4069 s
= sym_find((unsigned)p
>> VT_STRUCT_SHIFT
);
4079 /* define a new external reference to a function 'v' of type 'u' */
4080 Sym
*external_sym(int v
, int u
, int r
)
4085 /* push forward reference */
4086 s
= sym_push1(&global_stack
,
4088 s
->r
= r
| VT_CONST
| VT_FORWARD
;
4095 if ((vtop
->t
& VT_BTYPE
) != VT_PTR
)
4097 if (vtop
->r
& VT_LVAL
)
4099 vtop
->t
= pointed_type(vtop
->t
);
4100 /* an array is never an lvalue */
4101 if (!(vtop
->t
& VT_ARRAY
)) {
4103 /* if bound checking, the referenced pointer must be checked */
4104 if (do_bounds_check
)
4105 vtop
->r
|= VT_MUSTBOUND
;
4109 /* pass a parameter to a function and do type checking and casting */
4110 void gfunc_param_typed(GFuncContext
*gf
, Sym
*func
, Sym
*arg
)
4113 func_type
= func
->c
;
4114 if (func_type
== FUNC_OLD
||
4115 (func_type
== FUNC_ELLIPSIS
&& arg
== NULL
)) {
4116 /* default casting : only need to convert float to double */
4117 if ((vtop
->t
& VT_BTYPE
) == VT_FLOAT
)
4118 gen_cast(VT_DOUBLE
);
4119 } else if (arg
== NULL
) {
4120 error("too many arguments to function");
4122 gen_assign_cast(arg
->t
);
4129 int n
, t
, ft
, fc
, p
, align
, size
, r
, data_offset
;
4134 if (tok
== TOK_CINT
|| tok
== TOK_CCHAR
|| tok
== TOK_LCHAR
) {
4137 } else if (tok
== TOK_CUINT
) {
4138 vsetc(VT_INT
| VT_UNSIGNED
, VT_CONST
, &tokc
);
4140 } else if (tok
== TOK_CLLONG
) {
4141 vsetc(VT_LLONG
, VT_CONST
, &tokc
);
4143 } else if (tok
== TOK_CULLONG
) {
4144 vsetc(VT_LLONG
| VT_UNSIGNED
, VT_CONST
, &tokc
);
4146 } else if (tok
== TOK_CFLOAT
) {
4147 vsetc(VT_FLOAT
, VT_CONST
, &tokc
);
4149 } else if (tok
== TOK_CDOUBLE
) {
4150 vsetc(VT_DOUBLE
, VT_CONST
, &tokc
);
4152 } else if (tok
== TOK_CLDOUBLE
) {
4153 vsetc(VT_LDOUBLE
, VT_CONST
, &tokc
);
4155 } else if (tok
== TOK___FUNC__
) {
4156 /* special function name identifier */
4157 /* generate (char *) type */
4158 data_offset
= (int)data_section
->data_ptr
;
4159 vset(mk_pointer(VT_BYTE
), VT_CONST
, data_offset
);
4160 strcpy((void *)data_offset
, funcname
);
4161 data_offset
+= strlen(funcname
) + 1;
4162 data_section
->data_ptr
= (unsigned char *)data_offset
;
4164 } else if (tok
== TOK_LSTR
) {
4167 } else if (tok
== TOK_STR
) {
4168 /* string parsing */
4171 type_size(t
, &align
);
4172 data_offset
= (int)data_section
->data_ptr
;
4173 data_offset
= (data_offset
+ align
- 1) & -align
;
4175 /* we must declare it as an array first to use initializer parser */
4176 t
= VT_ARRAY
| mk_pointer(t
);
4177 decl_initializer(t
, VT_CONST
, data_offset
, 1, 0);
4178 data_offset
+= type_size(t
, &align
);
4179 /* put it as pointer */
4180 vset(t
& ~VT_ARRAY
, VT_CONST
, fc
);
4181 data_section
->data_ptr
= (unsigned char *)data_offset
;
4187 if (parse_btype(&t
, &ad
)) {
4188 ft
= type_decl(&n
, t
, TYPE_ABSTRACT
);
4190 /* check ISOC99 compound literal */
4192 /* data is allocated locally by default */
4197 /* all except arrays are lvalues */
4198 if (!(ft
& VT_ARRAY
))
4200 memset(&ad
, 0, sizeof(AttributeDef
));
4201 fc
= decl_initializer_alloc(ft
, &ad
, r
, 1);
4211 } else if (t
== '*') {
4214 } else if (t
== '&') {
4216 /* functions names must be treated as function pointers,
4217 except for unary '&' and sizeof. Since we consider that
4218 functions are not lvalues, we only have to handle it
4219 there and in function calls. */
4220 if ((vtop
->t
& VT_BTYPE
) != VT_FUNC
)
4222 vtop
->t
= mk_pointer(vtop
->t
);
4227 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
)
4228 vtop
->c
.i
= !vtop
->c
.i
;
4229 else if ((vtop
->r
& VT_VALMASK
) == VT_CMP
)
4230 vtop
->c
.i
= vtop
->c
.i
^ 1;
4232 vset(VT_INT
, VT_JMP
, gtst(1, 0));
4242 if (t
== TOK_SIZEOF
) {
4245 if (parse_btype(&t
, &ad
)) {
4246 t
= type_decl(&n
, t
, TYPE_ABSTRACT
);
4248 /* XXX: some code could be generated: add eval
4260 vpushi(type_size(t
, &t
));
4262 if (t
== TOK_INC
|| t
== TOK_DEC
) {
4265 } else if (t
== '-') {
4274 error("'%s' undeclared", get_tok_str(t
, NULL
));
4275 /* for simple function calls, we tolerate undeclared
4276 external reference */
4278 sym_push1(&global_stack
, p
, 0, FUNC_OLD
);
4279 /* int() function */
4280 s
= external_sym(t
, VT_FUNC
| (p
<< VT_STRUCT_SHIFT
), 0);
4282 vset(s
->t
, s
->r
, s
->c
);
4283 /* if forward reference, we must point to s */
4284 if (vtop
->r
& VT_FORWARD
)
4289 /* post operations */
4291 if (tok
== TOK_INC
|| tok
== TOK_DEC
) {
4294 } else if (tok
== '.' || tok
== TOK_ARROW
) {
4296 if (tok
== TOK_ARROW
)
4301 /* expect pointer on structure */
4302 if ((vtop
->t
& VT_BTYPE
) != VT_STRUCT
)
4303 expect("struct or union");
4304 s
= sym_find(((unsigned)vtop
->t
>> VT_STRUCT_SHIFT
) | SYM_STRUCT
);
4307 while ((s
= s
->next
) != NULL
) {
4312 error("field not found");
4313 /* add field offset to pointer */
4314 vtop
->t
= char_pointer_type
; /* change type to 'char *' */
4317 /* change type to field type, and set to lvalue */
4319 /* an array is never an lvalue */
4320 if (!(vtop
->t
& VT_ARRAY
))
4323 } else if (tok
== '[') {
4329 } else if (tok
== '(') {
4334 if ((vtop
->t
& VT_BTYPE
) != VT_FUNC
) {
4335 /* pointer test (no array accepted) */
4336 if ((vtop
->t
& (VT_BTYPE
| VT_ARRAY
)) == VT_PTR
) {
4337 vtop
->t
= pointed_type(vtop
->t
);
4338 if ((vtop
->t
& VT_BTYPE
) != VT_FUNC
)
4342 expect("function pointer");
4345 vtop
->r
&= ~VT_LVAL
; /* no lvalue */
4347 /* get return type */
4348 s
= sym_find((unsigned)vtop
->t
>> VT_STRUCT_SHIFT
);
4349 save_regs(); /* save used temporary registers */
4352 sa
= s
->next
; /* first parameter */
4353 #ifdef INVERT_FUNC_PARAMS
4355 int *str
, len
, parlevel
, *saved_macro_ptr
;
4358 /* read each argument and store it on a stack */
4359 /* XXX: merge it with macro args ? */
4361 while (tok
!= ')') {
4365 while ((parlevel
> 0 || (tok
!= ')' && tok
!= ',')) &&
4369 else if (tok
== ')')
4371 tok_add2(&str
, &len
, tok
, &tokc
);
4374 tok_add(&str
, &len
, -1); /* end of file added */
4375 tok_add(&str
, &len
, 0);
4376 s1
= sym_push2(&args
, 0, 0, (int)str
);
4377 s1
->next
= sa
; /* add reference to argument */
4387 /* now generate code in reverse order by reading the stack */
4388 saved_macro_ptr
= macro_ptr
;
4390 macro_ptr
= (int *)args
->c
;
4394 expect("',' or ')'");
4395 gfunc_param_typed(&gf
, s
, args
->next
);
4397 free((int *)args
->c
);
4401 macro_ptr
= saved_macro_ptr
;
4406 /* compute first implicit argument if a structure is returned */
4407 if ((s
->t
& VT_BTYPE
) == VT_STRUCT
) {
4408 /* get some space for the returned structure */
4409 size
= type_size(s
->t
, &align
);
4410 loc
= (loc
- size
) & -align
;
4412 ret
.r
= VT_LOCAL
| VT_LVAL
;
4413 /* pass it as 'int' to avoid structure arg passing
4415 vset(VT_INT
, VT_LOCAL
, loc
);
4421 /* return in register */
4422 if (is_float(ret
.t
)) {
4425 if ((ret
.t
& VT_BTYPE
) == VT_LLONG
)
4431 #ifndef INVERT_FUNC_PARAMS
4432 while (tok
!= ')') {
4434 gfunc_param_typed(&gf
, s
, sa
);
4442 error("too few arguments to function");
4446 vsetc(ret
.t
, ret
.r
, &ret
.c
);
4460 (tok
>= TOK_A_MOD
&& tok
<= TOK_A_DIV
) ||
4461 tok
== TOK_A_XOR
|| tok
== TOK_A_OR
||
4462 tok
== TOK_A_SHL
|| tok
== TOK_A_SAR
) {
4485 while ((l
== 0 && (tok
== '*' || tok
== '/' || tok
== '%')) ||
4486 (l
== 1 && (tok
== '+' || tok
== '-')) ||
4487 (l
== 2 && (tok
== TOK_SHL
|| tok
== TOK_SAR
)) ||
4488 (l
== 3 && ((tok
>= TOK_ULE
&& tok
<= TOK_GT
) ||
4489 tok
== TOK_ULT
|| tok
== TOK_UGE
)) ||
4490 (l
== 4 && (tok
== TOK_EQ
|| tok
== TOK_NE
)) ||
4491 (l
== 5 && tok
== '&') ||
4492 (l
== 6 && tok
== '^') ||
4493 (l
== 7 && tok
== '|') ||
4494 (l
== 8 && tok
== TOK_LAND
) ||
4495 (l
== 9 && tok
== TOK_LOR
)) {
4504 /* only used if non constant */
4512 if (tok
!= TOK_LAND
) {
4515 vset(VT_INT
, VT_JMPI
, t
);
4532 if (tok
!= TOK_LOR
) {
4535 vset(VT_INT
, VT_JMP
, t
);
4545 /* XXX: better constant handling */
4548 int t
, u
, c
, r1
, r2
, rc
;
4570 /* XXX: long long handling ? */
4572 if (is_float(vtop
->t
))
4600 /* parse a constant expression and return value in vtop */
4601 void expr_const1(void)
4607 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
)) != VT_CONST
)
4612 /* parse an integer constant and return its value */
4613 int expr_const(void)
4622 /* return the label token if current token is a label, otherwise
4629 /* fast test first */
4630 if (tok
< TOK_UIDENT
)
4632 /* no need to save tokc since we expect an identifier */
4640 /* XXX: may not work in all cases (macros ?) */
4649 void block(int *bsym
, int *csym
, int *case_sym
, int *def_sym
, int case_reg
)
4654 /* generate line number info */
4656 (last_line_num
!= line_num
|| last_ind
!= ind
)) {
4657 put_stabn(N_SLINE
, 0, line_num
, ind
- func_ind
);
4659 last_line_num
= line_num
;
4662 if (tok
== TOK_IF
) {
4669 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
4671 if (c
== TOK_ELSE
) {
4675 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
4676 gsym(d
); /* patch else jmp */
4679 } else if (tok
== TOK_WHILE
) {
4687 block(&a
, &b
, case_sym
, def_sym
, case_reg
);
4688 oad(0xe9, d
- ind
- 5); /* jmp */
4691 } else if (tok
== '{') {
4694 s
= local_stack
.top
;
4695 while (tok
!= '}') {
4698 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
4700 /* pop locally defined symbols */
4701 sym_pop(&local_stack
, s
);
4703 } else if (tok
== TOK_RETURN
) {
4707 gen_assign_cast(func_vt
);
4708 if ((func_vt
& VT_BTYPE
) == VT_STRUCT
) {
4709 /* if returning structure, must copy it to implicit
4710 first pointer arg location */
4711 vset(mk_pointer(func_vt
), VT_LOCAL
| VT_LVAL
, func_vc
);
4714 /* copy structure value to pointer */
4716 } else if (is_float(func_vt
)) {
4721 vtop
--; /* NOT vpop() because on x86 it would flush the fp stack */
4724 rsym
= gjmp(rsym
); /* jmp */
4725 } else if (tok
== TOK_BREAK
) {
4728 error("cannot break");
4729 *bsym
= gjmp(*bsym
);
4732 } else if (tok
== TOK_CONTINUE
) {
4735 error("cannot continue");
4736 *csym
= gjmp(*csym
);
4739 } else if (tok
== TOK_FOR
) {
4762 oad(0xe9, d
- ind
- 5); /* jmp */
4766 block(&a
, &b
, case_sym
, def_sym
, case_reg
);
4767 oad(0xe9, c
- ind
- 5); /* jmp */
4771 if (tok
== TOK_DO
) {
4776 block(&a
, &b
, case_sym
, def_sym
, case_reg
);
4787 if (tok
== TOK_SWITCH
) {
4791 /* XXX: other types than integer */
4792 case_reg
= gv(RC_INT
);
4796 b
= gjmp(0); /* jump to first case */
4798 block(&a
, csym
, &b
, &c
, case_reg
);
4799 /* if no default, jmp after switch */
4807 if (tok
== TOK_CASE
) {
4814 if (gnu_ext
&& tok
== TOK_DOTS
) {
4818 warning("empty case range");
4820 /* since a case is like a label, we must skip it with a jmp */
4823 vset(VT_INT
, case_reg
, 0);
4827 *case_sym
= gtst(1, 0);
4830 *case_sym
= gtst(1, 0);
4831 vset(VT_INT
, case_reg
, 0);
4834 *case_sym
= gtst(1, *case_sym
);
4838 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
4840 if (tok
== TOK_DEFAULT
) {
4846 error("too many 'default'");
4848 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
4850 if (tok
== TOK_GOTO
) {
4852 s
= sym_find1(&label_stack
, tok
);
4853 /* put forward definition if needed */
4855 s
= sym_push1(&label_stack
, tok
, VT_FORWARD
, 0);
4856 /* label already defined */
4857 if (s
->t
& VT_FORWARD
)
4858 s
->c
= gjmp(s
->c
); /* jmp xxx */
4860 oad(0xe9, s
->c
- ind
- 5); /* jmp xxx */
4867 s
= sym_find1(&label_stack
, b
);
4869 if (!(s
->t
& VT_FORWARD
))
4870 error("multiple defined label");
4875 sym_push1(&label_stack
, b
, 0, ind
);
4877 /* we accept this, but it is a mistake */
4879 warning("deprecated use of label at end of compound statement");
4881 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
4883 /* expression case */
4893 /* t is the array or struct type. c is the array or struct
4894 address. cur_index/cur_field is the pointer to the current
4895 value. 'size_only' is true if only size info is needed (only used
4897 void decl_designator(int t
, int r
, int c
,
4898 int *cur_index
, Sym
**cur_field
,
4902 int notfirst
, index
, align
, l
;
4905 if (gnu_ext
&& (l
= is_label()) != 0)
4908 while (tok
== '[' || tok
== '.') {
4910 if (!(t
& VT_ARRAY
))
4911 expect("array type");
4912 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
));
4914 index
= expr_const();
4915 if (index
< 0 || (s
->c
>= 0 && index
>= s
->c
))
4916 expect("invalid index");
4920 t
= pointed_type(t
);
4921 c
+= index
* type_size(t
, &align
);
4927 if ((t
& VT_BTYPE
) != VT_STRUCT
)
4928 expect("struct/union type");
4929 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
) | SYM_STRUCT
);
4941 t
= f
->t
| (t
& ~VT_TYPE
);
4956 t
= pointed_type(t
);
4957 c
+= index
* type_size(t
, &align
);
4961 error("too many field init");
4962 t
= f
->t
| (t
& ~VT_TYPE
);
4966 decl_initializer(t
, r
, c
, 0, size_only
);
4970 #define EXPR_CONST 1
4973 /* store a value or an expression directly in global data or in local array */
4974 void init_putv(int t
, int r
, int c
,
4975 int v
, int expr_type
)
4977 int saved_global_expr
, bt
;
4984 /* compound literals must be allocated globally in this case */
4985 saved_global_expr
= global_expr
;
4988 global_expr
= saved_global_expr
;
4995 if ((r
& VT_VALMASK
) == VT_CONST
) {
4996 /* XXX: do casting */
4997 /* XXX: not portable */
4998 bt
= vtop
->t
& VT_BTYPE
;
5001 *(char *)c
= vtop
->c
.i
;
5004 *(short *)c
= vtop
->c
.i
;
5007 *(double *)c
= vtop
->c
.d
;
5010 *(long double *)c
= vtop
->c
.ld
;
5014 *(long long *)c
= vtop
->c
.ll
;
5018 *(int *)c
= vtop
->c
.i
;
5030 /* put zeros for variable based init */
5031 void init_putz(int t
, int r
, int c
, int size
)
5035 if ((r
& VT_VALMASK
) == VT_CONST
) {
5036 /* nothing to do because global are already set to zero */
5043 vset(VT_INT
, VT_LOCAL
, c
);
5045 vpushi((int)&memset
);
5050 /* 't' contains the type and storage info. c is the address of the
5051 object. 'first' is true if array '{' must be read (multi dimension
5052 implicit array init handling). 'size_only' is true if size only
5053 evaluation is wanted (only for arrays). */
5054 void decl_initializer(int t
, int r
, int c
, int first
, int size_only
)
5056 int index
, array_length
, n
, no_oblock
, nb
, parlevel
, i
;
5057 int t1
, size1
, align1
, expr_type
;
5062 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
));
5065 t1
= pointed_type(t
);
5066 size1
= type_size(t1
, &align1
);
5069 if ((first
&& tok
!= TOK_LSTR
&& tok
!= TOK_STR
) ||
5075 /* only parse strings here if correct type (otherwise: handle
5076 them as ((w)char *) expressions */
5077 if ((tok
== TOK_LSTR
&&
5078 (t1
& VT_BTYPE
) == VT_INT
) ||
5080 (t1
& VT_BTYPE
) == VT_BYTE
)) {
5081 /* XXX: move multiple string parsing in parser ? */
5082 while (tok
== TOK_STR
|| tok
== TOK_LSTR
) {
5084 /* compute maximum number of chars wanted */
5086 if (n
>= 0 && nb
> (n
- array_length
))
5087 nb
= n
- array_length
;
5090 warning("initializer-string for array is too long");
5092 init_putv(t1
, r
, c
+ (array_length
+ i
) * size1
,
5093 ts
->str
[i
], EXPR_VAL
);
5099 /* only add trailing zero if enough storage (no
5100 warning in this case since it is standard) */
5101 if (n
< 0 || array_length
< n
) {
5103 init_putv(t1
, r
, c
+ (array_length
* size1
), 0, EXPR_VAL
);
5109 while (tok
!= '}') {
5110 decl_designator(t
, r
, c
, &index
, NULL
, size_only
);
5111 if (n
>= 0 && index
>= n
)
5112 error("index too large");
5113 /* must put zero in holes (note that doing it that way
5114 ensures that it even works with designators) */
5115 if (!size_only
&& array_length
< index
) {
5116 init_putz(t1
, r
, c
+ array_length
* size1
,
5117 (index
- array_length
) * size1
);
5120 if (index
> array_length
)
5121 array_length
= index
;
5122 /* special test for multi dimensional arrays (may not
5123 be strictly correct if designators are used at the
5125 if (index
>= n
&& no_oblock
)
5134 /* put zeros at the end */
5135 if (!size_only
&& n
>= 0 && array_length
< n
) {
5136 init_putz(t1
, r
, c
+ array_length
* size1
,
5137 (n
- array_length
) * size1
);
5139 /* patch type size if needed */
5141 s
->c
= array_length
;
5142 } else if ((t
& VT_BTYPE
) == VT_STRUCT
&& tok
== '{') {
5143 /* XXX: union needs only one init */
5145 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
) | SYM_STRUCT
);
5150 while (tok
!= '}') {
5151 decl_designator(t
, r
, c
, NULL
, &f
, size_only
);
5152 /* fill with zero between fields */
5154 if (!size_only
&& array_length
< index
) {
5155 init_putz(t
, r
, c
+ array_length
,
5156 index
- array_length
);
5158 index
= index
+ type_size(f
->t
, &align1
);
5159 if (index
> array_length
)
5160 array_length
= index
;
5166 /* put zeros at the end */
5167 if (!size_only
&& array_length
< n
) {
5168 init_putz(t
, r
, c
+ array_length
,
5172 } else if (tok
== '{') {
5174 decl_initializer(t
, r
, c
, first
, size_only
);
5176 } else if (size_only
) {
5177 /* just skip expression */
5179 while ((parlevel
> 0 || (tok
!= '}' && tok
!= ',')) &&
5183 else if (tok
== ')')
5188 /* currently, we always use constant expression for globals
5189 (may change for scripting case) */
5190 expr_type
= EXPR_CONST
;
5191 if ((r
& VT_VALMASK
) == VT_LOCAL
)
5192 expr_type
= EXPR_ANY
;
5193 init_putv(t
, r
, c
, 0, expr_type
);
5197 /* parse an initializer for type 't' if 'has_init' is true, and
5198 allocate space in local or global data space ('r' is either
5199 VT_LOCAL or VT_CONST). The allocated address in returned */
5200 int decl_initializer_alloc(int t
, AttributeDef
*ad
, int r
, int has_init
)
5202 int size
, align
, addr
, tok1
, data_offset
;
5203 int *init_str
, init_len
, level
, *saved_macro_ptr
;
5206 size
= type_size(t
, &align
);
5207 /* If unknown size, we must evaluate it before
5208 evaluating initializers because
5209 initializers can generate global data too
5210 (e.g. string pointers or ISOC99 compound
5211 literals). It also simplifies local
5212 initializers handling */
5215 saved_macro_ptr
= NULL
; /* avoid warning */
5219 error("unknown type size");
5220 /* get all init string */
5222 while (level
> 0 || (tok
!= ',' && tok
!= ';')) {
5224 error("unexpected end of file in initializer");
5225 tok_add2(&init_str
, &init_len
, tok
, &tokc
);
5228 else if (tok
== '}') {
5236 tok_add(&init_str
, &init_len
, -1);
5237 tok_add(&init_str
, &init_len
, 0);
5240 saved_macro_ptr
= macro_ptr
;
5241 macro_ptr
= init_str
;
5243 decl_initializer(t
, r
, 0, 1, 1);
5244 /* prepare second initializer parsing */
5245 macro_ptr
= init_str
;
5248 /* if still unknown size, error */
5249 size
= type_size(t
, &align
);
5251 error("unknown type size");
5253 /* take into account specified alignment if bigger */
5254 if (ad
->aligned
> align
)
5255 align
= ad
->aligned
;
5256 if ((r
& VT_VALMASK
) == VT_LOCAL
) {
5257 if (do_bounds_check
&& (t
& VT_ARRAY
))
5259 loc
= (loc
- size
) & -align
;
5261 /* handles bounds */
5262 /* XXX: currently, since we do only one pass, we cannot track
5263 '&' operators, so we add only arrays */
5264 if (do_bounds_check
&& (t
& VT_ARRAY
)) {
5266 /* add padding between regions */
5268 /* then add local bound info */
5269 bounds_ptr
= (int *)lbounds_section
->data_ptr
;
5270 *bounds_ptr
++ = addr
;
5271 *bounds_ptr
++ = size
;
5272 lbounds_section
->data_ptr
= (unsigned char *)bounds_ptr
;
5275 /* compute section */
5283 data_offset
= (int)sec
->data_ptr
;
5284 data_offset
= (data_offset
+ align
- 1) & -align
;
5286 /* very important to increment global
5287 pointer at this time because
5288 initializers themselves can create new
5290 data_offset
+= size
;
5291 /* handles bounds */
5292 if (do_bounds_check
) {
5294 /* first, we need to add at least one byte between each region */
5296 /* then add global bound info */
5297 bounds_ptr
= (int *)bounds_section
->data_ptr
;
5298 *bounds_ptr
++ = addr
;
5299 *bounds_ptr
++ = size
;
5300 bounds_section
->data_ptr
= (unsigned char *)bounds_ptr
;
5302 sec
->data_ptr
= (unsigned char *)data_offset
;
5305 decl_initializer(t
, r
, addr
, 1, 0);
5306 /* restore parse state if needed */
5309 macro_ptr
= saved_macro_ptr
;
5316 void put_func_debug(int t
)
5325 put_elf_sym(symtab_section
, ind
, 0,
5326 ELF32_ST_INFO(bind
, STT_FUNC
), 0,
5327 cur_text_section
->sh_num
, funcname
);
5329 /* XXX: we put here a dummy type */
5330 snprintf(buf
, sizeof(buf
), "%s:%c1",
5331 funcname
, t
& VT_STATIC
? 'f' : 'F');
5332 put_stabs(buf
, N_FUN
, 0, line_num
, ind
);
5338 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
5341 int t
, b
, v
, addr
, has_init
, r
;
5346 if (!parse_btype(&b
, &ad
)) {
5347 /* skip redundant ';' */
5348 /* XXX: find more elegant solution */
5353 /* special test for old K&R protos without explicit int
5354 type. Only accepted when defining global data */
5355 if (l
== VT_LOCAL
|| tok
< TOK_DEFINE
)
5359 if (((b
& VT_BTYPE
) == VT_ENUM
||
5360 (b
& VT_BTYPE
) == VT_STRUCT
) &&
5362 /* we accept no variable after */
5366 while (1) { /* iterate thru each declaration */
5367 t
= type_decl(&v
, b
, TYPE_DIRECT
);
5368 /* currently, we do not parse attribute in
5369 type_decl(). May change if needed */
5370 if (tok
== TOK___ATTRIBUTE__
)
5371 parse_attribute(&ad
);
5375 type_to_str(buf
, sizeof(buf
), t
, get_tok_str(v
, NULL
));
5376 printf("type = '%s'\n", buf
);
5381 error("cannot use local functions");
5383 expect("function definition");
5384 /* compute text section */
5385 cur_text_section
= ad
.section
;
5386 if (!cur_text_section
)
5387 cur_text_section
= text_section
;
5388 ind
= (int)cur_text_section
->data_ptr
;
5389 /* patch forward references */
5390 if ((sym
= sym_find(v
)) && (sym
->r
& VT_FORWARD
)) {
5391 greloc_patch(sym
, ind
);
5394 /* put function address */
5395 sym
= sym_push1(&global_stack
, v
, t
, ind
);
5398 funcname
= get_tok_str(v
, NULL
);
5399 /* put debug symbol */
5402 /* push a dummy symbol to enable local sym storage */
5403 sym_push1(&local_stack
, 0, 0, 0);
5407 block(NULL
, NULL
, NULL
, NULL
, 0);
5410 cur_text_section
->data_ptr
= (unsigned char *)ind
;
5411 sym_pop(&label_stack
, NULL
); /* reset label stack */
5412 sym_pop(&local_stack
, NULL
); /* reset local stack */
5413 /* end of function */
5415 put_stabn(N_FUN
, 0, 0, ind
- func_ind
);
5417 funcname
= ""; /* for safety */
5418 func_vt
= VT_VOID
; /* for safety */
5421 if (b
& VT_TYPEDEF
) {
5422 /* save typedefed type */
5423 /* XXX: test storage specifiers ? */
5424 sym_push(v
, t
| VT_TYPEDEF
, 0, 0);
5425 } else if ((t
& VT_BTYPE
) == VT_FUNC
) {
5426 /* external function definition */
5427 external_sym(v
, t
, 0);
5429 /* not lvalue if array */
5431 if (!(t
& VT_ARRAY
))
5433 if (b
& VT_EXTERN
) {
5434 /* external variable */
5435 external_sym(v
, t
, r
);
5441 has_init
= (tok
== '=');
5444 addr
= decl_initializer_alloc(t
, &ad
, r
,
5446 if (l
== VT_CONST
) {
5447 /* global scope: see if already defined */
5451 if (!is_compatible_types(sym
->t
, t
))
5452 error("incompatible types for redefinition of '%s'",
5453 get_tok_str(v
, NULL
));
5454 if (!(sym
->r
& VT_FORWARD
))
5455 error("redefinition of '%s'", get_tok_str(v
, NULL
));
5456 greloc_patch(sym
, addr
);
5459 sym_push(v
, t
, r
, addr
);
5473 /* put all global symbols in the extern stack and do all the
5474 resolving which can be done without using external symbols from DLLs */
5475 /* XXX: could try to verify types, but would not to save them in
5477 void resolve_global_syms(void)
5479 Sym
*s
, *s1
, *ext_sym
;
5482 s
= global_stack
.top
;
5485 /* do not save static or typedefed symbols or types */
5486 if (!(s
->t
& (VT_STATIC
| VT_TYPEDEF
)) &&
5487 !(s
->v
& (SYM_FIELD
| SYM_STRUCT
)) &&
5488 (s
->v
< SYM_FIRST_ANOM
)) {
5489 ext_sym
= sym_find1(&extern_stack
, s
->v
);
5491 /* if the symbol do not exist, we simply save it */
5492 ext_sym
= sym_push1(&extern_stack
, s
->v
, s
->t
, s
->c
);
5494 } else if (ext_sym
->r
& VT_FORWARD
) {
5495 /* external symbol already exists, but only as forward
5497 if (!(s
->r
& VT_FORWARD
)) {
5498 /* s is not forward, so we can relocate all symbols */
5499 greloc_patch(ext_sym
, s
->c
);
5501 /* the two symbols are forward: merge them */
5502 p
= (Reloc
**)&ext_sym
->c
;
5508 /* external symbol already exists and is defined :
5509 patch all references to it */
5510 if (!(s
->r
& VT_FORWARD
))
5511 error("'%s' defined twice", get_tok_str(s
->v
, NULL
));
5512 greloc_patch(s
, ext_sym
->c
);
5519 /* compile a C file. Return non zero if errors. */
5520 int tcc_compile_file(const char *filename1
)
5527 filename
= (char *)filename1
;
5529 file
= fopen(filename
, "r");
5531 error("file '%s' not found", filename
);
5532 include_stack_ptr
= include_stack
;
5533 ifdef_stack_ptr
= ifdef_stack
;
5536 anon_sym
= SYM_FIRST_ANOM
;
5538 /* file info: full path + filename */
5540 getcwd(buf
, sizeof(buf
));
5541 pstrcat(buf
, sizeof(buf
), "/");
5542 put_stabs(buf
, N_SO
, 0, 0, (unsigned long)text_section
->data_ptr
);
5543 put_stabs(filename
, N_SO
, 0, 0, (unsigned long)text_section
->data_ptr
);
5545 /* define common 'char *' type because it is often used internally
5546 for arrays and struct dereference */
5547 char_pointer_type
= mk_pointer(VT_BYTE
);
5549 define_start
= define_stack
.top
;
5551 ch
= '\n'; /* needed to parse correctly first preprocessor command */
5555 expect("declaration");
5558 /* end of translation unit info */
5560 put_stabn(N_SO
, 0, 0, (unsigned long)text_section
->data_ptr
);
5563 /* reset define stack, but leave -Dsymbols (may be incorrect if
5564 they are undefined) */
5565 sym_pop(&define_stack
, define_start
);
5567 resolve_global_syms();
5569 sym_pop(&global_stack
, NULL
);
5574 /* define a symbol. A value can also be provided with the '=' operator */
5575 /* XXX: currently only handles integers and string defines. should use
5576 tcc parser, but would need a custom 'FILE *' */
5577 void define_symbol(const char *sym
)
5585 p
= strchr(sym
, '=');
5587 pstrcpy(buf
, sizeof(buf
), sym
);
5591 if (len
> sizeof(buf
) - 1)
5592 len
= sizeof(buf
) - 1;
5593 memcpy(buf
, sym
, len
);
5598 ts
= tok_alloc(buf
, 0);
5604 tok_add2(&str
, &len
, TOK_CINT
, &cval
);
5607 cval
.ts
= tok_alloc(p
, 0);
5608 tok_add2(&str
, &len
, TOK_STR
, &cval
);
5610 tok_add(&str
, &len
, 0);
5611 sym_push1(&define_stack
, ts
->tok
, MACRO_OBJ
, (int)str
);
5614 void undef_symbol(const char *sym
)
5618 printf("undef %s\n", sym
);
5619 ts
= tok_alloc(sym
, 0);
5620 s
= sym_find1(&define_stack
, tok
);
5621 /* undefine symbol by putting an invalid name */
5623 sym_undef(&define_stack
, s
);
5626 /* open a dynamic library so that its symbol are available for
5627 compiled programs */
5628 void open_dll(char *libname
)
5633 snprintf(buf
, sizeof(buf
), "lib%s.so", libname
);
5634 h
= dlopen(buf
, RTLD_GLOBAL
| RTLD_LAZY
);
5636 error((char *)dlerror());
5639 static void *resolve_sym(const char *sym
)
5642 if (do_bounds_check
) {
5643 ptr
= bound_resolve_sym(sym
);
5647 return dlsym(NULL
, sym
);
5650 void resolve_extern_syms(void)
5656 s
= extern_stack
.top
;
5659 if (s
->r
& VT_FORWARD
) {
5660 /* if there is at least one relocation to do, then find it
5663 str
= get_tok_str(s
->v
, NULL
);
5664 addr
= (int)resolve_sym(str
);
5666 error("unresolved external reference '%s'", str
);
5667 greloc_patch(s
, addr
);
5674 static int put_elf_str(Section
*s
, const char *sym
)
5677 offset
= s
->data_ptr
- s
->data
;
5687 static void put_elf_sym(Section
*s
,
5688 unsigned long value
, unsigned long size
,
5689 int info
, int other
, int shndx
, const char *name
)
5694 sym
= (Elf32_Sym
*)s
->data_ptr
;
5696 name_offset
= put_elf_str(s
->link
, name
);
5699 sym
->st_name
= name_offset
;
5700 sym
->st_value
= value
;
5701 sym
->st_size
= size
;
5702 sym
->st_info
= info
;
5703 sym
->st_other
= other
;
5704 sym
->st_shndx
= shndx
;
5705 s
->data_ptr
+= sizeof(Elf32_Sym
);
5708 /* put stab debug information */
5711 unsigned long n_strx
; /* index into string table of name */
5712 unsigned char n_type
; /* type of symbol */
5713 unsigned char n_other
; /* misc info (usually empty) */
5714 unsigned short n_desc
; /* description field */
5715 unsigned long n_value
; /* value of symbol */
5718 static void put_stabs(const char *str
, int type
, int other
, int desc
, int value
)
5722 sym
= (Stab_Sym
*)stab_section
->data_ptr
;
5724 sym
->n_strx
= put_elf_str(stabstr_section
, str
);
5729 sym
->n_other
= other
;
5731 sym
->n_value
= value
;
5733 stab_section
->data_ptr
+= sizeof(Stab_Sym
);
5736 static void put_stabn(int type
, int other
, int desc
, int value
)
5738 put_stabs(NULL
, type
, other
, desc
, value
);
5741 static void put_stabd(int type
, int other
, int desc
)
5743 put_stabs(NULL
, type
, other
, desc
, 0);
5746 /* output an ELF file (currently, only for testing) */
5747 /* XXX: better program header generation */
5748 /* XXX: handle realloc'ed sections (instead of mmaping them) */
5749 /* XXX: generate dynamic reloc info + DLL tables */
5750 /* XXX: generate startup code */
5751 void build_exe(char *filename
)
5755 int shnum
, i
, phnum
, file_offset
, offset
, size
, j
;
5756 Section
*sec
, *strsec
;
5757 Elf32_Shdr
*shdr
, *sh
;
5758 Elf32_Phdr
*phdr
, *ph
;
5760 memset(&ehdr
, 0, sizeof(ehdr
));
5762 /* we add a section for symbols */
5763 strsec
= new_section(".shstrtab", SHT_STRTAB
, 0);
5764 put_elf_str(strsec
, "");
5766 /* count number of sections and compute number of program segments */
5767 shnum
= 1; /* section index zero is reserved */
5769 for(sec
= first_section
; sec
!= NULL
; sec
= sec
->next
) {
5771 if (sec
->sh_flags
& SHF_ALLOC
)
5774 /* allocate section headers */
5775 shdr
= malloc(shnum
* sizeof(Elf32_Shdr
));
5777 error("memory full");
5778 memset(shdr
, 0, shnum
* sizeof(Elf32_Shdr
));
5779 /* allocate program segment headers */
5780 phdr
= malloc(phnum
* sizeof(Elf32_Phdr
));
5782 error("memory full");
5783 memset(phdr
, 0, phnum
* sizeof(Elf32_Phdr
));
5785 /* XXX: find correct load order */
5786 file_offset
= sizeof(Elf32_Ehdr
) + phnum
* sizeof(Elf32_Phdr
);
5787 for(sec
= first_section
, i
= 1; sec
!= NULL
; sec
= sec
->next
, i
++) {
5789 sh
->sh_name
= put_elf_str(strsec
, sec
->name
);
5790 sh
->sh_type
= sec
->sh_type
;
5791 sh
->sh_flags
= sec
->sh_flags
;
5792 sh
->sh_entsize
= sec
->sh_entsize
;
5794 sh
->sh_link
= sec
->link
->sh_num
;
5795 if (sh
->sh_type
== SHT_STRTAB
) {
5796 sh
->sh_addralign
= 1;
5797 } else if (sh
->sh_type
== SHT_SYMTAB
||
5798 (sh
->sh_flags
& SHF_ALLOC
) == 0) {
5799 sh
->sh_addralign
= 4;
5801 sh
->sh_addr
= (Elf32_Word
)sec
->data
;
5802 sh
->sh_addralign
= 4096;
5804 sh
->sh_size
= (Elf32_Word
)sec
->data_ptr
- (Elf32_Word
)sec
->data
;
5805 /* align to section start */
5806 file_offset
= (file_offset
+ sh
->sh_addralign
- 1) &
5807 ~(sh
->sh_addralign
- 1);
5808 sh
->sh_offset
= file_offset
;
5809 file_offset
+= sh
->sh_size
;
5811 /* build program headers (simplistic - not fully correct) */
5813 for(i
=1;i
<shnum
;i
++) {
5815 if (sh
->sh_type
== SHT_PROGBITS
&&
5816 (sh
->sh_flags
& SHF_ALLOC
) != 0) {
5818 ph
->p_type
= PT_LOAD
;
5819 ph
->p_offset
= sh
->sh_offset
;
5820 ph
->p_vaddr
= sh
->sh_addr
;
5821 ph
->p_paddr
= ph
->p_vaddr
;
5822 ph
->p_filesz
= sh
->sh_size
;
5823 ph
->p_memsz
= sh
->sh_size
;
5825 if (sh
->sh_flags
& SHF_WRITE
)
5826 ph
->p_flags
|= PF_W
;
5827 if (sh
->sh_flags
& SHF_EXECINSTR
)
5828 ph
->p_flags
|= PF_X
;
5829 ph
->p_align
= sh
->sh_addralign
;
5834 file_offset
= (file_offset
+ 3) & -4;
5837 ehdr
.e_ident
[0] = ELFMAG0
;
5838 ehdr
.e_ident
[1] = ELFMAG1
;
5839 ehdr
.e_ident
[2] = ELFMAG2
;
5840 ehdr
.e_ident
[3] = ELFMAG3
;
5841 ehdr
.e_ident
[4] = ELFCLASS32
;
5842 ehdr
.e_ident
[5] = ELFDATA2LSB
;
5843 ehdr
.e_ident
[6] = EV_CURRENT
;
5844 ehdr
.e_type
= ET_EXEC
;
5845 ehdr
.e_machine
= EM_386
;
5846 ehdr
.e_version
= EV_CURRENT
;
5847 ehdr
.e_entry
= 0; /* XXX: patch it */
5848 ehdr
.e_phoff
= sizeof(Elf32_Ehdr
);
5849 ehdr
.e_shoff
= file_offset
;
5850 ehdr
.e_ehsize
= sizeof(Elf32_Ehdr
);
5851 ehdr
.e_phentsize
= sizeof(Elf32_Phdr
);
5852 ehdr
.e_phnum
= phnum
;
5853 ehdr
.e_shentsize
= sizeof(Elf32_Shdr
);
5854 ehdr
.e_shnum
= shnum
;
5855 ehdr
.e_shstrndx
= shnum
- 1;
5857 /* write elf file */
5858 f
= fopen(filename
, "w");
5860 error("could not write '%s'", filename
);
5861 fwrite(&ehdr
, 1, sizeof(Elf32_Ehdr
), f
);
5862 fwrite(phdr
, 1, phnum
* sizeof(Elf32_Phdr
), f
);
5863 offset
= sizeof(Elf32_Ehdr
) + phnum
* sizeof(Elf32_Phdr
);
5864 for(sec
= first_section
, i
= 1; sec
!= NULL
; sec
= sec
->next
, i
++) {
5866 while (offset
< sh
->sh_offset
) {
5870 size
= sec
->data_ptr
- sec
->data
;
5871 fwrite(sec
->data
, 1, size
, f
);
5874 while (offset
< ehdr
.e_shoff
) {
5878 fwrite(shdr
, 1, shnum
* sizeof(Elf32_Shdr
), f
);
5882 /* print the position in the source file of PC value 'pc' by reading
5883 the stabs debug information */
5884 static void rt_printline(unsigned long wanted_pc
)
5886 Stab_Sym
*sym
, *sym_end
;
5887 char func_name
[128];
5888 unsigned long func_addr
, last_pc
, pc
;
5889 const char *incl_files
[INCLUDE_STACK_SIZE
];
5890 int incl_index
, len
, last_line_num
, i
;
5891 const char *str
, *p
;
5893 func_name
[0] = '\0';
5896 last_pc
= 0xffffffff;
5898 sym
= (Stab_Sym
*)stab_section
->data
+ 1;
5899 sym_end
= (Stab_Sym
*)stab_section
->data_ptr
;
5900 while (sym
< sym_end
) {
5901 switch(sym
->n_type
) {
5902 /* function start or end */
5904 if (sym
->n_strx
== 0) {
5905 func_name
[0] = '\0';
5908 str
= stabstr_section
->data
+ sym
->n_strx
;
5909 p
= strchr(str
, ':');
5911 pstrcpy(func_name
, sizeof(func_name
), str
);
5914 if (len
> sizeof(func_name
) - 1)
5915 len
= sizeof(func_name
) - 1;
5916 memcpy(func_name
, str
, len
);
5917 func_name
[len
] = '\0';
5919 func_addr
= sym
->n_value
;
5922 /* line number info */
5924 pc
= sym
->n_value
+ func_addr
;
5925 if (wanted_pc
>= last_pc
&& wanted_pc
< pc
)
5928 last_line_num
= sym
->n_desc
;
5932 str
= stabstr_section
->data
+ sym
->n_strx
;
5934 if (incl_index
< INCLUDE_STACK_SIZE
) {
5935 incl_files
[incl_index
++] = str
;
5943 if (sym
->n_strx
== 0) {
5944 incl_index
= 0; /* end of translation unit */
5946 str
= stabstr_section
->data
+ sym
->n_strx
;
5947 /* do not add path */
5949 if (len
> 0 && str
[len
- 1] != '/')
5956 /* did not find line number info: */
5957 fprintf(stderr
, "(no debug info, pc=0x%08lx): ", wanted_pc
);
5960 for(i
= 0; i
< incl_index
- 1; i
++)
5961 fprintf(stderr
, "In file included from %s\n",
5963 if (incl_index
> 0) {
5964 fprintf(stderr
, "%s:%d: ",
5965 incl_files
[incl_index
- 1], last_line_num
);
5967 if (func_name
[0] != '\0') {
5968 fprintf(stderr
, "in function '%s()': ", func_name
);
5973 /* signal handler for fatal errors */
5974 static void sig_error(int signum
, siginfo_t
*siginf
, void *puc
)
5976 struct ucontext
*uc
= puc
;
5980 pc
= uc
->uc_mcontext
.gregs
[14];
5982 #error please put the right sigcontext field
5989 switch(siginf
->si_code
) {
5992 fprintf(stderr
, "division by zero\n");
5995 fprintf(stderr
, "floating point exception\n");
6001 fprintf(stderr
, "dereferencing invalid pointer\n");
6004 fprintf(stderr
, "illegal instruction\n");
6007 fprintf(stderr
, "abort() called\n");
6010 fprintf(stderr
, "caught signal %d\n", signum
);
6016 /* launch the compiled program with the given arguments */
6017 int launch_exe(int argc
, char **argv
)
6021 struct sigaction sigact
;
6023 s
= sym_find1(&extern_stack
, TOK_MAIN
);
6024 if (!s
|| (s
->r
& VT_FORWARD
))
6025 error("main() not defined");
6028 /* install TCC signal handlers to print debug info on fatal
6030 sigact
.sa_flags
= SA_SIGINFO
| SA_ONESHOT
;
6031 sigact
.sa_sigaction
= sig_error
;
6032 sigemptyset(&sigact
.sa_mask
);
6033 sigaction(SIGFPE
, &sigact
, NULL
);
6034 sigaction(SIGILL
, &sigact
, NULL
);
6035 sigaction(SIGSEGV
, &sigact
, NULL
);
6036 sigaction(SIGBUS
, &sigact
, NULL
);
6037 sigaction(SIGABRT
, &sigact
, NULL
);
6040 if (do_bounds_check
) {
6043 /* add all known static regions */
6044 p
= (int *)bounds_section
->data
;
6045 p_end
= (int *)bounds_section
->data_ptr
;
6047 __bound_new_region((void *)p
[0], p
[1]);
6052 t
= (int (*)())s
->c
;
6053 return (*t
)(argc
, argv
);
6059 printf("tcc version 0.9.3 - Tiny C Compiler - Copyright (C) 2001, 2002 Fabrice Bellard\n"
6060 "usage: tcc [-Idir] [-Dsym[=val]] [-Usym] [-llib] [-g] [-b]\n"
6061 " [-i infile] infile [infile_args...]\n"
6063 "-Idir : add include path 'dir'\n"
6064 "-Dsym[=val] : define 'sym' with value 'val'\n"
6065 "-Usym : undefine 'sym'\n"
6066 "-llib : link with dynamic library 'lib'\n"
6067 "-g : generate runtime debug info\n"
6068 "-b : compile with built-in memory and bounds checker (implies -g)\n"
6069 "-i infile : compile infile\n"
6073 int main(int argc
, char **argv
)
6075 char *p
, *r
, *outfile
;
6078 include_paths
[0] = "/usr/include";
6079 include_paths
[1] = "/usr/lib/tcc";
6080 include_paths
[2] = "/usr/local/lib/tcc";
6081 nb_include_paths
= 3;
6083 /* add all tokens */
6084 tok_ident
= TOK_IDENT
;
6085 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";
6089 tok_alloc(p
, r
- p
- 1);
6093 /* standard defines */
6094 define_symbol("__STDC__");
6096 define_symbol("__i386__");
6098 /* tiny C specific defines */
6099 define_symbol("__TINYC__");
6101 /* create standard sections */
6102 text_section
= new_section(".text", SHT_PROGBITS
, SHF_ALLOC
| SHF_EXECINSTR
);
6103 data_section
= new_section(".data", SHT_PROGBITS
, SHF_ALLOC
| SHF_WRITE
);
6104 /* XXX: should change type to SHT_NOBITS */
6105 bss_section
= new_section(".bss", SHT_PROGBITS
, SHF_ALLOC
| SHF_WRITE
);
6110 if (optind
>= argc
) {
6120 if (nb_include_paths
>= INCLUDE_PATHS_MAX
)
6121 error("too many include paths");
6122 include_paths
[nb_include_paths
++] = r
+ 2;
6123 } else if (r
[1] == 'D') {
6124 define_symbol(r
+ 2);
6125 } else if (r
[1] == 'U') {
6126 undef_symbol(r
+ 2);
6127 } else if (r
[1] == 'l') {
6129 } else if (r
[1] == 'i') {
6132 tcc_compile_file(argv
[optind
++]);
6133 } else if (r
[1] == 'b') {
6134 if (!do_bounds_check
) {
6135 do_bounds_check
= 1;
6136 /* create bounds sections */
6137 bounds_section
= new_section(".bounds",
6138 SHT_PROGBITS
, SHF_ALLOC
);
6139 lbounds_section
= new_section(".lbounds",
6140 SHT_PROGBITS
, SHF_ALLOC
);
6141 /* debug is implied */
6144 } else if (r
[1] == 'g') {
6150 stab_section
= new_section(".stab", SHT_PROGBITS
, 0);
6151 stab_section
->sh_entsize
= sizeof(Stab_Sym
);
6152 stabstr_section
= new_section(".stabstr", SHT_STRTAB
, 0);
6153 put_elf_str(stabstr_section
, "");
6154 stab_section
->link
= stabstr_section
;
6155 /* put first entry */
6156 put_stabs("", 0, 0, 0, 0);
6159 symtab_section
= new_section(".symtab", SHT_SYMTAB
, 0);
6160 symtab_section
->sh_entsize
= sizeof(Elf32_Sym
);
6161 strtab_section
= new_section(".strtab", SHT_STRTAB
, 0);
6162 put_elf_str(strtab_section
, "");
6163 symtab_section
->link
= strtab_section
;
6164 put_elf_sym(symtab_section
, 0, 0, 0, 0, 0, NULL
);
6166 } else if (r
[1] == 'o') {
6167 /* currently, only for testing, so not documented */
6170 outfile
= argv
[optind
++];
6172 fprintf(stderr
, "invalid option -- '%s'\n", r
);
6177 tcc_compile_file(argv
[optind
]);
6179 resolve_extern_syms();
6185 return launch_exe(argc
- optind
, argv
+ optind
);