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
, ...);
437 void rt_error(unsigned long pc
, const char *fmt
, ...);
439 void vset(int t
, int r
, int v
);
440 void type_to_str(char *buf
, int buf_size
,
441 int t
, const char *varstr
);
443 /* section generation */
444 void greloc(Sym
*s
, int addr
, int type
);
445 static int put_elf_str(Section
*s
, const char *sym
);
446 static void put_elf_sym(Section
*s
,
447 unsigned long value
, unsigned long size
,
448 int info
, int other
, int shndx
, const char *name
);
449 static void put_stabs(const char *str
, int type
, int other
, int desc
, int value
);
450 static void put_stabn(int type
, int other
, int desc
, int value
);
451 static void put_stabd(int type
, int other
, int desc
);
453 /* true if float/double/long double type */
454 static inline int is_float(int t
)
458 return bt
== VT_LDOUBLE
|| bt
== VT_DOUBLE
|| bt
== VT_FLOAT
;
463 #include "i386-gen.c"
465 #ifdef CONFIG_TCC_STATIC
467 #define RTLD_LAZY 0x001
468 #define RTLD_NOW 0x002
469 #define RTLD_GLOBAL 0x100
471 /* dummy function for profiling */
472 void *dlopen(const char *filename
, int flag
)
477 const char *dlerror(void)
482 typedef struct TCCSyms
{
487 #define TCCSYM(a) { #a, &a, },
489 /* add the symbol you want here if no dynamic linking is done */
490 static TCCSyms tcc_syms
[] = {
498 void *dlsym(void *handle
, char *symbol
)
502 while (p
->str
!= NULL
) {
503 if (!strcmp(p
->str
, symbol
))
512 /********************************************************/
513 /* runtime library is there */
514 /* XXX: we suppose that the host compiler handles 'long long'. It
515 would not be difficult to suppress this assumption */
517 /* XXX: these functions are defined in libgcc. Should provide a
518 portable code too. */
519 long long __divll(long long a
, long long b
)
524 long long __modll(long long a
, long long b
)
529 unsigned long long __divull(unsigned long long a
, unsigned long long b
)
534 unsigned long long __modull(unsigned long long a
, unsigned long long b
)
539 long long __sardi3(long long a
, int b
)
544 unsigned long long __shrdi3(unsigned long long a
, int b
)
549 long long __shldi3(long long a
, int b
)
554 float __ulltof(unsigned long long a
)
559 double __ulltod(unsigned long long a
)
564 long double __ulltold(unsigned long long a
)
566 return (long double)a
;
569 unsigned long long __ftoull(float a
)
571 return (unsigned long long)a
;
574 unsigned long long __dtoull(double a
)
576 return (unsigned long long)a
;
579 unsigned long long __ldtoull(long double a
)
581 return (unsigned long long)a
;
585 /********************************************************/
587 /* copy a string and truncate it */
588 char *pstrcpy(char *buf
, int buf_size
, const char *s
)
594 q_end
= buf
+ buf_size
- 1;
605 /* strcat and truncate */
606 char *pstrcat(char *buf
, int buf_size
, const char *s
)
611 pstrcpy(buf
+ len
, buf_size
- len
, s
);
615 Section
*new_section(const char *name
, int sh_type
, int sh_flags
)
617 Section
*sec
, **psec
;
620 sec
= malloc(sizeof(Section
));
622 error("memory full");
623 memset(sec
, 0, sizeof(Section
));
624 pstrcpy(sec
->name
, sizeof(sec
->name
), name
);
626 sec
->sh_num
= ++section_num
;
627 sec
->sh_type
= sh_type
;
628 sec
->sh_flags
= sh_flags
;
629 data
= mmap(NULL
, SECTION_VSIZE
,
630 PROT_EXEC
| PROT_READ
| PROT_WRITE
,
631 MAP_PRIVATE
| MAP_ANONYMOUS
,
633 if (data
== (void *)(-1))
634 error("could not mmap section '%s'", name
);
636 sec
->data_ptr
= data
;
637 psec
= &first_section
;
638 while (*psec
!= NULL
)
639 psec
= &(*psec
)->next
;
645 /* return a reference to a section, and create it if it does not
647 Section
*find_section(const char *name
)
651 for(sec
= first_section
; sec
!= NULL
; sec
= sec
->next
) {
652 if (!strcmp(name
, sec
->name
))
655 /* sections are created as PROGBITS */
656 return new_section(name
, SHT_PROGBITS
, SHF_ALLOC
);
659 /* add a new relocation entry to symbol 's' */
660 void greloc(Sym
*s
, int addr
, int type
)
663 p
= malloc(sizeof(Reloc
));
665 error("memory full");
668 p
->next
= (Reloc
*)s
->c
;
672 /* patch each relocation entry with value 'val' */
673 void greloc_patch(Sym
*s
, int val
)
680 greloc_patch1(p
, val
);
689 static inline int isid(int c
)
691 return (c
>= 'a' && c
<= 'z') ||
692 (c
>= 'A' && c
<= 'Z') ||
696 static inline int isnum(int c
)
698 return c
>= '0' && c
<= '9';
701 static inline int toup(int c
)
703 if (ch
>= 'a' && ch
<= 'z')
704 return ch
- 'a' + 'A';
712 for(f
= include_stack
; f
< include_stack_ptr
; f
++)
713 fprintf(stderr
, "In file included from %s:%d:\n",
714 f
->filename
, f
->line_num
);
715 fprintf(stderr
, "%s:%d: ", filename
, line_num
);
718 void error(const char *fmt
, ...)
723 vfprintf(stderr
, fmt
, ap
);
724 fprintf(stderr
, "\n");
729 void expect(const char *msg
)
731 error("%s expected", msg
);
734 void warning(const char *fmt
, ...)
740 fprintf(stderr
, "warning: ");
741 vfprintf(stderr
, fmt
, ap
);
742 fprintf(stderr
, "\n");
749 error("'%c' expected", c
);
753 void test_lvalue(void)
755 if (!(vtop
->r
& VT_LVAL
))
759 TokenSym
*tok_alloc(const char *str
, int len
)
761 TokenSym
*ts
, **pts
, **ptable
;
768 h
= ((h
<< 8) | (str
[i
] & 0xff)) % TOK_HASH_SIZE
;
770 pts
= &hash_ident
[h
];
775 if (ts
->len
== len
&& !memcmp(ts
->str
, str
, len
))
777 pts
= &(ts
->hash_next
);
780 if (tok_ident
>= SYM_FIRST_ANOM
)
781 error("memory full");
783 /* expand token table if needed */
784 i
= tok_ident
- TOK_IDENT
;
785 if ((i
% TOK_ALLOC_INCR
) == 0) {
786 ptable
= realloc(table_ident
, (i
+ TOK_ALLOC_INCR
) * sizeof(TokenSym
*));
788 error("memory full");
789 table_ident
= ptable
;
792 ts
= malloc(sizeof(TokenSym
) + len
);
794 error("memory full");
796 ts
->tok
= tok_ident
++;
798 ts
->hash_next
= NULL
;
799 memcpy(ts
->str
, str
, len
+ 1);
804 void add_char(char **pp
, int c
)
808 if (c
== '\'' || c
== '\"' || c
== '\\') {
809 /* XXX: could be more precise if char or string */
812 if (c
>= 32 && c
<= 126) {
819 *p
++ = '0' + ((c
>> 6) & 7);
820 *p
++ = '0' + ((c
>> 3) & 7);
821 *p
++ = '0' + (c
& 7);
827 /* XXX: buffer overflow */
828 char *get_tok_str(int v
, CValue
*cv
)
830 static char buf
[STRING_MAX_SIZE
+ 1];
835 if (v
== TOK_CINT
|| v
== TOK_CUINT
) {
836 sprintf(buf
, "%u", cv
->ui
);
838 } else if (v
== TOK_CCHAR
|| v
== TOK_LCHAR
) {
845 } else if (v
== TOK_STR
|| v
== TOK_LSTR
) {
849 for(i
=0;i
<ts
->len
;i
++)
850 add_char(&p
, ts
->str
[i
]);
854 } else if (v
< TOK_IDENT
) {
859 } else if (v
< tok_ident
) {
860 return table_ident
[v
- TOK_IDENT
]->str
;
862 /* should never happen */
867 /* push, without hashing */
868 Sym
*sym_push2(Sym
**ps
, int v
, int t
, int c
)
871 s
= malloc(sizeof(Sym
));
873 error("memory full");
884 /* find a symbol and return its associated structure. 's' is the top
885 of the symbol stack */
886 Sym
*sym_find2(Sym
*s
, int v
)
896 #define HASH_SYM(v) ((unsigned)(v) % SYM_HASH_SIZE)
898 /* find a symbol and return its associated structure. 'st' is the
900 Sym
*sym_find1(SymStack
*st
, int v
)
904 s
= st
->hash
[HASH_SYM(v
)];
913 Sym
*sym_push1(SymStack
*st
, int v
, int t
, int c
)
916 s
= sym_push2(&st
->top
, v
, t
, c
);
917 /* add in hash table */
919 ps
= &st
->hash
[HASH_SYM(v
)];
926 /* find a symbol in the right symbol space */
930 s
= sym_find1(&local_stack
, v
);
932 s
= sym_find1(&global_stack
, v
);
936 /* push a given symbol on the symbol stack */
937 Sym
*sym_push(int v
, int t
, int r
, int c
)
941 s
= sym_push1(&local_stack
, v
, t
, c
);
943 s
= sym_push1(&global_stack
, v
, t
, c
);
948 /* pop symbols until top reaches 'b' */
949 void sym_pop(SymStack
*st
, Sym
*b
)
956 /* free hash table entry, except if symbol was freed (only
957 used for #undef symbols) */
959 st
->hash
[HASH_SYM(s
->v
)] = s
->hash_next
;
966 /* undefined a hashed symbol (used for #undef). Its name is set to
968 void sym_undef(SymStack
*st
, Sym
*s
)
971 ss
= &st
->hash
[HASH_SYM(s
->v
)];
972 while (*ss
!= NULL
) {
975 ss
= &(*ss
)->hash_next
;
981 /* no need to put that inline */
984 if (include_stack_ptr
== include_stack
)
986 /* add end of include file debug info */
988 put_stabd(N_EINCL
, 0, 0);
990 /* pop include stack */
994 file
= include_stack_ptr
->file
;
995 filename
= include_stack_ptr
->filename
;
996 line_num
= include_stack_ptr
->line_num
;
1000 /* read next char from current input file */
1001 static inline void inp(void)
1004 /* faster than fgetc */
1005 ch1
= getc_unlocked(file
);
1007 if (handle_eof() < 0)
1014 // printf("ch1=%c 0x%x\n", ch1, ch1);
1017 /* input with '\\n' handling */
1018 static inline void minp(void)
1023 if (ch
== '\\' && ch1
== '\n') {
1027 //printf("ch=%c 0x%x\n", ch, ch);
1031 /* same as minp, but also skip comments */
1039 /* single line C++ comments */
1041 while (ch1
!= '\n' && ch1
!= -1)
1044 ch
= ' '; /* return space */
1045 } else if (ch1
== '*') {
1051 if (c
== '*' && ch1
== '/') {
1053 ch
= ' '; /* return space */
1065 void skip_spaces(void)
1067 while (ch
== ' ' || ch
== '\t')
1071 /* skip block of text until #else, #elif or #endif. skip also pairs of
1073 void preprocess_skip()
1078 while (ch
!= '\n') {
1089 (tok
== TOK_ELSE
|| tok
== TOK_ELIF
|| tok
== TOK_ENDIF
))
1091 if (tok
== TOK_IF
|| tok
== TOK_IFDEF
|| tok
== TOK_IFNDEF
)
1093 else if (tok
== TOK_ENDIF
)
1099 /* return the number of additionnal 'ints' necessary to store the
1101 static inline int tok_ext_size(int t
)
1118 return LDOUBLE_SIZE
/ 4;
1124 void tok_add(int **tok_str
, int *tok_len
, int t
)
1129 if ((len
& 63) == 0) {
1130 str
= realloc(str
, (len
+ 64) * sizeof(int));
1139 void tok_add2(int **tok_str
, int *tok_len
, int t
, CValue
*cv
)
1143 tok_add(tok_str
, tok_len
, t
);
1144 n
= tok_ext_size(t
);
1146 tok_add(tok_str
, tok_len
, cv
->tab
[i
]);
1149 /* get a token from an integer array and increment pointer accordingly */
1150 int tok_get(int **tok_str
, CValue
*cv
)
1156 n
= tok_ext_size(t
);
1163 /* eval an expression for #if/#elif */
1164 int expr_preprocess(void)
1166 int *str
, len
, c
, t
;
1174 next(); /* do macro subst */
1175 if (tok
== TOK_DEFINED
) {
1180 c
= sym_find1(&define_stack
, tok
) != 0;
1185 } else if (tok
>= TOK_IDENT
) {
1186 /* if undefined macro */
1190 tok_add2(&str
, &len
, tok
, &tokc
);
1192 tok_add(&str
, &len
, -1); /* simulate end of file */
1193 tok_add(&str
, &len
, 0);
1194 /* now evaluate C constant expression */
1204 void tok_print(int *str
)
1210 t
= tok_get(&str
, &cval
);
1213 printf(" %s", get_tok_str(t
, &cval
));
1219 void preprocess(void)
1221 int size
, i
, c
, v
, t
, *str
, len
;
1222 char buf
[1024], *q
, *p
;
1225 Sym
**ps
, *first
, *s
;
1230 if (tok
== TOK_DEFINE
) {
1233 /* XXX: should check if same macro (ANSI) */
1236 /* '(' must be just after macro definition for MACRO_FUNC */
1241 while (tok
!= ')') {
1242 if (tok
== TOK_DOTS
)
1243 tok
= TOK___VA_ARGS__
;
1244 s
= sym_push1(&define_stack
, tok
| SYM_FIELD
, 0, 0);
1258 if (ch
== '\n' || ch
== -1)
1261 tok_add2(&str
, &len
, tok
, &tokc
);
1263 tok_add(&str
, &len
, 0);
1265 printf("define %s %d: ", get_tok_str(v
, NULL
), t
);
1268 s
= sym_push1(&define_stack
, v
, t
, (int)str
);
1270 } else if (tok
== TOK_UNDEF
) {
1272 s
= sym_find1(&define_stack
, tok
);
1273 /* undefine symbol by putting an invalid name */
1275 sym_undef(&define_stack
, s
);
1276 } else if (tok
== TOK_INCLUDE
) {
1281 } else if (ch
== '\"') {
1286 while (ch
!= c
&& ch
!= '\n' && ch
!= -1) {
1287 if ((q
- buf
) < sizeof(buf
) - 1)
1295 error("#include syntax error");
1296 pstrcpy(buf
, sizeof(buf
), get_tok_str(tok
, &tokc
));
1299 /* eat all spaces and comments after include */
1300 /* XXX: slightly incorrect */
1301 while (ch1
!= '\n' && ch1
!= -1)
1304 if (include_stack_ptr
>= include_stack
+ INCLUDE_STACK_SIZE
)
1305 error("memory full");
1307 /* first search in current dir if "header.h" */
1309 p
= strrchr(filename
, '/');
1311 size
= p
+ 1 - filename
;
1312 if (size
> sizeof(buf1
) - 1)
1313 size
= sizeof(buf1
) - 1;
1314 memcpy(buf1
, filename
, size
);
1316 pstrcat(buf1
, sizeof(buf1
), buf
);
1317 f
= fopen(buf1
, "r");
1321 /* now search in standard include path */
1322 for(i
=nb_include_paths
- 1;i
>=0;i
--) {
1323 strcpy(buf1
, include_paths
[i
]);
1326 f
= fopen(buf1
, "r");
1330 error("include file '%s' not found", buf1
);
1333 /* push current file in stack */
1334 /* XXX: fix current line init */
1335 include_stack_ptr
->file
= file
;
1336 include_stack_ptr
->filename
= filename
;
1337 include_stack_ptr
->line_num
= line_num
;
1338 include_stack_ptr
++;
1340 filename
= strdup(buf1
);
1342 /* add include file debug info */
1344 put_stabs(filename
, N_BINCL
, 0, 0, 0);
1346 } else if (tok
== TOK_IFNDEF
) {
1349 } else if (tok
== TOK_IF
) {
1350 c
= expr_preprocess();
1352 } else if (tok
== TOK_IFDEF
) {
1356 c
= (sym_find1(&define_stack
, tok
) != 0) ^ c
;
1358 if (ifdef_stack_ptr
>= ifdef_stack
+ IFDEF_STACK_SIZE
)
1359 error("memory full");
1360 *ifdef_stack_ptr
++ = c
;
1362 } else if (tok
== TOK_ELSE
) {
1363 if (ifdef_stack_ptr
== ifdef_stack
||
1364 (ifdef_stack_ptr
[-1] & 2))
1365 error("#else after #else");
1366 c
= (ifdef_stack_ptr
[-1] ^= 3);
1368 } else if (tok
== TOK_ELIF
) {
1369 if (ifdef_stack_ptr
== ifdef_stack
||
1370 ifdef_stack_ptr
[-1] > 1)
1371 error("#elif after #else");
1372 c
= expr_preprocess();
1373 ifdef_stack_ptr
[-1] = c
;
1379 } else if (tok
== TOK_ENDIF
) {
1380 if (ifdef_stack_ptr
== ifdef_stack
)
1383 } else if (tok
== TOK_LINE
) {
1385 if (tok
!= TOK_CINT
)
1393 /* XXX: potential memory leak */
1394 filename
= strdup(get_tok_str(tok
, &tokc
));
1396 } else if (tok
== TOK_ERROR
) {
1399 /* ignore other preprocess commands or #! for C scripts */
1400 while (ch
!= '\n' && ch
!= -1)
1404 /* read a number in base b */
1410 if (ch
>= 'a' && ch
<= 'f')
1412 else if (ch
>= 'A' && ch
<= 'F')
1418 if (t
< 0 || t
>= b
)
1426 /* read a character for string or char constant and eval escape codes */
1435 /* at most three octal digits */
1439 c
= c
* 8 + ch
- '0';
1442 c
= c
* 8 + ch
- '0';
1447 } else if (ch
== 'x') {
1465 else if (ch
== 'e' && gnu_ext
)
1467 else if (ch
== '\'' || ch
== '\"' || ch
== '\\' || ch
== '?')
1470 error("invalid escaped char");
1477 /* we use 64 bit numbers */
1480 /* bn = (bn << shift) | or_val */
1481 void bn_lshift(unsigned int *bn
, int shift
, int or_val
)
1485 for(i
=0;i
<BN_SIZE
;i
++) {
1487 bn
[i
] = (v
<< shift
) | or_val
;
1488 or_val
= v
>> (32 - shift
);
1492 void bn_zero(unsigned int *bn
)
1495 for(i
=0;i
<BN_SIZE
;i
++) {
1500 void parse_number(void)
1502 int b
, t
, shift
, frac_bits
, s
, exp_val
;
1504 unsigned int bn
[BN_SIZE
];
1514 /* special dot handling */
1515 if (ch
>= '0' && ch
<= '9') {
1516 goto float_frac_parse
;
1517 } else if (ch
== '.') {
1528 } else if (t
== '0') {
1529 if (ch
== 'x' || ch
== 'X') {
1533 } else if (tcc_ext
&& (ch
== 'b' || ch
== 'B')) {
1539 /* parse all digits. cannot check octal numbers at this stage
1540 because of floating point constants */
1542 if (ch
>= 'a' && ch
<= 'f')
1544 else if (ch
>= 'A' && ch
<= 'F')
1552 if (q
>= token_buf
+ STRING_MAX_SIZE
) {
1554 error("number too long");
1560 ((ch
== 'e' || ch
== 'E') && b
== 10) ||
1561 ((ch
== 'p' || ch
== 'P') && (b
== 16 || b
== 2))) {
1563 /* NOTE: strtox should support that for hexa numbers, but
1564 non ISOC99 libcs do not support it, so we prefer to do
1566 /* hexadecimal or binary floats */
1567 /* XXX: handle overflows */
1579 } else if (t
>= 'a') {
1581 } else if (t
>= 'A') {
1586 bn_lshift(bn
, shift
, t
);
1593 if (t
>= 'a' && t
<= 'f') {
1595 } else if (t
>= 'A' && t
<= 'F') {
1597 } else if (t
>= '0' && t
<= '9') {
1603 error("invalid digit");
1604 bn_lshift(bn
, shift
, t
);
1609 if (ch
!= 'p' && ch
!= 'P')
1610 error("exponent expected");
1616 } else if (ch
== '-') {
1620 if (ch
< '0' || ch
> '9')
1621 error("exponent digits expected");
1622 while (ch
>= '0' && ch
<= '9') {
1623 exp_val
= exp_val
* 10 + ch
- '0';
1626 exp_val
= exp_val
* s
;
1628 /* now we can generate the number */
1629 /* XXX: should patch directly float number */
1630 d
= (double)bn
[1] * 4294967296.0 + (double)bn
[0];
1631 d
= ldexp(d
, exp_val
- frac_bits
);
1636 /* float : should handle overflow */
1638 } else if (t
== 'L') {
1641 /* XXX: not large enough */
1642 tokc
.ld
= (long double)d
;
1648 /* decimal floats */
1650 if (q
>= token_buf
+ STRING_MAX_SIZE
)
1655 while (ch
>= '0' && ch
<= '9') {
1656 if (q
>= token_buf
+ STRING_MAX_SIZE
)
1662 if (ch
== 'e' || ch
== 'E') {
1663 if (q
>= token_buf
+ STRING_MAX_SIZE
)
1667 if (ch
== '-' || ch
== '+') {
1668 if (q
>= token_buf
+ STRING_MAX_SIZE
)
1673 if (ch
< '0' || ch
> '9')
1674 error("exponent digits expected");
1675 while (ch
>= '0' && ch
<= '9') {
1676 if (q
>= token_buf
+ STRING_MAX_SIZE
)
1688 tokc
.f
= strtof(token_buf
, NULL
);
1689 } else if (t
== 'L') {
1692 tokc
.ld
= strtold(token_buf
, NULL
);
1695 tokc
.d
= strtod(token_buf
, NULL
);
1699 unsigned long long n
, n1
;
1702 /* integer number */
1705 if (b
== 10 && *q
== '0') {
1712 /* no need for checks except for base 10 / 8 errors */
1715 } else if (t
>= 'a') {
1717 } else if (t
>= 'A') {
1722 error("invalid digit");
1726 /* detect overflow */
1728 error("integer constant overflow");
1731 /* XXX: not exactly ANSI compliant */
1732 if ((n
& 0xffffffff00000000LL
) != 0) {
1737 } else if (n
> 0x7fffffff) {
1747 error("three 'l' in integer constant");
1750 if (tok
== TOK_CINT
)
1752 else if (tok
== TOK_CUINT
)
1756 } else if (t
== 'U') {
1757 if (tok
== TOK_CINT
)
1759 else if (tok
== TOK_CLLONG
)
1766 if (tok
== TOK_CINT
|| tok
== TOK_CUINT
)
1774 /* return next token without macro substitution */
1775 void next_nomacro1(void)
1783 while (ch
== '\n') {
1785 while (ch
== ' ' || ch
== 9)
1788 /* preprocessor command if # at start of line after
1793 if (ch
!= ' ' && ch
!= '\t' && ch
!= '\f')
1811 while (isid(ch
) || isnum(ch
)) {
1812 if (q
>= token_buf
+ STRING_MAX_SIZE
)
1813 error("ident too long");
1818 ts
= tok_alloc(token_buf
, q
- token_buf
);
1820 } else if (isnum(ch
) || ch
== '.') {
1822 } else if (ch
== '\'') {
1830 } else if (ch
== '\"') {
1835 while (ch
!= '\"') {
1838 error("unterminated string");
1839 if (q
>= token_buf
+ STRING_MAX_SIZE
)
1840 error("string too long");
1844 tokc
.ts
= tok_alloc(token_buf
, q
- token_buf
);
1847 q
= "<=\236>=\235!=\225&&\240||\241++\244--\242==\224<<\1>>\2+=\253-=\255*=\252/=\257%=\245&=\246^=\336|=\374->\313..\250##\266";
1852 if (*q
== tok
&& q
[1] == ch
) {
1855 /* three chars tests */
1856 if (tok
== TOK_SHL
|| tok
== TOK_SAR
) {
1861 } else if (tok
== TOK_DOTS
) {
1863 error("parse error");
1870 /* single char substitutions */
1873 else if (tok
== '>')
1878 /* return next token without macro substitution. Can read input from
1885 tok
= tok_get(¯o_ptr
, &tokc
);
1891 /* substitute args in macro_str and return allocated string */
1892 int *macro_arg_subst(Sym
**nested_list
, int *macro_str
, Sym
*args
)
1894 int *st
, last_tok
, t
, notfirst
, *str
, len
;
1903 t
= tok_get(¯o_str
, &cval
);
1908 t
= tok_get(¯o_str
, &cval
);
1911 s
= sym_find2(args
, t
);
1913 token_buf
[0] = '\0';
1918 pstrcat(token_buf
, sizeof(token_buf
), " ");
1919 t
= tok_get(&st
, &cval
);
1920 pstrcat(token_buf
, sizeof(token_buf
), get_tok_str(t
, &cval
));
1924 printf("stringize: %s\n", token_buf
);
1927 ts
= tok_alloc(token_buf
, 0);
1929 tok_add2(&str
, &len
, TOK_STR
, &cval
);
1931 tok_add2(&str
, &len
, t
, &cval
);
1933 } else if (t
>= TOK_IDENT
) {
1934 s
= sym_find2(args
, t
);
1937 /* if '##' is present before or after , no arg substitution */
1938 if (*macro_str
== TOK_TWOSHARPS
|| last_tok
== TOK_TWOSHARPS
) {
1940 tok_add(&str
, &len
, *st
++);
1942 macro_subst(&str
, &len
, nested_list
, st
);
1945 tok_add(&str
, &len
, t
);
1948 tok_add2(&str
, &len
, t
, &cval
);
1952 tok_add(&str
, &len
, 0);
1956 /* handle the '##' operator */
1957 int *macro_twosharps(int *macro_str
)
1960 int *macro_str1
, macro_str1_len
, *macro_ptr1
;
1972 while (*macro_ptr
== TOK_TWOSHARPS
) {
1974 macro_ptr1
= macro_ptr
;
1977 t
= tok_get(¯o_ptr
, &cval
);
1978 /* XXX: we handle only most common cases:
1979 ident + ident or ident + number */
1980 if (tok
>= TOK_IDENT
&&
1981 (t
>= TOK_IDENT
|| t
== TOK_CINT
)) {
1982 p
= get_tok_str(tok
, &tokc
);
1983 pstrcpy(token_buf
, sizeof(token_buf
), p
);
1984 p
= get_tok_str(t
, &cval
);
1985 pstrcat(token_buf
, sizeof(token_buf
), p
);
1986 ts
= tok_alloc(token_buf
, 0);
1987 tok
= ts
->tok
; /* modify current token */
1989 /* cannot merge tokens: skip '##' */
1990 macro_ptr
= macro_ptr1
;
1995 tok_add2(¯o_str1
, ¯o_str1_len
, tok
, &tokc
);
1997 tok_add(¯o_str1
, ¯o_str1_len
, 0);
2003 /* do macro substitution of macro_str and add result to
2004 (tok_str,tok_len). If macro_str is NULL, then input stream token is
2005 substituted. 'nested_list' is the list of all macros we got inside
2006 to avoid recursing. */
2007 void macro_subst(int **tok_str
, int *tok_len
,
2008 Sym
**nested_list
, int *macro_str
)
2010 Sym
*s
, *args
, *sa
, *sa1
;
2011 int *str
, parlevel
, len
, *mstr
, t
, *saved_macro_ptr
;
2012 int mstr_allocated
, *macro_str1
;
2015 saved_macro_ptr
= macro_ptr
;
2016 macro_ptr
= macro_str
;
2019 /* first scan for '##' operator handling */
2020 macro_str1
= macro_twosharps(macro_str
);
2021 macro_ptr
= macro_str1
;
2028 /* special macros */
2029 if (tok
== TOK___LINE__
) {
2031 tok_add2(tok_str
, tok_len
, TOK_CINT
, &cval
);
2032 } else if (tok
== TOK___FILE__
) {
2033 cval
.ts
= tok_alloc(filename
, 0);
2034 tok_add2(tok_str
, tok_len
, TOK_STR
, &cval
);
2035 } else if (tok
== TOK___DATE__
) {
2036 cval
.ts
= tok_alloc("Jan 1 1970", 0);
2037 tok_add2(tok_str
, tok_len
, TOK_STR
, &cval
);
2038 } else if (tok
== TOK___TIME__
) {
2039 cval
.ts
= tok_alloc("00:00:00", 0);
2040 tok_add2(tok_str
, tok_len
, TOK_STR
, &cval
);
2041 } else if ((s
= sym_find1(&define_stack
, tok
)) != NULL
) {
2042 /* if symbol is a macro, prepare substitution */
2043 /* if nested substitution, do nothing */
2044 if (sym_find2(*nested_list
, tok
))
2048 if (s
->t
== MACRO_FUNC
) {
2049 /* NOTE: we do not use next_nomacro to avoid eating the
2050 next token. XXX: find better solution */
2054 while (ch
== ' ' || ch
== '\t' || ch
== '\n')
2058 if (t
!= '(') /* no macro subst */
2061 /* argument macro */
2066 while (tok
!= ')' && sa
) {
2070 while ((parlevel
> 0 ||
2073 sa
->v
== (TOK___VA_ARGS__
| SYM_FIELD
)))) &&
2077 else if (tok
== ')')
2079 tok_add2(&str
, &len
, tok
, &tokc
);
2082 tok_add(&str
, &len
, 0);
2083 sym_push2(&args
, sa
->v
& ~SYM_FIELD
, 0, (int)str
);
2091 /* now subst each arg */
2092 mstr
= macro_arg_subst(nested_list
, mstr
, args
);
2103 sym_push2(nested_list
, s
->v
, 0, 0);
2104 macro_subst(tok_str
, tok_len
, nested_list
, mstr
);
2105 /* pop nested defined symbol */
2107 *nested_list
= sa1
->prev
;
2113 /* no need to add if reading input stream */
2116 tok_add2(tok_str
, tok_len
, tok
, &tokc
);
2118 /* only replace one macro while parsing input stream */
2122 macro_ptr
= saved_macro_ptr
;
2127 /* return next token with macro substitution */
2133 /* special 'ungettok' case for label parsing */
2141 /* if not reading from macro substuted string, then try to substitute */
2145 macro_subst(&ptr
, &len
, &nested_list
, NULL
);
2147 tok_add(&ptr
, &len
, 0);
2149 macro_ptr_allocated
= ptr
;
2157 /* end of macro string: free it */
2158 free(macro_ptr_allocated
);
2165 printf("token = %s\n", get_tok_str(tok
, tokc
));
2169 void swap(int *p
, int *q
)
2177 void vsetc(int t
, int r
, CValue
*vc
)
2179 if (vtop
>= vstack
+ VSTACK_SIZE
)
2180 error("memory full");
2181 /* cannot let cpu flags if other instruction are generated */
2182 /* XXX: VT_JMP test too ? */
2183 if ((vtop
->r
& VT_VALMASK
) == VT_CMP
)
2188 vtop
->r2
= VT_CONST
;
2192 /* push integer constant */
2197 vsetc(VT_INT
, VT_CONST
, &cval
);
2200 void vset(int t
, int r
, int v
)
2217 void vpushv(SValue
*v
)
2219 if (vtop
>= vstack
+ VSTACK_SIZE
)
2220 error("memory full");
2230 /* save r to the memory stack, and mark it as being free */
2231 void save_reg(int r
)
2233 int l
, i
, saved
, t
, size
, align
;
2236 /* modify all stack values */
2239 for(p
=vstack
;p
<=vtop
;p
++) {
2240 i
= p
->r
& VT_VALMASK
;
2241 if ((p
->r
& VT_VALMASK
) == r
||
2242 (p
->r2
& VT_VALMASK
) == r
) {
2243 /* must save value on stack if not already done */
2245 /* store register in the stack */
2247 if (!is_float(t
) && (t
& VT_BTYPE
) != VT_LLONG
)
2249 size
= type_size(t
, &align
);
2250 loc
= (loc
- size
) & -align
;
2252 sv
.r
= VT_LOCAL
| VT_LVAL
;
2255 /* XXX: x86 specific: need to pop fp register ST0 if saved */
2257 o(0xd9dd); /* fstp %st(1) */
2259 /* special long long case */
2260 if ((p
->t
& VT_BTYPE
) == VT_LLONG
) {
2267 /* mark that stack entry as being saved on the stack */
2279 /* find a free register of class 'rc'. If none, save one register */
2285 /* find a free register */
2286 for(r
=0;r
<NB_REGS
;r
++) {
2287 if (reg_classes
[r
] & rc
) {
2288 for(p
=vstack
;p
<=vtop
;p
++) {
2289 if ((p
->r
& VT_VALMASK
) == r
||
2290 (p
->r2
& VT_VALMASK
) == r
)
2298 /* no register left : free the first one on the stack (VERY
2299 IMPORTANT to start from the bottom to ensure that we don't
2300 spill registers used in gen_opi()) */
2301 for(p
=vstack
;p
<=vtop
;p
++) {
2302 r
= p
->r
& VT_VALMASK
;
2303 if (r
< VT_CONST
&& (reg_classes
[r
] & rc
)) {
2311 void save_regs(void)
2316 for(p
=vstack
;p
<=vtop
;p
++) {
2317 r
= p
->r
& VT_VALMASK
;
2324 /* move register 's' to 'r', and flush previous value of r to memory
2326 void move_reg(int r
, int s
)
2339 /* get address of vtop (vtop MUST BE an lvalue) */
2342 vtop
->r
&= ~VT_LVAL
;
2343 /* tricky: if saved lvalue, then we can go back to lvalue */
2344 if ((vtop
->r
& VT_VALMASK
) == VT_LLOCAL
)
2345 vtop
->r
= (vtop
->r
& ~VT_VALMASK
) | VT_LOCAL
| VT_LVAL
;
2348 /* generate lvalue bound code */
2351 vtop
->r
&= ~VT_MUSTBOUND
;
2352 /* if lvalue, then use checking code before dereferencing */
2353 if (vtop
->r
& VT_LVAL
) {
2356 gen_bounded_ptr_add1();
2357 gen_bounded_ptr_add2(1);
2362 /* store vtop a register belonging to class 'rc'. lvalues are
2363 converted to values. Cannot be used if cannot be converted to
2364 register value (such as structures). */
2367 int r
, r2
, rc2
, bit_pos
, bit_size
, size
, align
, i
, data_offset
;
2368 unsigned long long ll
;
2370 /* NOTE: get_reg can modify vstack[] */
2371 if (vtop
->t
& VT_BITFIELD
) {
2372 bit_pos
= (vtop
->t
>> VT_STRUCT_SHIFT
) & 0x3f;
2373 bit_size
= (vtop
->t
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f;
2374 /* remove bit field info to avoid loops */
2375 vtop
->t
&= ~(VT_BITFIELD
| (-1 << VT_STRUCT_SHIFT
));
2376 /* generate shifts */
2377 vpushi(32 - (bit_pos
+ bit_size
));
2379 vpushi(32 - bit_size
);
2380 /* NOTE: transformed to SHR if unsigned */
2384 if (is_float(vtop
->t
) &&
2385 (vtop
->r
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
) {
2386 /* CPUs usually cannot use float constants, so we store them
2387 generically in data segment */
2388 size
= type_size(vtop
->t
, &align
);
2389 data_offset
= (int)data_section
->data_ptr
;
2390 data_offset
= (data_offset
+ align
- 1) & -align
;
2391 /* XXX: not portable yet */
2394 ((int *)data_offset
)[i
] = vtop
->c
.tab
[i
];
2396 vtop
->c
.ul
= data_offset
;
2397 data_offset
+= size
<< 2;
2398 data_section
->data_ptr
= (unsigned char *)data_offset
;
2400 if (vtop
->r
& VT_MUSTBOUND
)
2403 r
= vtop
->r
& VT_VALMASK
;
2404 /* need to reload if:
2406 - lvalue (need to dereference pointer)
2407 - already a register, but not in the right class */
2408 if (r
>= VT_CONST
||
2409 (vtop
->r
& VT_LVAL
) ||
2410 !(reg_classes
[r
] & rc
) ||
2411 ((vtop
->t
& VT_BTYPE
) == VT_LLONG
&&
2412 !(reg_classes
[vtop
->r2
] & rc
))) {
2414 if ((vtop
->t
& VT_BTYPE
) == VT_LLONG
) {
2415 /* two register type load : expand to two words
2417 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
) {
2420 vtop
->c
.ui
= ll
; /* first word */
2422 vtop
->r
= r
; /* save register value */
2423 vpushi(ll
>> 32); /* second word */
2424 } else if (r
>= VT_CONST
||
2425 (vtop
->r
& VT_LVAL
)) {
2426 /* load from memory */
2429 vtop
[-1].r
= r
; /* save register value */
2430 /* increment pointer to get second word */
2437 /* move registers */
2440 vtop
[-1].r
= r
; /* save register value */
2441 vtop
->r
= vtop
[-1].r2
;
2443 /* allocate second register */
2450 /* write second register */
2453 /* one register type load */
2462 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
2463 void gv2(int rc1
, int rc2
)
2465 /* generate more generic register first */
2471 /* test if reload is needed for first register */
2472 if ((vtop
[-1].r
& VT_VALMASK
) >= VT_CONST
) {
2482 /* test if reload is needed for first register */
2483 if ((vtop
[0].r
& VT_VALMASK
) >= VT_CONST
) {
2489 /* expand long long on stack in two int registers */
2494 u
= vtop
->t
& VT_UNSIGNED
;
2497 vtop
[0].r
= vtop
[-1].r2
;
2498 vtop
[0].r2
= VT_CONST
;
2499 vtop
[-1].r2
= VT_CONST
;
2500 vtop
[0].t
= VT_INT
| u
;
2501 vtop
[-1].t
= VT_INT
| u
;
2504 /* build a long long from two ints */
2507 gv2(RC_INT
, RC_INT
);
2508 vtop
[-1].r2
= vtop
[0].r
;
2513 /* rotate n first stack elements to the bottom */
2520 for(i
=-n
+1;i
!=0;i
++)
2521 vtop
[i
] = vtop
[i
+1];
2525 /* pop stack value */
2528 /* for x86, we need to pop the FP stack */
2529 if ((vtop
->r
& VT_VALMASK
) == REG_ST0
) {
2530 o(0xd9dd); /* fstp %st(1) */
2535 /* convert stack entry to register and duplicate its value in another
2543 if ((t
& VT_BTYPE
) == VT_LLONG
) {
2550 /* stack: H L L1 H1 */
2558 /* duplicate value */
2569 load(r1
, &sv
); /* move r to r1 */
2571 /* duplicates value */
2576 /* generate CPU independent (unsigned) long long operations */
2577 void gen_opl(int op
)
2579 int t
, a
, b
, op1
, c
, i
;
2598 /* call generic long long function */
2606 vtop
->r2
= REG_LRET
;
2619 /* stack: L1 H1 L2 H2 */
2624 vtop
[-2] = vtop
[-3];
2627 /* stack: H1 H2 L1 L2 */
2633 /* stack: H1 H2 L1 L2 ML MH */
2636 /* stack: ML MH H1 H2 L1 L2 */
2640 /* stack: ML MH H1 L2 H2 L1 */
2645 /* stack: ML MH M1 M2 */
2648 } else if (op
== '+' || op
== '-') {
2649 /* XXX: add non carry method too (for MIPS ?) */
2655 /* stack: H1 H2 (L1 op L2) */
2658 gen_op(op1
+ 1); /* TOK_xxxC2 */
2661 /* stack: H1 H2 (L1 op L2) */
2664 /* stack: (L1 op L2) H1 H2 */
2666 /* stack: (L1 op L2) (H1 op H2) */
2674 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_FORWARD
)) == VT_CONST
) {
2679 /* stack: L H shift */
2681 /* constant: simpler */
2682 /* NOTE: all comments are for SHL. the other cases are
2683 done by swaping words */
2694 if (op
!= TOK_SAR
) {
2724 /* XXX: should provide a faster fallback on x86 ? */
2739 /* compare operations */
2745 /* stack: L1 H1 L2 H2 */
2747 vtop
[-1] = vtop
[-2];
2749 /* stack: L1 L2 H1 H2 */
2752 /* when values are equal, we need to compare low words. since
2753 the jump is inverted, we invert the test too. */
2756 else if (op1
== TOK_GT
)
2758 else if (op1
== TOK_ULT
)
2760 else if (op1
== TOK_UGT
)
2765 if (op1
!= TOK_NE
) {
2769 /* generate non equal test */
2770 /* XXX: NOT PORTABLE yet */
2774 b
= psym(0x850f, 0);
2780 vset(VT_INT
, VT_JMPI
, a
);
2785 /* handle constant optimizations and various machine independant opt */
2786 void gen_opc(int op
)
2793 /* currently, we cannot do computations with forward symbols */
2794 c1
= (v1
->r
& (VT_VALMASK
| VT_LVAL
| VT_FORWARD
)) == VT_CONST
;
2795 c2
= (v2
->r
& (VT_VALMASK
| VT_LVAL
| VT_FORWARD
)) == VT_CONST
;
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;
2804 case '*': v1
->c
.i
*= fc
; break;
2806 case '/': v1
->c
.i
/= fc
; break; /* XXX: zero case ? */
2807 case '%': v1
->c
.i
%= fc
; break; /* XXX: zero case ? */
2808 case TOK_UDIV
: v1
->c
.i
= (unsigned)v1
->c
.i
/ fc
; break; /* XXX: zero case ? */
2809 case TOK_UMOD
: v1
->c
.i
= (unsigned)v1
->c
.i
% fc
; break; /* XXX: zero case ? */
2810 case TOK_SHL
: v1
->c
.i
<<= fc
; break;
2811 case TOK_SHR
: v1
->c
.i
= (unsigned)v1
->c
.i
>> fc
; break;
2812 case TOK_SAR
: v1
->c
.i
>>= fc
; break;
2814 case TOK_ULT
: v1
->c
.i
= (unsigned)v1
->c
.i
< (unsigned)fc
; break;
2815 case TOK_UGE
: v1
->c
.i
= (unsigned)v1
->c
.i
>= (unsigned)fc
; break;
2816 case TOK_EQ
: v1
->c
.i
= v1
->c
.i
== fc
; break;
2817 case TOK_NE
: v1
->c
.i
= v1
->c
.i
!= fc
; break;
2818 case TOK_ULE
: v1
->c
.i
= (unsigned)v1
->c
.i
<= (unsigned)fc
; break;
2819 case TOK_UGT
: v1
->c
.i
= (unsigned)v1
->c
.i
> (unsigned)fc
; break;
2820 case TOK_LT
: v1
->c
.i
= v1
->c
.i
< fc
; break;
2821 case TOK_GE
: v1
->c
.i
= v1
->c
.i
>= fc
; break;
2822 case TOK_LE
: v1
->c
.i
= v1
->c
.i
<= fc
; break;
2823 case TOK_GT
: v1
->c
.i
= v1
->c
.i
> fc
; break;
2825 case TOK_LAND
: v1
->c
.i
= v1
->c
.i
&& fc
; break;
2826 case TOK_LOR
: v1
->c
.i
= v1
->c
.i
|| fc
; break;
2832 /* if commutative ops, put c2 as constant */
2833 if (c1
&& (op
== '+' || op
== '&' || op
== '^' ||
2834 op
== '|' || op
== '*')) {
2839 if (c2
&& (((op
== '*' || op
== '/' || op
== TOK_UDIV
||
2842 ((op
== '+' || op
== '-' || op
== '|' || op
== '^' ||
2843 op
== TOK_SHL
|| op
== TOK_SHR
|| op
== TOK_SAR
) &&
2849 } else if (c2
&& (op
== '*' || op
== TOK_PDIV
|| op
== TOK_UDIV
)) {
2850 /* try to use shifts instead of muls or divs */
2851 if (fc
> 0 && (fc
& (fc
- 1)) == 0) {
2860 else if (op
== TOK_PDIV
)
2868 /* call low level op generator */
2869 /* XXX: remove explicit registers */
2875 int pointed_size(int t
)
2877 return type_size(pointed_type(t
), &t
);
2881 void check_pointer_types(SValue
*p1
, SValue
*p2
)
2883 char buf1
[256], buf2
[256];
2887 if (!is_compatible_types(t1
, t2
)) {
2888 type_to_str(buf1
, sizeof(buf1
), t1
, NULL
);
2889 type_to_str(buf2
, sizeof(buf2
), t2
, NULL
);
2890 error("incompatible pointers '%s' and '%s'", buf1
, buf2
);
2895 /* generic gen_op: handles types problems */
2898 int u
, t1
, t2
, bt1
, bt2
, t
;
2902 bt1
= t1
& VT_BTYPE
;
2903 bt2
= t2
& VT_BTYPE
;
2905 if (bt1
== VT_PTR
|| bt2
== VT_PTR
) {
2906 /* at least one operand is a pointer */
2907 /* relationnal op: must be both pointers */
2908 if (op
>= TOK_ULT
&& op
<= TOK_GT
) {
2909 // check_pointer_types(vtop, vtop - 1);
2910 /* pointers are handled are unsigned */
2911 t
= VT_INT
| VT_UNSIGNED
;
2914 /* if both pointers, then it must be the '-' op */
2915 if ((t1
& VT_BTYPE
) == VT_PTR
&&
2916 (t2
& VT_BTYPE
) == VT_PTR
) {
2918 error("cannot use pointers here");
2919 // check_pointer_types(vtop - 1, vtop);
2920 /* XXX: check that types are compatible */
2921 u
= pointed_size(t1
);
2923 /* set to integer type */
2928 /* exactly one pointer : must be '+' or '-'. */
2929 if (op
!= '-' && op
!= '+')
2930 error("cannot use pointers here");
2931 /* Put pointer as first operand */
2932 if ((t2
& VT_BTYPE
) == VT_PTR
) {
2936 /* XXX: cast to int ? (long long case) */
2937 vpushi(pointed_size(vtop
[-1].t
));
2939 if (do_bounds_check
) {
2940 /* if bounded pointers, we generate a special code to
2947 gen_bounded_ptr_add1();
2948 gen_bounded_ptr_add2(0);
2952 /* put again type if gen_opc() swaped operands */
2955 } else if (is_float(bt1
) || is_float(bt2
)) {
2956 /* compute bigger type and do implicit casts */
2957 if (bt1
== VT_LDOUBLE
|| bt2
== VT_LDOUBLE
) {
2959 } else if (bt1
== VT_DOUBLE
|| bt2
== VT_DOUBLE
) {
2964 /* floats can only be used for a few operations */
2965 if (op
!= '+' && op
!= '-' && op
!= '*' && op
!= '/' &&
2966 (op
< TOK_ULT
|| op
> TOK_GT
))
2967 error("invalid operands for binary operation");
2969 } else if (bt1
== VT_LLONG
|| bt2
== VT_LLONG
) {
2970 /* cast to biggest op */
2972 /* convert to unsigned if it does not fit in a long long */
2973 if ((t1
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_LLONG
| VT_UNSIGNED
) ||
2974 (t2
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_LLONG
| VT_UNSIGNED
))
2978 /* integer operations */
2980 /* convert to unsigned if it does not fit in an integer */
2981 if ((t1
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
) ||
2982 (t2
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
))
2985 /* XXX: currently, some unsigned operations are explicit, so
2986 we modify them here */
2987 if (t
& VT_UNSIGNED
) {
2994 else if (op
== TOK_LT
)
2996 else if (op
== TOK_GT
)
2998 else if (op
== TOK_LE
)
3000 else if (op
== TOK_GE
)
3006 /* special case for shifts and long long: we keep the shift as
3008 if (op
== TOK_SHR
|| op
== TOK_SAR
|| op
== TOK_SHL
)
3014 else if ((t
& VT_BTYPE
) == VT_LLONG
)
3018 if (op
>= TOK_ULT
&& op
<= TOK_GT
) {
3019 /* relationnal op: the result is an int */
3027 /* generic itof for unsigned long long case */
3028 void gen_cvt_itof1(int t
)
3032 if ((vtop
->t
& (VT_BTYPE
| VT_UNSIGNED
)) ==
3033 (VT_LLONG
| VT_UNSIGNED
)) {
3038 vpushi((int)&__ulltof
);
3039 else if (t
== VT_DOUBLE
)
3040 vpushi((int)&__ulltod
);
3042 vpushi((int)&__ulltold
);
3051 /* generic ftoi for unsigned long long case */
3052 void gen_cvt_ftoi1(int t
)
3057 if (t
== (VT_LLONG
| VT_UNSIGNED
)) {
3058 /* not handled natively */
3060 st
= vtop
->t
& VT_BTYPE
;
3063 vpushi((int)&__ftoull
);
3064 else if (st
== VT_DOUBLE
)
3065 vpushi((int)&__dtoull
);
3067 vpushi((int)&__ldtoull
);
3071 vtop
->r2
= REG_LRET
;
3077 /* force char or short cast */
3078 void force_charshort_cast(int t
)
3082 /* XXX: add optimization if lvalue : just change type and offset */
3087 if (t
& VT_UNSIGNED
) {
3088 vpushi((1 << bits
) - 1);
3099 /* cast 'vtop' to 't' type */
3100 void gen_cast(int t
)
3102 int sbt
, dbt
, sf
, df
, c
, st1
, dt1
;
3104 /* special delayed cast for char/short */
3105 /* XXX: in some cases (multiple cascaded casts), it may still
3107 if (vtop
->r
& VT_MUSTCAST
) {
3108 vtop
->r
&= ~VT_MUSTCAST
;
3109 force_charshort_cast(vtop
->t
);
3113 sbt
= vtop
->t
& VT_BTYPE
;
3118 c
= (vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_FORWARD
)) == VT_CONST
;
3120 /* convert from fp to fp */
3122 /* constant case: we can do it now */
3123 /* XXX: in ISOC, cannot do it if error in convert */
3124 if (dbt
== VT_FLOAT
&& sbt
== VT_DOUBLE
)
3125 vtop
->c
.f
= (float)vtop
->c
.d
;
3126 else if (dbt
== VT_FLOAT
&& sbt
== VT_LDOUBLE
)
3127 vtop
->c
.f
= (float)vtop
->c
.ld
;
3128 else if (dbt
== VT_DOUBLE
&& sbt
== VT_FLOAT
)
3129 vtop
->c
.d
= (double)vtop
->c
.f
;
3130 else if (dbt
== VT_DOUBLE
&& sbt
== VT_LDOUBLE
)
3131 vtop
->c
.d
= (double)vtop
->c
.ld
;
3132 else if (dbt
== VT_LDOUBLE
&& sbt
== VT_FLOAT
)
3133 vtop
->c
.ld
= (long double)vtop
->c
.f
;
3134 else if (dbt
== VT_LDOUBLE
&& sbt
== VT_DOUBLE
)
3135 vtop
->c
.ld
= (long double)vtop
->c
.d
;
3137 /* non constant case: generate code */
3141 /* convert int to fp */
3142 st1
= vtop
->t
& (VT_BTYPE
| VT_UNSIGNED
);
3145 case VT_LLONG
| VT_UNSIGNED
:
3147 /* XXX: add const cases for long long */
3149 case VT_INT
| VT_UNSIGNED
:
3151 case VT_FLOAT
: vtop
->c
.f
= (float)vtop
->c
.ui
; break;
3152 case VT_DOUBLE
: vtop
->c
.d
= (double)vtop
->c
.ui
; break;
3153 case VT_LDOUBLE
: vtop
->c
.ld
= (long double)vtop
->c
.ui
; break;
3158 case VT_FLOAT
: vtop
->c
.f
= (float)vtop
->c
.i
; break;
3159 case VT_DOUBLE
: vtop
->c
.d
= (double)vtop
->c
.i
; break;
3160 case VT_LDOUBLE
: vtop
->c
.ld
= (long double)vtop
->c
.i
; break;
3169 /* convert fp to int */
3170 dt1
= t
& (VT_BTYPE
| VT_UNSIGNED
);
3171 /* we handle char/short/etc... with generic code */
3172 if (dt1
!= (VT_INT
| VT_UNSIGNED
) &&
3173 dt1
!= (VT_LLONG
| VT_UNSIGNED
) &&
3178 case VT_LLONG
| VT_UNSIGNED
:
3180 /* XXX: add const cases for long long */
3182 case VT_INT
| VT_UNSIGNED
:
3184 case VT_FLOAT
: vtop
->c
.ui
= (unsigned int)vtop
->c
.d
; break;
3185 case VT_DOUBLE
: vtop
->c
.ui
= (unsigned int)vtop
->c
.d
; break;
3186 case VT_LDOUBLE
: vtop
->c
.ui
= (unsigned int)vtop
->c
.d
; break;
3192 case VT_FLOAT
: vtop
->c
.i
= (int)vtop
->c
.d
; break;
3193 case VT_DOUBLE
: vtop
->c
.i
= (int)vtop
->c
.d
; break;
3194 case VT_LDOUBLE
: vtop
->c
.i
= (int)vtop
->c
.d
; break;
3202 if (dt1
== VT_INT
&& (t
& (VT_BTYPE
| VT_UNSIGNED
)) != dt1
) {
3203 /* additionnal cast for char/short/bool... */
3207 } else if (dbt
== VT_LLONG
) {
3208 /* scalar to long long */
3210 if ((vtop
->t
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
))
3211 vtop
->c
.ll
= vtop
->c
.ui
;
3213 vtop
->c
.ll
= vtop
->c
.i
;
3215 /* machine independant conversion */
3217 /* generate high word */
3218 if ((vtop
->t
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
)) {
3226 /* patch second register */
3227 vtop
[-1].r2
= vtop
->r
;
3230 } else if (dbt
== VT_BOOL
) {
3231 /* scalar to bool */
3234 } else if (dbt
== VT_BYTE
|| dbt
== VT_SHORT
) {
3235 force_charshort_cast(t
);
3236 } else if (dbt
== VT_INT
) {
3238 if (sbt
== VT_LLONG
) {
3239 /* from long long: just take low order word */
3242 } else if (vtop
->r
& VT_LVAL
) {
3243 /* if lvalue and single word type, nothing to do (XXX:
3244 maybe incorrect for sizeof op) */
3253 /* return type size. Put alignment at 'a' */
3254 int type_size(int t
, int *a
)
3260 if (bt
== VT_STRUCT
) {
3262 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
) | SYM_STRUCT
);
3263 *a
= 4; /* XXX: cannot store it yet. Doing that is safe */
3265 } else if (bt
== VT_PTR
) {
3267 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
));
3268 return type_size(s
->t
, a
) * s
->c
;
3273 } else if (bt
== VT_LDOUBLE
) {
3275 return LDOUBLE_SIZE
;
3276 } else if (bt
== VT_DOUBLE
|| bt
== VT_LLONG
) {
3279 } else if (bt
== VT_INT
|| bt
== VT_ENUM
|| bt
== VT_FLOAT
) {
3282 } else if (bt
== VT_SHORT
) {
3286 /* char, void, function, _Bool */
3292 /* return the pointed type of t */
3293 int pointed_type(int t
)
3296 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
));
3297 return s
->t
| (t
& ~VT_TYPE
);
3300 int mk_pointer(int t
)
3304 sym_push(p
, t
, 0, -1);
3305 return VT_PTR
| (p
<< VT_STRUCT_SHIFT
) | (t
& ~VT_TYPE
);
3308 int is_compatible_types(int t1
, int t2
)
3315 bt1
= t1
& VT_BTYPE
;
3316 bt2
= t2
& VT_BTYPE
;
3317 if (bt1
== VT_PTR
) {
3318 t1
= pointed_type(t1
);
3319 /* if function, then convert implicitely to function pointer */
3320 if (bt2
!= VT_FUNC
) {
3323 t2
= pointed_type(t2
);
3325 /* void matches everything */
3328 if (t1
== VT_VOID
|| t2
== VT_VOID
)
3330 return is_compatible_types(t1
, t2
);
3331 } else if (bt1
== VT_STRUCT
) {
3333 } else if (bt1
== VT_FUNC
) {
3336 s1
= sym_find(((unsigned)t1
>> VT_STRUCT_SHIFT
));
3337 s2
= sym_find(((unsigned)t2
>> VT_STRUCT_SHIFT
));
3338 if (!is_compatible_types(s1
->t
, s2
->t
))
3340 /* XXX: not complete */
3341 if (s1
->c
== FUNC_OLD
|| s2
->c
== FUNC_OLD
)
3345 while (s1
!= NULL
) {
3348 if (!is_compatible_types(s1
->t
, s2
->t
))
3357 /* XXX: not complete */
3362 /* print a type. If 'varstr' is not NULL, then the variable is also
3363 printed in the type */
3365 /* XXX: add array and function pointers */
3366 void type_to_str(char *buf
, int buf_size
,
3367 int t
, const char *varstr
)
3377 if (t
& VT_UNSIGNED
)
3378 pstrcat(buf
, buf_size
, "unsigned ");
3408 tstr
= "long double";
3410 pstrcat(buf
, buf_size
, tstr
);
3414 if (bt
== VT_STRUCT
)
3418 pstrcat(buf
, buf_size
, tstr
);
3419 v
= (unsigned)t
>> VT_STRUCT_SHIFT
;
3420 if (v
>= SYM_FIRST_ANOM
)
3421 pstrcat(buf
, buf_size
, "<anonymous>");
3423 pstrcat(buf
, buf_size
, get_tok_str(v
, NULL
));
3426 s
= sym_find((unsigned)t
>> VT_STRUCT_SHIFT
);
3427 type_to_str(buf
, buf_size
, s
->t
, varstr
);
3428 pstrcat(buf
, buf_size
, "(");
3430 while (sa
!= NULL
) {
3431 type_to_str(buf1
, sizeof(buf1
), sa
->t
, NULL
);
3432 pstrcat(buf
, buf_size
, buf1
);
3435 pstrcat(buf
, buf_size
, ", ");
3437 pstrcat(buf
, buf_size
, ")");
3440 s
= sym_find((unsigned)t
>> VT_STRUCT_SHIFT
);
3441 pstrcpy(buf1
, sizeof(buf1
), "*");
3443 pstrcat(buf1
, sizeof(buf1
), varstr
);
3444 type_to_str(buf
, buf_size
, s
->t
, buf1
);
3448 pstrcat(buf
, buf_size
, " ");
3449 pstrcat(buf
, buf_size
, varstr
);
3454 /* verify type compatibility to store vtop in 'dt' type, and generate
3456 void gen_assign_cast(int dt
)
3459 char buf1
[256], buf2
[256];
3461 st
= vtop
->t
; /* source type */
3462 if ((dt
& VT_BTYPE
) == VT_PTR
) {
3463 /* special cases for pointers */
3464 /* a function is implicitely a function pointer */
3465 if ((st
& VT_BTYPE
) == VT_FUNC
) {
3466 if (!is_compatible_types(pointed_type(dt
), st
))
3471 /* '0' can also be a pointer */
3472 if ((st
& VT_BTYPE
) == VT_INT
&&
3473 ((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_FORWARD
)) == VT_CONST
) &&
3477 if (!is_compatible_types(dt
, st
)) {
3479 type_to_str(buf1
, sizeof(buf1
), st
, NULL
);
3480 type_to_str(buf2
, sizeof(buf2
), dt
, NULL
);
3481 error("cannot cast '%s' to '%s'", buf1
, buf2
);
3487 /* store vtop in lvalue pushed on stack */
3490 int sbt
, dbt
, ft
, r
, t
, size
, align
, bit_size
, bit_pos
, rc
, delayed_cast
;
3494 sbt
= vtop
->t
& VT_BTYPE
;
3495 dbt
= ft
& VT_BTYPE
;
3496 if (((sbt
== VT_INT
|| sbt
== VT_SHORT
) && dbt
== VT_BYTE
) ||
3497 (sbt
== VT_INT
&& dbt
== VT_SHORT
)) {
3498 /* optimize char/short casts */
3499 delayed_cast
= VT_MUSTCAST
;
3500 vtop
->t
= ft
& VT_TYPE
;
3503 gen_assign_cast(ft
& VT_TYPE
);
3506 if (sbt
== VT_STRUCT
) {
3507 /* if structure, only generate pointer */
3508 /* structure assignment : generate memcpy */
3509 /* XXX: optimize if small size */
3514 size
= type_size(vtop
->t
, &align
);
3528 vpushi((int)&memcpy
);
3530 /* leave source on stack */
3531 } else if (ft
& VT_BITFIELD
) {
3532 /* bitfield store handling */
3533 bit_pos
= (ft
>> VT_STRUCT_SHIFT
) & 0x3f;
3534 bit_size
= (ft
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f;
3535 /* remove bit field info to avoid loops */
3536 vtop
[-1].t
= ft
& ~(VT_BITFIELD
| (-1 << VT_STRUCT_SHIFT
));
3538 /* duplicate destination */
3540 vtop
[-1] = vtop
[-2];
3542 /* mask and shift source */
3543 vpushi((1 << bit_size
) - 1);
3547 /* load destination, mask and or with source */
3549 vpushi(~(((1 << bit_size
) - 1) << bit_pos
));
3555 /* bound check case */
3556 if (vtop
[-1].r
& VT_MUSTBOUND
) {
3564 r
= gv(rc
); /* generate value */
3565 /* if lvalue was saved on stack, must read it */
3566 if ((vtop
[-1].r
& VT_VALMASK
) == VT_LLOCAL
) {
3568 t
= get_reg(RC_INT
);
3570 sv
.r
= VT_LOCAL
| VT_LVAL
;
3571 sv
.c
.ul
= vtop
[-1].c
.ul
;
3573 vtop
[-1].r
= t
| VT_LVAL
;
3576 /* two word case handling : store second register at word + 4 */
3577 if ((ft
& VT_BTYPE
) == VT_LLONG
) {
3579 /* convert to int to increment easily */
3586 /* XXX: it works because r2 is spilled last ! */
3587 store(vtop
->r2
, vtop
- 1);
3590 vtop
--; /* NOT vpop() because on x86 it would flush the fp stack */
3591 vtop
->r
|= delayed_cast
;
3595 /* post defines POST/PRE add. c is the token ++ or -- */
3596 void inc(int post
, int c
)
3599 vdup(); /* save lvalue */
3601 gv_dup(); /* duplicate value */
3606 vpushi(c
- TOK_MID
);
3608 vstore(); /* store value */
3610 vpop(); /* if post op, return saved value */
3613 /* Parse GNUC __attribute__ extension. Currently, the following
3614 extensions are recognized:
3615 - aligned(n) : set data/function alignment.
3616 - section(x) : generate data/code in this section.
3617 - unused : currently ignored, but may be used someday.
3619 void parse_attribute(AttributeDef
*ad
)
3626 while (tok
!= ')') {
3627 if (tok
< TOK_IDENT
)
3628 expect("attribute name");
3633 case TOK___SECTION__
:
3636 expect("section name");
3637 ad
->section
= find_section(tokc
.ts
->str
);
3642 case TOK___ALIGNED__
:
3645 if (n
<= 0 || (n
& (n
- 1)) != 0)
3646 error("alignment must be a positive power of two");
3651 case TOK___UNUSED__
:
3652 /* currently, no need to handle it because tcc does not
3653 track unused objects */
3656 warning("'%s' attribute ignored", get_tok_str(t
, NULL
));
3657 /* skip parameters */
3658 /* XXX: skip parenthesis too */
3661 while (tok
!= ')' && tok
!= -1)
3675 /* enum/struct/union declaration */
3676 int struct_decl(int u
)
3678 int a
, t
, b
, v
, size
, align
, maxalign
, c
, offset
;
3679 int bit_size
, bit_pos
, bsize
, bt
, lbit_pos
;
3683 a
= tok
; /* save decl type */
3688 /* struct already defined ? return it */
3689 /* XXX: check consistency */
3690 s
= sym_find(v
| SYM_STRUCT
);
3693 error("invalid type");
3699 s
= sym_push(v
| SYM_STRUCT
, a
, 0, 0);
3700 /* put struct/union/enum name in type */
3702 u
= u
| (v
<< VT_STRUCT_SHIFT
);
3707 error("struct/union/enum already defined");
3708 /* cannot be empty */
3715 if (a
== TOK_ENUM
) {
3722 /* enum symbols have static storage */
3723 sym_push(v
, VT_STATIC
| VT_INT
, VT_CONST
, c
);
3728 parse_btype(&b
, &ad
);
3733 t
= type_decl(&v
, b
, TYPE_DIRECT
);
3734 if ((t
& VT_BTYPE
) == VT_FUNC
||
3735 (t
& (VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
)))
3736 error("invalid type for '%s'",
3737 get_tok_str(v
, NULL
));
3743 bit_size
= expr_const();
3744 /* XXX: handle v = 0 case for messages */
3746 error("negative width in bit-field '%s'",
3747 get_tok_str(v
, NULL
));
3748 if (v
&& bit_size
== 0)
3749 error("zero width for bit-field '%s'",
3750 get_tok_str(v
, NULL
));
3752 size
= type_size(t
, &align
);
3754 if (bit_size
>= 0) {
3759 error("bitfields must have scalar type");
3761 if (bit_size
> bsize
) {
3762 error("width of '%s' exceeds its type",
3763 get_tok_str(v
, NULL
));
3764 } else if (bit_size
== bsize
) {
3765 /* no need for bit fields */
3767 } else if (bit_size
== 0) {
3768 /* XXX: what to do if only padding in a
3770 /* zero size: means to pad */
3774 /* we do not have enough room ? */
3775 if ((bit_pos
+ bit_size
) > bsize
)
3778 /* XXX: handle LSB first */
3780 (bit_pos
<< VT_STRUCT_SHIFT
) |
3781 (bit_size
<< (VT_STRUCT_SHIFT
+ 6));
3782 bit_pos
+= bit_size
;
3788 /* add new memory data only if starting
3790 if (lbit_pos
== 0) {
3791 if (a
== TOK_STRUCT
) {
3792 c
= (c
+ align
- 1) & -align
;
3800 if (align
> maxalign
)
3804 printf("add field %s offset=%d",
3805 get_tok_str(v
, NULL
), offset
);
3806 if (t
& VT_BITFIELD
) {
3807 printf(" pos=%d size=%d",
3808 (t
>> VT_STRUCT_SHIFT
) & 0x3f,
3809 (t
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f);
3813 ss
= sym_push(v
| SYM_FIELD
, t
, 0, offset
);
3817 if (tok
== ';' || tok
== -1)
3827 /* size for struct/union, dummy for enum */
3828 s
->c
= (c
+ maxalign
- 1) & -maxalign
;
3833 /* return 0 if no type declaration. otherwise, return the basic type
3836 int parse_btype(int *type_ptr
, AttributeDef
*ad
)
3838 int t
, u
, type_found
;
3841 memset(ad
, 0, sizeof(AttributeDef
));
3852 if ((t
& VT_BTYPE
) != 0)
3853 error("too many basic types");
3867 if ((t
& VT_BTYPE
) == VT_DOUBLE
) {
3868 t
= (t
& ~VT_BTYPE
) | VT_LDOUBLE
;
3869 } else if ((t
& VT_BTYPE
) == VT_LONG
) {
3870 t
= (t
& ~VT_BTYPE
) | VT_LLONG
;
3884 if ((t
& VT_BTYPE
) == VT_LONG
) {
3885 t
= (t
& ~VT_BTYPE
) | VT_LDOUBLE
;
3892 u
= struct_decl(VT_ENUM
);
3896 u
= struct_decl(VT_STRUCT
);
3899 /* type modifiers */
3927 /* GNUC attribute */
3928 case TOK___ATTRIBUTE__
:
3929 parse_attribute(ad
);
3933 if (!s
|| !(s
->t
& VT_TYPEDEF
))
3935 t
|= (s
->t
& ~VT_TYPEDEF
);
3942 /* long is never used as type */
3943 if ((t
& VT_BTYPE
) == VT_LONG
)
3944 t
= (t
& ~VT_BTYPE
) | VT_INT
;
3949 int post_type(int t
)
3951 int p
, n
, pt
, l
, t1
;
3952 Sym
**plast
, *s
, *first
;
3956 /* function declaration */
3961 while (tok
!= ')') {
3962 /* read param name and compute offset */
3963 if (l
!= FUNC_OLD
) {
3964 if (!parse_btype(&pt
, &ad
)) {
3966 error("invalid type");
3973 if ((pt
& VT_BTYPE
) == VT_VOID
&& tok
== ')')
3975 pt
= type_decl(&n
, pt
, TYPE_DIRECT
| TYPE_ABSTRACT
);
3976 if ((pt
& VT_BTYPE
) == VT_VOID
)
3977 error("parameter declared as void");
3984 /* array must be transformed to pointer according to ANSI C */
3986 s
= sym_push(n
| SYM_FIELD
, pt
, 0, 0);
3991 if (l
== FUNC_NEW
&& tok
== TOK_DOTS
) {
3998 /* if no parameters, then old type prototype */
4002 t1
= t
& (VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
);
4003 t
= post_type(t
& ~(VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
));
4004 /* we push a anonymous symbol which will contain the function prototype */
4006 s
= sym_push(p
, t
, 0, l
);
4008 t
= t1
| VT_FUNC
| (p
<< VT_STRUCT_SHIFT
);
4009 } else if (tok
== '[') {
4010 /* array definition */
4016 error("invalid array size");
4019 /* parse next post type */
4020 t1
= t
& (VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
);
4021 t
= post_type(t
& ~(VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
));
4023 /* we push a anonymous symbol which will contain the array
4026 sym_push(p
, t
, 0, n
);
4027 t
= t1
| VT_ARRAY
| VT_PTR
| (p
<< VT_STRUCT_SHIFT
);
4032 /* Read a type declaration (except basic type), and return the
4033 type. If v is true, then also put variable name in 'vtop->c' */
4034 int type_decl(int *v
, int t
, int td
)
4039 while (tok
== '*') {
4041 while (tok
== TOK_CONST
|| tok
== TOK_VOLATILE
|| tok
== TOK_RESTRICT
)
4046 /* recursive type */
4047 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
4050 u
= type_decl(v
, 0, td
);
4054 /* type identifier */
4055 if (tok
>= TOK_IDENT
&& (td
& TYPE_DIRECT
)) {
4059 if (!(td
& TYPE_ABSTRACT
))
4060 expect("identifier");
4064 /* append t at the end of u */
4070 s
= sym_find((unsigned)p
>> VT_STRUCT_SHIFT
);
4080 /* define a new external reference to a function 'v' of type 'u' */
4081 Sym
*external_sym(int v
, int u
, int r
)
4086 /* push forward reference */
4087 s
= sym_push1(&global_stack
,
4089 s
->r
= r
| VT_CONST
| VT_FORWARD
;
4096 if ((vtop
->t
& VT_BTYPE
) != VT_PTR
)
4098 if (vtop
->r
& VT_LVAL
)
4100 vtop
->t
= pointed_type(vtop
->t
);
4101 /* an array is never an lvalue */
4102 if (!(vtop
->t
& VT_ARRAY
)) {
4104 /* if bound checking, the referenced pointer must be checked */
4105 if (do_bounds_check
)
4106 vtop
->r
|= VT_MUSTBOUND
;
4110 /* pass a parameter to a function and do type checking and casting */
4111 void gfunc_param_typed(GFuncContext
*gf
, Sym
*func
, Sym
*arg
)
4114 func_type
= func
->c
;
4115 if (func_type
== FUNC_OLD
||
4116 (func_type
== FUNC_ELLIPSIS
&& arg
== NULL
)) {
4117 /* default casting : only need to convert float to double */
4118 if ((vtop
->t
& VT_BTYPE
) == VT_FLOAT
)
4119 gen_cast(VT_DOUBLE
);
4120 } else if (arg
== NULL
) {
4121 error("too many arguments to function");
4123 gen_assign_cast(arg
->t
);
4130 int n
, t
, ft
, fc
, p
, align
, size
, r
, data_offset
;
4135 if (tok
== TOK_CINT
|| tok
== TOK_CCHAR
|| tok
== TOK_LCHAR
) {
4138 } else if (tok
== TOK_CUINT
) {
4139 vsetc(VT_INT
| VT_UNSIGNED
, VT_CONST
, &tokc
);
4141 } else if (tok
== TOK_CLLONG
) {
4142 vsetc(VT_LLONG
, VT_CONST
, &tokc
);
4144 } else if (tok
== TOK_CULLONG
) {
4145 vsetc(VT_LLONG
| VT_UNSIGNED
, VT_CONST
, &tokc
);
4147 } else if (tok
== TOK_CFLOAT
) {
4148 vsetc(VT_FLOAT
, VT_CONST
, &tokc
);
4150 } else if (tok
== TOK_CDOUBLE
) {
4151 vsetc(VT_DOUBLE
, VT_CONST
, &tokc
);
4153 } else if (tok
== TOK_CLDOUBLE
) {
4154 vsetc(VT_LDOUBLE
, VT_CONST
, &tokc
);
4156 } else if (tok
== TOK___FUNC__
) {
4157 /* special function name identifier */
4158 /* generate (char *) type */
4159 data_offset
= (int)data_section
->data_ptr
;
4160 vset(mk_pointer(VT_BYTE
), VT_CONST
, data_offset
);
4161 strcpy((void *)data_offset
, funcname
);
4162 data_offset
+= strlen(funcname
) + 1;
4163 data_section
->data_ptr
= (unsigned char *)data_offset
;
4165 } else if (tok
== TOK_LSTR
) {
4168 } else if (tok
== TOK_STR
) {
4169 /* string parsing */
4172 type_size(t
, &align
);
4173 data_offset
= (int)data_section
->data_ptr
;
4174 data_offset
= (data_offset
+ align
- 1) & -align
;
4176 /* we must declare it as an array first to use initializer parser */
4177 t
= VT_ARRAY
| mk_pointer(t
);
4178 decl_initializer(t
, VT_CONST
, data_offset
, 1, 0);
4179 data_offset
+= type_size(t
, &align
);
4180 /* put it as pointer */
4181 vset(t
& ~VT_ARRAY
, VT_CONST
, fc
);
4182 data_section
->data_ptr
= (unsigned char *)data_offset
;
4188 if (parse_btype(&t
, &ad
)) {
4189 ft
= type_decl(&n
, t
, TYPE_ABSTRACT
);
4191 /* check ISOC99 compound literal */
4193 /* data is allocated locally by default */
4198 /* all except arrays are lvalues */
4199 if (!(ft
& VT_ARRAY
))
4201 memset(&ad
, 0, sizeof(AttributeDef
));
4202 fc
= decl_initializer_alloc(ft
, &ad
, r
, 1);
4212 } else if (t
== '*') {
4215 } else if (t
== '&') {
4217 /* functions names must be treated as function pointers,
4218 except for unary '&' and sizeof. Since we consider that
4219 functions are not lvalues, we only have to handle it
4220 there and in function calls. */
4221 if ((vtop
->t
& VT_BTYPE
) != VT_FUNC
)
4223 vtop
->t
= mk_pointer(vtop
->t
);
4228 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
)
4229 vtop
->c
.i
= !vtop
->c
.i
;
4230 else if ((vtop
->r
& VT_VALMASK
) == VT_CMP
)
4231 vtop
->c
.i
= vtop
->c
.i
^ 1;
4233 vset(VT_INT
, VT_JMP
, gtst(1, 0));
4243 if (t
== TOK_SIZEOF
) {
4246 if (parse_btype(&t
, &ad
)) {
4247 t
= type_decl(&n
, t
, TYPE_ABSTRACT
);
4249 /* XXX: some code could be generated: add eval
4261 vpushi(type_size(t
, &t
));
4263 if (t
== TOK_INC
|| t
== TOK_DEC
) {
4266 } else if (t
== '-') {
4275 error("'%s' undeclared", get_tok_str(t
, NULL
));
4276 /* for simple function calls, we tolerate undeclared
4277 external reference */
4279 sym_push1(&global_stack
, p
, 0, FUNC_OLD
);
4280 /* int() function */
4281 s
= external_sym(t
, VT_FUNC
| (p
<< VT_STRUCT_SHIFT
), 0);
4283 vset(s
->t
, s
->r
, s
->c
);
4284 /* if forward reference, we must point to s */
4285 if (vtop
->r
& VT_FORWARD
)
4290 /* post operations */
4292 if (tok
== TOK_INC
|| tok
== TOK_DEC
) {
4295 } else if (tok
== '.' || tok
== TOK_ARROW
) {
4297 if (tok
== TOK_ARROW
)
4302 /* expect pointer on structure */
4303 if ((vtop
->t
& VT_BTYPE
) != VT_STRUCT
)
4304 expect("struct or union");
4305 s
= sym_find(((unsigned)vtop
->t
>> VT_STRUCT_SHIFT
) | SYM_STRUCT
);
4308 while ((s
= s
->next
) != NULL
) {
4313 error("field not found");
4314 /* add field offset to pointer */
4315 vtop
->t
= char_pointer_type
; /* change type to 'char *' */
4318 /* change type to field type, and set to lvalue */
4320 /* an array is never an lvalue */
4321 if (!(vtop
->t
& VT_ARRAY
))
4324 } else if (tok
== '[') {
4330 } else if (tok
== '(') {
4335 if ((vtop
->t
& VT_BTYPE
) != VT_FUNC
) {
4336 /* pointer test (no array accepted) */
4337 if ((vtop
->t
& (VT_BTYPE
| VT_ARRAY
)) == VT_PTR
) {
4338 vtop
->t
= pointed_type(vtop
->t
);
4339 if ((vtop
->t
& VT_BTYPE
) != VT_FUNC
)
4343 expect("function pointer");
4346 vtop
->r
&= ~VT_LVAL
; /* no lvalue */
4348 /* get return type */
4349 s
= sym_find((unsigned)vtop
->t
>> VT_STRUCT_SHIFT
);
4350 save_regs(); /* save used temporary registers */
4353 sa
= s
->next
; /* first parameter */
4354 #ifdef INVERT_FUNC_PARAMS
4356 int *str
, len
, parlevel
, *saved_macro_ptr
;
4359 /* read each argument and store it on a stack */
4360 /* XXX: merge it with macro args ? */
4362 while (tok
!= ')') {
4366 while ((parlevel
> 0 || (tok
!= ')' && tok
!= ',')) &&
4370 else if (tok
== ')')
4372 tok_add2(&str
, &len
, tok
, &tokc
);
4375 tok_add(&str
, &len
, -1); /* end of file added */
4376 tok_add(&str
, &len
, 0);
4377 s1
= sym_push2(&args
, 0, 0, (int)str
);
4378 s1
->next
= sa
; /* add reference to argument */
4388 /* now generate code in reverse order by reading the stack */
4389 saved_macro_ptr
= macro_ptr
;
4391 macro_ptr
= (int *)args
->c
;
4395 expect("',' or ')'");
4396 gfunc_param_typed(&gf
, s
, args
->next
);
4398 free((int *)args
->c
);
4402 macro_ptr
= saved_macro_ptr
;
4407 /* compute first implicit argument if a structure is returned */
4408 if ((s
->t
& VT_BTYPE
) == VT_STRUCT
) {
4409 /* get some space for the returned structure */
4410 size
= type_size(s
->t
, &align
);
4411 loc
= (loc
- size
) & -align
;
4413 ret
.r
= VT_LOCAL
| VT_LVAL
;
4414 /* pass it as 'int' to avoid structure arg passing
4416 vset(VT_INT
, VT_LOCAL
, loc
);
4422 /* return in register */
4423 if (is_float(ret
.t
)) {
4426 if ((ret
.t
& VT_BTYPE
) == VT_LLONG
)
4432 #ifndef INVERT_FUNC_PARAMS
4433 while (tok
!= ')') {
4435 gfunc_param_typed(&gf
, s
, sa
);
4443 error("too few arguments to function");
4447 vsetc(ret
.t
, ret
.r
, &ret
.c
);
4461 (tok
>= TOK_A_MOD
&& tok
<= TOK_A_DIV
) ||
4462 tok
== TOK_A_XOR
|| tok
== TOK_A_OR
||
4463 tok
== TOK_A_SHL
|| tok
== TOK_A_SAR
) {
4486 while ((l
== 0 && (tok
== '*' || tok
== '/' || tok
== '%')) ||
4487 (l
== 1 && (tok
== '+' || tok
== '-')) ||
4488 (l
== 2 && (tok
== TOK_SHL
|| tok
== TOK_SAR
)) ||
4489 (l
== 3 && ((tok
>= TOK_ULE
&& tok
<= TOK_GT
) ||
4490 tok
== TOK_ULT
|| tok
== TOK_UGE
)) ||
4491 (l
== 4 && (tok
== TOK_EQ
|| tok
== TOK_NE
)) ||
4492 (l
== 5 && tok
== '&') ||
4493 (l
== 6 && tok
== '^') ||
4494 (l
== 7 && tok
== '|') ||
4495 (l
== 8 && tok
== TOK_LAND
) ||
4496 (l
== 9 && tok
== TOK_LOR
)) {
4505 /* only used if non constant */
4513 if (tok
!= TOK_LAND
) {
4516 vset(VT_INT
, VT_JMPI
, t
);
4533 if (tok
!= TOK_LOR
) {
4536 vset(VT_INT
, VT_JMP
, t
);
4546 /* XXX: better constant handling */
4549 int t
, u
, c
, r1
, r2
, rc
;
4571 /* XXX: long long handling ? */
4573 if (is_float(vtop
->t
))
4601 /* parse a constant expression and return value in vtop */
4602 void expr_const1(void)
4608 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
)) != VT_CONST
)
4613 /* parse an integer constant and return its value */
4614 int expr_const(void)
4623 /* return the label token if current token is a label, otherwise
4630 /* fast test first */
4631 if (tok
< TOK_UIDENT
)
4633 /* no need to save tokc since we expect an identifier */
4641 /* XXX: may not work in all cases (macros ?) */
4650 void block(int *bsym
, int *csym
, int *case_sym
, int *def_sym
, int case_reg
)
4655 /* generate line number info */
4657 (last_line_num
!= line_num
|| last_ind
!= ind
)) {
4658 put_stabn(N_SLINE
, 0, line_num
, ind
- func_ind
);
4660 last_line_num
= line_num
;
4663 if (tok
== TOK_IF
) {
4670 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
4672 if (c
== TOK_ELSE
) {
4676 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
4677 gsym(d
); /* patch else jmp */
4680 } else if (tok
== TOK_WHILE
) {
4688 block(&a
, &b
, case_sym
, def_sym
, case_reg
);
4689 oad(0xe9, d
- ind
- 5); /* jmp */
4692 } else if (tok
== '{') {
4695 s
= local_stack
.top
;
4696 while (tok
!= '}') {
4699 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
4701 /* pop locally defined symbols */
4702 sym_pop(&local_stack
, s
);
4704 } else if (tok
== TOK_RETURN
) {
4708 gen_assign_cast(func_vt
);
4709 if ((func_vt
& VT_BTYPE
) == VT_STRUCT
) {
4710 /* if returning structure, must copy it to implicit
4711 first pointer arg location */
4712 vset(mk_pointer(func_vt
), VT_LOCAL
| VT_LVAL
, func_vc
);
4715 /* copy structure value to pointer */
4717 } else if (is_float(func_vt
)) {
4722 vtop
--; /* NOT vpop() because on x86 it would flush the fp stack */
4725 rsym
= gjmp(rsym
); /* jmp */
4726 } else if (tok
== TOK_BREAK
) {
4729 error("cannot break");
4730 *bsym
= gjmp(*bsym
);
4733 } else if (tok
== TOK_CONTINUE
) {
4736 error("cannot continue");
4737 *csym
= gjmp(*csym
);
4740 } else if (tok
== TOK_FOR
) {
4763 oad(0xe9, d
- ind
- 5); /* jmp */
4767 block(&a
, &b
, case_sym
, def_sym
, case_reg
);
4768 oad(0xe9, c
- ind
- 5); /* jmp */
4772 if (tok
== TOK_DO
) {
4777 block(&a
, &b
, case_sym
, def_sym
, case_reg
);
4788 if (tok
== TOK_SWITCH
) {
4792 /* XXX: other types than integer */
4793 case_reg
= gv(RC_INT
);
4797 b
= gjmp(0); /* jump to first case */
4799 block(&a
, csym
, &b
, &c
, case_reg
);
4800 /* if no default, jmp after switch */
4808 if (tok
== TOK_CASE
) {
4815 if (gnu_ext
&& tok
== TOK_DOTS
) {
4819 warning("empty case range");
4821 /* since a case is like a label, we must skip it with a jmp */
4824 vset(VT_INT
, case_reg
, 0);
4828 *case_sym
= gtst(1, 0);
4831 *case_sym
= gtst(1, 0);
4832 vset(VT_INT
, case_reg
, 0);
4835 *case_sym
= gtst(1, *case_sym
);
4839 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
4841 if (tok
== TOK_DEFAULT
) {
4847 error("too many 'default'");
4849 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
4851 if (tok
== TOK_GOTO
) {
4853 s
= sym_find1(&label_stack
, tok
);
4854 /* put forward definition if needed */
4856 s
= sym_push1(&label_stack
, tok
, VT_FORWARD
, 0);
4857 /* label already defined */
4858 if (s
->t
& VT_FORWARD
)
4859 s
->c
= gjmp(s
->c
); /* jmp xxx */
4861 oad(0xe9, s
->c
- ind
- 5); /* jmp xxx */
4868 s
= sym_find1(&label_stack
, b
);
4870 if (!(s
->t
& VT_FORWARD
))
4871 error("multiple defined label");
4876 sym_push1(&label_stack
, b
, 0, ind
);
4878 /* we accept this, but it is a mistake */
4880 warning("deprecated use of label at end of compound statement");
4882 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
4884 /* expression case */
4894 /* t is the array or struct type. c is the array or struct
4895 address. cur_index/cur_field is the pointer to the current
4896 value. 'size_only' is true if only size info is needed (only used
4898 void decl_designator(int t
, int r
, int c
,
4899 int *cur_index
, Sym
**cur_field
,
4903 int notfirst
, index
, align
, l
;
4906 if (gnu_ext
&& (l
= is_label()) != 0)
4909 while (tok
== '[' || tok
== '.') {
4911 if (!(t
& VT_ARRAY
))
4912 expect("array type");
4913 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
));
4915 index
= expr_const();
4916 if (index
< 0 || (s
->c
>= 0 && index
>= s
->c
))
4917 expect("invalid index");
4921 t
= pointed_type(t
);
4922 c
+= index
* type_size(t
, &align
);
4928 if ((t
& VT_BTYPE
) != VT_STRUCT
)
4929 expect("struct/union type");
4930 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
) | SYM_STRUCT
);
4942 t
= f
->t
| (t
& ~VT_TYPE
);
4957 t
= pointed_type(t
);
4958 c
+= index
* type_size(t
, &align
);
4962 error("too many field init");
4963 t
= f
->t
| (t
& ~VT_TYPE
);
4967 decl_initializer(t
, r
, c
, 0, size_only
);
4971 #define EXPR_CONST 1
4974 /* store a value or an expression directly in global data or in local array */
4975 void init_putv(int t
, int r
, int c
,
4976 int v
, int expr_type
)
4978 int saved_global_expr
, bt
;
4985 /* compound literals must be allocated globally in this case */
4986 saved_global_expr
= global_expr
;
4989 global_expr
= saved_global_expr
;
4996 if ((r
& VT_VALMASK
) == VT_CONST
) {
4997 /* XXX: do casting */
4998 /* XXX: not portable */
4999 bt
= vtop
->t
& VT_BTYPE
;
5002 *(char *)c
= vtop
->c
.i
;
5005 *(short *)c
= vtop
->c
.i
;
5008 *(double *)c
= vtop
->c
.d
;
5011 *(long double *)c
= vtop
->c
.ld
;
5015 *(long long *)c
= vtop
->c
.ll
;
5019 *(int *)c
= vtop
->c
.i
;
5031 /* put zeros for variable based init */
5032 void init_putz(int t
, int r
, int c
, int size
)
5036 if ((r
& VT_VALMASK
) == VT_CONST
) {
5037 /* nothing to do because global are already set to zero */
5044 vset(VT_INT
, VT_LOCAL
, c
);
5046 vpushi((int)&memset
);
5051 /* 't' contains the type and storage info. c is the address of the
5052 object. 'first' is true if array '{' must be read (multi dimension
5053 implicit array init handling). 'size_only' is true if size only
5054 evaluation is wanted (only for arrays). */
5055 void decl_initializer(int t
, int r
, int c
, int first
, int size_only
)
5057 int index
, array_length
, n
, no_oblock
, nb
, parlevel
, i
;
5058 int t1
, size1
, align1
, expr_type
;
5063 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
));
5066 t1
= pointed_type(t
);
5067 size1
= type_size(t1
, &align1
);
5070 if ((first
&& tok
!= TOK_LSTR
&& tok
!= TOK_STR
) ||
5076 /* only parse strings here if correct type (otherwise: handle
5077 them as ((w)char *) expressions */
5078 if ((tok
== TOK_LSTR
&&
5079 (t1
& VT_BTYPE
) == VT_INT
) ||
5081 (t1
& VT_BTYPE
) == VT_BYTE
)) {
5082 /* XXX: move multiple string parsing in parser ? */
5083 while (tok
== TOK_STR
|| tok
== TOK_LSTR
) {
5085 /* compute maximum number of chars wanted */
5087 if (n
>= 0 && nb
> (n
- array_length
))
5088 nb
= n
- array_length
;
5091 warning("initializer-string for array is too long");
5093 init_putv(t1
, r
, c
+ (array_length
+ i
) * size1
,
5094 ts
->str
[i
], EXPR_VAL
);
5100 /* only add trailing zero if enough storage (no
5101 warning in this case since it is standard) */
5102 if (n
< 0 || array_length
< n
) {
5104 init_putv(t1
, r
, c
+ (array_length
* size1
), 0, EXPR_VAL
);
5110 while (tok
!= '}') {
5111 decl_designator(t
, r
, c
, &index
, NULL
, size_only
);
5112 if (n
>= 0 && index
>= n
)
5113 error("index too large");
5114 /* must put zero in holes (note that doing it that way
5115 ensures that it even works with designators) */
5116 if (!size_only
&& array_length
< index
) {
5117 init_putz(t1
, r
, c
+ array_length
* size1
,
5118 (index
- array_length
) * size1
);
5121 if (index
> array_length
)
5122 array_length
= index
;
5123 /* special test for multi dimensional arrays (may not
5124 be strictly correct if designators are used at the
5126 if (index
>= n
&& no_oblock
)
5135 /* put zeros at the end */
5136 if (!size_only
&& n
>= 0 && array_length
< n
) {
5137 init_putz(t1
, r
, c
+ array_length
* size1
,
5138 (n
- array_length
) * size1
);
5140 /* patch type size if needed */
5142 s
->c
= array_length
;
5143 } else if ((t
& VT_BTYPE
) == VT_STRUCT
&& tok
== '{') {
5144 /* XXX: union needs only one init */
5146 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
) | SYM_STRUCT
);
5151 while (tok
!= '}') {
5152 decl_designator(t
, r
, c
, NULL
, &f
, size_only
);
5153 /* fill with zero between fields */
5155 if (!size_only
&& array_length
< index
) {
5156 init_putz(t
, r
, c
+ array_length
,
5157 index
- array_length
);
5159 index
= index
+ type_size(f
->t
, &align1
);
5160 if (index
> array_length
)
5161 array_length
= index
;
5167 /* put zeros at the end */
5168 if (!size_only
&& array_length
< n
) {
5169 init_putz(t
, r
, c
+ array_length
,
5173 } else if (tok
== '{') {
5175 decl_initializer(t
, r
, c
, first
, size_only
);
5177 } else if (size_only
) {
5178 /* just skip expression */
5180 while ((parlevel
> 0 || (tok
!= '}' && tok
!= ',')) &&
5184 else if (tok
== ')')
5189 /* currently, we always use constant expression for globals
5190 (may change for scripting case) */
5191 expr_type
= EXPR_CONST
;
5192 if ((r
& VT_VALMASK
) == VT_LOCAL
)
5193 expr_type
= EXPR_ANY
;
5194 init_putv(t
, r
, c
, 0, expr_type
);
5198 /* parse an initializer for type 't' if 'has_init' is true, and
5199 allocate space in local or global data space ('r' is either
5200 VT_LOCAL or VT_CONST). The allocated address in returned */
5201 int decl_initializer_alloc(int t
, AttributeDef
*ad
, int r
, int has_init
)
5203 int size
, align
, addr
, tok1
, data_offset
;
5204 int *init_str
, init_len
, level
, *saved_macro_ptr
;
5207 size
= type_size(t
, &align
);
5208 /* If unknown size, we must evaluate it before
5209 evaluating initializers because
5210 initializers can generate global data too
5211 (e.g. string pointers or ISOC99 compound
5212 literals). It also simplifies local
5213 initializers handling */
5216 saved_macro_ptr
= NULL
; /* avoid warning */
5220 error("unknown type size");
5221 /* get all init string */
5223 while (level
> 0 || (tok
!= ',' && tok
!= ';')) {
5225 error("unexpected end of file in initializer");
5226 tok_add2(&init_str
, &init_len
, tok
, &tokc
);
5229 else if (tok
== '}') {
5237 tok_add(&init_str
, &init_len
, -1);
5238 tok_add(&init_str
, &init_len
, 0);
5241 saved_macro_ptr
= macro_ptr
;
5242 macro_ptr
= init_str
;
5244 decl_initializer(t
, r
, 0, 1, 1);
5245 /* prepare second initializer parsing */
5246 macro_ptr
= init_str
;
5249 /* if still unknown size, error */
5250 size
= type_size(t
, &align
);
5252 error("unknown type size");
5254 /* take into account specified alignment if bigger */
5255 if (ad
->aligned
> align
)
5256 align
= ad
->aligned
;
5257 if ((r
& VT_VALMASK
) == VT_LOCAL
) {
5258 if (do_bounds_check
&& (t
& VT_ARRAY
))
5260 loc
= (loc
- size
) & -align
;
5262 /* handles bounds */
5263 /* XXX: currently, since we do only one pass, we cannot track
5264 '&' operators, so we add only arrays */
5265 if (do_bounds_check
&& (t
& VT_ARRAY
)) {
5267 /* add padding between regions */
5269 /* then add local bound info */
5270 bounds_ptr
= (int *)lbounds_section
->data_ptr
;
5271 *bounds_ptr
++ = addr
;
5272 *bounds_ptr
++ = size
;
5273 lbounds_section
->data_ptr
= (unsigned char *)bounds_ptr
;
5276 /* compute section */
5284 data_offset
= (int)sec
->data_ptr
;
5285 data_offset
= (data_offset
+ align
- 1) & -align
;
5287 /* very important to increment global
5288 pointer at this time because
5289 initializers themselves can create new
5291 data_offset
+= size
;
5292 /* handles bounds */
5293 if (do_bounds_check
) {
5295 /* first, we need to add at least one byte between each region */
5297 /* then add global bound info */
5298 bounds_ptr
= (int *)bounds_section
->data_ptr
;
5299 *bounds_ptr
++ = addr
;
5300 *bounds_ptr
++ = size
;
5301 bounds_section
->data_ptr
= (unsigned char *)bounds_ptr
;
5303 sec
->data_ptr
= (unsigned char *)data_offset
;
5306 decl_initializer(t
, r
, addr
, 1, 0);
5307 /* restore parse state if needed */
5310 macro_ptr
= saved_macro_ptr
;
5317 void put_func_debug(int t
)
5326 put_elf_sym(symtab_section
, ind
, 0,
5327 ELF32_ST_INFO(bind
, STT_FUNC
), 0,
5328 cur_text_section
->sh_num
, funcname
);
5330 /* XXX: we put here a dummy type */
5331 snprintf(buf
, sizeof(buf
), "%s:%c1",
5332 funcname
, t
& VT_STATIC
? 'f' : 'F');
5333 put_stabs(buf
, N_FUN
, 0, line_num
, ind
);
5339 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
5342 int t
, b
, v
, addr
, has_init
, r
;
5347 if (!parse_btype(&b
, &ad
)) {
5348 /* skip redundant ';' */
5349 /* XXX: find more elegant solution */
5354 /* special test for old K&R protos without explicit int
5355 type. Only accepted when defining global data */
5356 if (l
== VT_LOCAL
|| tok
< TOK_DEFINE
)
5360 if (((b
& VT_BTYPE
) == VT_ENUM
||
5361 (b
& VT_BTYPE
) == VT_STRUCT
) &&
5363 /* we accept no variable after */
5367 while (1) { /* iterate thru each declaration */
5368 t
= type_decl(&v
, b
, TYPE_DIRECT
);
5369 /* currently, we do not parse attribute in
5370 type_decl(). May change if needed */
5371 if (tok
== TOK___ATTRIBUTE__
)
5372 parse_attribute(&ad
);
5376 type_to_str(buf
, sizeof(buf
), t
, get_tok_str(v
, NULL
));
5377 printf("type = '%s'\n", buf
);
5382 error("cannot use local functions");
5384 expect("function definition");
5385 /* compute text section */
5386 cur_text_section
= ad
.section
;
5387 if (!cur_text_section
)
5388 cur_text_section
= text_section
;
5389 ind
= (int)cur_text_section
->data_ptr
;
5390 /* patch forward references */
5391 if ((sym
= sym_find(v
)) && (sym
->r
& VT_FORWARD
)) {
5392 greloc_patch(sym
, ind
);
5395 /* put function address */
5396 sym
= sym_push1(&global_stack
, v
, t
, ind
);
5399 funcname
= get_tok_str(v
, NULL
);
5400 /* put debug symbol */
5403 /* push a dummy symbol to enable local sym storage */
5404 sym_push1(&local_stack
, 0, 0, 0);
5408 block(NULL
, NULL
, NULL
, NULL
, 0);
5411 cur_text_section
->data_ptr
= (unsigned char *)ind
;
5412 sym_pop(&label_stack
, NULL
); /* reset label stack */
5413 sym_pop(&local_stack
, NULL
); /* reset local stack */
5414 /* end of function */
5416 put_stabn(N_FUN
, 0, 0, ind
- func_ind
);
5418 funcname
= ""; /* for safety */
5419 func_vt
= VT_VOID
; /* for safety */
5422 if (b
& VT_TYPEDEF
) {
5423 /* save typedefed type */
5424 /* XXX: test storage specifiers ? */
5425 sym_push(v
, t
| VT_TYPEDEF
, 0, 0);
5426 } else if ((t
& VT_BTYPE
) == VT_FUNC
) {
5427 /* external function definition */
5428 external_sym(v
, t
, 0);
5430 /* not lvalue if array */
5432 if (!(t
& VT_ARRAY
))
5434 if (b
& VT_EXTERN
) {
5435 /* external variable */
5436 external_sym(v
, t
, r
);
5442 has_init
= (tok
== '=');
5445 addr
= decl_initializer_alloc(t
, &ad
, r
,
5447 if (l
== VT_CONST
) {
5448 /* global scope: see if already defined */
5452 if (!is_compatible_types(sym
->t
, t
))
5453 error("incompatible types for redefinition of '%s'",
5454 get_tok_str(v
, NULL
));
5455 if (!(sym
->r
& VT_FORWARD
))
5456 error("redefinition of '%s'", get_tok_str(v
, NULL
));
5457 greloc_patch(sym
, addr
);
5460 sym_push(v
, t
, r
, addr
);
5474 /* put all global symbols in the extern stack and do all the
5475 resolving which can be done without using external symbols from DLLs */
5476 /* XXX: could try to verify types, but would not to save them in
5478 void resolve_global_syms(void)
5480 Sym
*s
, *s1
, *ext_sym
;
5483 s
= global_stack
.top
;
5486 /* do not save static or typedefed symbols or types */
5487 if (!(s
->t
& (VT_STATIC
| VT_TYPEDEF
)) &&
5488 !(s
->v
& (SYM_FIELD
| SYM_STRUCT
)) &&
5489 (s
->v
< SYM_FIRST_ANOM
)) {
5490 ext_sym
= sym_find1(&extern_stack
, s
->v
);
5492 /* if the symbol do not exist, we simply save it */
5493 ext_sym
= sym_push1(&extern_stack
, s
->v
, s
->t
, s
->c
);
5495 } else if (ext_sym
->r
& VT_FORWARD
) {
5496 /* external symbol already exists, but only as forward
5498 if (!(s
->r
& VT_FORWARD
)) {
5499 /* s is not forward, so we can relocate all symbols */
5500 greloc_patch(ext_sym
, s
->c
);
5502 /* the two symbols are forward: merge them */
5503 p
= (Reloc
**)&ext_sym
->c
;
5509 /* external symbol already exists and is defined :
5510 patch all references to it */
5511 if (!(s
->r
& VT_FORWARD
))
5512 error("'%s' defined twice", get_tok_str(s
->v
, NULL
));
5513 greloc_patch(s
, ext_sym
->c
);
5520 /* compile a C file. Return non zero if errors. */
5521 int tcc_compile_file(const char *filename1
)
5528 filename
= (char *)filename1
;
5530 file
= fopen(filename
, "r");
5532 error("file '%s' not found", filename
);
5533 include_stack_ptr
= include_stack
;
5534 ifdef_stack_ptr
= ifdef_stack
;
5537 anon_sym
= SYM_FIRST_ANOM
;
5539 /* file info: full path + filename */
5541 getcwd(buf
, sizeof(buf
));
5542 pstrcat(buf
, sizeof(buf
), "/");
5543 put_stabs(buf
, N_SO
, 0, 0, (unsigned long)text_section
->data_ptr
);
5544 put_stabs(filename
, N_SO
, 0, 0, (unsigned long)text_section
->data_ptr
);
5546 /* define common 'char *' type because it is often used internally
5547 for arrays and struct dereference */
5548 char_pointer_type
= mk_pointer(VT_BYTE
);
5550 define_start
= define_stack
.top
;
5552 ch
= '\n'; /* needed to parse correctly first preprocessor command */
5556 expect("declaration");
5559 /* end of translation unit info */
5561 put_stabn(N_SO
, 0, 0, (unsigned long)text_section
->data_ptr
);
5564 /* reset define stack, but leave -Dsymbols (may be incorrect if
5565 they are undefined) */
5566 sym_pop(&define_stack
, define_start
);
5568 resolve_global_syms();
5570 sym_pop(&global_stack
, NULL
);
5575 /* define a symbol. A value can also be provided with the '=' operator */
5576 /* XXX: currently only handles integers and string defines. should use
5577 tcc parser, but would need a custom 'FILE *' */
5578 void define_symbol(const char *sym
)
5586 p
= strchr(sym
, '=');
5588 pstrcpy(buf
, sizeof(buf
), sym
);
5592 if (len
> sizeof(buf
) - 1)
5593 len
= sizeof(buf
) - 1;
5594 memcpy(buf
, sym
, len
);
5599 ts
= tok_alloc(buf
, 0);
5605 tok_add2(&str
, &len
, TOK_CINT
, &cval
);
5608 cval
.ts
= tok_alloc(p
, 0);
5609 tok_add2(&str
, &len
, TOK_STR
, &cval
);
5611 tok_add(&str
, &len
, 0);
5612 sym_push1(&define_stack
, ts
->tok
, MACRO_OBJ
, (int)str
);
5615 void undef_symbol(const char *sym
)
5619 printf("undef %s\n", sym
);
5620 ts
= tok_alloc(sym
, 0);
5621 s
= sym_find1(&define_stack
, tok
);
5622 /* undefine symbol by putting an invalid name */
5624 sym_undef(&define_stack
, s
);
5627 /* open a dynamic library so that its symbol are available for
5628 compiled programs */
5629 void open_dll(char *libname
)
5634 snprintf(buf
, sizeof(buf
), "lib%s.so", libname
);
5635 h
= dlopen(buf
, RTLD_GLOBAL
| RTLD_LAZY
);
5637 error((char *)dlerror());
5640 static void *resolve_sym(const char *sym
)
5643 if (do_bounds_check
) {
5644 ptr
= bound_resolve_sym(sym
);
5648 return dlsym(NULL
, sym
);
5651 void resolve_extern_syms(void)
5657 s
= extern_stack
.top
;
5660 if (s
->r
& VT_FORWARD
) {
5661 /* if there is at least one relocation to do, then find it
5664 str
= get_tok_str(s
->v
, NULL
);
5665 addr
= (int)resolve_sym(str
);
5667 error("unresolved external reference '%s'", str
);
5668 greloc_patch(s
, addr
);
5675 static int put_elf_str(Section
*s
, const char *sym
)
5678 offset
= s
->data_ptr
- s
->data
;
5688 static void put_elf_sym(Section
*s
,
5689 unsigned long value
, unsigned long size
,
5690 int info
, int other
, int shndx
, const char *name
)
5695 sym
= (Elf32_Sym
*)s
->data_ptr
;
5697 name_offset
= put_elf_str(s
->link
, name
);
5700 sym
->st_name
= name_offset
;
5701 sym
->st_value
= value
;
5702 sym
->st_size
= size
;
5703 sym
->st_info
= info
;
5704 sym
->st_other
= other
;
5705 sym
->st_shndx
= shndx
;
5706 s
->data_ptr
+= sizeof(Elf32_Sym
);
5709 /* put stab debug information */
5712 unsigned long n_strx
; /* index into string table of name */
5713 unsigned char n_type
; /* type of symbol */
5714 unsigned char n_other
; /* misc info (usually empty) */
5715 unsigned short n_desc
; /* description field */
5716 unsigned long n_value
; /* value of symbol */
5719 static void put_stabs(const char *str
, int type
, int other
, int desc
, int value
)
5723 sym
= (Stab_Sym
*)stab_section
->data_ptr
;
5725 sym
->n_strx
= put_elf_str(stabstr_section
, str
);
5730 sym
->n_other
= other
;
5732 sym
->n_value
= value
;
5734 stab_section
->data_ptr
+= sizeof(Stab_Sym
);
5737 static void put_stabn(int type
, int other
, int desc
, int value
)
5739 put_stabs(NULL
, type
, other
, desc
, value
);
5742 static void put_stabd(int type
, int other
, int desc
)
5744 put_stabs(NULL
, type
, other
, desc
, 0);
5747 /* output an ELF file (currently, only for testing) */
5748 /* XXX: better program header generation */
5749 /* XXX: handle realloc'ed sections (instead of mmaping them) */
5750 /* XXX: generate dynamic reloc info + DLL tables */
5751 /* XXX: generate startup code */
5752 void build_exe(char *filename
)
5756 int shnum
, i
, phnum
, file_offset
, offset
, size
, j
;
5757 Section
*sec
, *strsec
;
5758 Elf32_Shdr
*shdr
, *sh
;
5759 Elf32_Phdr
*phdr
, *ph
;
5761 memset(&ehdr
, 0, sizeof(ehdr
));
5763 /* we add a section for symbols */
5764 strsec
= new_section(".shstrtab", SHT_STRTAB
, 0);
5765 put_elf_str(strsec
, "");
5767 /* count number of sections and compute number of program segments */
5768 shnum
= 1; /* section index zero is reserved */
5770 for(sec
= first_section
; sec
!= NULL
; sec
= sec
->next
) {
5772 if (sec
->sh_flags
& SHF_ALLOC
)
5775 /* allocate section headers */
5776 shdr
= malloc(shnum
* sizeof(Elf32_Shdr
));
5778 error("memory full");
5779 memset(shdr
, 0, shnum
* sizeof(Elf32_Shdr
));
5780 /* allocate program segment headers */
5781 phdr
= malloc(phnum
* sizeof(Elf32_Phdr
));
5783 error("memory full");
5784 memset(phdr
, 0, phnum
* sizeof(Elf32_Phdr
));
5786 /* XXX: find correct load order */
5787 file_offset
= sizeof(Elf32_Ehdr
) + phnum
* sizeof(Elf32_Phdr
);
5788 for(sec
= first_section
, i
= 1; sec
!= NULL
; sec
= sec
->next
, i
++) {
5790 sh
->sh_name
= put_elf_str(strsec
, sec
->name
);
5791 sh
->sh_type
= sec
->sh_type
;
5792 sh
->sh_flags
= sec
->sh_flags
;
5793 sh
->sh_entsize
= sec
->sh_entsize
;
5795 sh
->sh_link
= sec
->link
->sh_num
;
5796 if (sh
->sh_type
== SHT_STRTAB
) {
5797 sh
->sh_addralign
= 1;
5798 } else if (sh
->sh_type
== SHT_SYMTAB
||
5799 (sh
->sh_flags
& SHF_ALLOC
) == 0) {
5800 sh
->sh_addralign
= 4;
5802 sh
->sh_addr
= (Elf32_Word
)sec
->data
;
5803 sh
->sh_addralign
= 4096;
5805 sh
->sh_size
= (Elf32_Word
)sec
->data_ptr
- (Elf32_Word
)sec
->data
;
5806 /* align to section start */
5807 file_offset
= (file_offset
+ sh
->sh_addralign
- 1) &
5808 ~(sh
->sh_addralign
- 1);
5809 sh
->sh_offset
= file_offset
;
5810 file_offset
+= sh
->sh_size
;
5812 /* build program headers (simplistic - not fully correct) */
5814 for(i
=1;i
<shnum
;i
++) {
5816 if (sh
->sh_type
== SHT_PROGBITS
&&
5817 (sh
->sh_flags
& SHF_ALLOC
) != 0) {
5819 ph
->p_type
= PT_LOAD
;
5820 ph
->p_offset
= sh
->sh_offset
;
5821 ph
->p_vaddr
= sh
->sh_addr
;
5822 ph
->p_paddr
= ph
->p_vaddr
;
5823 ph
->p_filesz
= sh
->sh_size
;
5824 ph
->p_memsz
= sh
->sh_size
;
5826 if (sh
->sh_flags
& SHF_WRITE
)
5827 ph
->p_flags
|= PF_W
;
5828 if (sh
->sh_flags
& SHF_EXECINSTR
)
5829 ph
->p_flags
|= PF_X
;
5830 ph
->p_align
= sh
->sh_addralign
;
5835 file_offset
= (file_offset
+ 3) & -4;
5838 ehdr
.e_ident
[0] = ELFMAG0
;
5839 ehdr
.e_ident
[1] = ELFMAG1
;
5840 ehdr
.e_ident
[2] = ELFMAG2
;
5841 ehdr
.e_ident
[3] = ELFMAG3
;
5842 ehdr
.e_ident
[4] = ELFCLASS32
;
5843 ehdr
.e_ident
[5] = ELFDATA2LSB
;
5844 ehdr
.e_ident
[6] = EV_CURRENT
;
5845 ehdr
.e_type
= ET_EXEC
;
5846 ehdr
.e_machine
= EM_386
;
5847 ehdr
.e_version
= EV_CURRENT
;
5848 ehdr
.e_entry
= 0; /* XXX: patch it */
5849 ehdr
.e_phoff
= sizeof(Elf32_Ehdr
);
5850 ehdr
.e_shoff
= file_offset
;
5851 ehdr
.e_ehsize
= sizeof(Elf32_Ehdr
);
5852 ehdr
.e_phentsize
= sizeof(Elf32_Phdr
);
5853 ehdr
.e_phnum
= phnum
;
5854 ehdr
.e_shentsize
= sizeof(Elf32_Shdr
);
5855 ehdr
.e_shnum
= shnum
;
5856 ehdr
.e_shstrndx
= shnum
- 1;
5858 /* write elf file */
5859 f
= fopen(filename
, "w");
5861 error("could not write '%s'", filename
);
5862 fwrite(&ehdr
, 1, sizeof(Elf32_Ehdr
), f
);
5863 fwrite(phdr
, 1, phnum
* sizeof(Elf32_Phdr
), f
);
5864 offset
= sizeof(Elf32_Ehdr
) + phnum
* sizeof(Elf32_Phdr
);
5865 for(sec
= first_section
, i
= 1; sec
!= NULL
; sec
= sec
->next
, i
++) {
5867 while (offset
< sh
->sh_offset
) {
5871 size
= sec
->data_ptr
- sec
->data
;
5872 fwrite(sec
->data
, 1, size
, f
);
5875 while (offset
< ehdr
.e_shoff
) {
5879 fwrite(shdr
, 1, shnum
* sizeof(Elf32_Shdr
), f
);
5883 /* print the position in the source file of PC value 'pc' by reading
5884 the stabs debug information */
5885 static void rt_printline(unsigned long wanted_pc
)
5887 Stab_Sym
*sym
, *sym_end
;
5888 char func_name
[128];
5889 unsigned long func_addr
, last_pc
, pc
;
5890 const char *incl_files
[INCLUDE_STACK_SIZE
];
5891 int incl_index
, len
, last_line_num
, i
;
5892 const char *str
, *p
;
5894 func_name
[0] = '\0';
5897 last_pc
= 0xffffffff;
5899 sym
= (Stab_Sym
*)stab_section
->data
+ 1;
5900 sym_end
= (Stab_Sym
*)stab_section
->data_ptr
;
5901 while (sym
< sym_end
) {
5902 switch(sym
->n_type
) {
5903 /* function start or end */
5905 if (sym
->n_strx
== 0) {
5906 func_name
[0] = '\0';
5909 str
= stabstr_section
->data
+ sym
->n_strx
;
5910 p
= strchr(str
, ':');
5912 pstrcpy(func_name
, sizeof(func_name
), str
);
5915 if (len
> sizeof(func_name
) - 1)
5916 len
= sizeof(func_name
) - 1;
5917 memcpy(func_name
, str
, len
);
5918 func_name
[len
] = '\0';
5920 func_addr
= sym
->n_value
;
5923 /* line number info */
5925 pc
= sym
->n_value
+ func_addr
;
5926 if (wanted_pc
>= last_pc
&& wanted_pc
< pc
)
5929 last_line_num
= sym
->n_desc
;
5933 str
= stabstr_section
->data
+ sym
->n_strx
;
5935 if (incl_index
< INCLUDE_STACK_SIZE
) {
5936 incl_files
[incl_index
++] = str
;
5944 if (sym
->n_strx
== 0) {
5945 incl_index
= 0; /* end of translation unit */
5947 str
= stabstr_section
->data
+ sym
->n_strx
;
5948 /* do not add path */
5950 if (len
> 0 && str
[len
- 1] != '/')
5957 /* did not find line number info: */
5958 fprintf(stderr
, "(no debug info, pc=0x%08lx): ", wanted_pc
);
5961 for(i
= 0; i
< incl_index
- 1; i
++)
5962 fprintf(stderr
, "In file included from %s\n",
5964 if (incl_index
> 0) {
5965 fprintf(stderr
, "%s:%d: ",
5966 incl_files
[incl_index
- 1], last_line_num
);
5968 if (func_name
[0] != '\0') {
5969 fprintf(stderr
, "in function '%s()': ", func_name
);
5973 /* emit a run time error at position 'pc' */
5974 void rt_error(unsigned long pc
, const char *fmt
, ...)
5980 vfprintf(stderr
, fmt
, ap
);
5981 fprintf(stderr
, "\n");
5986 /* signal handler for fatal errors */
5987 static void sig_error(int signum
, siginfo_t
*siginf
, void *puc
)
5989 struct ucontext
*uc
= puc
;
5993 pc
= uc
->uc_mcontext
.gregs
[14];
5995 #error please put the right sigcontext field
6000 switch(siginf
->si_code
) {
6003 rt_error(pc
, "division by zero");
6006 rt_error(pc
, "floating point exception");
6012 rt_error(pc
, "dereferencing invalid pointer");
6015 rt_error(pc
, "illegal instruction");
6018 rt_error(pc
, "abort() called");
6021 rt_error(pc
, "caught signal %d", signum
);
6027 /* launch the compiled program with the given arguments */
6028 int launch_exe(int argc
, char **argv
)
6032 struct sigaction sigact
;
6034 s
= sym_find1(&extern_stack
, TOK_MAIN
);
6035 if (!s
|| (s
->r
& VT_FORWARD
))
6036 error("main() not defined");
6039 /* install TCC signal handlers to print debug info on fatal
6041 sigact
.sa_flags
= SA_SIGINFO
| SA_ONESHOT
;
6042 sigact
.sa_sigaction
= sig_error
;
6043 sigemptyset(&sigact
.sa_mask
);
6044 sigaction(SIGFPE
, &sigact
, NULL
);
6045 sigaction(SIGILL
, &sigact
, NULL
);
6046 sigaction(SIGSEGV
, &sigact
, NULL
);
6047 sigaction(SIGBUS
, &sigact
, NULL
);
6048 sigaction(SIGABRT
, &sigact
, NULL
);
6051 if (do_bounds_check
) {
6054 /* add all known static regions */
6055 p
= (int *)bounds_section
->data
;
6056 p_end
= (int *)bounds_section
->data_ptr
;
6058 __bound_new_region((void *)p
[0], p
[1]);
6063 t
= (int (*)())s
->c
;
6064 return (*t
)(argc
, argv
);
6070 printf("tcc version 0.9.3 - Tiny C Compiler - Copyright (C) 2001, 2002 Fabrice Bellard\n"
6071 "usage: tcc [-Idir] [-Dsym[=val]] [-Usym] [-llib] [-g] [-b]\n"
6072 " [-i infile] infile [infile_args...]\n"
6074 "-Idir : add include path 'dir'\n"
6075 "-Dsym[=val] : define 'sym' with value 'val'\n"
6076 "-Usym : undefine 'sym'\n"
6077 "-llib : link with dynamic library 'lib'\n"
6078 "-g : generate runtime debug info\n"
6079 "-b : compile with built-in memory and bounds checker (implies -g)\n"
6080 "-i infile : compile infile\n"
6084 int main(int argc
, char **argv
)
6086 char *p
, *r
, *outfile
;
6089 include_paths
[0] = "/usr/include";
6090 include_paths
[1] = "/usr/lib/tcc";
6091 include_paths
[2] = "/usr/local/lib/tcc";
6092 nb_include_paths
= 3;
6094 /* add all tokens */
6095 tok_ident
= TOK_IDENT
;
6096 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";
6100 tok_alloc(p
, r
- p
- 1);
6104 /* standard defines */
6105 define_symbol("__STDC__");
6107 define_symbol("__i386__");
6109 /* tiny C specific defines */
6110 define_symbol("__TINYC__");
6112 /* create standard sections */
6113 text_section
= new_section(".text", SHT_PROGBITS
, SHF_ALLOC
| SHF_EXECINSTR
);
6114 data_section
= new_section(".data", SHT_PROGBITS
, SHF_ALLOC
| SHF_WRITE
);
6115 /* XXX: should change type to SHT_NOBITS */
6116 bss_section
= new_section(".bss", SHT_PROGBITS
, SHF_ALLOC
| SHF_WRITE
);
6121 if (optind
>= argc
) {
6131 if (nb_include_paths
>= INCLUDE_PATHS_MAX
)
6132 error("too many include paths");
6133 include_paths
[nb_include_paths
++] = r
+ 2;
6134 } else if (r
[1] == 'D') {
6135 define_symbol(r
+ 2);
6136 } else if (r
[1] == 'U') {
6137 undef_symbol(r
+ 2);
6138 } else if (r
[1] == 'l') {
6140 } else if (r
[1] == 'i') {
6143 tcc_compile_file(argv
[optind
++]);
6144 } else if (r
[1] == 'b') {
6145 if (!do_bounds_check
) {
6146 do_bounds_check
= 1;
6147 /* create bounds sections */
6148 bounds_section
= new_section(".bounds",
6149 SHT_PROGBITS
, SHF_ALLOC
);
6150 lbounds_section
= new_section(".lbounds",
6151 SHT_PROGBITS
, SHF_ALLOC
);
6152 /* debug is implied */
6155 } else if (r
[1] == 'g') {
6161 stab_section
= new_section(".stab", SHT_PROGBITS
, 0);
6162 stab_section
->sh_entsize
= sizeof(Stab_Sym
);
6163 stabstr_section
= new_section(".stabstr", SHT_STRTAB
, 0);
6164 put_elf_str(stabstr_section
, "");
6165 stab_section
->link
= stabstr_section
;
6166 /* put first entry */
6167 put_stabs("", 0, 0, 0, 0);
6170 symtab_section
= new_section(".symtab", SHT_SYMTAB
, 0);
6171 symtab_section
->sh_entsize
= sizeof(Elf32_Sym
);
6172 strtab_section
= new_section(".strtab", SHT_STRTAB
, 0);
6173 put_elf_str(strtab_section
, "");
6174 symtab_section
->link
= strtab_section
;
6175 put_elf_sym(symtab_section
, 0, 0, 0, 0, 0, NULL
);
6177 } else if (r
[1] == 'o') {
6178 /* currently, only for testing, so not documented */
6181 outfile
= argv
[optind
++];
6183 fprintf(stderr
, "invalid option -- '%s'\n", r
);
6188 tcc_compile_file(argv
[optind
]);
6190 resolve_extern_syms();
6196 return launch_exe(argc
- optind
, argv
+ optind
);