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.
32 #include <sys/ucontext.h>
37 #ifndef CONFIG_TCC_STATIC
44 /* preprocessor debug */
47 /* target selection */
48 //#define TCC_TARGET_I386 /* i386 code generator */
49 //#define TCC_TARGET_IL /* .NET CLI generator */
51 /* default target is I386 */
52 #if !defined(TCC_TARGET_I386) && !defined(TCC_TARGET_IL)
53 #define TCC_TARGET_I386
56 #if !defined(WIN32) && !defined(TCC_UCLIBC) && !defined(TCC_TARGET_IL)
57 #define CONFIG_TCC_BCHECK /* enable bound checking code */
60 #ifndef CONFIG_TCC_PREFIX
61 #define CONFIG_TCC_PREFIX "/usr/local"
64 /* amount of virtual memory associated to a section (currently, we do
66 #define SECTION_VSIZE (1024 * 1024)
68 #define INCLUDE_STACK_SIZE 32
69 #define IFDEF_STACK_SIZE 64
70 #define VSTACK_SIZE 64
71 #define STRING_MAX_SIZE 1024
72 #define INCLUDE_PATHS_MAX 32
74 #define TOK_HASH_SIZE 2048 /* must be a power of two */
75 #define TOK_ALLOC_INCR 512 /* must be a power of two */
76 #define SYM_HASH_SIZE 1031
78 /* token symbol management */
79 typedef struct TokenSym
{
80 struct TokenSym
*hash_next
;
81 int tok
; /* token number */
87 typedef union CValue
{
93 unsigned int ul
; /* address (should be unsigned long on 64 bit cpu) */
95 unsigned long long ull
;
102 typedef struct SValue
{
104 unsigned short r
; /* register + flags */
105 unsigned short r2
; /* second register, used for 'long long'
106 type. If not used, set to VT_CONST */
107 CValue c
; /* constant */
110 /* symbol management */
112 int v
; /* symbol token */
113 int t
; /* associated type */
114 int r
; /* associated register */
115 int c
; /* associated number */
116 struct Sym
*next
; /* next related symbol */
117 struct Sym
*prev
; /* prev symbol in stack */
118 struct Sym
*hash_next
; /* next symbol in hash table */
121 typedef struct SymStack
{
123 struct Sym
*hash
[SYM_HASH_SIZE
];
126 /* relocation entry (currently only used for functions or variables */
127 typedef struct Reloc
{
128 int type
; /* type of relocation */
129 int addr
; /* address of relocation */
130 struct Reloc
*next
; /* next relocation */
133 #define RELOC_ADDR32 1 /* 32 bits relocation */
134 #define RELOC_REL32 2 /* 32 bits relative relocation */
136 /* section definition */
137 typedef struct Section
{
138 unsigned char *data
; /* section data */
139 unsigned char *data_ptr
; /* current data pointer */
140 int sh_num
; /* elf section number */
141 int sh_type
; /* elf section type */
142 int sh_flags
; /* elf section flags */
143 int sh_entsize
; /* elf entry size */
144 struct Section
*link
; /* link to another section */
145 struct Section
*next
;
146 char name
[64]; /* section name */
149 /* GNUC attribute definition */
150 typedef struct AttributeDef
{
153 unsigned char func_call
; /* FUNC_CDECL or FUNC_STDCALL */
156 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
157 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
158 #define SYM_FIRST_ANOM (1 << (31 - VT_STRUCT_SHIFT)) /* first anonymous sym */
160 /* stored in 'Sym.c' field */
161 #define FUNC_NEW 1 /* ansi function prototype */
162 #define FUNC_OLD 2 /* old function prototype */
163 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
165 /* stored in 'Sym.r' field */
166 #define FUNC_CDECL 0 /* standard c call */
167 #define FUNC_STDCALL 1 /* pascal c call */
169 /* field 'Sym.t' for macros */
170 #define MACRO_OBJ 0 /* object like macro */
171 #define MACRO_FUNC 1 /* function like macro */
173 /* type_decl() types */
174 #define TYPE_ABSTRACT 1 /* type without variable */
175 #define TYPE_DIRECT 2 /* type with variable */
177 #define IO_BUF_SIZE 8192
179 typedef struct BufferedFile
{
180 unsigned char *buf_ptr
;
181 unsigned char *buf_end
;
183 int line_num
; /* current line number - here to simply code */
184 char filename
[1024]; /* current filename - here to simply code */
185 unsigned char buffer
[IO_BUF_SIZE
+ 1]; /* extra size for CH_EOB char */
188 #define CH_EOB 0 /* end of buffer or '\0' char in file */
189 #define CH_EOF (-1) /* end of file */
191 /* parsing state (used to save parser state to reparse part of the
192 source several times) */
193 typedef struct ParseState
{
200 /* used to record tokens */
201 typedef struct TokenString
{
208 struct BufferedFile
*file
;
209 int ch
, ch1
, tok
, tok1
;
213 Section
*first_section
;
215 Section
*text_section
, *data_section
, *bss_section
; /* predefined sections */
216 Section
*cur_text_section
; /* current section where function code is
218 /* bound check related sections */
219 Section
*bounds_section
; /* contains global data bound description */
220 Section
*lbounds_section
; /* contains local data bound description */
222 Section
*stab_section
, *stabstr_section
, *symtab_section
, *strtab_section
;
224 /* loc : local variable index
225 ind : output code index
227 anon_sym: anonymous symbol index
230 prog
, ind
, loc
, const_wanted
;
231 int global_expr
; /* true if compound literals must be allocated
232 globally (used during initializers parsing */
233 int func_vt
, func_vc
; /* current function return type (used by
234 return instruction) */
235 int last_line_num
, last_ind
, func_ind
; /* debug last line number and pc */
237 TokenSym
**table_ident
;
238 TokenSym
*hash_ident
[TOK_HASH_SIZE
];
239 char token_buf
[STRING_MAX_SIZE
+ 1];
241 /* contains global symbols which remain between each translation unit */
242 SymStack extern_stack
;
243 SymStack define_stack
, global_stack
, local_stack
, label_stack
;
245 SValue vstack
[VSTACK_SIZE
], *vtop
;
246 int *macro_ptr
, *macro_ptr_allocated
;
247 BufferedFile
*include_stack
[INCLUDE_STACK_SIZE
], **include_stack_ptr
;
248 int ifdef_stack
[IFDEF_STACK_SIZE
], *ifdef_stack_ptr
;
249 char *include_paths
[INCLUDE_PATHS_MAX
];
250 int nb_include_paths
;
251 int char_pointer_type
;
253 /* compile with debug symbol (and use them if error during execution) */
256 /* compile with built-in memory and bounds checker */
257 int do_bounds_check
= 0;
259 /* display benchmark infos */
264 /* use GNU C extensions */
267 /* use Tiny C extensions */
274 /* The current value can be: */
275 #define VT_VALMASK 0x00ff
276 #define VT_CONST 0x00f0 /* constant in vc
277 (must be first non register value) */
278 #define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */
279 #define VT_LOCAL 0x00f2 /* offset on stack */
280 #define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */
281 #define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */
282 #define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */
283 #define VT_LVAL 0x0100 /* var is an lvalue */
284 #define VT_FORWARD 0x0200 /* value is forward reference */
285 #define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for
286 char/short stored in integer registers) */
287 #define VT_MUSTBOUND 0x0800 /* bound checking must be done before
288 dereferencing value */
289 #define VT_BOUNDED 0x8000 /* value is bounded. The address of the
290 bounding function call point is in vc */
291 #define VT_LVAL_BYTE 0x1000 /* lvalue is a byte */
292 #define VT_LVAL_SHORT 0x2000 /* lvalue is a short */
293 #define VT_LVAL_UNSIGNED 0x4000 /* lvalue is unsigned */
294 #define VT_LVAL_TYPE (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)
297 #define VT_STRUCT_SHIFT 16 /* structure/enum name shift (16 bits left) */
299 #define VT_INT 0 /* integer type */
300 #define VT_BYTE 1 /* signed byte type */
301 #define VT_SHORT 2 /* short type */
302 #define VT_VOID 3 /* void type */
303 #define VT_PTR 4 /* pointer */
304 #define VT_ENUM 5 /* enum definition */
305 #define VT_FUNC 6 /* function type */
306 #define VT_STRUCT 7 /* struct/union definition */
307 #define VT_FLOAT 8 /* IEEE float */
308 #define VT_DOUBLE 9 /* IEEE double */
309 #define VT_LDOUBLE 10 /* IEEE long double */
310 #define VT_BOOL 11 /* ISOC99 boolean type */
311 #define VT_LLONG 12 /* 64 bit integer */
312 #define VT_LONG 13 /* long integer (NEVER USED as type, only
314 #define VT_BTYPE 0x000f /* mask for basic type */
315 #define VT_UNSIGNED 0x0010 /* unsigned type */
316 #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
317 #define VT_BITFIELD 0x0040 /* bitfield modifier */
320 #define VT_EXTERN 0x00000080 /* extern definition */
321 #define VT_STATIC 0x00000100 /* static variable */
322 #define VT_TYPEDEF 0x00000200 /* typedef definition */
324 /* type mask (except storage) */
325 #define VT_TYPE (~(VT_EXTERN | VT_STATIC | VT_TYPEDEF))
329 /* warning: the following compare tokens depend on i386 asm code */
341 #define TOK_LAND 0xa0
345 #define TOK_MID 0xa3 /* inc/dec, to void constant */
347 #define TOK_UDIV 0xb0 /* unsigned division */
348 #define TOK_UMOD 0xb1 /* unsigned modulo */
349 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
350 #define TOK_CINT 0xb3 /* number in tokc */
351 #define TOK_CCHAR 0xb4 /* char constant in tokc */
352 #define TOK_STR 0xb5 /* pointer to string in tokc */
353 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
354 #define TOK_LCHAR 0xb7
355 #define TOK_LSTR 0xb8
356 #define TOK_CFLOAT 0xb9 /* float constant */
357 #define TOK_LINENUM 0xba /* line number info */
358 #define TOK_CDOUBLE 0xc0 /* double constant */
359 #define TOK_CLDOUBLE 0xc1 /* long double constant */
360 #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
361 #define TOK_ADDC1 0xc3 /* add with carry generation */
362 #define TOK_ADDC2 0xc4 /* add with carry use */
363 #define TOK_SUBC1 0xc5 /* add with carry generation */
364 #define TOK_SUBC2 0xc6 /* add with carry use */
365 #define TOK_CUINT 0xc8 /* unsigned int constant */
366 #define TOK_CLLONG 0xc9 /* long long constant */
367 #define TOK_CULLONG 0xca /* unsigned long long constant */
368 #define TOK_ARROW 0xcb
369 #define TOK_DOTS 0xcc /* three dots */
370 #define TOK_SHR 0xcd /* unsigned shift right */
372 #define TOK_SHL 0x01 /* shift left */
373 #define TOK_SAR 0x02 /* signed shift right */
375 /* assignement operators : normal operator or 0x80 */
376 #define TOK_A_MOD 0xa5
377 #define TOK_A_AND 0xa6
378 #define TOK_A_MUL 0xaa
379 #define TOK_A_ADD 0xab
380 #define TOK_A_SUB 0xad
381 #define TOK_A_DIV 0xaf
382 #define TOK_A_XOR 0xde
383 #define TOK_A_OR 0xfc
384 #define TOK_A_SHL 0x81
385 #define TOK_A_SAR 0x82
387 #define TOK_EOF (-1) /* end of file */
389 /* all identificators and strings have token above that */
390 #define TOK_IDENT 256
411 /* ignored types Must have contiguous values */
417 TOK___SIGNED__
, /* gcc keyword */
420 TOK___INLINE__
, /* gcc keyword */
423 /* unsupported type */
437 /* preprocessor only */
438 TOK_UIDENT
, /* first "user" ident (not keyword) */
439 TOK_DEFINE
= TOK_UIDENT
,
455 /* special identifiers */
458 /* attribute identifiers */
476 "int\0void\0char\0if\0else\0while\0break\0return\0for\0extern\0static\0"
477 "unsigned\0goto\0do\0continue\0switch\0case\0const\0volatile\0long\0"
478 "register\0signed\0__signed__\0auto\0inline\0__inline__\0restrict\0"
479 "float\0double\0_Bool\0short\0struct\0union\0typedef\0default\0enum\0"
480 "sizeof\0__attribute__\0"
481 /* the following are not keywords. They are included to ease parsing */
482 "define\0include\0ifdef\0ifndef\0elif\0endif\0"
483 "defined\0undef\0error\0line\0"
484 "__LINE__\0__FILE__\0__DATE__\0__TIME__\0__VA_ARGS__\0"
487 "section\0__section__\0aligned\0__aligned__\0unused\0__unused__\0"
488 "cdecl\0__cdecl\0__cdecl__\0stdcall\0__stdcall\0__stdcall__\0"
489 "noreturn\0__noreturn__\0"
493 #define snprintf _snprintf
496 #if defined(WIN32) || defined(TCC_UCLIBC)
497 /* currently incorrect */
498 long double strtold(const char *nptr
, char **endptr
)
500 return (long double)strtod(nptr
, endptr
);
502 float strtof(const char *nptr
, char **endptr
)
504 return (float)strtod(nptr
, endptr
);
507 /* XXX: need to define this to use them in non ISOC99 context */
508 extern float strtof (const char *__nptr
, char **__endptr
);
509 extern long double strtold (const char *__nptr
, char **__endptr
);
512 char *pstrcpy(char *buf
, int buf_size
, const char *s
);
513 char *pstrcat(char *buf
, int buf_size
, const char *s
);
517 void next_nomacro(void);
518 int expr_const(void);
522 void decl_initializer(int t
, int r
, int c
, int first
, int size_only
);
523 int decl_initializer_alloc(int t
, AttributeDef
*ad
, int r
, int has_init
);
525 void gv2(int rc1
, int rc2
);
526 void move_reg(int r
, int s
);
527 void save_regs(int n
);
528 void save_reg(int r
);
534 void macro_subst(TokenString
*tok_str
,
535 Sym
**nested_list
, int *macro_str
);
536 int save_reg_forced(int r
);
538 void force_charshort_cast(int t
);
539 void gen_cast(int t
);
541 Sym
*sym_find(int v
);
542 Sym
*sym_push(int v
, int t
, int r
, int c
);
545 int type_size(int t
, int *a
);
546 int pointed_type(int t
);
547 int pointed_size(int t
);
548 int is_compatible_types(int t1
, int t2
);
549 int parse_btype(int *type_ptr
, AttributeDef
*ad
);
550 int type_decl(AttributeDef
*ad
, int *v
, int t
, int td
);
552 void error(const char *fmt
, ...);
553 void rt_error(unsigned long pc
, const char *fmt
, ...);
555 void vset(int t
, int r
, int v
);
556 void type_to_str(char *buf
, int buf_size
,
557 int t
, const char *varstr
);
559 /* section generation */
560 void greloc(Sym
*s
, int addr
, int type
);
561 static int put_elf_str(Section
*s
, const char *sym
);
562 static void put_elf_sym(Section
*s
,
563 unsigned long value
, unsigned long size
,
564 int info
, int other
, int shndx
, const char *name
);
565 static void put_stabs(const char *str
, int type
, int other
, int desc
, int value
);
566 static void put_stabn(int type
, int other
, int desc
, int value
);
567 static void put_stabd(int type
, int other
, int desc
);
569 /* true if float/double/long double type */
570 static inline int is_float(int t
)
574 return bt
== VT_LDOUBLE
|| bt
== VT_DOUBLE
|| bt
== VT_FLOAT
;
577 #ifdef CONFIG_TCC_BCHECK
581 #ifdef TCC_TARGET_I386
582 #include "i386-gen.c"
588 #ifdef CONFIG_TCC_STATIC
590 #define RTLD_LAZY 0x001
591 #define RTLD_NOW 0x002
592 #define RTLD_GLOBAL 0x100
594 /* dummy function for profiling */
595 void *dlopen(const char *filename
, int flag
)
600 const char *dlerror(void)
605 typedef struct TCCSyms
{
610 #define TCCSYM(a) { #a, &a, },
612 /* add the symbol you want here if no dynamic linking is done */
613 static TCCSyms tcc_syms
[] = {
621 void *dlsym(void *handle
, const char *symbol
)
625 while (p
->str
!= NULL
) {
626 if (!strcmp(p
->str
, symbol
))
635 /********************************************************/
636 /* runtime library is there */
637 /* XXX: we suppose that the host compiler handles 'long long'. It
638 would not be difficult to suppress this assumption */
640 long long __divll(long long a
, long long b
)
645 long long __modll(long long a
, long long b
)
650 unsigned long long __divull(unsigned long long a
, unsigned long long b
)
655 unsigned long long __modull(unsigned long long a
, unsigned long long b
)
660 long long __sardi3(long long a
, int b
)
665 unsigned long long __shrdi3(unsigned long long a
, int b
)
670 long long __shldi3(long long a
, int b
)
675 float __ulltof(unsigned long long a
)
680 double __ulltod(unsigned long long a
)
685 long double __ulltold(unsigned long long a
)
687 return (long double)a
;
690 unsigned long long __ftoull(float a
)
692 return (unsigned long long)a
;
695 unsigned long long __dtoull(double a
)
697 return (unsigned long long)a
;
700 unsigned long long __ldtoull(long double a
)
702 return (unsigned long long)a
;
706 /********************************************************/
708 /* we use our own 'finite' function to avoid potential problems with
709 non standard math libs */
710 /* XXX: endianness dependant */
711 int ieee_finite(double d
)
714 return ((unsigned)((p
[1] | 0x800fffff) + 1)) >> 31;
717 /* copy a string and truncate it. */
718 char *pstrcpy(char *buf
, int buf_size
, const char *s
)
725 q_end
= buf
+ buf_size
- 1;
737 /* strcat and truncate. */
738 char *pstrcat(char *buf
, int buf_size
, const char *s
)
743 pstrcpy(buf
+ len
, buf_size
- len
, s
);
747 Section
*new_section(const char *name
, int sh_type
, int sh_flags
)
749 Section
*sec
, **psec
;
752 sec
= malloc(sizeof(Section
));
754 error("memory full");
755 memset(sec
, 0, sizeof(Section
));
756 pstrcpy(sec
->name
, sizeof(sec
->name
), name
);
758 sec
->sh_num
= ++section_num
;
759 sec
->sh_type
= sh_type
;
760 sec
->sh_flags
= sh_flags
;
762 /* XXX: currently, a single malloc */
763 data
= malloc(SECTION_VSIZE
);
765 error("could not alloc section '%s'", name
);
767 data
= mmap(NULL
, SECTION_VSIZE
,
768 PROT_EXEC
| PROT_READ
| PROT_WRITE
,
769 MAP_PRIVATE
| MAP_ANONYMOUS
,
771 if (data
== (void *)(-1))
772 error("could not mmap section '%s'", name
);
775 sec
->data_ptr
= data
;
776 psec
= &first_section
;
777 while (*psec
!= NULL
)
778 psec
= &(*psec
)->next
;
784 /* return a reference to a section, and create it if it does not
786 Section
*find_section(const char *name
)
790 for(sec
= first_section
; sec
!= NULL
; sec
= sec
->next
) {
791 if (!strcmp(name
, sec
->name
))
794 /* sections are created as PROGBITS */
795 return new_section(name
, SHT_PROGBITS
, SHF_ALLOC
);
798 /* add a new relocation entry to symbol 's' */
799 void greloc(Sym
*s
, int addr
, int type
)
802 p
= malloc(sizeof(Reloc
));
804 error("memory full");
807 p
->next
= (Reloc
*)s
->c
;
811 /* patch each relocation entry with value 'val' */
812 void greloc_patch(Sym
*s
, int val
)
819 greloc_patch1(p
, val
);
828 static inline int isid(int c
)
830 return (c
>= 'a' && c
<= 'z') ||
831 (c
>= 'A' && c
<= 'Z') ||
835 static inline int isnum(int c
)
837 return c
>= '0' && c
<= '9';
840 static inline int toup(int c
)
842 if (ch
>= 'a' && ch
<= 'z')
843 return ch
- 'a' + 'A';
852 for(f
= include_stack
; f
< include_stack_ptr
; f
++)
853 fprintf(stderr
, "In file included from %s:%d:\n",
854 (*f
)->filename
, (*f
)->line_num
);
855 fprintf(stderr
, "%s:%d: ", file
->filename
, file
->line_num
);
857 fprintf(stderr
, "tcc: ");
861 void error(const char *fmt
, ...)
866 vfprintf(stderr
, fmt
, ap
);
867 fprintf(stderr
, "\n");
872 void expect(const char *msg
)
874 error("%s expected", msg
);
877 void warning(const char *fmt
, ...)
883 fprintf(stderr
, "warning: ");
884 vfprintf(stderr
, fmt
, ap
);
885 fprintf(stderr
, "\n");
892 error("'%c' expected", c
);
896 void test_lvalue(void)
898 if (!(vtop
->r
& VT_LVAL
))
902 TokenSym
*tok_alloc(const char *str
, int len
)
904 TokenSym
*ts
, **pts
, **ptable
;
911 h
= (h
* 263 + ((unsigned char *)str
)[i
]) & (TOK_HASH_SIZE
- 1);
913 pts
= &hash_ident
[h
];
918 if (ts
->len
== len
&& !memcmp(ts
->str
, str
, len
))
920 pts
= &(ts
->hash_next
);
923 if (tok_ident
>= SYM_FIRST_ANOM
)
924 error("memory full");
926 /* expand token table if needed */
927 i
= tok_ident
- TOK_IDENT
;
928 if ((i
% TOK_ALLOC_INCR
) == 0) {
929 ptable
= realloc(table_ident
, (i
+ TOK_ALLOC_INCR
) * sizeof(TokenSym
*));
931 error("memory full");
932 table_ident
= ptable
;
935 ts
= malloc(sizeof(TokenSym
) + len
);
937 error("memory full");
939 ts
->tok
= tok_ident
++;
941 ts
->hash_next
= NULL
;
942 memcpy(ts
->str
, str
, len
+ 1);
947 void add_char(char **pp
, int c
)
951 if (c
== '\'' || c
== '\"' || c
== '\\') {
952 /* XXX: could be more precise if char or string */
955 if (c
>= 32 && c
<= 126) {
962 *p
++ = '0' + ((c
>> 6) & 7);
963 *p
++ = '0' + ((c
>> 3) & 7);
964 *p
++ = '0' + (c
& 7);
970 /* XXX: buffer overflow */
971 char *get_tok_str(int v
, CValue
*cv
)
973 static char buf
[STRING_MAX_SIZE
+ 1];
978 if (v
== TOK_CINT
|| v
== TOK_CUINT
) {
979 sprintf(buf
, "%u", cv
->ui
);
981 } else if (v
== TOK_CCHAR
|| v
== TOK_LCHAR
) {
988 } else if (v
== TOK_STR
|| v
== TOK_LSTR
) {
992 for(i
=0;i
<ts
->len
;i
++)
993 add_char(&p
, ts
->str
[i
]);
997 } else if (v
< TOK_IDENT
) {
1002 } else if (v
< tok_ident
) {
1003 return table_ident
[v
- TOK_IDENT
]->str
;
1005 /* should never happen */
1010 /* push, without hashing */
1011 Sym
*sym_push2(Sym
**ps
, int v
, int t
, int c
)
1014 s
= malloc(sizeof(Sym
));
1016 error("memory full");
1027 /* find a symbol and return its associated structure. 's' is the top
1028 of the symbol stack */
1029 Sym
*sym_find2(Sym
*s
, int v
)
1039 #define HASH_SYM(v) ((unsigned)(v) % SYM_HASH_SIZE)
1041 /* find a symbol and return its associated structure. 'st' is the
1043 Sym
*sym_find1(SymStack
*st
, int v
)
1047 s
= st
->hash
[HASH_SYM(v
)];
1056 Sym
*sym_push1(SymStack
*st
, int v
, int t
, int c
)
1059 s
= sym_push2(&st
->top
, v
, t
, c
);
1060 /* add in hash table */
1062 ps
= &st
->hash
[HASH_SYM(v
)];
1069 /* find a symbol in the right symbol space */
1070 Sym
*sym_find(int v
)
1073 s
= sym_find1(&local_stack
, v
);
1075 s
= sym_find1(&global_stack
, v
);
1079 /* push a given symbol on the symbol stack */
1080 Sym
*sym_push(int v
, int t
, int r
, int c
)
1083 if (local_stack
.top
)
1084 s
= sym_push1(&local_stack
, v
, t
, c
);
1086 s
= sym_push1(&global_stack
, v
, t
, c
);
1091 /* pop symbols until top reaches 'b' */
1092 void sym_pop(SymStack
*st
, Sym
*b
)
1099 /* free hash table entry, except if symbol was freed (only
1100 used for #undef symbols) */
1102 st
->hash
[HASH_SYM(s
->v
)] = s
->hash_next
;
1109 /* undefined a hashed symbol (used for #undef). Its name is set to
1111 void sym_undef(SymStack
*st
, Sym
*s
)
1114 ss
= &st
->hash
[HASH_SYM(s
->v
)];
1115 while (*ss
!= NULL
) {
1118 ss
= &(*ss
)->hash_next
;
1126 BufferedFile
*tcc_open(const char *filename
)
1131 fd
= open(filename
, O_RDONLY
);
1134 bf
= malloc(sizeof(BufferedFile
));
1140 bf
->buf_ptr
= bf
->buffer
;
1141 bf
->buf_end
= bf
->buffer
;
1142 bf
->buffer
[0] = CH_EOB
; /* put eob symbol */
1143 pstrcpy(bf
->filename
, sizeof(bf
->filename
), filename
);
1145 // printf("opening '%s'\n", filename);
1149 void tcc_close(BufferedFile
*bf
)
1151 total_lines
+= bf
->line_num
;
1156 /* read one char. MUST call tcc_fillbuf if CH_EOB is read */
1157 #define TCC_GETC(bf) (*(bf)->buf_ptr++)
1159 /* fill input buffer and return next char */
1160 int tcc_getc_slow(BufferedFile
*bf
)
1163 /* only tries to read if really end of buffer */
1164 if (bf
->buf_ptr
>= bf
->buf_end
) {
1166 len
= read(bf
->fd
, bf
->buffer
, IO_BUF_SIZE
);
1173 bf
->buf_ptr
= bf
->buffer
;
1174 bf
->buf_end
= bf
->buffer
+ len
;
1175 *bf
->buf_end
= CH_EOB
;
1177 if (bf
->buf_ptr
< bf
->buf_end
) {
1178 return *bf
->buf_ptr
++;
1180 bf
->buf_ptr
= bf
->buf_end
;
1185 /* no need to put that inline */
1186 void handle_eob(void)
1189 ch1
= tcc_getc_slow(file
);
1193 if (include_stack_ptr
== include_stack
)
1195 /* add end of include file debug info */
1197 put_stabd(N_EINCL
, 0, 0);
1199 /* pop include stack */
1201 include_stack_ptr
--;
1202 file
= *include_stack_ptr
;
1206 /* read next char from current input file */
1207 static inline void inp(void)
1209 ch1
= TCC_GETC(file
);
1210 /* end of buffer/file handling */
1215 // printf("ch1=%c 0x%x\n", ch1, ch1);
1218 /* input with '\\n' handling */
1219 static inline void minp(void)
1224 if (ch
== '\\' && ch1
== '\n') {
1228 //printf("ch=%c 0x%x\n", ch, ch);
1232 /* same as minp, but also skip comments */
1240 /* single line C++ comments */
1242 while (ch1
!= '\n' && ch1
!= -1)
1245 ch
= ' '; /* return space */
1246 } else if (ch1
== '*') {
1252 if (c
== '*' && ch1
== '/') {
1254 ch
= ' '; /* return space */
1266 void skip_spaces(void)
1268 while (ch
== ' ' || ch
== '\t')
1272 /* skip block of text until #else, #elif or #endif. skip also pairs of
1274 void preprocess_skip(void)
1279 while (ch
!= '\n') {
1290 (tok
== TOK_ELSE
|| tok
== TOK_ELIF
|| tok
== TOK_ENDIF
))
1292 if (tok
== TOK_IF
|| tok
== TOK_IFDEF
|| tok
== TOK_IFNDEF
)
1294 else if (tok
== TOK_ENDIF
)
1300 /* ParseState handling */
1302 /* XXX: currently, no include file info is stored. Thus, we cannot display
1303 accurate messages if the function or data definition spans multiple
1306 /* save current parse state in 's' */
1307 void save_parse_state(ParseState
*s
)
1309 s
->line_num
= file
->line_num
;
1310 s
->macro_ptr
= macro_ptr
;
1315 /* restore parse state from 's' */
1316 void restore_parse_state(ParseState
*s
)
1318 file
->line_num
= s
->line_num
;
1319 macro_ptr
= s
->macro_ptr
;
1324 /* return the number of additionnal 'ints' necessary to store the
1326 static inline int tok_ext_size(int t
)
1344 return LDOUBLE_SIZE
/ 4;
1350 /* token string handling */
1352 static inline void tok_str_new(TokenString
*s
)
1356 s
->last_line_num
= -1;
1359 static void tok_str_add(TokenString
*s
, int t
)
1365 if ((len
& 63) == 0) {
1366 str
= realloc(str
, (len
+ 64) * sizeof(int));
1375 static void tok_str_add2(TokenString
*s
, int t
, CValue
*cv
)
1379 n
= tok_ext_size(t
);
1381 tok_str_add(s
, cv
->tab
[i
]);
1384 /* add the current parse token in token string 's' */
1385 static void tok_str_add_tok(TokenString
*s
)
1389 /* save line number info */
1390 if (file
->line_num
!= s
->last_line_num
) {
1391 s
->last_line_num
= file
->line_num
;
1392 cval
.i
= s
->last_line_num
;
1393 tok_str_add2(s
, TOK_LINENUM
, &cval
);
1395 tok_str_add2(s
, tok
, &tokc
);
1398 /* get a token from an integer array and increment pointer accordingly */
1399 static int tok_get(int **tok_str
, CValue
*cv
)
1405 n
= tok_ext_size(t
);
1412 /* eval an expression for #if/#elif */
1413 int expr_preprocess(void)
1423 next(); /* do macro subst */
1424 if (tok
== TOK_DEFINED
) {
1429 c
= sym_find1(&define_stack
, tok
) != 0;
1434 } else if (tok
>= TOK_IDENT
) {
1435 /* if undefined macro */
1439 tok_str_add_tok(&str
);
1441 tok_str_add(&str
, -1); /* simulate end of file */
1442 tok_str_add(&str
, 0);
1443 /* now evaluate C constant expression */
1444 macro_ptr
= str
.str
;
1452 #if defined(DEBUG) || defined(PP_DEBUG)
1453 void tok_print(int *str
)
1459 t
= tok_get(&str
, &cval
);
1462 printf(" %s", get_tok_str(t
, &cval
));
1468 /* parse after #define */
1469 void parse_define(void)
1471 Sym
*s
, *first
, **ps
;
1472 int v
, t
, varg
, is_vaargs
;
1476 /* XXX: should check if same macro (ANSI) */
1479 /* '(' must be just after macro definition for MACRO_FUNC */
1484 while (tok
!= ')') {
1488 if (varg
== TOK_DOTS
) {
1489 varg
= TOK___VA_ARGS__
;
1491 } else if (tok
== TOK_DOTS
&& gnu_ext
) {
1495 if (varg
< TOK_IDENT
)
1496 error("badly punctuated parameter list");
1497 s
= sym_push1(&define_stack
, varg
| SYM_FIELD
, is_vaargs
, 0);
1509 if (ch
== '\n' || ch
== -1)
1512 tok_str_add2(&str
, tok
, &tokc
);
1514 tok_str_add(&str
, 0);
1516 printf("define %s %d: ", get_tok_str(v
, NULL
), t
);
1519 s
= sym_push1(&define_stack
, v
, t
, (int)str
.str
);
1523 void preprocess(void)
1526 char buf
[1024], *q
, *p
;
1534 if (tok
== TOK_DEFINE
) {
1537 } else if (tok
== TOK_UNDEF
) {
1539 s
= sym_find1(&define_stack
, tok
);
1540 /* undefine symbol by putting an invalid name */
1542 sym_undef(&define_stack
, s
);
1543 } else if (tok
== TOK_INCLUDE
) {
1548 } else if (ch
== '\"') {
1553 while (ch
!= c
&& ch
!= '\n' && ch
!= -1) {
1554 if ((q
- buf
) < sizeof(buf
) - 1)
1562 error("#include syntax error");
1563 pstrcpy(buf
, sizeof(buf
), get_tok_str(tok
, &tokc
));
1566 /* eat all spaces and comments after include */
1567 /* XXX: slightly incorrect */
1568 while (ch1
!= '\n' && ch1
!= -1)
1571 if (include_stack_ptr
>= include_stack
+ INCLUDE_STACK_SIZE
)
1572 error("memory full");
1574 /* first search in current dir if "header.h" */
1576 p
= strrchr(file
->filename
, '/');
1578 size
= p
+ 1 - file
->filename
;
1579 if (size
> sizeof(buf1
) - 1)
1580 size
= sizeof(buf1
) - 1;
1581 memcpy(buf1
, file
->filename
, size
);
1583 pstrcat(buf1
, sizeof(buf1
), buf
);
1588 /* now search in standard include path */
1589 for(i
=nb_include_paths
- 1;i
>=0;i
--) {
1590 strcpy(buf1
, include_paths
[i
]);
1597 error("include file '%s' not found", buf
);
1600 /* push current file in stack */
1601 /* XXX: fix current line init */
1602 *include_stack_ptr
++ = file
;
1604 /* add include file debug info */
1606 put_stabs(file
->filename
, N_BINCL
, 0, 0, 0);
1608 } else if (tok
== TOK_IFNDEF
) {
1611 } else if (tok
== TOK_IF
) {
1612 c
= expr_preprocess();
1614 } else if (tok
== TOK_IFDEF
) {
1618 c
= (sym_find1(&define_stack
, tok
) != 0) ^ c
;
1620 if (ifdef_stack_ptr
>= ifdef_stack
+ IFDEF_STACK_SIZE
)
1621 error("memory full");
1622 *ifdef_stack_ptr
++ = c
;
1624 } else if (tok
== TOK_ELSE
) {
1625 if (ifdef_stack_ptr
== ifdef_stack
)
1626 error("#else without matching #if");
1627 if (ifdef_stack_ptr
[-1] & 2)
1628 error("#else after #else");
1629 c
= (ifdef_stack_ptr
[-1] ^= 3);
1631 } else if (tok
== TOK_ELIF
) {
1632 if (ifdef_stack_ptr
== ifdef_stack
)
1633 error("#elif without matching #if");
1634 c
= ifdef_stack_ptr
[-1];
1636 error("#elif after #else");
1637 /* last #if/#elif expression was true: we skip */
1640 c
= expr_preprocess();
1641 ifdef_stack_ptr
[-1] = c
;
1648 } else if (tok
== TOK_ENDIF
) {
1649 if (ifdef_stack_ptr
== ifdef_stack
)
1650 error("#endif without matching #if");
1652 } else if (tok
== TOK_LINE
) {
1654 if (tok
!= TOK_CINT
)
1656 file
->line_num
= tokc
.i
;
1662 pstrcpy(file
->filename
, sizeof(file
->filename
),
1663 get_tok_str(tok
, &tokc
));
1665 } else if (tok
== TOK_ERROR
) {
1668 /* ignore other preprocess commands or #! for C scripts */
1669 while (ch
!= '\n' && ch
!= -1)
1673 /* read a number in base b */
1679 if (ch
>= 'a' && ch
<= 'f')
1681 else if (ch
>= 'A' && ch
<= 'F')
1687 if (t
< 0 || t
>= b
)
1695 /* read a character for string or char constant and eval escape codes */
1704 /* at most three octal digits */
1708 c
= c
* 8 + ch
- '0';
1711 c
= c
* 8 + ch
- '0';
1716 } else if (ch
== 'x') {
1734 else if (ch
== 'e' && gnu_ext
)
1736 else if (ch
== '\'' || ch
== '\"' || ch
== '\\' || ch
== '?')
1739 error("invalid escaped char");
1746 /* we use 64 bit numbers */
1749 /* bn = (bn << shift) | or_val */
1750 void bn_lshift(unsigned int *bn
, int shift
, int or_val
)
1754 for(i
=0;i
<BN_SIZE
;i
++) {
1756 bn
[i
] = (v
<< shift
) | or_val
;
1757 or_val
= v
>> (32 - shift
);
1761 void bn_zero(unsigned int *bn
)
1764 for(i
=0;i
<BN_SIZE
;i
++) {
1769 void parse_number(void)
1771 int b
, t
, shift
, frac_bits
, s
, exp_val
;
1773 unsigned int bn
[BN_SIZE
];
1783 /* special dot handling */
1784 if (ch
>= '0' && ch
<= '9') {
1785 goto float_frac_parse
;
1786 } else if (ch
== '.') {
1797 } else if (t
== '0') {
1798 if (ch
== 'x' || ch
== 'X') {
1802 } else if (tcc_ext
&& (ch
== 'b' || ch
== 'B')) {
1808 /* parse all digits. cannot check octal numbers at this stage
1809 because of floating point constants */
1811 if (ch
>= 'a' && ch
<= 'f')
1813 else if (ch
>= 'A' && ch
<= 'F')
1821 if (q
>= token_buf
+ STRING_MAX_SIZE
) {
1823 error("number too long");
1829 ((ch
== 'e' || ch
== 'E') && b
== 10) ||
1830 ((ch
== 'p' || ch
== 'P') && (b
== 16 || b
== 2))) {
1832 /* NOTE: strtox should support that for hexa numbers, but
1833 non ISOC99 libcs do not support it, so we prefer to do
1835 /* hexadecimal or binary floats */
1836 /* XXX: handle overflows */
1848 } else if (t
>= 'a') {
1850 } else if (t
>= 'A') {
1855 bn_lshift(bn
, shift
, t
);
1862 if (t
>= 'a' && t
<= 'f') {
1864 } else if (t
>= 'A' && t
<= 'F') {
1866 } else if (t
>= '0' && t
<= '9') {
1872 error("invalid digit");
1873 bn_lshift(bn
, shift
, t
);
1878 if (ch
!= 'p' && ch
!= 'P')
1879 error("exponent expected");
1885 } else if (ch
== '-') {
1889 if (ch
< '0' || ch
> '9')
1890 error("exponent digits expected");
1891 while (ch
>= '0' && ch
<= '9') {
1892 exp_val
= exp_val
* 10 + ch
- '0';
1895 exp_val
= exp_val
* s
;
1897 /* now we can generate the number */
1898 /* XXX: should patch directly float number */
1899 d
= (double)bn
[1] * 4294967296.0 + (double)bn
[0];
1900 d
= ldexp(d
, exp_val
- frac_bits
);
1905 /* float : should handle overflow */
1907 } else if (t
== 'L') {
1910 /* XXX: not large enough */
1911 tokc
.ld
= (long double)d
;
1917 /* decimal floats */
1919 if (q
>= token_buf
+ STRING_MAX_SIZE
)
1924 while (ch
>= '0' && ch
<= '9') {
1925 if (q
>= token_buf
+ STRING_MAX_SIZE
)
1931 if (ch
== 'e' || ch
== 'E') {
1932 if (q
>= token_buf
+ STRING_MAX_SIZE
)
1936 if (ch
== '-' || ch
== '+') {
1937 if (q
>= token_buf
+ STRING_MAX_SIZE
)
1942 if (ch
< '0' || ch
> '9')
1943 error("exponent digits expected");
1944 while (ch
>= '0' && ch
<= '9') {
1945 if (q
>= token_buf
+ STRING_MAX_SIZE
)
1957 tokc
.f
= strtof(token_buf
, NULL
);
1958 } else if (t
== 'L') {
1961 tokc
.ld
= strtold(token_buf
, NULL
);
1964 tokc
.d
= strtod(token_buf
, NULL
);
1968 unsigned long long n
, n1
;
1971 /* integer number */
1974 if (b
== 10 && *q
== '0') {
1981 /* no need for checks except for base 10 / 8 errors */
1984 } else if (t
>= 'a') {
1986 } else if (t
>= 'A') {
1991 error("invalid digit");
1995 /* detect overflow */
1997 error("integer constant overflow");
2000 /* XXX: not exactly ANSI compliant */
2001 if ((n
& 0xffffffff00000000LL
) != 0) {
2006 } else if (n
> 0x7fffffff) {
2016 error("three 'l' in integer constant");
2019 if (tok
== TOK_CINT
)
2021 else if (tok
== TOK_CUINT
)
2025 } else if (t
== 'U') {
2026 if (tok
== TOK_CINT
)
2028 else if (tok
== TOK_CLLONG
)
2035 if (tok
== TOK_CINT
|| tok
== TOK_CUINT
)
2043 /* return next token without macro substitution */
2044 void next_nomacro1(void)
2052 while (ch
== '\n') {
2054 while (ch
== ' ' || ch
== '\t')
2057 /* preprocessor command if # at start of line after
2062 if (ch
!= ' ' && ch
!= '\t' && ch
!= '\f')
2080 while (isid(ch
) || isnum(ch
)) {
2081 if (q
>= token_buf
+ STRING_MAX_SIZE
)
2082 error("ident too long");
2087 ts
= tok_alloc(token_buf
, q
- token_buf
);
2089 } else if (isnum(ch
) || ch
== '.') {
2091 } else if (ch
== '\'') {
2099 } else if (ch
== '\"') {
2104 while (ch
!= '\"') {
2107 error("unterminated string");
2108 if (q
>= token_buf
+ STRING_MAX_SIZE
)
2109 error("string too long");
2113 tokc
.ts
= tok_alloc(token_buf
, q
- token_buf
);
2116 q
= "<=\236>=\235!=\225&&\240||\241++\244--\242==\224<<\1>>\2+=\253-=\255*=\252/=\257%=\245&=\246^=\336|=\374->\313..\250##\266";
2121 if (*q
== tok
&& q
[1] == ch
) {
2124 /* three chars tests */
2125 if (tok
== TOK_SHL
|| tok
== TOK_SAR
) {
2130 } else if (tok
== TOK_DOTS
) {
2132 error("parse error");
2139 /* single char substitutions */
2142 else if (tok
== '>')
2147 /* return next token without macro substitution. Can read input from
2155 tok
= tok_get(¯o_ptr
, &tokc
);
2156 if (tok
== TOK_LINENUM
) {
2157 file
->line_num
= tokc
.i
;
2166 /* substitute args in macro_str and return allocated string */
2167 int *macro_arg_subst(Sym
**nested_list
, int *macro_str
, Sym
*args
)
2169 int *st
, last_tok
, t
, notfirst
;
2178 t
= tok_get(¯o_str
, &cval
);
2183 t
= tok_get(¯o_str
, &cval
);
2186 s
= sym_find2(args
, t
);
2188 token_buf
[0] = '\0';
2193 pstrcat(token_buf
, sizeof(token_buf
), " ");
2194 t
= tok_get(&st
, &cval
);
2195 pstrcat(token_buf
, sizeof(token_buf
), get_tok_str(t
, &cval
));
2199 printf("stringize: %s\n", token_buf
);
2202 ts
= tok_alloc(token_buf
, 0);
2204 tok_str_add2(&str
, TOK_STR
, &cval
);
2206 tok_str_add2(&str
, t
, &cval
);
2208 } else if (t
>= TOK_IDENT
) {
2209 s
= sym_find2(args
, t
);
2212 /* if '##' is present before or after, no arg substitution */
2213 if (*macro_str
== TOK_TWOSHARPS
|| last_tok
== TOK_TWOSHARPS
) {
2214 /* special case for var arg macros : ## eats the
2215 ',' if empty VA_ARGS riable. */
2216 /* XXX: test of the ',' is not 100%
2217 reliable. should fix it to avoid security
2219 if (gnu_ext
&& s
->t
&& *st
== 0 &&
2220 last_tok
== TOK_TWOSHARPS
&&
2221 str
.len
>= 2&& str
.str
[str
.len
- 2] == ',') {
2222 /* suppress ',' '##' */
2226 tok_str_add(&str
, *st
++);
2229 macro_subst(&str
, nested_list
, st
);
2232 tok_str_add(&str
, t
);
2235 tok_str_add2(&str
, t
, &cval
);
2239 tok_str_add(&str
, 0);
2243 /* handle the '##' operator */
2244 int *macro_twosharps(int *macro_str
)
2251 TokenString macro_str1
;
2253 tok_str_new(¯o_str1
);
2259 while (*macro_ptr
== TOK_TWOSHARPS
) {
2261 macro_ptr1
= macro_ptr
;
2264 t
= tok_get(¯o_ptr
, &cval
);
2265 /* XXX: we handle only most common cases:
2266 ident + ident or ident + number */
2267 if (tok
>= TOK_IDENT
&&
2268 (t
>= TOK_IDENT
|| t
== TOK_CINT
)) {
2269 p
= get_tok_str(tok
, &tokc
);
2270 pstrcpy(token_buf
, sizeof(token_buf
), p
);
2271 p
= get_tok_str(t
, &cval
);
2272 pstrcat(token_buf
, sizeof(token_buf
), p
);
2273 ts
= tok_alloc(token_buf
, 0);
2274 tok
= ts
->tok
; /* modify current token */
2276 /* cannot merge tokens: skip '##' */
2277 macro_ptr
= macro_ptr1
;
2282 tok_str_add2(¯o_str1
, tok
, &tokc
);
2284 tok_str_add(¯o_str1
, 0);
2285 return macro_str1
.str
;
2288 /* do macro substitution of macro_str and add result to
2289 (tok_str,tok_len). If macro_str is NULL, then input stream token is
2290 substituted. 'nested_list' is the list of all macros we got inside
2291 to avoid recursing. */
2292 void macro_subst(TokenString
*tok_str
,
2293 Sym
**nested_list
, int *macro_str
)
2295 Sym
*s
, *args
, *sa
, *sa1
;
2296 int parlevel
, *mstr
, t
, *saved_macro_ptr
;
2297 int mstr_allocated
, *macro_str1
;
2301 saved_macro_ptr
= macro_ptr
;
2302 macro_ptr
= macro_str
;
2305 /* first scan for '##' operator handling */
2306 macro_str1
= macro_twosharps(macro_str
);
2307 macro_ptr
= macro_str1
;
2314 /* special macros */
2315 if (tok
== TOK___LINE__
) {
2316 cval
.i
= file
->line_num
;
2317 tok_str_add2(tok_str
, TOK_CINT
, &cval
);
2318 } else if (tok
== TOK___FILE__
) {
2319 cval
.ts
= tok_alloc(file
->filename
, 0);
2320 tok_str_add2(tok_str
, TOK_STR
, &cval
);
2321 } else if (tok
== TOK___DATE__
) {
2322 cval
.ts
= tok_alloc("Jan 1 1970", 0);
2323 tok_str_add2(tok_str
, TOK_STR
, &cval
);
2324 } else if (tok
== TOK___TIME__
) {
2325 cval
.ts
= tok_alloc("00:00:00", 0);
2326 tok_str_add2(tok_str
, TOK_STR
, &cval
);
2327 } else if ((s
= sym_find1(&define_stack
, tok
)) != NULL
) {
2328 /* if symbol is a macro, prepare substitution */
2329 /* if nested substitution, do nothing */
2330 if (sym_find2(*nested_list
, tok
))
2334 if (s
->t
== MACRO_FUNC
) {
2335 /* NOTE: we do not use next_nomacro to avoid eating the
2336 next token. XXX: find better solution */
2340 while (ch
== ' ' || ch
== '\t' || ch
== '\n')
2344 if (t
!= '(') /* no macro subst */
2347 /* argument macro */
2352 /* NOTE: empty args are allowed, except if no args */
2354 /* handle '()' case */
2355 if (!args
&& tok
== ')')
2358 error("macro '%s' used with too many args",
2359 get_tok_str(s
->v
, 0));
2362 /* NOTE: non zero sa->t indicates VA_ARGS */
2363 while ((parlevel
> 0 ||
2365 (tok
!= ',' || sa
->t
))) &&
2369 else if (tok
== ')')
2371 tok_str_add2(&str
, tok
, &tokc
);
2374 tok_str_add(&str
, 0);
2375 sym_push2(&args
, sa
->v
& ~SYM_FIELD
, sa
->t
, (int)str
.str
);
2378 /* special case for gcc var args: add an empty
2379 var arg argument if it is omitted */
2380 if (sa
&& sa
->t
&& gnu_ext
)
2390 error("macro '%s' used with too few args",
2391 get_tok_str(s
->v
, 0));
2394 /* now subst each arg */
2395 mstr
= macro_arg_subst(nested_list
, mstr
, args
);
2406 sym_push2(nested_list
, s
->v
, 0, 0);
2407 macro_subst(tok_str
, nested_list
, mstr
);
2408 /* pop nested defined symbol */
2410 *nested_list
= sa1
->prev
;
2416 /* no need to add if reading input stream */
2419 tok_str_add2(tok_str
, tok
, &tokc
);
2421 /* only replace one macro while parsing input stream */
2425 macro_ptr
= saved_macro_ptr
;
2430 /* return next token with macro substitution */
2436 /* special 'ungettok' case for label parsing */
2444 /* if not reading from macro substituted string, then try
2446 /* XXX: optimize non macro case */
2449 macro_subst(&str
, &nested_list
, NULL
);
2451 tok_str_add(&str
, 0);
2452 macro_ptr
= str
.str
;
2453 macro_ptr_allocated
= str
.str
;
2461 /* end of macro string: free it */
2462 free(macro_ptr_allocated
);
2469 printf("token = %s\n", get_tok_str(tok
, tokc
));
2473 void swap(int *p
, int *q
)
2481 void vsetc(int t
, int r
, CValue
*vc
)
2483 if (vtop
>= vstack
+ VSTACK_SIZE
)
2484 error("memory full");
2485 /* cannot let cpu flags if other instruction are generated */
2486 /* XXX: VT_JMP test too ? */
2487 if ((vtop
->r
& VT_VALMASK
) == VT_CMP
)
2492 vtop
->r2
= VT_CONST
;
2496 /* push integer constant */
2501 vsetc(VT_INT
, VT_CONST
, &cval
);
2504 void vset(int t
, int r
, int v
)
2521 void vpushv(SValue
*v
)
2523 if (vtop
>= vstack
+ VSTACK_SIZE
)
2524 error("memory full");
2534 /* save r to the memory stack, and mark it as being free */
2535 void save_reg(int r
)
2537 int l
, i
, saved
, t
, size
, align
;
2540 /* modify all stack values */
2543 for(p
=vstack
;p
<=vtop
;p
++) {
2544 i
= p
->r
& VT_VALMASK
;
2545 if ((p
->r
& VT_VALMASK
) == r
||
2546 (p
->r2
& VT_VALMASK
) == r
) {
2547 /* must save value on stack if not already done */
2549 /* store register in the stack */
2551 if ((p
->r
& VT_LVAL
) ||
2552 (!is_float(t
) && (t
& VT_BTYPE
) != VT_LLONG
))
2554 size
= type_size(t
, &align
);
2555 loc
= (loc
- size
) & -align
;
2557 sv
.r
= VT_LOCAL
| VT_LVAL
;
2560 #ifdef TCC_TARGET_I386
2561 /* x86 specific: need to pop fp register ST0 if saved */
2563 o(0xd9dd); /* fstp %st(1) */
2566 /* special long long case */
2567 if ((t
& VT_BTYPE
) == VT_LLONG
) {
2574 /* mark that stack entry as being saved on the stack */
2586 /* find a free register of class 'rc'. If none, save one register */
2592 /* find a free register */
2593 for(r
=0;r
<NB_REGS
;r
++) {
2594 if (reg_classes
[r
] & rc
) {
2595 for(p
=vstack
;p
<=vtop
;p
++) {
2596 if ((p
->r
& VT_VALMASK
) == r
||
2597 (p
->r2
& VT_VALMASK
) == r
)
2605 /* no register left : free the first one on the stack (VERY
2606 IMPORTANT to start from the bottom to ensure that we don't
2607 spill registers used in gen_opi()) */
2608 for(p
=vstack
;p
<=vtop
;p
++) {
2609 r
= p
->r
& VT_VALMASK
;
2610 if (r
< VT_CONST
&& (reg_classes
[r
] & rc
)) {
2618 /* save registers up to (vtop - n) stack entry */
2619 void save_regs(int n
)
2624 for(p
= vstack
;p
<= p1
; p
++) {
2625 r
= p
->r
& VT_VALMASK
;
2632 /* move register 's' to 'r', and flush previous value of r to memory
2634 void move_reg(int r
, int s
)
2647 /* get address of vtop (vtop MUST BE an lvalue) */
2650 vtop
->r
&= ~VT_LVAL
;
2651 /* tricky: if saved lvalue, then we can go back to lvalue */
2652 if ((vtop
->r
& VT_VALMASK
) == VT_LLOCAL
)
2653 vtop
->r
= (vtop
->r
& ~VT_VALMASK
) | VT_LOCAL
| VT_LVAL
;
2656 #ifdef CONFIG_TCC_BCHECK
2657 /* generate lvalue bound code */
2662 vtop
->r
&= ~VT_MUSTBOUND
;
2663 /* if lvalue, then use checking code before dereferencing */
2664 if (vtop
->r
& VT_LVAL
) {
2665 /* if not VT_BOUNDED value, then make one */
2666 if (!(vtop
->r
& VT_BOUNDED
)) {
2667 lval_type
= vtop
->r
& (VT_LVAL_TYPE
| VT_LVAL
);
2670 gen_bounded_ptr_add();
2671 vtop
->r
|= lval_type
;
2673 /* then check for dereferencing */
2674 gen_bounded_ptr_deref();
2679 /* store vtop a register belonging to class 'rc'. lvalues are
2680 converted to values. Cannot be used if cannot be converted to
2681 register value (such as structures). */
2684 int r
, r2
, rc2
, bit_pos
, bit_size
, size
, align
, i
, data_offset
;
2685 unsigned long long ll
;
2687 /* NOTE: get_reg can modify vstack[] */
2688 if (vtop
->t
& VT_BITFIELD
) {
2689 bit_pos
= (vtop
->t
>> VT_STRUCT_SHIFT
) & 0x3f;
2690 bit_size
= (vtop
->t
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f;
2691 /* remove bit field info to avoid loops */
2692 vtop
->t
&= ~(VT_BITFIELD
| (-1 << VT_STRUCT_SHIFT
));
2693 /* generate shifts */
2694 vpushi(32 - (bit_pos
+ bit_size
));
2696 vpushi(32 - bit_size
);
2697 /* NOTE: transformed to SHR if unsigned */
2701 if (is_float(vtop
->t
) &&
2702 (vtop
->r
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
) {
2703 /* CPUs usually cannot use float constants, so we store them
2704 generically in data segment */
2705 size
= type_size(vtop
->t
, &align
);
2706 data_offset
= (int)data_section
->data_ptr
;
2707 data_offset
= (data_offset
+ align
- 1) & -align
;
2708 /* XXX: not portable yet */
2711 ((int *)data_offset
)[i
] = vtop
->c
.tab
[i
];
2713 vtop
->c
.ul
= data_offset
;
2714 data_offset
+= size
<< 2;
2715 data_section
->data_ptr
= (unsigned char *)data_offset
;
2717 #ifdef CONFIG_TCC_BCHECK
2718 if (vtop
->r
& VT_MUSTBOUND
)
2722 r
= vtop
->r
& VT_VALMASK
;
2723 /* need to reload if:
2725 - lvalue (need to dereference pointer)
2726 - already a register, but not in the right class */
2727 if (r
>= VT_CONST
||
2728 (vtop
->r
& VT_LVAL
) ||
2729 !(reg_classes
[r
] & rc
) ||
2730 ((vtop
->t
& VT_BTYPE
) == VT_LLONG
&&
2731 !(reg_classes
[vtop
->r2
] & rc
))) {
2733 if ((vtop
->t
& VT_BTYPE
) == VT_LLONG
) {
2734 /* two register type load : expand to two words
2736 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
) {
2739 vtop
->c
.ui
= ll
; /* first word */
2741 vtop
->r
= r
; /* save register value */
2742 vpushi(ll
>> 32); /* second word */
2743 } else if (r
>= VT_CONST
||
2744 (vtop
->r
& VT_LVAL
)) {
2745 /* load from memory */
2748 vtop
[-1].r
= r
; /* save register value */
2749 /* increment pointer to get second word */
2756 /* move registers */
2759 vtop
[-1].r
= r
; /* save register value */
2760 vtop
->r
= vtop
[-1].r2
;
2762 /* allocate second register */
2769 /* write second register */
2771 } else if ((vtop
->r
& VT_LVAL
) && !is_float(vtop
->t
)) {
2773 /* lvalue of scalar type : need to use lvalue type
2774 because of possible cast */
2777 /* compute memory access type */
2778 if (vtop
->r
& VT_LVAL_BYTE
)
2780 else if (vtop
->r
& VT_LVAL_SHORT
)
2782 if (vtop
->r
& VT_LVAL_UNSIGNED
)
2786 /* restore wanted type */
2789 /* one register type load */
2798 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
2799 void gv2(int rc1
, int rc2
)
2801 /* generate more generic register first */
2807 /* test if reload is needed for first register */
2808 if ((vtop
[-1].r
& VT_VALMASK
) >= VT_CONST
) {
2818 /* test if reload is needed for first register */
2819 if ((vtop
[0].r
& VT_VALMASK
) >= VT_CONST
) {
2825 /* expand long long on stack in two int registers */
2830 u
= vtop
->t
& VT_UNSIGNED
;
2833 vtop
[0].r
= vtop
[-1].r2
;
2834 vtop
[0].r2
= VT_CONST
;
2835 vtop
[-1].r2
= VT_CONST
;
2836 vtop
[0].t
= VT_INT
| u
;
2837 vtop
[-1].t
= VT_INT
| u
;
2840 /* build a long long from two ints */
2843 gv2(RC_INT
, RC_INT
);
2844 vtop
[-1].r2
= vtop
[0].r
;
2849 /* rotate n first stack elements to the bottom */
2856 for(i
=-n
+1;i
!=0;i
++)
2857 vtop
[i
] = vtop
[i
+1];
2861 /* pop stack value */
2865 v
= vtop
->r
& VT_VALMASK
;
2866 #ifdef TCC_TARGET_I386
2867 /* for x86, we need to pop the FP stack */
2869 o(0xd9dd); /* fstp %st(1) */
2872 if (v
== VT_JMP
|| v
== VT_JMPI
) {
2873 /* need to put correct jump if && or || without test */
2879 /* convert stack entry to register and duplicate its value in another
2887 if ((t
& VT_BTYPE
) == VT_LLONG
) {
2894 /* stack: H L L1 H1 */
2902 /* duplicate value */
2913 load(r1
, &sv
); /* move r to r1 */
2915 /* duplicates value */
2920 /* generate CPU independent (unsigned) long long operations */
2921 void gen_opl(int op
)
2923 int t
, a
, b
, op1
, c
, i
;
2942 /* call generic long long function */
2943 gfunc_start(&gf
, FUNC_CDECL
);
2950 vtop
->r2
= REG_LRET
;
2963 /* stack: L1 H1 L2 H2 */
2968 vtop
[-2] = vtop
[-3];
2971 /* stack: H1 H2 L1 L2 */
2977 /* stack: H1 H2 L1 L2 ML MH */
2980 /* stack: ML MH H1 H2 L1 L2 */
2984 /* stack: ML MH H1 L2 H2 L1 */
2989 /* stack: ML MH M1 M2 */
2992 } else if (op
== '+' || op
== '-') {
2993 /* XXX: add non carry method too (for MIPS or alpha) */
2999 /* stack: H1 H2 (L1 op L2) */
3002 gen_op(op1
+ 1); /* TOK_xxxC2 */
3005 /* stack: H1 H2 (L1 op L2) */
3008 /* stack: (L1 op L2) H1 H2 */
3010 /* stack: (L1 op L2) (H1 op H2) */
3018 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_FORWARD
)) == VT_CONST
) {
3023 /* stack: L H shift */
3025 /* constant: simpler */
3026 /* NOTE: all comments are for SHL. the other cases are
3027 done by swaping words */
3038 if (op
!= TOK_SAR
) {
3068 /* XXX: should provide a faster fallback on x86 ? */
3083 /* compare operations */
3089 /* stack: L1 H1 L2 H2 */
3091 vtop
[-1] = vtop
[-2];
3093 /* stack: L1 L2 H1 H2 */
3096 /* when values are equal, we need to compare low words. since
3097 the jump is inverted, we invert the test too. */
3100 else if (op1
== TOK_GT
)
3102 else if (op1
== TOK_ULT
)
3104 else if (op1
== TOK_UGT
)
3109 if (op1
!= TOK_NE
) {
3113 /* generate non equal test */
3114 /* XXX: NOT PORTABLE yet */
3118 #ifdef TCC_TARGET_I386
3119 b
= psym(0x850f, 0);
3121 error("not implemented");
3129 vset(VT_INT
, VT_JMPI
, a
);
3134 /* handle integer constant optimizations and various machine
3136 void gen_opic(int op
)
3143 /* currently, we cannot do computations with forward symbols */
3144 c1
= (v1
->r
& (VT_VALMASK
| VT_LVAL
| VT_FORWARD
)) == VT_CONST
;
3145 c2
= (v2
->r
& (VT_VALMASK
| VT_LVAL
| VT_FORWARD
)) == VT_CONST
;
3149 case '+': v1
->c
.i
+= fc
; break;
3150 case '-': v1
->c
.i
-= fc
; break;
3151 case '&': v1
->c
.i
&= fc
; break;
3152 case '^': v1
->c
.i
^= fc
; break;
3153 case '|': v1
->c
.i
|= fc
; break;
3154 case '*': v1
->c
.i
*= fc
; break;
3161 /* if division by zero, generate explicit division */
3164 error("division by zero in constant");
3168 default: v1
->c
.i
/= fc
; break;
3169 case '%': v1
->c
.i
%= fc
; break;
3170 case TOK_UDIV
: v1
->c
.i
= (unsigned)v1
->c
.i
/ fc
; break;
3171 case TOK_UMOD
: v1
->c
.i
= (unsigned)v1
->c
.i
% fc
; break;
3174 case TOK_SHL
: v1
->c
.i
<<= fc
; break;
3175 case TOK_SHR
: v1
->c
.i
= (unsigned)v1
->c
.i
>> fc
; break;
3176 case TOK_SAR
: v1
->c
.i
>>= fc
; break;
3178 case TOK_ULT
: v1
->c
.i
= (unsigned)v1
->c
.i
< (unsigned)fc
; break;
3179 case TOK_UGE
: v1
->c
.i
= (unsigned)v1
->c
.i
>= (unsigned)fc
; break;
3180 case TOK_EQ
: v1
->c
.i
= v1
->c
.i
== fc
; break;
3181 case TOK_NE
: v1
->c
.i
= v1
->c
.i
!= fc
; break;
3182 case TOK_ULE
: v1
->c
.i
= (unsigned)v1
->c
.i
<= (unsigned)fc
; break;
3183 case TOK_UGT
: v1
->c
.i
= (unsigned)v1
->c
.i
> (unsigned)fc
; break;
3184 case TOK_LT
: v1
->c
.i
= v1
->c
.i
< fc
; break;
3185 case TOK_GE
: v1
->c
.i
= v1
->c
.i
>= fc
; break;
3186 case TOK_LE
: v1
->c
.i
= v1
->c
.i
<= fc
; break;
3187 case TOK_GT
: v1
->c
.i
= v1
->c
.i
> fc
; break;
3189 case TOK_LAND
: v1
->c
.i
= v1
->c
.i
&& fc
; break;
3190 case TOK_LOR
: v1
->c
.i
= v1
->c
.i
|| fc
; break;
3196 /* if commutative ops, put c2 as constant */
3197 if (c1
&& (op
== '+' || op
== '&' || op
== '^' ||
3198 op
== '|' || op
== '*')) {
3203 if (c2
&& (((op
== '*' || op
== '/' || op
== TOK_UDIV
||
3206 ((op
== '+' || op
== '-' || op
== '|' || op
== '^' ||
3207 op
== TOK_SHL
|| op
== TOK_SHR
|| op
== TOK_SAR
) &&
3213 } else if (c2
&& (op
== '*' || op
== TOK_PDIV
|| op
== TOK_UDIV
)) {
3214 /* try to use shifts instead of muls or divs */
3215 if (fc
> 0 && (fc
& (fc
- 1)) == 0) {
3224 else if (op
== TOK_PDIV
)
3232 /* call low level op generator */
3238 /* generate a floating point operation with constant propagation */
3239 void gen_opif(int op
)
3247 /* currently, we cannot do computations with forward symbols */
3248 c1
= (v1
->r
& (VT_VALMASK
| VT_LVAL
| VT_FORWARD
)) == VT_CONST
;
3249 c2
= (v2
->r
& (VT_VALMASK
| VT_LVAL
| VT_FORWARD
)) == VT_CONST
;
3251 if (v1
->t
== VT_FLOAT
) {
3254 } else if (v1
->t
== VT_DOUBLE
) {
3262 /* NOTE: we only do constant propagation if finite number (not
3263 NaN or infinity) (ANSI spec) */
3264 if (!ieee_finite(f1
) || !ieee_finite(f2
))
3268 case '+': f1
+= f2
; break;
3269 case '-': f1
-= f2
; break;
3270 case '*': f1
*= f2
; break;
3274 error("division by zero in constant");
3279 /* XXX: also handles tests ? */
3283 /* XXX: overflow test ? */
3284 if (v1
->t
== VT_FLOAT
) {
3286 } else if (v1
->t
== VT_DOUBLE
) {
3299 int pointed_size(int t
)
3301 return type_size(pointed_type(t
), &t
);
3305 void check_pointer_types(SValue
*p1
, SValue
*p2
)
3307 char buf1
[256], buf2
[256];
3311 if (!is_compatible_types(t1
, t2
)) {
3312 type_to_str(buf1
, sizeof(buf1
), t1
, NULL
);
3313 type_to_str(buf2
, sizeof(buf2
), t2
, NULL
);
3314 error("incompatible pointers '%s' and '%s'", buf1
, buf2
);
3319 /* generic gen_op: handles types problems */
3322 int u
, t1
, t2
, bt1
, bt2
, t
;
3326 bt1
= t1
& VT_BTYPE
;
3327 bt2
= t2
& VT_BTYPE
;
3329 if (bt1
== VT_PTR
|| bt2
== VT_PTR
) {
3330 /* at least one operand is a pointer */
3331 /* relationnal op: must be both pointers */
3332 if (op
>= TOK_ULT
&& op
<= TOK_GT
) {
3333 // check_pointer_types(vtop, vtop - 1);
3334 /* pointers are handled are unsigned */
3335 t
= VT_INT
| VT_UNSIGNED
;
3338 /* if both pointers, then it must be the '-' op */
3339 if ((t1
& VT_BTYPE
) == VT_PTR
&&
3340 (t2
& VT_BTYPE
) == VT_PTR
) {
3342 error("cannot use pointers here");
3343 // check_pointer_types(vtop - 1, vtop);
3344 /* XXX: check that types are compatible */
3345 u
= pointed_size(t1
);
3347 /* set to integer type */
3352 /* exactly one pointer : must be '+' or '-'. */
3353 if (op
!= '-' && op
!= '+')
3354 error("cannot use pointers here");
3355 /* Put pointer as first operand */
3356 if ((t2
& VT_BTYPE
) == VT_PTR
) {
3360 /* XXX: cast to int ? (long long case) */
3361 vpushi(pointed_size(vtop
[-1].t
));
3363 #ifdef CONFIG_TCC_BCHECK
3364 /* if evaluating constant expression, no code should be
3365 generated, so no bound check */
3366 if (do_bounds_check
&& !const_wanted
) {
3367 /* if bounded pointers, we generate a special code to
3374 gen_bounded_ptr_add();
3380 /* put again type if gen_opic() swaped operands */
3383 } else if (is_float(bt1
) || is_float(bt2
)) {
3384 /* compute bigger type and do implicit casts */
3385 if (bt1
== VT_LDOUBLE
|| bt2
== VT_LDOUBLE
) {
3387 } else if (bt1
== VT_DOUBLE
|| bt2
== VT_DOUBLE
) {
3392 /* floats can only be used for a few operations */
3393 if (op
!= '+' && op
!= '-' && op
!= '*' && op
!= '/' &&
3394 (op
< TOK_ULT
|| op
> TOK_GT
))
3395 error("invalid operands for binary operation");
3397 } else if (bt1
== VT_LLONG
|| bt2
== VT_LLONG
) {
3398 /* cast to biggest op */
3400 /* convert to unsigned if it does not fit in a long long */
3401 if ((t1
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_LLONG
| VT_UNSIGNED
) ||
3402 (t2
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_LLONG
| VT_UNSIGNED
))
3406 /* integer operations */
3408 /* convert to unsigned if it does not fit in an integer */
3409 if ((t1
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
) ||
3410 (t2
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
))
3413 /* XXX: currently, some unsigned operations are explicit, so
3414 we modify them here */
3415 if (t
& VT_UNSIGNED
) {
3422 else if (op
== TOK_LT
)
3424 else if (op
== TOK_GT
)
3426 else if (op
== TOK_LE
)
3428 else if (op
== TOK_GE
)
3434 /* special case for shifts and long long: we keep the shift as
3436 if (op
== TOK_SHR
|| op
== TOK_SAR
|| op
== TOK_SHL
)
3442 else if ((t
& VT_BTYPE
) == VT_LLONG
)
3446 if (op
>= TOK_ULT
&& op
<= TOK_GT
) {
3447 /* relationnal op: the result is an int */
3455 /* generic itof for unsigned long long case */
3456 void gen_cvt_itof1(int t
)
3460 if ((vtop
->t
& (VT_BTYPE
| VT_UNSIGNED
)) ==
3461 (VT_LLONG
| VT_UNSIGNED
)) {
3463 gfunc_start(&gf
, FUNC_CDECL
);
3466 vpushi((int)&__ulltof
);
3467 else if (t
== VT_DOUBLE
)
3468 vpushi((int)&__ulltod
);
3470 vpushi((int)&__ulltold
);
3479 /* generic ftoi for unsigned long long case */
3480 void gen_cvt_ftoi1(int t
)
3485 if (t
== (VT_LLONG
| VT_UNSIGNED
)) {
3486 /* not handled natively */
3487 gfunc_start(&gf
, FUNC_CDECL
);
3488 st
= vtop
->t
& VT_BTYPE
;
3491 vpushi((int)&__ftoull
);
3492 else if (st
== VT_DOUBLE
)
3493 vpushi((int)&__dtoull
);
3495 vpushi((int)&__ldtoull
);
3499 vtop
->r2
= REG_LRET
;
3505 /* force char or short cast */
3506 void force_charshort_cast(int t
)
3510 /* XXX: add optimization if lvalue : just change type and offset */
3515 if (t
& VT_UNSIGNED
) {
3516 vpushi((1 << bits
) - 1);
3527 /* cast 'vtop' to 't' type */
3528 void gen_cast(int t
)
3530 int sbt
, dbt
, sf
, df
, c
;
3532 /* special delayed cast for char/short */
3533 /* XXX: in some cases (multiple cascaded casts), it may still
3535 if (vtop
->r
& VT_MUSTCAST
) {
3536 vtop
->r
&= ~VT_MUSTCAST
;
3537 force_charshort_cast(vtop
->t
);
3540 dbt
= t
& (VT_BTYPE
| VT_UNSIGNED
);
3541 sbt
= vtop
->t
& (VT_BTYPE
| VT_UNSIGNED
);
3546 c
= (vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_FORWARD
)) == VT_CONST
;
3548 /* convert from fp to fp */
3550 /* constant case: we can do it now */
3551 /* XXX: in ISOC, cannot do it if error in convert */
3552 if (dbt
== VT_FLOAT
&& sbt
== VT_DOUBLE
)
3553 vtop
->c
.f
= (float)vtop
->c
.d
;
3554 else if (dbt
== VT_FLOAT
&& sbt
== VT_LDOUBLE
)
3555 vtop
->c
.f
= (float)vtop
->c
.ld
;
3556 else if (dbt
== VT_DOUBLE
&& sbt
== VT_FLOAT
)
3557 vtop
->c
.d
= (double)vtop
->c
.f
;
3558 else if (dbt
== VT_DOUBLE
&& sbt
== VT_LDOUBLE
)
3559 vtop
->c
.d
= (double)vtop
->c
.ld
;
3560 else if (dbt
== VT_LDOUBLE
&& sbt
== VT_FLOAT
)
3561 vtop
->c
.ld
= (long double)vtop
->c
.f
;
3562 else if (dbt
== VT_LDOUBLE
&& sbt
== VT_DOUBLE
)
3563 vtop
->c
.ld
= (long double)vtop
->c
.d
;
3565 /* non constant case: generate code */
3569 /* convert int to fp */
3572 case VT_LLONG
| VT_UNSIGNED
:
3574 /* XXX: add const cases for long long */
3576 case VT_INT
| VT_UNSIGNED
:
3578 case VT_FLOAT
: vtop
->c
.f
= (float)vtop
->c
.ui
; break;
3579 case VT_DOUBLE
: vtop
->c
.d
= (double)vtop
->c
.ui
; break;
3580 case VT_LDOUBLE
: vtop
->c
.ld
= (long double)vtop
->c
.ui
; break;
3585 case VT_FLOAT
: vtop
->c
.f
= (float)vtop
->c
.i
; break;
3586 case VT_DOUBLE
: vtop
->c
.d
= (double)vtop
->c
.i
; break;
3587 case VT_LDOUBLE
: vtop
->c
.ld
= (long double)vtop
->c
.i
; break;
3596 /* convert fp to int */
3597 /* we handle char/short/etc... with generic code */
3598 if (dbt
!= (VT_INT
| VT_UNSIGNED
) &&
3599 dbt
!= (VT_LLONG
| VT_UNSIGNED
) &&
3604 case VT_LLONG
| VT_UNSIGNED
:
3606 /* XXX: add const cases for long long */
3608 case VT_INT
| VT_UNSIGNED
:
3610 case VT_FLOAT
: vtop
->c
.ui
= (unsigned int)vtop
->c
.d
; break;
3611 case VT_DOUBLE
: vtop
->c
.ui
= (unsigned int)vtop
->c
.d
; break;
3612 case VT_LDOUBLE
: vtop
->c
.ui
= (unsigned int)vtop
->c
.d
; break;
3618 case VT_FLOAT
: vtop
->c
.i
= (int)vtop
->c
.d
; break;
3619 case VT_DOUBLE
: vtop
->c
.i
= (int)vtop
->c
.d
; break;
3620 case VT_LDOUBLE
: vtop
->c
.i
= (int)vtop
->c
.d
; break;
3628 if (dbt
== VT_INT
&& (t
& (VT_BTYPE
| VT_UNSIGNED
)) != dbt
) {
3629 /* additionnal cast for char/short/bool... */
3633 } else if ((dbt
& VT_BTYPE
) == VT_LLONG
) {
3634 if ((sbt
& VT_BTYPE
) != VT_LLONG
) {
3635 /* scalar to long long */
3637 if (sbt
== (VT_INT
| VT_UNSIGNED
))
3638 vtop
->c
.ll
= vtop
->c
.ui
;
3640 vtop
->c
.ll
= vtop
->c
.i
;
3642 /* machine independant conversion */
3644 /* generate high word */
3645 if (sbt
== (VT_INT
| VT_UNSIGNED
)) {
3653 /* patch second register */
3654 vtop
[-1].r2
= vtop
->r
;
3658 } else if (dbt
== VT_BOOL
) {
3659 /* scalar to bool */
3662 } else if ((dbt
& VT_BTYPE
) == VT_BYTE
||
3663 (dbt
& VT_BTYPE
) == VT_SHORT
) {
3664 force_charshort_cast(t
);
3665 } else if ((dbt
& VT_BTYPE
) == VT_INT
) {
3667 if (sbt
== VT_LLONG
) {
3668 /* from long long: just take low order word */
3672 /* if lvalue and single word type, nothing to do because
3673 the lvalue already contains the real type size (see
3674 VT_LVAL_xxx constants) */
3680 /* return type size. Put alignment at 'a' */
3681 int type_size(int t
, int *a
)
3687 if (bt
== VT_STRUCT
) {
3689 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
) | SYM_STRUCT
);
3690 *a
= 4; /* XXX: cannot store it yet. Doing that is safe */
3692 } else if (bt
== VT_PTR
) {
3694 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
));
3695 return type_size(s
->t
, a
) * s
->c
;
3700 } else if (bt
== VT_LDOUBLE
) {
3702 return LDOUBLE_SIZE
;
3703 } else if (bt
== VT_DOUBLE
|| bt
== VT_LLONG
) {
3706 } else if (bt
== VT_INT
|| bt
== VT_ENUM
|| bt
== VT_FLOAT
) {
3709 } else if (bt
== VT_SHORT
) {
3713 /* char, void, function, _Bool */
3719 /* return the pointed type of t */
3720 int pointed_type(int t
)
3723 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
));
3724 return s
->t
| (t
& ~VT_TYPE
);
3727 int mk_pointer(int t
)
3731 sym_push(p
, t
, 0, -1);
3732 return VT_PTR
| (p
<< VT_STRUCT_SHIFT
) | (t
& ~VT_TYPE
);
3735 int is_compatible_types(int t1
, int t2
)
3742 bt1
= t1
& VT_BTYPE
;
3743 bt2
= t2
& VT_BTYPE
;
3744 if (bt1
== VT_PTR
) {
3745 t1
= pointed_type(t1
);
3746 /* if function, then convert implicitely to function pointer */
3747 if (bt2
!= VT_FUNC
) {
3750 t2
= pointed_type(t2
);
3752 /* void matches everything */
3755 if (t1
== VT_VOID
|| t2
== VT_VOID
)
3757 return is_compatible_types(t1
, t2
);
3758 } else if (bt1
== VT_STRUCT
|| bt2
== VT_STRUCT
) {
3760 } else if (bt1
== VT_FUNC
) {
3763 s1
= sym_find(((unsigned)t1
>> VT_STRUCT_SHIFT
));
3764 s2
= sym_find(((unsigned)t2
>> VT_STRUCT_SHIFT
));
3765 if (!is_compatible_types(s1
->t
, s2
->t
))
3767 /* XXX: not complete */
3768 if (s1
->c
== FUNC_OLD
|| s2
->c
== FUNC_OLD
)
3772 while (s1
!= NULL
) {
3775 if (!is_compatible_types(s1
->t
, s2
->t
))
3784 /* XXX: not complete */
3789 /* print a type. If 'varstr' is not NULL, then the variable is also
3790 printed in the type */
3792 /* XXX: add array and function pointers */
3793 void type_to_str(char *buf
, int buf_size
,
3794 int t
, const char *varstr
)
3804 if (t
& VT_UNSIGNED
)
3805 pstrcat(buf
, buf_size
, "unsigned ");
3835 tstr
= "long double";
3837 pstrcat(buf
, buf_size
, tstr
);
3841 if (bt
== VT_STRUCT
)
3845 pstrcat(buf
, buf_size
, tstr
);
3846 v
= (unsigned)t
>> VT_STRUCT_SHIFT
;
3847 if (v
>= SYM_FIRST_ANOM
)
3848 pstrcat(buf
, buf_size
, "<anonymous>");
3850 pstrcat(buf
, buf_size
, get_tok_str(v
, NULL
));
3853 s
= sym_find((unsigned)t
>> VT_STRUCT_SHIFT
);
3854 type_to_str(buf
, buf_size
, s
->t
, varstr
);
3855 pstrcat(buf
, buf_size
, "(");
3857 while (sa
!= NULL
) {
3858 type_to_str(buf1
, sizeof(buf1
), sa
->t
, NULL
);
3859 pstrcat(buf
, buf_size
, buf1
);
3862 pstrcat(buf
, buf_size
, ", ");
3864 pstrcat(buf
, buf_size
, ")");
3867 s
= sym_find((unsigned)t
>> VT_STRUCT_SHIFT
);
3868 pstrcpy(buf1
, sizeof(buf1
), "*");
3870 pstrcat(buf1
, sizeof(buf1
), varstr
);
3871 type_to_str(buf
, buf_size
, s
->t
, buf1
);
3875 pstrcat(buf
, buf_size
, " ");
3876 pstrcat(buf
, buf_size
, varstr
);
3881 /* verify type compatibility to store vtop in 'dt' type, and generate
3883 void gen_assign_cast(int dt
)
3886 char buf1
[256], buf2
[256];
3888 st
= vtop
->t
; /* source type */
3889 if ((dt
& VT_BTYPE
) == VT_PTR
) {
3890 /* special cases for pointers */
3891 /* a function is implicitely a function pointer */
3892 if ((st
& VT_BTYPE
) == VT_FUNC
) {
3893 if (!is_compatible_types(pointed_type(dt
), st
))
3898 /* '0' can also be a pointer */
3899 if ((st
& VT_BTYPE
) == VT_INT
&&
3900 ((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_FORWARD
)) == VT_CONST
) &&
3904 if (!is_compatible_types(dt
, st
)) {
3906 type_to_str(buf1
, sizeof(buf1
), st
, NULL
);
3907 type_to_str(buf2
, sizeof(buf2
), dt
, NULL
);
3908 error("cannot cast '%s' to '%s'", buf1
, buf2
);
3914 /* store vtop in lvalue pushed on stack */
3917 int sbt
, dbt
, ft
, r
, t
, size
, align
, bit_size
, bit_pos
, rc
, delayed_cast
;
3921 sbt
= vtop
->t
& VT_BTYPE
;
3922 dbt
= ft
& VT_BTYPE
;
3923 if (((sbt
== VT_INT
|| sbt
== VT_SHORT
) && dbt
== VT_BYTE
) ||
3924 (sbt
== VT_INT
&& dbt
== VT_SHORT
)) {
3925 /* optimize char/short casts */
3926 delayed_cast
= VT_MUSTCAST
;
3927 vtop
->t
= ft
& VT_TYPE
;
3930 gen_assign_cast(ft
& VT_TYPE
);
3933 if (sbt
== VT_STRUCT
) {
3934 /* if structure, only generate pointer */
3935 /* structure assignment : generate memcpy */
3936 /* XXX: optimize if small size */
3938 gfunc_start(&gf
, FUNC_CDECL
);
3940 size
= type_size(vtop
->t
, &align
);
3954 vpushi((int)&memcpy
);
3956 /* leave source on stack */
3957 } else if (ft
& VT_BITFIELD
) {
3958 /* bitfield store handling */
3959 bit_pos
= (ft
>> VT_STRUCT_SHIFT
) & 0x3f;
3960 bit_size
= (ft
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f;
3961 /* remove bit field info to avoid loops */
3962 vtop
[-1].t
= ft
& ~(VT_BITFIELD
| (-1 << VT_STRUCT_SHIFT
));
3964 /* duplicate destination */
3966 vtop
[-1] = vtop
[-2];
3968 /* mask and shift source */
3969 vpushi((1 << bit_size
) - 1);
3973 /* load destination, mask and or with source */
3975 vpushi(~(((1 << bit_size
) - 1) << bit_pos
));
3981 #ifdef CONFIG_TCC_BCHECK
3982 /* bound check case */
3983 if (vtop
[-1].r
& VT_MUSTBOUND
) {
3992 r
= gv(rc
); /* generate value */
3993 /* if lvalue was saved on stack, must read it */
3994 if ((vtop
[-1].r
& VT_VALMASK
) == VT_LLOCAL
) {
3996 t
= get_reg(RC_INT
);
3998 sv
.r
= VT_LOCAL
| VT_LVAL
;
3999 sv
.c
.ul
= vtop
[-1].c
.ul
;
4001 vtop
[-1].r
= t
| VT_LVAL
;
4004 /* two word case handling : store second register at word + 4 */
4005 if ((ft
& VT_BTYPE
) == VT_LLONG
) {
4007 /* convert to int to increment easily */
4014 /* XXX: it works because r2 is spilled last ! */
4015 store(vtop
->r2
, vtop
- 1);
4018 vtop
--; /* NOT vpop() because on x86 it would flush the fp stack */
4019 vtop
->r
|= delayed_cast
;
4023 /* post defines POST/PRE add. c is the token ++ or -- */
4024 void inc(int post
, int c
)
4027 vdup(); /* save lvalue */
4029 gv_dup(); /* duplicate value */
4034 vpushi(c
- TOK_MID
);
4036 vstore(); /* store value */
4038 vpop(); /* if post op, return saved value */
4041 /* Parse GNUC __attribute__ extension. Currently, the following
4042 extensions are recognized:
4043 - aligned(n) : set data/function alignment.
4044 - section(x) : generate data/code in this section.
4045 - unused : currently ignored, but may be used someday.
4047 void parse_attribute(AttributeDef
*ad
)
4054 while (tok
!= ')') {
4055 if (tok
< TOK_IDENT
)
4056 expect("attribute name");
4061 case TOK___SECTION__
:
4064 expect("section name");
4065 ad
->section
= find_section(tokc
.ts
->str
);
4070 case TOK___ALIGNED__
:
4073 if (n
<= 0 || (n
& (n
- 1)) != 0)
4074 error("alignment must be a positive power of two");
4079 case TOK___UNUSED__
:
4080 /* currently, no need to handle it because tcc does not
4081 track unused objects */
4084 case TOK___NORETURN__
:
4085 /* currently, no need to handle it because tcc does not
4086 track unused objects */
4091 ad
->func_call
= FUNC_CDECL
;
4095 case TOK___STDCALL__
:
4096 ad
->func_call
= FUNC_STDCALL
;
4099 warning("'%s' attribute ignored", get_tok_str(t
, NULL
));
4100 /* skip parameters */
4101 /* XXX: skip parenthesis too */
4104 while (tok
!= ')' && tok
!= -1)
4118 /* enum/struct/union declaration */
4119 int struct_decl(int u
)
4121 int a
, t
, b
, v
, size
, align
, maxalign
, c
, offset
;
4122 int bit_size
, bit_pos
, bsize
, bt
, lbit_pos
;
4126 a
= tok
; /* save decl type */
4131 /* struct already defined ? return it */
4132 /* XXX: check consistency */
4133 s
= sym_find(v
| SYM_STRUCT
);
4136 error("invalid type");
4142 s
= sym_push(v
| SYM_STRUCT
, a
, 0, 0);
4143 /* put struct/union/enum name in type */
4145 u
= u
| (v
<< VT_STRUCT_SHIFT
);
4150 error("struct/union/enum already defined");
4151 /* cannot be empty */
4158 if (a
== TOK_ENUM
) {
4165 /* enum symbols have static storage */
4166 sym_push(v
, VT_STATIC
| VT_INT
, VT_CONST
, c
);
4171 parse_btype(&b
, &ad
);
4176 t
= type_decl(&ad
, &v
, b
, TYPE_DIRECT
);
4177 if ((t
& VT_BTYPE
) == VT_FUNC
||
4178 (t
& (VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
)))
4179 error("invalid type for '%s'",
4180 get_tok_str(v
, NULL
));
4186 bit_size
= expr_const();
4187 /* XXX: handle v = 0 case for messages */
4189 error("negative width in bit-field '%s'",
4190 get_tok_str(v
, NULL
));
4191 if (v
&& bit_size
== 0)
4192 error("zero width for bit-field '%s'",
4193 get_tok_str(v
, NULL
));
4195 size
= type_size(t
, &align
);
4197 if (bit_size
>= 0) {
4202 error("bitfields must have scalar type");
4204 if (bit_size
> bsize
) {
4205 error("width of '%s' exceeds its type",
4206 get_tok_str(v
, NULL
));
4207 } else if (bit_size
== bsize
) {
4208 /* no need for bit fields */
4210 } else if (bit_size
== 0) {
4211 /* XXX: what to do if only padding in a
4213 /* zero size: means to pad */
4217 /* we do not have enough room ? */
4218 if ((bit_pos
+ bit_size
) > bsize
)
4221 /* XXX: handle LSB first */
4223 (bit_pos
<< VT_STRUCT_SHIFT
) |
4224 (bit_size
<< (VT_STRUCT_SHIFT
+ 6));
4225 bit_pos
+= bit_size
;
4231 /* add new memory data only if starting
4233 if (lbit_pos
== 0) {
4234 if (a
== TOK_STRUCT
) {
4235 c
= (c
+ align
- 1) & -align
;
4243 if (align
> maxalign
)
4247 printf("add field %s offset=%d",
4248 get_tok_str(v
, NULL
), offset
);
4249 if (t
& VT_BITFIELD
) {
4250 printf(" pos=%d size=%d",
4251 (t
>> VT_STRUCT_SHIFT
) & 0x3f,
4252 (t
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f);
4256 ss
= sym_push(v
| SYM_FIELD
, t
, 0, offset
);
4260 if (tok
== ';' || tok
== -1)
4270 /* size for struct/union, dummy for enum */
4271 s
->c
= (c
+ maxalign
- 1) & -maxalign
;
4276 /* return 0 if no type declaration. otherwise, return the basic type
4279 int parse_btype(int *type_ptr
, AttributeDef
*ad
)
4281 int t
, u
, type_found
;
4284 memset(ad
, 0, sizeof(AttributeDef
));
4295 if ((t
& VT_BTYPE
) != 0)
4296 error("too many basic types");
4310 if ((t
& VT_BTYPE
) == VT_DOUBLE
) {
4311 t
= (t
& ~VT_BTYPE
) | VT_LDOUBLE
;
4312 } else if ((t
& VT_BTYPE
) == VT_LONG
) {
4313 t
= (t
& ~VT_BTYPE
) | VT_LLONG
;
4327 if ((t
& VT_BTYPE
) == VT_LONG
) {
4328 t
= (t
& ~VT_BTYPE
) | VT_LDOUBLE
;
4335 u
= struct_decl(VT_ENUM
);
4339 u
= struct_decl(VT_STRUCT
);
4342 /* type modifiers */
4347 case TOK___SIGNED__
:
4350 case TOK___INLINE__
:
4372 /* GNUC attribute */
4373 case TOK___ATTRIBUTE__
:
4374 parse_attribute(ad
);
4378 if (!s
|| !(s
->t
& VT_TYPEDEF
))
4380 t
|= (s
->t
& ~VT_TYPEDEF
);
4387 /* long is never used as type */
4388 if ((t
& VT_BTYPE
) == VT_LONG
)
4389 t
= (t
& ~VT_BTYPE
) | VT_INT
;
4394 int post_type(int t
, AttributeDef
*ad
)
4396 int p
, n
, pt
, l
, t1
;
4397 Sym
**plast
, *s
, *first
;
4401 /* function declaration */
4406 while (tok
!= ')') {
4407 /* read param name and compute offset */
4408 if (l
!= FUNC_OLD
) {
4409 if (!parse_btype(&pt
, &ad1
)) {
4411 error("invalid type");
4418 if ((pt
& VT_BTYPE
) == VT_VOID
&& tok
== ')')
4420 pt
= type_decl(&ad1
, &n
, pt
, TYPE_DIRECT
| TYPE_ABSTRACT
);
4421 if ((pt
& VT_BTYPE
) == VT_VOID
)
4422 error("parameter declared as void");
4429 /* array must be transformed to pointer according to ANSI C */
4431 s
= sym_push(n
| SYM_FIELD
, pt
, 0, 0);
4436 if (l
== FUNC_NEW
&& tok
== TOK_DOTS
) {
4443 /* if no parameters, then old type prototype */
4447 t1
= t
& (VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
);
4448 t
= post_type(t
& ~(VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
), ad
);
4449 /* we push a anonymous symbol which will contain the function prototype */
4451 s
= sym_push(p
, t
, ad
->func_call
, l
);
4453 t
= t1
| VT_FUNC
| (p
<< VT_STRUCT_SHIFT
);
4454 } else if (tok
== '[') {
4455 /* array definition */
4461 error("invalid array size");
4464 /* parse next post type */
4465 t1
= t
& (VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
);
4466 t
= post_type(t
& ~(VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
), ad
);
4468 /* we push a anonymous symbol which will contain the array
4471 sym_push(p
, t
, 0, n
);
4472 t
= t1
| VT_ARRAY
| VT_PTR
| (p
<< VT_STRUCT_SHIFT
);
4477 /* Read a type declaration (except basic type), and return the
4478 type. 'td' is a bitmask indicating which kind of type decl is
4479 expected. 't' should contain the basic type. 'ad' is the attribute
4480 definition of the basic type. It can be modified by type_decl(). */
4481 int type_decl(AttributeDef
*ad
, int *v
, int t
, int td
)
4486 while (tok
== '*') {
4488 while (tok
== TOK_CONST
|| tok
== TOK_VOLATILE
|| tok
== TOK_RESTRICT
)
4493 /* recursive type */
4494 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
4497 /* XXX: this is not correct to modify 'ad' at this point, but
4498 the syntax is not clear */
4499 if (tok
== TOK___ATTRIBUTE__
)
4500 parse_attribute(ad
);
4501 u
= type_decl(ad
, v
, 0, td
);
4505 /* type identifier */
4506 if (tok
>= TOK_IDENT
&& (td
& TYPE_DIRECT
)) {
4510 if (!(td
& TYPE_ABSTRACT
))
4511 expect("identifier");
4515 /* append t at the end of u */
4516 t
= post_type(t
, ad
);
4517 if (tok
== TOK___ATTRIBUTE__
)
4518 parse_attribute(ad
);
4523 s
= sym_find((unsigned)p
>> VT_STRUCT_SHIFT
);
4533 /* define a new external reference to a function 'v' of type 'u' */
4534 Sym
*external_sym(int v
, int u
, int r
)
4539 /* push forward reference */
4540 s
= sym_push1(&global_stack
,
4542 s
->r
= r
| VT_CONST
| VT_FORWARD
;
4547 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
4548 static int lvalue_type(int t
)
4555 else if (bt
== VT_SHORT
)
4559 if (t
& VT_UNSIGNED
)
4560 r
|= VT_LVAL_UNSIGNED
;
4564 /* indirection with full error checking and bound check */
4565 static void indir(void)
4567 if ((vtop
->t
& VT_BTYPE
) != VT_PTR
)
4569 if (vtop
->r
& VT_LVAL
)
4571 vtop
->t
= pointed_type(vtop
->t
);
4572 /* an array is never an lvalue */
4573 if (!(vtop
->t
& VT_ARRAY
)) {
4574 vtop
->r
|= lvalue_type(vtop
->t
);
4575 /* if bound checking, the referenced pointer must be checked */
4576 if (do_bounds_check
)
4577 vtop
->r
|= VT_MUSTBOUND
;
4581 /* pass a parameter to a function and do type checking and casting */
4582 void gfunc_param_typed(GFuncContext
*gf
, Sym
*func
, Sym
*arg
)
4585 func_type
= func
->c
;
4586 if (func_type
== FUNC_OLD
||
4587 (func_type
== FUNC_ELLIPSIS
&& arg
== NULL
)) {
4588 /* default casting : only need to convert float to double */
4589 if ((vtop
->t
& VT_BTYPE
) == VT_FLOAT
)
4590 gen_cast(VT_DOUBLE
);
4591 } else if (arg
== NULL
) {
4592 error("too many arguments to function");
4594 gen_assign_cast(arg
->t
);
4601 int n
, t
, ft
, fc
, p
, align
, size
, r
, data_offset
;
4606 if (tok
== TOK_CINT
|| tok
== TOK_CCHAR
|| tok
== TOK_LCHAR
) {
4609 } else if (tok
== TOK_CUINT
) {
4610 vsetc(VT_INT
| VT_UNSIGNED
, VT_CONST
, &tokc
);
4612 } else if (tok
== TOK_CLLONG
) {
4613 vsetc(VT_LLONG
, VT_CONST
, &tokc
);
4615 } else if (tok
== TOK_CULLONG
) {
4616 vsetc(VT_LLONG
| VT_UNSIGNED
, VT_CONST
, &tokc
);
4618 } else if (tok
== TOK_CFLOAT
) {
4619 vsetc(VT_FLOAT
, VT_CONST
, &tokc
);
4621 } else if (tok
== TOK_CDOUBLE
) {
4622 vsetc(VT_DOUBLE
, VT_CONST
, &tokc
);
4624 } else if (tok
== TOK_CLDOUBLE
) {
4625 vsetc(VT_LDOUBLE
, VT_CONST
, &tokc
);
4627 } else if (tok
== TOK___FUNC__
) {
4628 /* special function name identifier */
4629 /* generate (char *) type */
4630 data_offset
= (int)data_section
->data_ptr
;
4631 vset(mk_pointer(VT_BYTE
), VT_CONST
, data_offset
);
4632 strcpy((void *)data_offset
, funcname
);
4633 data_offset
+= strlen(funcname
) + 1;
4634 data_section
->data_ptr
= (unsigned char *)data_offset
;
4636 } else if (tok
== TOK_LSTR
) {
4639 } else if (tok
== TOK_STR
) {
4640 /* string parsing */
4643 type_size(t
, &align
);
4644 data_offset
= (int)data_section
->data_ptr
;
4645 data_offset
= (data_offset
+ align
- 1) & -align
;
4647 /* we must declare it as an array first to use initializer parser */
4648 t
= VT_ARRAY
| mk_pointer(t
);
4649 decl_initializer(t
, VT_CONST
, data_offset
, 1, 0);
4650 data_offset
+= type_size(t
, &align
);
4651 /* put it as pointer */
4652 vset(t
& ~VT_ARRAY
, VT_CONST
, fc
);
4653 data_section
->data_ptr
= (unsigned char *)data_offset
;
4659 if (parse_btype(&t
, &ad
)) {
4660 ft
= type_decl(&ad
, &n
, t
, TYPE_ABSTRACT
);
4662 /* check ISOC99 compound literal */
4664 /* data is allocated locally by default */
4669 /* all except arrays are lvalues */
4670 if (!(ft
& VT_ARRAY
))
4671 r
|= lvalue_type(ft
);
4672 memset(&ad
, 0, sizeof(AttributeDef
));
4673 fc
= decl_initializer_alloc(ft
, &ad
, r
, 1);
4683 } else if (t
== '*') {
4686 } else if (t
== '&') {
4688 /* functions names must be treated as function pointers,
4689 except for unary '&' and sizeof. Since we consider that
4690 functions are not lvalues, we only have to handle it
4691 there and in function calls. */
4692 /* arrays can also be used although they are not lvalues */
4693 if ((vtop
->t
& VT_BTYPE
) != VT_FUNC
&&
4694 !(vtop
->t
& VT_ARRAY
))
4696 vtop
->t
= mk_pointer(vtop
->t
);
4701 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
)
4702 vtop
->c
.i
= !vtop
->c
.i
;
4703 else if ((vtop
->r
& VT_VALMASK
) == VT_CMP
)
4704 vtop
->c
.i
= vtop
->c
.i
^ 1;
4706 vset(VT_INT
, VT_JMP
, gtst(1, 0));
4716 if (t
== TOK_SIZEOF
) {
4719 if (parse_btype(&t
, &ad
)) {
4720 t
= type_decl(&ad
, &n
, t
, TYPE_ABSTRACT
);
4722 /* XXX: some code could be generated: add eval
4734 vpushi(type_size(t
, &t
));
4736 if (t
== TOK_INC
|| t
== TOK_DEC
) {
4739 } else if (t
== '-') {
4746 expect("identifier");
4750 error("'%s' undeclared", get_tok_str(t
, NULL
));
4751 /* for simple function calls, we tolerate undeclared
4752 external reference */
4754 sym_push1(&global_stack
, p
, 0, FUNC_OLD
);
4755 /* int() function */
4756 s
= external_sym(t
, VT_FUNC
| (p
<< VT_STRUCT_SHIFT
), 0);
4758 vset(s
->t
, s
->r
, s
->c
);
4759 /* if forward reference, we must point to s */
4760 if (vtop
->r
& VT_FORWARD
)
4765 /* post operations */
4767 if (tok
== TOK_INC
|| tok
== TOK_DEC
) {
4770 } else if (tok
== '.' || tok
== TOK_ARROW
) {
4772 if (tok
== TOK_ARROW
)
4777 /* expect pointer on structure */
4778 if ((vtop
->t
& VT_BTYPE
) != VT_STRUCT
)
4779 expect("struct or union");
4780 s
= sym_find(((unsigned)vtop
->t
>> VT_STRUCT_SHIFT
) | SYM_STRUCT
);
4783 while ((s
= s
->next
) != NULL
) {
4788 error("field not found");
4789 /* add field offset to pointer */
4790 vtop
->t
= char_pointer_type
; /* change type to 'char *' */
4793 /* change type to field type, and set to lvalue */
4795 /* an array is never an lvalue */
4796 if (!(vtop
->t
& VT_ARRAY
))
4797 vtop
->r
|= lvalue_type(vtop
->t
);
4799 } else if (tok
== '[') {
4805 } else if (tok
== '(') {
4810 if ((vtop
->t
& VT_BTYPE
) != VT_FUNC
) {
4811 /* pointer test (no array accepted) */
4812 if ((vtop
->t
& (VT_BTYPE
| VT_ARRAY
)) == VT_PTR
) {
4813 vtop
->t
= pointed_type(vtop
->t
);
4814 if ((vtop
->t
& VT_BTYPE
) != VT_FUNC
)
4818 expect("function pointer");
4821 vtop
->r
&= ~VT_LVAL
; /* no lvalue */
4823 /* get return type */
4824 s
= sym_find((unsigned)vtop
->t
>> VT_STRUCT_SHIFT
);
4825 save_regs(0); /* save used temporary registers */
4826 gfunc_start(&gf
, s
->r
);
4828 sa
= s
->next
; /* first parameter */
4829 #ifdef INVERT_FUNC_PARAMS
4833 ParseState saved_parse_state
;
4836 /* read each argument and store it on a stack */
4837 /* XXX: merge it with macro args ? */
4843 while ((parlevel
> 0 || (tok
!= ')' && tok
!= ',')) &&
4847 else if (tok
== ')')
4849 tok_str_add_tok(&str
);
4852 tok_str_add(&str
, -1); /* end of file added */
4853 tok_str_add(&str
, 0);
4854 s1
= sym_push2(&args
, 0, 0, (int)str
.str
);
4855 s1
->next
= sa
; /* add reference to argument */
4864 /* now generate code in reverse order by reading the stack */
4865 save_parse_state(&saved_parse_state
);
4867 macro_ptr
= (int *)args
->c
;
4871 expect("',' or ')'");
4872 gfunc_param_typed(&gf
, s
, args
->next
);
4874 free((int *)args
->c
);
4878 restore_parse_state(&saved_parse_state
);
4881 /* compute first implicit argument if a structure is returned */
4882 if ((s
->t
& VT_BTYPE
) == VT_STRUCT
) {
4883 /* get some space for the returned structure */
4884 size
= type_size(s
->t
, &align
);
4885 loc
= (loc
- size
) & -align
;
4887 ret
.r
= VT_LOCAL
| VT_LVAL
;
4888 /* pass it as 'int' to avoid structure arg passing
4890 vset(VT_INT
, VT_LOCAL
, loc
);
4896 /* return in register */
4897 if (is_float(ret
.t
)) {
4900 if ((ret
.t
& VT_BTYPE
) == VT_LLONG
)
4906 #ifndef INVERT_FUNC_PARAMS
4910 gfunc_param_typed(&gf
, s
, sa
);
4920 error("too few arguments to function");
4924 vsetc(ret
.t
, ret
.r
, &ret
.c
);
4938 (tok
>= TOK_A_MOD
&& tok
<= TOK_A_DIV
) ||
4939 tok
== TOK_A_XOR
|| tok
== TOK_A_OR
||
4940 tok
== TOK_A_SHL
|| tok
== TOK_A_SAR
) {
4963 while ((l
== 0 && (tok
== '*' || tok
== '/' || tok
== '%')) ||
4964 (l
== 1 && (tok
== '+' || tok
== '-')) ||
4965 (l
== 2 && (tok
== TOK_SHL
|| tok
== TOK_SAR
)) ||
4966 (l
== 3 && ((tok
>= TOK_ULE
&& tok
<= TOK_GT
) ||
4967 tok
== TOK_ULT
|| tok
== TOK_UGE
)) ||
4968 (l
== 4 && (tok
== TOK_EQ
|| tok
== TOK_NE
)) ||
4969 (l
== 5 && tok
== '&') ||
4970 (l
== 6 && tok
== '^') ||
4971 (l
== 7 && tok
== '|') ||
4972 (l
== 8 && tok
== TOK_LAND
) ||
4973 (l
== 9 && tok
== TOK_LOR
)) {
4982 /* only used if non constant */
4990 if (tok
!= TOK_LAND
) {
4993 vset(VT_INT
, VT_JMPI
, t
);
5010 if (tok
!= TOK_LOR
) {
5013 vset(VT_INT
, VT_JMP
, t
);
5023 /* XXX: better constant handling */
5026 int t
, u
, c
, r1
, r2
, rc
;
5046 save_regs(1); /* we need to save all registers here except
5047 at the top because it is a branch point */
5050 /* XXX: long long handling ? */
5052 if (is_float(vtop
->t
))
5055 vtop
--; /* no vpop so that FP stack is not flushed */
5080 /* parse a constant expression and return value in vtop */
5081 void expr_const1(void)
5087 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
)) != VT_CONST
)
5092 /* parse an integer constant and return its value */
5093 int expr_const(void)
5102 /* return the label token if current token is a label, otherwise
5109 /* fast test first */
5110 if (tok
< TOK_UIDENT
)
5112 /* no need to save tokc since we expect an identifier */
5120 /* XXX: may not work in all cases (macros ?) */
5129 void block(int *bsym
, int *csym
, int *case_sym
, int *def_sym
, int case_reg
)
5134 /* generate line number info */
5136 (last_line_num
!= file
->line_num
|| last_ind
!= ind
)) {
5137 put_stabn(N_SLINE
, 0, file
->line_num
, ind
- func_ind
);
5139 last_line_num
= file
->line_num
;
5142 if (tok
== TOK_IF
) {
5149 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
5151 if (c
== TOK_ELSE
) {
5155 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
5156 gsym(d
); /* patch else jmp */
5159 } else if (tok
== TOK_WHILE
) {
5167 block(&a
, &b
, case_sym
, def_sym
, case_reg
);
5171 } else if (tok
== '{') {
5174 s
= local_stack
.top
;
5175 while (tok
!= '}') {
5178 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
5180 /* pop locally defined symbols */
5181 sym_pop(&local_stack
, s
);
5183 } else if (tok
== TOK_RETURN
) {
5187 gen_assign_cast(func_vt
);
5188 if ((func_vt
& VT_BTYPE
) == VT_STRUCT
) {
5189 /* if returning structure, must copy it to implicit
5190 first pointer arg location */
5191 vset(mk_pointer(func_vt
), VT_LOCAL
| VT_LVAL
, func_vc
);
5194 /* copy structure value to pointer */
5196 } else if (is_float(func_vt
)) {
5201 vtop
--; /* NOT vpop() because on x86 it would flush the fp stack */
5204 rsym
= gjmp(rsym
); /* jmp */
5205 } else if (tok
== TOK_BREAK
) {
5208 error("cannot break");
5209 *bsym
= gjmp(*bsym
);
5212 } else if (tok
== TOK_CONTINUE
) {
5215 error("cannot continue");
5216 *csym
= gjmp(*csym
);
5219 } else if (tok
== TOK_FOR
) {
5246 block(&a
, &b
, case_sym
, def_sym
, case_reg
);
5251 if (tok
== TOK_DO
) {
5256 block(&a
, &b
, case_sym
, def_sym
, case_reg
);
5267 if (tok
== TOK_SWITCH
) {
5271 /* XXX: other types than integer */
5272 case_reg
= gv(RC_INT
);
5276 b
= gjmp(0); /* jump to first case */
5278 block(&a
, csym
, &b
, &c
, case_reg
);
5279 /* if no default, jmp after switch */
5287 if (tok
== TOK_CASE
) {
5294 if (gnu_ext
&& tok
== TOK_DOTS
) {
5298 warning("empty case range");
5300 /* since a case is like a label, we must skip it with a jmp */
5303 vset(VT_INT
, case_reg
, 0);
5307 *case_sym
= gtst(1, 0);
5310 *case_sym
= gtst(1, 0);
5311 vset(VT_INT
, case_reg
, 0);
5314 *case_sym
= gtst(1, *case_sym
);
5318 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
5320 if (tok
== TOK_DEFAULT
) {
5326 error("too many 'default'");
5328 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
5330 if (tok
== TOK_GOTO
) {
5332 s
= sym_find1(&label_stack
, tok
);
5333 /* put forward definition if needed */
5335 s
= sym_push1(&label_stack
, tok
, VT_FORWARD
, 0);
5336 /* label already defined */
5337 if (s
->t
& VT_FORWARD
)
5347 s
= sym_find1(&label_stack
, b
);
5349 if (!(s
->t
& VT_FORWARD
))
5350 error("multiple defined label");
5355 sym_push1(&label_stack
, b
, 0, ind
);
5357 /* we accept this, but it is a mistake */
5359 warning("deprecated use of label at end of compound statement");
5361 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
5363 /* expression case */
5373 /* t is the array or struct type. c is the array or struct
5374 address. cur_index/cur_field is the pointer to the current
5375 value. 'size_only' is true if only size info is needed (only used
5377 void decl_designator(int t
, int r
, int c
,
5378 int *cur_index
, Sym
**cur_field
,
5382 int notfirst
, index
, align
, l
;
5385 if (gnu_ext
&& (l
= is_label()) != 0)
5388 while (tok
== '[' || tok
== '.') {
5390 if (!(t
& VT_ARRAY
))
5391 expect("array type");
5392 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
));
5394 index
= expr_const();
5395 if (index
< 0 || (s
->c
>= 0 && index
>= s
->c
))
5396 expect("invalid index");
5400 t
= pointed_type(t
);
5401 c
+= index
* type_size(t
, &align
);
5407 if ((t
& VT_BTYPE
) != VT_STRUCT
)
5408 expect("struct/union type");
5409 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
) | SYM_STRUCT
);
5421 t
= f
->t
| (t
& ~VT_TYPE
);
5436 t
= pointed_type(t
);
5437 c
+= index
* type_size(t
, &align
);
5441 error("too many field init");
5442 t
= f
->t
| (t
& ~VT_TYPE
);
5446 decl_initializer(t
, r
, c
, 0, size_only
);
5450 #define EXPR_CONST 1
5453 /* store a value or an expression directly in global data or in local array */
5454 void init_putv(int t
, int r
, int c
,
5455 int v
, int expr_type
)
5457 int saved_global_expr
, bt
;
5464 /* compound literals must be allocated globally in this case */
5465 saved_global_expr
= global_expr
;
5468 global_expr
= saved_global_expr
;
5475 if ((r
& VT_VALMASK
) == VT_CONST
) {
5476 /* XXX: not portable */
5481 *(char *)c
= vtop
->c
.i
;
5484 *(short *)c
= vtop
->c
.i
;
5487 *(double *)c
= vtop
->c
.d
;
5490 *(long double *)c
= vtop
->c
.ld
;
5493 *(long long *)c
= vtop
->c
.ll
;
5496 *(int *)c
= vtop
->c
.i
;
5508 /* put zeros for variable based init */
5509 void init_putz(int t
, int r
, int c
, int size
)
5513 if ((r
& VT_VALMASK
) == VT_CONST
) {
5514 /* nothing to do because globals are already set to zero */
5516 gfunc_start(&gf
, FUNC_CDECL
);
5521 vset(VT_INT
, VT_LOCAL
, c
);
5523 vpushi((int)&memset
);
5528 /* 't' contains the type and storage info. c is the address of the
5529 object. 'first' is true if array '{' must be read (multi dimension
5530 implicit array init handling). 'size_only' is true if size only
5531 evaluation is wanted (only for arrays). */
5532 void decl_initializer(int t
, int r
, int c
, int first
, int size_only
)
5534 int index
, array_length
, n
, no_oblock
, nb
, parlevel
, i
;
5535 int t1
, size1
, align1
, expr_type
;
5540 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
));
5543 t1
= pointed_type(t
);
5544 size1
= type_size(t1
, &align1
);
5547 if ((first
&& tok
!= TOK_LSTR
&& tok
!= TOK_STR
) ||
5553 /* only parse strings here if correct type (otherwise: handle
5554 them as ((w)char *) expressions */
5555 if ((tok
== TOK_LSTR
&&
5556 (t1
& VT_BTYPE
) == VT_INT
) ||
5558 (t1
& VT_BTYPE
) == VT_BYTE
)) {
5559 /* XXX: move multiple string parsing in parser ? */
5560 while (tok
== TOK_STR
|| tok
== TOK_LSTR
) {
5562 /* compute maximum number of chars wanted */
5564 if (n
>= 0 && nb
> (n
- array_length
))
5565 nb
= n
- array_length
;
5568 warning("initializer-string for array is too long");
5570 init_putv(t1
, r
, c
+ (array_length
+ i
) * size1
,
5571 ts
->str
[i
], EXPR_VAL
);
5577 /* only add trailing zero if enough storage (no
5578 warning in this case since it is standard) */
5579 if (n
< 0 || array_length
< n
) {
5581 init_putv(t1
, r
, c
+ (array_length
* size1
), 0, EXPR_VAL
);
5587 while (tok
!= '}') {
5588 decl_designator(t
, r
, c
, &index
, NULL
, size_only
);
5589 if (n
>= 0 && index
>= n
)
5590 error("index too large");
5591 /* must put zero in holes (note that doing it that way
5592 ensures that it even works with designators) */
5593 if (!size_only
&& array_length
< index
) {
5594 init_putz(t1
, r
, c
+ array_length
* size1
,
5595 (index
- array_length
) * size1
);
5598 if (index
> array_length
)
5599 array_length
= index
;
5600 /* special test for multi dimensional arrays (may not
5601 be strictly correct if designators are used at the
5603 if (index
>= n
&& no_oblock
)
5612 /* put zeros at the end */
5613 if (!size_only
&& n
>= 0 && array_length
< n
) {
5614 init_putz(t1
, r
, c
+ array_length
* size1
,
5615 (n
- array_length
) * size1
);
5617 /* patch type size if needed */
5619 s
->c
= array_length
;
5620 } else if ((t
& VT_BTYPE
) == VT_STRUCT
&& tok
== '{') {
5621 /* XXX: union needs only one init */
5623 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
) | SYM_STRUCT
);
5628 while (tok
!= '}') {
5629 decl_designator(t
, r
, c
, NULL
, &f
, size_only
);
5630 /* fill with zero between fields */
5632 if (!size_only
&& array_length
< index
) {
5633 init_putz(t
, r
, c
+ array_length
,
5634 index
- array_length
);
5636 index
= index
+ type_size(f
->t
, &align1
);
5637 if (index
> array_length
)
5638 array_length
= index
;
5644 /* put zeros at the end */
5645 if (!size_only
&& array_length
< n
) {
5646 init_putz(t
, r
, c
+ array_length
,
5650 } else if (tok
== '{') {
5652 decl_initializer(t
, r
, c
, first
, size_only
);
5654 } else if (size_only
) {
5655 /* just skip expression */
5657 while ((parlevel
> 0 || (tok
!= '}' && tok
!= ',')) &&
5661 else if (tok
== ')')
5666 /* currently, we always use constant expression for globals
5667 (may change for scripting case) */
5668 expr_type
= EXPR_CONST
;
5669 if ((r
& VT_VALMASK
) == VT_LOCAL
)
5670 expr_type
= EXPR_ANY
;
5671 init_putv(t
, r
, c
, 0, expr_type
);
5675 /* parse an initializer for type 't' if 'has_init' is true, and
5676 allocate space in local or global data space ('r' is either
5677 VT_LOCAL or VT_CONST). The allocated address in returned */
5678 int decl_initializer_alloc(int t
, AttributeDef
*ad
, int r
, int has_init
)
5680 int size
, align
, addr
, data_offset
;
5682 ParseState saved_parse_state
;
5683 TokenString init_str
;
5686 size
= type_size(t
, &align
);
5687 /* If unknown size, we must evaluate it before
5688 evaluating initializers because
5689 initializers can generate global data too
5690 (e.g. string pointers or ISOC99 compound
5691 literals). It also simplifies local
5692 initializers handling */
5693 tok_str_new(&init_str
);
5696 error("unknown type size");
5697 /* get all init string */
5699 while (level
> 0 || (tok
!= ',' && tok
!= ';')) {
5701 error("unexpected end of file in initializer");
5702 tok_str_add_tok(&init_str
);
5705 else if (tok
== '}') {
5712 tok_str_add(&init_str
, -1);
5713 tok_str_add(&init_str
, 0);
5716 save_parse_state(&saved_parse_state
);
5718 macro_ptr
= init_str
.str
;
5720 decl_initializer(t
, r
, 0, 1, 1);
5721 /* prepare second initializer parsing */
5722 macro_ptr
= init_str
.str
;
5725 /* if still unknown size, error */
5726 size
= type_size(t
, &align
);
5728 error("unknown type size");
5730 /* take into account specified alignment if bigger */
5731 if (ad
->aligned
> align
)
5732 align
= ad
->aligned
;
5733 if ((r
& VT_VALMASK
) == VT_LOCAL
) {
5734 if (do_bounds_check
&& (t
& VT_ARRAY
))
5736 #ifdef TCC_TARGET_IL
5737 /* XXX: ugly patch to allocate local variables for IL, just
5742 loc
= (loc
- size
) & -align
;
5745 /* handles bounds */
5746 /* XXX: currently, since we do only one pass, we cannot track
5747 '&' operators, so we add only arrays */
5748 if (do_bounds_check
&& (t
& VT_ARRAY
)) {
5750 /* add padding between regions */
5752 /* then add local bound info */
5753 bounds_ptr
= (int *)lbounds_section
->data_ptr
;
5754 *bounds_ptr
++ = addr
;
5755 *bounds_ptr
++ = size
;
5756 lbounds_section
->data_ptr
= (unsigned char *)bounds_ptr
;
5759 /* compute section */
5767 data_offset
= (int)sec
->data_ptr
;
5768 data_offset
= (data_offset
+ align
- 1) & -align
;
5770 /* very important to increment global
5771 pointer at this time because
5772 initializers themselves can create new
5774 data_offset
+= size
;
5775 /* handles bounds */
5776 if (do_bounds_check
) {
5778 /* first, we need to add at least one byte between each region */
5780 /* then add global bound info */
5781 bounds_ptr
= (int *)bounds_section
->data_ptr
;
5782 *bounds_ptr
++ = addr
;
5783 *bounds_ptr
++ = size
;
5784 bounds_section
->data_ptr
= (unsigned char *)bounds_ptr
;
5786 sec
->data_ptr
= (unsigned char *)data_offset
;
5789 decl_initializer(t
, r
, addr
, 1, 0);
5790 /* restore parse state if needed */
5793 restore_parse_state(&saved_parse_state
);
5799 void put_func_debug(int t
)
5808 put_elf_sym(symtab_section
, ind
, 0,
5809 ELF32_ST_INFO(bind
, STT_FUNC
), 0,
5810 cur_text_section
->sh_num
, funcname
);
5812 /* XXX: we put here a dummy type */
5813 snprintf(buf
, sizeof(buf
), "%s:%c1",
5814 funcname
, t
& VT_STATIC
? 'f' : 'F');
5815 put_stabs(buf
, N_FUN
, 0, file
->line_num
, ind
);
5821 /* not finished : try to put some local vars in registers */
5822 //#define CONFIG_REG_VARS
5824 #ifdef CONFIG_REG_VARS
5825 void add_var_ref(int t
)
5827 printf("%s:%d: &%s\n",
5828 file
->filename
, file
->line_num
,
5829 get_tok_str(t
, NULL
));
5832 /* first pass on a function with heuristic to extract variable usage
5833 and pointer references to local variables for register allocation */
5834 void analyse_function(void)
5841 /* any symbol coming after '&' is considered as being a
5842 variable whose reference is taken. It is highly unaccurate
5843 but it is difficult to do better without a complete parse */
5846 /* if '& number', then no need to examine next tokens */
5847 if (tok
== TOK_CINT
||
5849 tok
== TOK_CLLONG
||
5850 tok
== TOK_CULLONG
) {
5852 } else if (tok
>= TOK_UIDENT
) {
5853 /* if '& ident [' or '& ident ->', then ident address
5857 if (tok
!= '[' && tok
!= TOK_ARROW
)
5861 while (tok
!= '}' && tok
!= ';' &&
5862 !((tok
== ',' || tok
== ')') && level
== 0)) {
5863 if (tok
>= TOK_UIDENT
) {
5865 } else if (tok
== '(') {
5867 } else if (tok
== ')') {
5880 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
5883 int t
, b
, v
, addr
, has_init
, r
;
5888 if (!parse_btype(&b
, &ad
)) {
5889 /* skip redundant ';' */
5890 /* XXX: find more elegant solution */
5895 /* special test for old K&R protos without explicit int
5896 type. Only accepted when defining global data */
5897 if (l
== VT_LOCAL
|| tok
< TOK_DEFINE
)
5901 if (((b
& VT_BTYPE
) == VT_ENUM
||
5902 (b
& VT_BTYPE
) == VT_STRUCT
) &&
5904 /* we accept no variable after */
5908 while (1) { /* iterate thru each declaration */
5909 t
= type_decl(&ad
, &v
, b
, TYPE_DIRECT
);
5913 type_to_str(buf
, sizeof(buf
), t
, get_tok_str(v
, NULL
));
5914 printf("type = '%s'\n", buf
);
5918 #ifdef CONFIG_REG_VARS
5919 TokenString func_str
;
5920 ParseState saved_parse_state
;
5925 error("cannot use local functions");
5927 expect("function definition");
5929 #ifdef CONFIG_REG_VARS
5930 /* parse all function code and record it */
5932 tok_str_new(&func_str
);
5938 error("unexpected end of file");
5939 tok_str_add_tok(&func_str
);
5944 } else if (t
== '}') {
5946 if (block_level
== 0)
5950 tok_str_add(&func_str
, -1);
5951 tok_str_add(&func_str
, 0);
5953 save_parse_state(&saved_parse_state
);
5955 macro_ptr
= func_str
.str
;
5960 /* compute text section */
5961 cur_text_section
= ad
.section
;
5962 if (!cur_text_section
)
5963 cur_text_section
= text_section
;
5964 ind
= (int)cur_text_section
->data_ptr
;
5965 /* patch forward references */
5966 if ((sym
= sym_find(v
)) && (sym
->r
& VT_FORWARD
)) {
5967 greloc_patch(sym
, ind
);
5970 /* put function address */
5971 sym
= sym_push1(&global_stack
, v
, t
, ind
);
5974 funcname
= get_tok_str(v
, NULL
);
5975 /* put debug symbol */
5978 /* push a dummy symbol to enable local sym storage */
5979 sym_push1(&local_stack
, 0, 0, 0);
5983 #ifdef CONFIG_REG_VARS
5984 macro_ptr
= func_str
.str
;
5987 block(NULL
, NULL
, NULL
, NULL
, 0);
5990 cur_text_section
->data_ptr
= (unsigned char *)ind
;
5991 sym_pop(&label_stack
, NULL
); /* reset label stack */
5992 sym_pop(&local_stack
, NULL
); /* reset local stack */
5993 /* end of function */
5995 put_stabn(N_FUN
, 0, 0, ind
- func_ind
);
5997 funcname
= ""; /* for safety */
5998 func_vt
= VT_VOID
; /* for safety */
5999 ind
= 0; /* for safety */
6001 #ifdef CONFIG_REG_VARS
6003 restore_parse_state(&saved_parse_state
);
6007 if (b
& VT_TYPEDEF
) {
6008 /* save typedefed type */
6009 /* XXX: test storage specifiers ? */
6010 sym_push(v
, t
| VT_TYPEDEF
, 0, 0);
6011 } else if ((t
& VT_BTYPE
) == VT_FUNC
) {
6012 /* external function definition */
6013 external_sym(v
, t
, 0);
6015 /* not lvalue if array */
6017 if (!(t
& VT_ARRAY
))
6018 r
|= lvalue_type(t
);
6019 if (b
& VT_EXTERN
) {
6020 /* external variable */
6021 external_sym(v
, t
, r
);
6027 has_init
= (tok
== '=');
6030 addr
= decl_initializer_alloc(t
, &ad
, r
,
6032 if (l
== VT_CONST
) {
6033 /* global scope: see if already defined */
6037 if (!is_compatible_types(sym
->t
, t
))
6038 error("incompatible types for redefinition of '%s'",
6039 get_tok_str(v
, NULL
));
6040 if (!(sym
->r
& VT_FORWARD
))
6041 error("redefinition of '%s'", get_tok_str(v
, NULL
));
6042 greloc_patch(sym
, addr
);
6045 sym_push(v
, t
, r
, addr
);
6059 /* put all global symbols in the extern stack and do all the
6060 resolving which can be done without using external symbols from DLLs */
6061 /* XXX: could try to verify types, but would not to save them in
6063 void resolve_global_syms(void)
6065 Sym
*s
, *s1
, *ext_sym
;
6068 s
= global_stack
.top
;
6071 /* do not save static or typedefed symbols or types */
6072 if (!(s
->t
& (VT_STATIC
| VT_TYPEDEF
)) &&
6073 !(s
->v
& (SYM_FIELD
| SYM_STRUCT
)) &&
6074 (s
->v
< SYM_FIRST_ANOM
)) {
6075 ext_sym
= sym_find1(&extern_stack
, s
->v
);
6077 /* if the symbol do not exist, we simply save it */
6078 ext_sym
= sym_push1(&extern_stack
, s
->v
, s
->t
, s
->c
);
6080 } else if (ext_sym
->r
& VT_FORWARD
) {
6081 /* external symbol already exists, but only as forward
6083 if (!(s
->r
& VT_FORWARD
)) {
6084 /* s is not forward, so we can relocate all symbols */
6085 greloc_patch(ext_sym
, s
->c
);
6087 /* the two symbols are forward: merge them */
6088 p
= (Reloc
**)&ext_sym
->c
;
6094 /* external symbol already exists and is defined :
6095 patch all references to it */
6096 if (!(s
->r
& VT_FORWARD
))
6097 error("'%s' defined twice", get_tok_str(s
->v
, NULL
));
6098 greloc_patch(s
, ext_sym
->c
);
6105 /* compile the C file opened in 'file'. Return non zero if errors. */
6106 int tcc_compile(TCCState
*s
)
6112 include_stack_ptr
= include_stack
;
6113 ifdef_stack_ptr
= ifdef_stack
;
6116 anon_sym
= SYM_FIRST_ANOM
;
6118 /* file info: full path + filename */
6120 getcwd(buf
, sizeof(buf
));
6121 pstrcat(buf
, sizeof(buf
), "/");
6122 put_stabs(buf
, N_SO
, 0, 0, (unsigned long)text_section
->data_ptr
);
6123 put_stabs(file
->filename
, N_SO
, 0, 0,
6124 (unsigned long)text_section
->data_ptr
);
6126 /* define common 'char *' type because it is often used internally
6127 for arrays and struct dereference */
6128 char_pointer_type
= mk_pointer(VT_BYTE
);
6130 define_start
= define_stack
.top
;
6132 ch
= '\n'; /* needed to parse correctly first preprocessor command */
6136 expect("declaration");
6138 /* end of translation unit info */
6140 put_stabn(N_SO
, 0, 0, (unsigned long)text_section
->data_ptr
);
6143 /* reset define stack, but leave -Dsymbols (may be incorrect if
6144 they are undefined) */
6145 sym_pop(&define_stack
, define_start
);
6147 resolve_global_syms();
6149 sym_pop(&global_stack
, NULL
);
6154 int tcc_compile_file(TCCState
*s
, const char *filename1
)
6157 file
= tcc_open(filename1
);
6159 error("file '%s' not found", filename1
);
6160 ret
= tcc_compile(s
);
6165 int tcc_compile_string(TCCState
*s
, const char *str
)
6167 BufferedFile bf1
, *bf
= &bf1
;
6170 /* init file structure */
6172 bf
->buf_ptr
= (char *)str
;
6173 bf
->buf_end
= (char *)str
+ strlen(bf
->buffer
);
6174 pstrcpy(bf
->filename
, sizeof(bf
->filename
), "<string>");
6178 ret
= tcc_compile(s
);
6180 /* currently, no need to close */
6184 /* define a symbol. A value can also be provided with the '=' operator */
6185 void tcc_define_symbol(TCCState
*s
, const char *sym
, const char *value
)
6187 BufferedFile bf1
, *bf
= &bf1
;
6189 pstrcpy(bf
->buffer
, IO_BUF_SIZE
, sym
);
6190 pstrcat(bf
->buffer
, IO_BUF_SIZE
, " ");
6194 pstrcat(bf
->buffer
, IO_BUF_SIZE
, value
);
6196 /* init file structure */
6198 bf
->buf_ptr
= bf
->buffer
;
6199 bf
->buf_end
= bf
->buffer
+ strlen(bf
->buffer
);
6200 bf
->filename
[0] = '\0';
6204 include_stack_ptr
= include_stack
;
6206 /* parse with define parser */
6208 ch
= '\n'; /* needed to parse correctly first preprocessor command */
6214 void tcc_undefine_symbol(TCCState
*s1
, const char *sym
)
6218 ts
= tok_alloc(sym
, 0);
6219 s
= sym_find1(&define_stack
, tok
);
6220 /* undefine symbol by putting an invalid name */
6222 sym_undef(&define_stack
, s
);
6225 /* open a dynamic library so that its symbol are available for
6226 compiled programs */
6227 /* XXX: open the lib only to actually run the program */
6228 int tcc_add_dll(TCCState
*s
, const char *library_name
)
6232 h
= dlopen(library_name
, RTLD_GLOBAL
| RTLD_LAZY
);
6234 error((char *)dlerror());
6238 /* If the symbol already exists, then it is redefined */
6239 int tcc_add_symbol(TCCState
*s
, const char *name
, void *value
)
6245 ts
= tok_alloc(name
, 0);
6247 ext_sym
= sym_find1(&extern_stack
, v
);
6249 if (ext_sym
->r
& VT_FORWARD
) {
6250 greloc_patch(ext_sym
, (long)value
);
6252 /* redefine symbol */
6253 ext_sym
->c
= (long)value
;
6256 ext_sym
= sym_push1(&extern_stack
, v
, VT_INT
, (long)value
);
6257 ext_sym
->r
= VT_CONST
;
6262 static void *resolve_sym(const char *sym
)
6264 #ifdef CONFIG_TCC_BCHECK
6265 if (do_bounds_check
) {
6267 ptr
= bound_resolve_sym(sym
);
6272 return dlsym(NULL
, sym
);
6275 void resolve_extern_syms(void)
6281 s
= extern_stack
.top
;
6284 if (s
->r
& VT_FORWARD
) {
6285 /* if there is at least one relocation to do, then find it
6288 str
= get_tok_str(s
->v
, NULL
);
6289 addr
= (int)resolve_sym(str
);
6291 error("unresolved external reference '%s'", str
);
6292 greloc_patch(s
, addr
);
6299 static int put_elf_str(Section
*s
, const char *sym
)
6302 offset
= s
->data_ptr
- s
->data
;
6312 static void put_elf_sym(Section
*s
,
6313 unsigned long value
, unsigned long size
,
6314 int info
, int other
, int shndx
, const char *name
)
6319 sym
= (Elf32_Sym
*)s
->data_ptr
;
6321 name_offset
= put_elf_str(s
->link
, name
);
6324 sym
->st_name
= name_offset
;
6325 sym
->st_value
= value
;
6326 sym
->st_size
= size
;
6327 sym
->st_info
= info
;
6328 sym
->st_other
= other
;
6329 sym
->st_shndx
= shndx
;
6330 s
->data_ptr
+= sizeof(Elf32_Sym
);
6333 /* put stab debug information */
6336 unsigned long n_strx
; /* index into string table of name */
6337 unsigned char n_type
; /* type of symbol */
6338 unsigned char n_other
; /* misc info (usually empty) */
6339 unsigned short n_desc
; /* description field */
6340 unsigned long n_value
; /* value of symbol */
6343 static void put_stabs(const char *str
, int type
, int other
, int desc
, int value
)
6347 sym
= (Stab_Sym
*)stab_section
->data_ptr
;
6349 sym
->n_strx
= put_elf_str(stabstr_section
, str
);
6354 sym
->n_other
= other
;
6356 sym
->n_value
= value
;
6358 stab_section
->data_ptr
+= sizeof(Stab_Sym
);
6361 static void put_stabn(int type
, int other
, int desc
, int value
)
6363 put_stabs(NULL
, type
, other
, desc
, value
);
6366 static void put_stabd(int type
, int other
, int desc
)
6368 put_stabs(NULL
, type
, other
, desc
, 0);
6371 /* output an ELF file (currently, only for testing) */
6372 /* XXX: generate dynamic reloc info + DLL tables */
6373 /* XXX: generate startup code */
6374 /* XXX: better program header generation */
6375 /* XXX: handle realloc'ed sections (instead of mmaping them) */
6376 int tcc_output_file(TCCState
*s
, const char *filename
, int file_type
)
6380 int shnum
, i
, phnum
, file_offset
, offset
, size
, j
;
6381 Section
*sec
, *strsec
;
6382 Elf32_Shdr
*shdr
, *sh
;
6383 Elf32_Phdr
*phdr
, *ph
;
6385 memset(&ehdr
, 0, sizeof(ehdr
));
6387 /* we add a section for symbols */
6388 strsec
= new_section(".shstrtab", SHT_STRTAB
, 0);
6389 put_elf_str(strsec
, "");
6391 /* count number of sections and compute number of program segments */
6392 shnum
= 1; /* section index zero is reserved */
6394 for(sec
= first_section
; sec
!= NULL
; sec
= sec
->next
) {
6396 if (sec
->sh_flags
& SHF_ALLOC
)
6399 /* allocate section headers */
6400 shdr
= malloc(shnum
* sizeof(Elf32_Shdr
));
6402 error("memory full");
6403 memset(shdr
, 0, shnum
* sizeof(Elf32_Shdr
));
6404 /* allocate program segment headers */
6405 phdr
= malloc(phnum
* sizeof(Elf32_Phdr
));
6407 error("memory full");
6408 memset(phdr
, 0, phnum
* sizeof(Elf32_Phdr
));
6410 /* XXX: find correct load order */
6411 file_offset
= sizeof(Elf32_Ehdr
) + phnum
* sizeof(Elf32_Phdr
);
6412 for(sec
= first_section
, i
= 1; sec
!= NULL
; sec
= sec
->next
, i
++) {
6414 sh
->sh_name
= put_elf_str(strsec
, sec
->name
);
6415 sh
->sh_type
= sec
->sh_type
;
6416 sh
->sh_flags
= sec
->sh_flags
;
6417 sh
->sh_entsize
= sec
->sh_entsize
;
6419 sh
->sh_link
= sec
->link
->sh_num
;
6420 if (sh
->sh_type
== SHT_STRTAB
) {
6421 sh
->sh_addralign
= 1;
6422 } else if (sh
->sh_type
== SHT_SYMTAB
||
6423 (sh
->sh_flags
& SHF_ALLOC
) == 0) {
6424 sh
->sh_addralign
= 4;
6426 sh
->sh_addr
= (Elf32_Word
)sec
->data
;
6427 sh
->sh_addralign
= 4096;
6429 sh
->sh_size
= (Elf32_Word
)sec
->data_ptr
- (Elf32_Word
)sec
->data
;
6430 /* align to section start */
6431 file_offset
= (file_offset
+ sh
->sh_addralign
- 1) &
6432 ~(sh
->sh_addralign
- 1);
6433 sh
->sh_offset
= file_offset
;
6434 file_offset
+= sh
->sh_size
;
6436 /* build program headers (simplistic - not fully correct) */
6438 for(i
=1;i
<shnum
;i
++) {
6440 if (sh
->sh_type
== SHT_PROGBITS
&&
6441 (sh
->sh_flags
& SHF_ALLOC
) != 0) {
6443 ph
->p_type
= PT_LOAD
;
6444 ph
->p_offset
= sh
->sh_offset
;
6445 ph
->p_vaddr
= sh
->sh_addr
;
6446 ph
->p_paddr
= ph
->p_vaddr
;
6447 ph
->p_filesz
= sh
->sh_size
;
6448 ph
->p_memsz
= sh
->sh_size
;
6450 if (sh
->sh_flags
& SHF_WRITE
)
6451 ph
->p_flags
|= PF_W
;
6452 if (sh
->sh_flags
& SHF_EXECINSTR
)
6453 ph
->p_flags
|= PF_X
;
6454 ph
->p_align
= sh
->sh_addralign
;
6459 file_offset
= (file_offset
+ 3) & -4;
6462 ehdr
.e_ident
[0] = ELFMAG0
;
6463 ehdr
.e_ident
[1] = ELFMAG1
;
6464 ehdr
.e_ident
[2] = ELFMAG2
;
6465 ehdr
.e_ident
[3] = ELFMAG3
;
6466 ehdr
.e_ident
[4] = ELFCLASS32
;
6467 ehdr
.e_ident
[5] = ELFDATA2LSB
;
6468 ehdr
.e_ident
[6] = EV_CURRENT
;
6469 ehdr
.e_type
= ET_EXEC
;
6470 ehdr
.e_machine
= EM_386
;
6471 ehdr
.e_version
= EV_CURRENT
;
6472 ehdr
.e_entry
= 0; /* XXX: patch it */
6473 ehdr
.e_phoff
= sizeof(Elf32_Ehdr
);
6474 ehdr
.e_shoff
= file_offset
;
6475 ehdr
.e_ehsize
= sizeof(Elf32_Ehdr
);
6476 ehdr
.e_phentsize
= sizeof(Elf32_Phdr
);
6477 ehdr
.e_phnum
= phnum
;
6478 ehdr
.e_shentsize
= sizeof(Elf32_Shdr
);
6479 ehdr
.e_shnum
= shnum
;
6480 ehdr
.e_shstrndx
= shnum
- 1;
6482 /* write elf file */
6483 f
= fopen(filename
, "w");
6485 error("could not write '%s'", filename
);
6486 fwrite(&ehdr
, 1, sizeof(Elf32_Ehdr
), f
);
6487 fwrite(phdr
, 1, phnum
* sizeof(Elf32_Phdr
), f
);
6488 offset
= sizeof(Elf32_Ehdr
) + phnum
* sizeof(Elf32_Phdr
);
6489 for(sec
= first_section
, i
= 1; sec
!= NULL
; sec
= sec
->next
, i
++) {
6491 while (offset
< sh
->sh_offset
) {
6495 size
= sec
->data_ptr
- sec
->data
;
6496 fwrite(sec
->data
, 1, size
, f
);
6499 while (offset
< ehdr
.e_shoff
) {
6503 fwrite(shdr
, 1, shnum
* sizeof(Elf32_Shdr
), f
);
6508 /* print the position in the source file of PC value 'pc' by reading
6509 the stabs debug information */
6510 static void rt_printline(unsigned long wanted_pc
)
6512 Stab_Sym
*sym
, *sym_end
;
6513 char func_name
[128];
6514 unsigned long func_addr
, last_pc
, pc
;
6515 const char *incl_files
[INCLUDE_STACK_SIZE
];
6516 int incl_index
, len
, last_line_num
, i
;
6517 const char *str
, *p
;
6519 func_name
[0] = '\0';
6522 last_pc
= 0xffffffff;
6524 sym
= (Stab_Sym
*)stab_section
->data
+ 1;
6525 sym_end
= (Stab_Sym
*)stab_section
->data_ptr
;
6526 while (sym
< sym_end
) {
6527 switch(sym
->n_type
) {
6528 /* function start or end */
6530 if (sym
->n_strx
== 0) {
6531 func_name
[0] = '\0';
6534 str
= stabstr_section
->data
+ sym
->n_strx
;
6535 p
= strchr(str
, ':');
6537 pstrcpy(func_name
, sizeof(func_name
), str
);
6540 if (len
> sizeof(func_name
) - 1)
6541 len
= sizeof(func_name
) - 1;
6542 memcpy(func_name
, str
, len
);
6543 func_name
[len
] = '\0';
6545 func_addr
= sym
->n_value
;
6548 /* line number info */
6550 pc
= sym
->n_value
+ func_addr
;
6551 if (wanted_pc
>= last_pc
&& wanted_pc
< pc
)
6554 last_line_num
= sym
->n_desc
;
6558 str
= stabstr_section
->data
+ sym
->n_strx
;
6560 if (incl_index
< INCLUDE_STACK_SIZE
) {
6561 incl_files
[incl_index
++] = str
;
6569 if (sym
->n_strx
== 0) {
6570 incl_index
= 0; /* end of translation unit */
6572 str
= stabstr_section
->data
+ sym
->n_strx
;
6573 /* do not add path */
6575 if (len
> 0 && str
[len
- 1] != '/')
6582 /* did not find line number info: */
6583 fprintf(stderr
, "(no debug info, pc=0x%08lx): ", wanted_pc
);
6586 for(i
= 0; i
< incl_index
- 1; i
++)
6587 fprintf(stderr
, "In file included from %s\n",
6589 if (incl_index
> 0) {
6590 fprintf(stderr
, "%s:%d: ",
6591 incl_files
[incl_index
- 1], last_line_num
);
6593 if (func_name
[0] != '\0') {
6594 fprintf(stderr
, "in function '%s()': ", func_name
);
6598 /* emit a run time error at position 'pc' */
6599 void rt_error(unsigned long pc
, const char *fmt
, ...)
6605 vfprintf(stderr
, fmt
, ap
);
6606 fprintf(stderr
, "\n");
6612 /* signal handler for fatal errors */
6613 static void sig_error(int signum
, siginfo_t
*siginf
, void *puc
)
6615 struct ucontext
*uc
= puc
;
6619 pc
= uc
->uc_mcontext
.gregs
[14];
6621 #error please put the right sigcontext field
6626 switch(siginf
->si_code
) {
6629 rt_error(pc
, "division by zero");
6632 rt_error(pc
, "floating point exception");
6638 rt_error(pc
, "dereferencing invalid pointer");
6641 rt_error(pc
, "illegal instruction");
6644 rt_error(pc
, "abort() called");
6647 rt_error(pc
, "caught signal %d", signum
);
6654 /* launch the compiled program with the given arguments */
6655 int tcc_run(TCCState
*s1
, int argc
, char **argv
)
6660 resolve_extern_syms();
6662 s
= sym_find1(&extern_stack
, TOK_MAIN
);
6663 if (!s
|| (s
->r
& VT_FORWARD
))
6664 error("main() not defined");
6668 error("debug mode currently not available for Windows");
6670 struct sigaction sigact
;
6671 /* install TCC signal handlers to print debug info on fatal
6673 sigact
.sa_flags
= SA_SIGINFO
| SA_ONESHOT
;
6674 sigact
.sa_sigaction
= sig_error
;
6675 sigemptyset(&sigact
.sa_mask
);
6676 sigaction(SIGFPE
, &sigact
, NULL
);
6677 sigaction(SIGILL
, &sigact
, NULL
);
6678 sigaction(SIGSEGV
, &sigact
, NULL
);
6679 sigaction(SIGBUS
, &sigact
, NULL
);
6680 sigaction(SIGABRT
, &sigact
, NULL
);
6684 #ifdef CONFIG_TCC_BCHECK
6685 if (do_bounds_check
) {
6688 /* add all known static regions */
6689 p
= (int *)bounds_section
->data
;
6690 p_end
= (int *)bounds_section
->data_ptr
;
6692 __bound_new_region((void *)p
[0], p
[1]);
6698 t
= (int (*)())s
->c
;
6699 return (*t
)(argc
, argv
);
6702 TCCState
*tcc_new(void)
6707 s
= malloc(sizeof(TCCState
));
6711 /* default include paths */
6712 nb_include_paths
= 0;
6713 tcc_add_include_path(s
, "/usr/include");
6714 tcc_add_include_path(s
, CONFIG_TCC_PREFIX
"/lib/tcc/include");
6716 /* add all tokens */
6717 tok_ident
= TOK_IDENT
;
6722 tok_alloc(p
, r
- p
- 1);
6726 /* standard defines */
6727 tcc_define_symbol(s
, "__STDC__", NULL
);
6729 tcc_define_symbol(s
, "__i386__", NULL
);
6731 /* tiny C specific defines */
6732 tcc_define_symbol(s
, "__TINYC__", NULL
);
6734 /* create standard sections */
6735 text_section
= new_section(".text", SHT_PROGBITS
, SHF_ALLOC
| SHF_EXECINSTR
);
6736 data_section
= new_section(".data", SHT_PROGBITS
, SHF_ALLOC
| SHF_WRITE
);
6737 /* XXX: should change type to SHT_NOBITS */
6738 bss_section
= new_section(".bss", SHT_PROGBITS
, SHF_ALLOC
| SHF_WRITE
);
6743 void tcc_delete(TCCState
*s
)
6748 int tcc_add_include_path(TCCState
*s
, const char *pathname
)
6752 if (nb_include_paths
>= INCLUDE_PATHS_MAX
)
6754 pathname1
= strdup(pathname
);
6757 include_paths
[nb_include_paths
++] = pathname1
;
6761 #if !defined(LIBTCC)
6765 printf("tcc version 0.9.8 - Tiny C Compiler - Copyright (C) 2001, 2002 Fabrice Bellard\n"
6766 "usage: tcc [-Idir] [-Dsym[=val]] [-Usym] [-llib] [-g] [-b]\n"
6767 " [-i infile] infile [infile_args...]\n"
6769 "-Idir : add include path 'dir'\n"
6770 "-Dsym[=val] : define 'sym' with value 'val'\n"
6771 "-Usym : undefine 'sym'\n"
6772 "-llib : link with dynamic library 'lib'\n"
6773 "-g : generate runtime debug info\n"
6774 #ifdef CONFIG_TCC_BCHECK
6775 "-b : compile with built-in memory and bounds checker (implies -g)\n"
6777 "-i infile : compile infile\n"
6781 int main(int argc
, char **argv
)
6792 if (optind
>= argc
) {
6802 if (tcc_add_include_path(s
, r
+ 2) < 0)
6803 error("too many include paths");
6804 } else if (r
[1] == 'D') {
6807 value
= strchr(sym
, '=');
6812 tcc_define_symbol(s
, sym
, value
);
6813 } else if (r
[1] == 'U') {
6814 tcc_undefine_symbol(s
, r
+ 2);
6815 } else if (r
[1] == 'l') {
6817 snprintf(buf
, sizeof(buf
), "lib%s.so", r
+ 2);
6818 tcc_add_dll(s
, buf
);
6819 } else if (r
[1] == 'i') {
6822 tcc_compile_file(s
, argv
[optind
++]);
6823 } else if (!strcmp(r
+ 1, "bench")) {
6825 #ifdef CONFIG_TCC_BCHECK
6826 } else if (r
[1] == 'b') {
6827 if (!do_bounds_check
) {
6828 do_bounds_check
= 1;
6830 tcc_define_symbol(s
, "__BOUNDS_CHECKING_ON", NULL
);
6831 /* create bounds sections */
6832 bounds_section
= new_section(".bounds",
6833 SHT_PROGBITS
, SHF_ALLOC
);
6834 lbounds_section
= new_section(".lbounds",
6835 SHT_PROGBITS
, SHF_ALLOC
);
6836 /* debug is implied */
6840 } else if (r
[1] == 'g') {
6841 #ifdef CONFIG_TCC_BCHECK
6848 stab_section
= new_section(".stab", SHT_PROGBITS
, 0);
6849 stab_section
->sh_entsize
= sizeof(Stab_Sym
);
6850 stabstr_section
= new_section(".stabstr", SHT_STRTAB
, 0);
6851 put_elf_str(stabstr_section
, "");
6852 stab_section
->link
= stabstr_section
;
6853 /* put first entry */
6854 put_stabs("", 0, 0, 0, 0);
6857 symtab_section
= new_section(".symtab", SHT_SYMTAB
, 0);
6858 symtab_section
->sh_entsize
= sizeof(Elf32_Sym
);
6859 strtab_section
= new_section(".strtab", SHT_STRTAB
, 0);
6860 put_elf_str(strtab_section
, "");
6861 symtab_section
->link
= strtab_section
;
6862 put_elf_sym(symtab_section
, 0, 0, 0, 0, 0, NULL
);
6864 } else if (r
[1] == 'o') {
6865 /* currently, only for testing, so not documented */
6868 outfile
= argv
[optind
++];
6870 error("invalid option -- '%s'", r
);
6874 tcc_compile_file(s
, argv
[optind
]);
6877 printf("total: %d idents, %d lines, %d bytes\n",
6878 tok_ident
- TOK_IDENT
, total_lines
, total_bytes
);
6882 tcc_output_file(s
, outfile
, TCC_FILE_EXE
);
6885 return tcc_run(s
, argc
- optind
, argv
+ optind
);