2 * TCC - Tiny C Compiler
4 * Copyright (c) 2001-2004 Fabrice Bellard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library 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 GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 #define CONFIG_TCC_STATIC
42 #include <sys/timeb.h>
46 #include <sys/ucontext.h>
49 #endif /* !CONFIG_TCCBOOT */
62 /* preprocessor debug */
64 /* include file debug */
72 /* target selection */
73 //#define TCC_TARGET_I386 /* i386 code generator */
74 //#define TCC_TARGET_ARM /* ARMv4 code generator */
75 //#define TCC_TARGET_C67 /* TMS320C67xx code generator */
77 /* default target is I386 */
78 #if !defined(TCC_TARGET_I386) && !defined(TCC_TARGET_ARM) && \
79 !defined(TCC_TARGET_C67)
80 #define TCC_TARGET_I386
83 #if !defined(WIN32) && !defined(TCC_UCLIBC) && !defined(TCC_TARGET_ARM) && \
84 !defined(TCC_TARGET_C67)
85 #define CONFIG_TCC_BCHECK /* enable bound checking code */
88 #if defined(WIN32) && !defined(TCC_TARGET_PE)
89 #define CONFIG_TCC_STATIC
92 /* define it to include assembler support */
93 #if !defined(TCC_TARGET_ARM) && !defined(TCC_TARGET_C67)
94 #define CONFIG_TCC_ASM
97 /* object format selection */
98 #if defined(TCC_TARGET_C67)
99 #define TCC_TARGET_COFF
108 /* path to find crt1.o, crti.o and crtn.o. Only needed when generating
109 executables or dlls */
110 #define CONFIG_TCC_CRT_PREFIX "/usr/lib"
112 #define INCLUDE_STACK_SIZE 32
113 #define IFDEF_STACK_SIZE 64
114 #define VSTACK_SIZE 256
115 #define STRING_MAX_SIZE 1024
116 #define PACK_STACK_SIZE 8
118 #define TOK_HASH_SIZE 8192 /* must be a power of two */
119 #define TOK_ALLOC_INCR 512 /* must be a power of two */
120 #define TOK_MAX_SIZE 4 /* token max size in int unit when stored in string */
122 /* token symbol management */
123 typedef struct TokenSym
{
124 struct TokenSym
*hash_next
;
125 struct Sym
*sym_define
; /* direct pointer to define */
126 struct Sym
*sym_label
; /* direct pointer to label */
127 struct Sym
*sym_struct
; /* direct pointer to structure */
128 struct Sym
*sym_identifier
; /* direct pointer to identifier */
129 int tok
; /* token number */
134 typedef struct CString
{
135 int size
; /* size in bytes */
136 void *data
; /* either 'char *' or 'int *' */
138 void *data_allocated
; /* if non NULL, data has been malloced */
141 /* type definition */
142 typedef struct CType
{
148 typedef union CValue
{
154 unsigned int ul
; /* address (should be unsigned long on 64 bit cpu) */
156 unsigned long long ull
;
157 struct CString
*cstr
;
163 typedef struct SValue
{
164 CType type
; /* type */
165 unsigned short r
; /* register + flags */
166 unsigned short r2
; /* second register, used for 'long long'
167 type. If not used, set to VT_CONST */
168 CValue c
; /* constant, if VT_CONST */
169 struct Sym
*sym
; /* symbol, if (VT_SYM | VT_CONST) */
172 /* symbol management */
174 int v
; /* symbol token */
175 int r
; /* associated register */
176 int c
; /* associated number */
177 CType type
; /* associated type */
178 struct Sym
*next
; /* next related symbol */
179 struct Sym
*prev
; /* prev symbol in stack */
180 struct Sym
*prev_tok
; /* previous symbol for this token */
183 /* section definition */
184 /* XXX: use directly ELF structure for parameters ? */
185 /* special flag to indicate that the section should not be linked to
187 #define SHF_PRIVATE 0x80000000
189 typedef struct Section
{
190 unsigned long data_offset
; /* current data offset */
191 unsigned char *data
; /* section data */
192 unsigned long data_allocated
; /* used for realloc() handling */
193 int sh_name
; /* elf section name (only used during output) */
194 int sh_num
; /* elf section number */
195 int sh_type
; /* elf section type */
196 int sh_flags
; /* elf section flags */
197 int sh_info
; /* elf section info */
198 int sh_addralign
; /* elf section alignment */
199 int sh_entsize
; /* elf entry size */
200 unsigned long sh_size
; /* section size (only used during output) */
201 unsigned long sh_addr
; /* address at which the section is relocated */
202 unsigned long sh_offset
; /* address at which the section is relocated */
203 int nb_hashed_syms
; /* used to resize the hash table */
204 struct Section
*link
; /* link to another section */
205 struct Section
*reloc
; /* corresponding section for relocation, if any */
206 struct Section
*hash
; /* hash table for symbols */
207 struct Section
*next
;
208 char name
[1]; /* section name */
211 typedef struct DLLReference
{
216 /* GNUC attribute definition */
217 typedef struct AttributeDef
{
221 unsigned char func_call
; /* FUNC_CDECL, FUNC_STDCALL, FUNC_FASTCALLx */
222 unsigned char dllexport
;
225 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
226 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
227 #define SYM_FIRST_ANOM 0x10000000 /* first anonymous sym */
229 /* stored in 'Sym.c' field */
230 #define FUNC_NEW 1 /* ansi function prototype */
231 #define FUNC_OLD 2 /* old function prototype */
232 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
234 /* stored in 'Sym.r' field */
235 #define FUNC_CDECL 0 /* standard c call */
236 #define FUNC_STDCALL 1 /* pascal c call */
237 #define FUNC_FASTCALL1 2 /* first param in %eax */
238 #define FUNC_FASTCALL2 3 /* first parameters in %eax, %edx */
239 #define FUNC_FASTCALL3 4 /* first parameter in %eax, %edx, %ecx */
241 /* field 'Sym.t' for macros */
242 #define MACRO_OBJ 0 /* object like macro */
243 #define MACRO_FUNC 1 /* function like macro */
245 /* field 'Sym.r' for C labels */
246 #define LABEL_DEFINED 0 /* label is defined */
247 #define LABEL_FORWARD 1 /* label is forward defined */
248 #define LABEL_DECLARED 2 /* label is declared but never used */
250 /* type_decl() types */
251 #define TYPE_ABSTRACT 1 /* type without variable */
252 #define TYPE_DIRECT 2 /* type with variable */
254 #define IO_BUF_SIZE 8192
256 typedef struct BufferedFile
{
260 int line_num
; /* current line number - here to simplify code */
261 int ifndef_macro
; /* #ifndef macro / #endif search */
262 int ifndef_macro_saved
; /* saved ifndef_macro */
263 int *ifdef_stack_ptr
; /* ifdef_stack value at the start of the file */
264 char inc_type
; /* type of include */
265 char inc_filename
[512]; /* filename specified by the user */
266 char filename
[1024]; /* current filename - here to simplify code */
267 unsigned char buffer
[IO_BUF_SIZE
+ 1]; /* extra size for CH_EOB char */
270 #define CH_EOB '\\' /* end of buffer or '\0' char in file */
271 #define CH_EOF (-1) /* end of file */
273 /* parsing state (used to save parser state to reparse part of the
274 source several times) */
275 typedef struct ParseState
{
282 /* used to record tokens */
283 typedef struct TokenString
{
290 /* include file cache, used to find files faster and also to eliminate
291 inclusion if the include file is protected by #ifndef ... #endif */
292 typedef struct CachedInclude
{
294 int hash_next
; /* -1 if none */
295 char type
; /* '"' or '>' to give include type */
296 char filename
[1]; /* path specified in #include */
299 #define CACHED_INCLUDES_HASH_SIZE 512
302 static struct BufferedFile
*file
;
305 static CString tokcstr
; /* current parsed string, if any */
306 /* additional informations about token */
307 static int tok_flags
;
308 #define TOK_FLAG_BOL 0x0001 /* beginning of line before */
309 #define TOK_FLAG_BOF 0x0002 /* beginning of file before */
310 #define TOK_FLAG_ENDIF 0x0004 /* a endif was found matching starting #ifdef */
312 static int *macro_ptr
, *macro_ptr_allocated
;
313 static int *unget_saved_macro_ptr
;
314 static int unget_saved_buffer
[TOK_MAX_SIZE
+ 1];
315 static int unget_buffer_enabled
;
316 static int parse_flags
;
317 #define PARSE_FLAG_PREPROCESS 0x0001 /* activate preprocessing */
318 #define PARSE_FLAG_TOK_NUM 0x0002 /* return numbers instead of TOK_PPNUM */
319 #define PARSE_FLAG_LINEFEED 0x0004 /* line feed is returned as a
320 token. line feed is also
322 #define PARSE_FLAG_ASM_COMMENTS 0x0008 /* '#' can be used for line comment */
324 static Section
*text_section
, *data_section
, *bss_section
; /* predefined sections */
325 static Section
*cur_text_section
; /* current section where function code is
327 #ifdef CONFIG_TCC_ASM
328 static Section
*last_text_section
; /* to handle .previous asm directive */
330 /* bound check related sections */
331 static Section
*bounds_section
; /* contains global data bound description */
332 static Section
*lbounds_section
; /* contains local data bound description */
333 /* symbol sections */
334 static Section
*symtab_section
, *strtab_section
;
337 static Section
*stab_section
, *stabstr_section
;
339 /* loc : local variable index
340 ind : output code index
342 anon_sym: anonymous symbol index
344 static int rsym
, anon_sym
, ind
, loc
;
345 /* expression generation modifiers */
346 static int const_wanted
; /* true if constant wanted */
347 static int nocode_wanted
; /* true if no code generation wanted for an expression */
348 static int global_expr
; /* true if compound literals must be allocated
349 globally (used during initializers parsing */
350 static CType func_vt
; /* current function return type (used by return
353 static int last_line_num
, last_ind
, func_ind
; /* debug last line number and pc */
354 static int tok_ident
;
355 static TokenSym
**table_ident
;
356 static TokenSym
*hash_ident
[TOK_HASH_SIZE
];
357 static char token_buf
[STRING_MAX_SIZE
+ 1];
358 static char *funcname
;
359 static Sym
*global_stack
, *local_stack
;
360 static Sym
*define_stack
;
361 static Sym
*global_label_stack
, *local_label_stack
;
362 /* symbol allocator */
363 #define SYM_POOL_NB (8192 / sizeof(Sym))
364 static Sym
*sym_free_first
;
366 static SValue vstack
[VSTACK_SIZE
], *vtop
;
367 /* some predefined types */
368 static CType char_pointer_type
, func_old_type
, int_type
;
369 /* true if isid(c) || isnum(c) */
370 static unsigned char isidnum_table
[256];
372 /* compile with debug symbol (and use them if error during execution) */
373 static int do_debug
= 0;
375 /* compile with built-in memory and bounds checker */
376 static int do_bounds_check
= 0;
378 /* display benchmark infos */
380 static int do_bench
= 0;
382 static int total_lines
;
383 static int total_bytes
;
385 /* use GNU C extensions */
386 static int gnu_ext
= 1;
388 /* use Tiny C extensions */
389 static int tcc_ext
= 1;
391 /* max number of callers shown if error */
392 static int num_callers
= 6;
393 static const char **rt_bound_error_msg
;
395 /* XXX: get rid of this ASAP */
396 static struct TCCState
*tcc_state
;
398 /* give the path of the tcc libraries */
399 static const char *tcc_lib_path
= CONFIG_TCCDIR
;
404 BufferedFile
**include_stack_ptr
;
405 int *ifdef_stack_ptr
;
407 /* include file handling */
408 char **include_paths
;
409 int nb_include_paths
;
410 char **sysinclude_paths
;
411 int nb_sysinclude_paths
;
412 CachedInclude
**cached_includes
;
413 int nb_cached_includes
;
415 char **library_paths
;
416 int nb_library_paths
;
418 /* array of all loaded dlls (including those referenced by loaded
420 DLLReference
**loaded_dlls
;
425 int nb_sections
; /* number of sections, including first dummy section */
430 unsigned long *got_offsets
;
432 /* give the correspondance from symtab indexes to dynsym indexes */
433 int *symtab_to_dynsym
;
435 /* temporary dynamic symbol sections (for dll loading) */
436 Section
*dynsymtab_section
;
437 /* exported dynamic symbol section */
440 int nostdinc
; /* if true, no standard headers are added */
441 int nostdlib
; /* if true, no standard libraries are added */
443 int nocommon
; /* if true, do not use common symbols for .bss data */
445 /* if true, static linking is performed */
448 /* if true, all symbols are exported */
451 /* if true, only link in referenced objects from archive */
454 /* address of text section */
455 unsigned long text_addr
;
458 /* output format, see TCC_OUTPUT_FORMAT_xxx */
461 /* C language options */
462 int char_is_unsigned
;
463 int leading_underscore
;
465 /* warning switches */
466 int warn_write_strings
;
467 int warn_unsupported
;
470 int warn_implicit_function_declaration
;
474 void (*error_func
)(void *opaque
, const char *msg
);
475 int error_set_jmp_enabled
;
476 jmp_buf error_jmp_buf
;
479 /* tiny assembler state */
482 /* see include_stack_ptr */
483 BufferedFile
*include_stack
[INCLUDE_STACK_SIZE
];
485 /* see ifdef_stack_ptr */
486 int ifdef_stack
[IFDEF_STACK_SIZE
];
488 /* see cached_includes */
489 int cached_includes_hash
[CACHED_INCLUDES_HASH_SIZE
];
492 int pack_stack
[PACK_STACK_SIZE
];
496 /* The current value can be: */
497 #define VT_VALMASK 0x00ff
498 #define VT_CONST 0x00f0 /* constant in vc
499 (must be first non register value) */
500 #define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */
501 #define VT_LOCAL 0x00f2 /* offset on stack */
502 #define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */
503 #define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */
504 #define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */
505 #define VT_LVAL 0x0100 /* var is an lvalue */
506 #define VT_SYM 0x0200 /* a symbol value is added */
507 #define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for
508 char/short stored in integer registers) */
509 #define VT_MUSTBOUND 0x0800 /* bound checking must be done before
510 dereferencing value */
511 #define VT_BOUNDED 0x8000 /* value is bounded. The address of the
512 bounding function call point is in vc */
513 #define VT_LVAL_BYTE 0x1000 /* lvalue is a byte */
514 #define VT_LVAL_SHORT 0x2000 /* lvalue is a short */
515 #define VT_LVAL_UNSIGNED 0x4000 /* lvalue is unsigned */
516 #define VT_LVAL_TYPE (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)
519 #define VT_INT 0 /* integer type */
520 #define VT_BYTE 1 /* signed byte type */
521 #define VT_SHORT 2 /* short type */
522 #define VT_VOID 3 /* void type */
523 #define VT_PTR 4 /* pointer */
524 #define VT_ENUM 5 /* enum definition */
525 #define VT_FUNC 6 /* function type */
526 #define VT_STRUCT 7 /* struct/union definition */
527 #define VT_FLOAT 8 /* IEEE float */
528 #define VT_DOUBLE 9 /* IEEE double */
529 #define VT_LDOUBLE 10 /* IEEE long double */
530 #define VT_BOOL 11 /* ISOC99 boolean type */
531 #define VT_LLONG 12 /* 64 bit integer */
532 #define VT_LONG 13 /* long integer (NEVER USED as type, only
534 #define VT_BTYPE 0x000f /* mask for basic type */
535 #define VT_UNSIGNED 0x0010 /* unsigned type */
536 #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
537 #define VT_BITFIELD 0x0040 /* bitfield modifier */
538 #define VT_CONSTANT 0x0800 /* const modifier */
539 #define VT_VOLATILE 0x1000 /* volatile modifier */
540 #define VT_SIGNED 0x2000 /* signed type */
543 #define VT_EXTERN 0x00000080 /* extern definition */
544 #define VT_STATIC 0x00000100 /* static variable */
545 #define VT_TYPEDEF 0x00000200 /* typedef definition */
546 #define VT_INLINE 0x00000400 /* inline definition */
548 #define VT_STRUCT_SHIFT 16 /* shift for bitfield shift values */
550 /* type mask (except storage) */
551 #define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE)
552 #define VT_TYPE (~(VT_STORAGE))
556 /* warning: the following compare tokens depend on i386 asm code */
568 #define TOK_LAND 0xa0
572 #define TOK_MID 0xa3 /* inc/dec, to void constant */
574 #define TOK_UDIV 0xb0 /* unsigned division */
575 #define TOK_UMOD 0xb1 /* unsigned modulo */
576 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
577 #define TOK_CINT 0xb3 /* number in tokc */
578 #define TOK_CCHAR 0xb4 /* char constant in tokc */
579 #define TOK_STR 0xb5 /* pointer to string in tokc */
580 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
581 #define TOK_LCHAR 0xb7
582 #define TOK_LSTR 0xb8
583 #define TOK_CFLOAT 0xb9 /* float constant */
584 #define TOK_LINENUM 0xba /* line number info */
585 #define TOK_CDOUBLE 0xc0 /* double constant */
586 #define TOK_CLDOUBLE 0xc1 /* long double constant */
587 #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
588 #define TOK_ADDC1 0xc3 /* add with carry generation */
589 #define TOK_ADDC2 0xc4 /* add with carry use */
590 #define TOK_SUBC1 0xc5 /* add with carry generation */
591 #define TOK_SUBC2 0xc6 /* add with carry use */
592 #define TOK_CUINT 0xc8 /* unsigned int constant */
593 #define TOK_CLLONG 0xc9 /* long long constant */
594 #define TOK_CULLONG 0xca /* unsigned long long constant */
595 #define TOK_ARROW 0xcb
596 #define TOK_DOTS 0xcc /* three dots */
597 #define TOK_SHR 0xcd /* unsigned shift right */
598 #define TOK_PPNUM 0xce /* preprocessor number */
600 #define TOK_SHL 0x01 /* shift left */
601 #define TOK_SAR 0x02 /* signed shift right */
603 /* assignement operators : normal operator or 0x80 */
604 #define TOK_A_MOD 0xa5
605 #define TOK_A_AND 0xa6
606 #define TOK_A_MUL 0xaa
607 #define TOK_A_ADD 0xab
608 #define TOK_A_SUB 0xad
609 #define TOK_A_DIV 0xaf
610 #define TOK_A_XOR 0xde
611 #define TOK_A_OR 0xfc
612 #define TOK_A_SHL 0x81
613 #define TOK_A_SAR 0x82
616 #define offsetof(type, field) ((size_t) &((type *)0)->field)
620 #define countof(tab) (sizeof(tab) / sizeof((tab)[0]))
623 /* WARNING: the content of this string encodes token numbers */
624 static char tok_two_chars
[] = "<=\236>=\235!=\225&&\240||\241++\244--\242==\224<<\1>>\2+=\253-=\255*=\252/=\257%=\245&=\246^=\336|=\374->\313..\250##\266";
626 #define TOK_EOF (-1) /* end of file */
627 #define TOK_LINEFEED 10 /* line feed */
629 /* all identificators and strings have token above that */
630 #define TOK_IDENT 256
632 /* only used for i386 asm opcodes definitions */
633 #define DEF_ASM(x) DEF(TOK_ASM_ ## x, #x)
636 DEF(TOK_ASM_ ## x ## b, #x "b") \
637 DEF(TOK_ASM_ ## x ## w, #x "w") \
638 DEF(TOK_ASM_ ## x ## l, #x "l") \
639 DEF(TOK_ASM_ ## x, #x)
642 DEF(TOK_ASM_ ## x ## w, #x "w") \
643 DEF(TOK_ASM_ ## x ## l, #x "l") \
644 DEF(TOK_ASM_ ## x, #x)
647 DEF(TOK_ASM_ ## f ## x ## s, "f" #x "s") \
648 DEF(TOK_ASM_ ## fi ## x ## l, "fi" #x "l") \
649 DEF(TOK_ASM_ ## f ## x ## l, "f" #x "l") \
650 DEF(TOK_ASM_ ## fi ## x ## s, "fi" #x "s")
653 DEF(TOK_ASM_ ## f ## x, "f" #x ) \
654 DEF(TOK_ASM_ ## f ## x ## p, "f" #x "p") \
657 #define DEF_ASMTEST(x) \
689 #define TOK_ASM_int TOK_INT
692 TOK_LAST
= TOK_IDENT
- 1,
693 #define DEF(id, str) id,
698 static const char tcc_keywords
[] =
699 #define DEF(id, str) str "\0"
704 #define TOK_UIDENT TOK_DEFINE
707 int __stdcall
GetModuleFileNameA(void *, char *, int);
708 void *__stdcall
GetProcAddress(void *, const char *);
709 void *__stdcall
GetModuleHandleA(const char *);
710 void *__stdcall
LoadLibraryA(const char *);
711 int __stdcall
FreeConsole(void);
713 #define snprintf _snprintf
714 #define vsnprintf _vsnprintf
716 #define strtold (long double)strtod
717 #define strtof (float)strtod
718 #define strtoll (long long)strtol
720 #elif defined(TCC_UCLIBC) || defined(__FreeBSD__)
721 /* currently incorrect */
722 long double strtold(const char *nptr
, char **endptr
)
724 return (long double)strtod(nptr
, endptr
);
726 float strtof(const char *nptr
, char **endptr
)
728 return (float)strtod(nptr
, endptr
);
731 /* XXX: need to define this to use them in non ISOC99 context */
732 extern float strtof (const char *__nptr
, char **__endptr
);
733 extern long double strtold (const char *__nptr
, char **__endptr
);
736 static char *pstrcpy(char *buf
, int buf_size
, const char *s
);
737 static char *pstrcat(char *buf
, int buf_size
, const char *s
);
738 static const char *tcc_basename(const char *name
);
740 static void next(void);
741 static void next_nomacro(void);
742 static void parse_expr_type(CType
*type
);
743 static void expr_type(CType
*type
);
744 static void unary_type(CType
*type
);
745 static void block(int *bsym
, int *csym
, int *case_sym
, int *def_sym
,
746 int case_reg
, int is_expr
);
747 static int expr_const(void);
748 static void expr_eq(void);
749 static void gexpr(void);
750 static void gen_inline_functions(void);
751 static void decl(int l
);
752 static void decl_initializer(CType
*type
, Section
*sec
, unsigned long c
,
753 int first
, int size_only
);
754 static void decl_initializer_alloc(CType
*type
, AttributeDef
*ad
, int r
,
755 int has_init
, int v
, int scope
);
757 void gv2(int rc1
, int rc2
);
758 void move_reg(int r
, int s
);
759 void save_regs(int n
);
760 void save_reg(int r
);
765 int get_reg_ex(int rc
,int rc2
);
767 static void macro_subst(TokenString
*tok_str
, Sym
**nested_list
,
768 const int *macro_str
, int can_read_stream
);
770 void force_charshort_cast(int t
);
771 static void gen_cast(CType
*type
);
773 static Sym
*sym_find(int v
);
774 static Sym
*sym_push(int v
, CType
*type
, int r
, int c
);
777 static int type_size(CType
*type
, int *a
);
778 static inline CType
*pointed_type(CType
*type
);
779 static int pointed_size(CType
*type
);
780 static int lvalue_type(int t
);
781 static int parse_btype(CType
*type
, AttributeDef
*ad
);
782 static void type_decl(CType
*type
, AttributeDef
*ad
, int *v
, int td
);
783 static int is_compatible_types(CType
*type1
, CType
*type2
);
785 int ieee_finite(double d
);
786 void error(const char *fmt
, ...);
790 void lexpand_nr(void);
791 static void vpush_global_sym(CType
*type
, int v
);
792 void vset(CType
*type
, int r
, int v
);
793 void type_to_str(char *buf
, int buf_size
,
794 CType
*type
, const char *varstr
);
795 char *get_tok_str(int v
, CValue
*cv
);
796 static Sym
*get_sym_ref(CType
*type
, Section
*sec
,
797 unsigned long offset
, unsigned long size
);
798 static Sym
*external_global_sym(int v
, CType
*type
, int r
);
800 /* section generation */
801 static void section_realloc(Section
*sec
, unsigned long new_size
);
802 static void *section_ptr_add(Section
*sec
, unsigned long size
);
803 static void put_extern_sym(Sym
*sym
, Section
*section
,
804 unsigned long value
, unsigned long size
);
805 static void greloc(Section
*s
, Sym
*sym
, unsigned long addr
, int type
);
806 static int put_elf_str(Section
*s
, const char *sym
);
807 static int put_elf_sym(Section
*s
,
808 unsigned long value
, unsigned long size
,
809 int info
, int other
, int shndx
, const char *name
);
810 static int add_elf_sym(Section
*s
, unsigned long value
, unsigned long size
,
811 int info
, int other
, int sh_num
, const char *name
);
812 static void put_elf_reloc(Section
*symtab
, Section
*s
, unsigned long offset
,
813 int type
, int symbol
);
814 static void put_stabs(const char *str
, int type
, int other
, int desc
,
815 unsigned long value
);
816 static void put_stabs_r(const char *str
, int type
, int other
, int desc
,
817 unsigned long value
, Section
*sec
, int sym_index
);
818 static void put_stabn(int type
, int other
, int desc
, int value
);
819 static void put_stabd(int type
, int other
, int desc
);
820 static int tcc_add_dll(TCCState
*s
, const char *filename
, int flags
);
822 #define AFF_PRINT_ERROR 0x0001 /* print error if file not found */
823 #define AFF_REFERENCED_DLL 0x0002 /* load a referenced dll from another dll */
824 static int tcc_add_file_internal(TCCState
*s
, const char *filename
, int flags
);
827 int tcc_output_coff(TCCState
*s1
, FILE *f
);
830 void *resolve_sym(TCCState
*s1
, const char *sym
, int type
);
831 int pe_load_def_file(struct TCCState
*s1
, FILE *fp
);
832 void pe_setup_paths(struct TCCState
*s1
, int *p_output_type
, const char **p_outfile
, char *first_file
);
833 unsigned long pe_add_runtime(struct TCCState
*s1
);
834 int tcc_output_pe(struct TCCState
*s1
, const char *filename
);
838 #ifdef CONFIG_TCC_ASM
840 typedef struct ExprValue
{
845 #define MAX_ASM_OPERANDS 30
847 typedef struct ASMOperand
{
848 int id
; /* GCC 3 optionnal identifier (0 if number only supported */
850 char asm_str
[16]; /* computed asm string for operand */
851 SValue
*vt
; /* C value of the expression */
852 int ref_index
; /* if >= 0, gives reference to a output constraint */
853 int input_index
; /* if >= 0, gives reference to an input constraint */
854 int priority
; /* priority, used to assign registers */
855 int reg
; /* if >= 0, register number used for this operand */
856 int is_llong
; /* true if double register value */
857 int is_memory
; /* true if memory operand */
858 int is_rw
; /* for '+' modifier */
861 static void asm_expr(TCCState
*s1
, ExprValue
*pe
);
862 static int asm_int_expr(TCCState
*s1
);
863 static int find_constraint(ASMOperand
*operands
, int nb_operands
,
864 const char *name
, const char **pp
);
866 static int tcc_assemble(TCCState
*s1
, int do_preprocess
);
870 static void asm_instr(void);
871 static void asm_global_instr(void);
873 /* true if float/double/long double type */
874 static inline int is_float(int t
)
878 return bt
== VT_LDOUBLE
|| bt
== VT_DOUBLE
|| bt
== VT_FLOAT
;
881 #ifdef TCC_TARGET_I386
882 #include "i386-gen.c"
885 #ifdef TCC_TARGET_ARM
889 #ifdef TCC_TARGET_C67
893 #ifdef CONFIG_TCC_STATIC
895 #define RTLD_LAZY 0x001
896 #define RTLD_NOW 0x002
897 #define RTLD_GLOBAL 0x100
898 #define RTLD_DEFAULT NULL
900 /* dummy function for profiling */
901 void *dlopen(const char *filename
, int flag
)
906 const char *dlerror(void)
911 typedef struct TCCSyms
{
916 #define TCCSYM(a) { #a, &a, },
918 /* add the symbol you want here if no dynamic linking is done */
919 static TCCSyms tcc_syms
[] = {
920 #if !defined(CONFIG_TCCBOOT)
929 void *resolve_sym(TCCState
*s1
, const char *symbol
, int type
)
933 while (p
->str
!= NULL
) {
934 if (!strcmp(p
->str
, symbol
))
941 #elif !defined(WIN32)
945 void *resolve_sym(TCCState
*s1
, const char *sym
, int type
)
947 return dlsym(RTLD_DEFAULT
, sym
);
952 /********************************************************/
954 /* we use our own 'finite' function to avoid potential problems with
955 non standard math libs */
956 /* XXX: endianness dependent */
957 int ieee_finite(double d
)
960 return ((unsigned)((p
[1] | 0x800fffff) + 1)) >> 31;
963 /* copy a string and truncate it. */
964 static char *pstrcpy(char *buf
, int buf_size
, const char *s
)
971 q_end
= buf
+ buf_size
- 1;
983 /* strcat and truncate. */
984 static char *pstrcat(char *buf
, int buf_size
, const char *s
)
989 pstrcpy(buf
+ len
, buf_size
- len
, s
);
993 static int strstart(const char *str
, const char *val
, const char **ptr
)
1009 /* memory management */
1015 static inline void tcc_free(void *ptr
)
1018 mem_cur_size
-= malloc_usable_size(ptr
);
1023 static void *tcc_malloc(unsigned long size
)
1028 error("memory full");
1030 mem_cur_size
+= malloc_usable_size(ptr
);
1031 if (mem_cur_size
> mem_max_size
)
1032 mem_max_size
= mem_cur_size
;
1037 static void *tcc_mallocz(unsigned long size
)
1040 ptr
= tcc_malloc(size
);
1041 memset(ptr
, 0, size
);
1045 static inline void *tcc_realloc(void *ptr
, unsigned long size
)
1049 mem_cur_size
-= malloc_usable_size(ptr
);
1051 ptr1
= realloc(ptr
, size
);
1053 /* NOTE: count not correct if alloc error, but not critical */
1054 mem_cur_size
+= malloc_usable_size(ptr1
);
1055 if (mem_cur_size
> mem_max_size
)
1056 mem_max_size
= mem_cur_size
;
1061 static char *tcc_strdup(const char *str
)
1064 ptr
= tcc_malloc(strlen(str
) + 1);
1069 #define free(p) use_tcc_free(p)
1070 #define malloc(s) use_tcc_malloc(s)
1071 #define realloc(p, s) use_tcc_realloc(p, s)
1073 static void dynarray_add(void ***ptab
, int *nb_ptr
, void *data
)
1080 /* every power of two we double array size */
1081 if ((nb
& (nb
- 1)) == 0) {
1086 pp
= tcc_realloc(pp
, nb_alloc
* sizeof(void *));
1088 error("memory full");
1095 /* symbol allocator */
1096 static Sym
*__sym_malloc(void)
1098 Sym
*sym_pool
, *sym
, *last_sym
;
1101 sym_pool
= tcc_malloc(SYM_POOL_NB
* sizeof(Sym
));
1103 last_sym
= sym_free_first
;
1105 for(i
= 0; i
< SYM_POOL_NB
; i
++) {
1106 sym
->next
= last_sym
;
1110 sym_free_first
= last_sym
;
1114 static inline Sym
*sym_malloc(void)
1117 sym
= sym_free_first
;
1119 sym
= __sym_malloc();
1120 sym_free_first
= sym
->next
;
1124 static inline void sym_free(Sym
*sym
)
1126 sym
->next
= sym_free_first
;
1127 sym_free_first
= sym
;
1130 Section
*new_section(TCCState
*s1
, const char *name
, int sh_type
, int sh_flags
)
1134 sec
= tcc_mallocz(sizeof(Section
) + strlen(name
));
1135 strcpy(sec
->name
, name
);
1136 sec
->sh_type
= sh_type
;
1137 sec
->sh_flags
= sh_flags
;
1144 sec
->sh_addralign
= 4;
1147 sec
->sh_addralign
= 1;
1150 sec
->sh_addralign
= 32; /* default conservative alignment */
1154 /* only add section if not private */
1155 if (!(sh_flags
& SHF_PRIVATE
)) {
1156 sec
->sh_num
= s1
->nb_sections
;
1157 dynarray_add((void ***)&s1
->sections
, &s1
->nb_sections
, sec
);
1162 static void free_section(Section
*s
)
1168 /* realloc section and set its content to zero */
1169 static void section_realloc(Section
*sec
, unsigned long new_size
)
1172 unsigned char *data
;
1174 size
= sec
->data_allocated
;
1177 while (size
< new_size
)
1179 data
= tcc_realloc(sec
->data
, size
);
1181 error("memory full");
1182 memset(data
+ sec
->data_allocated
, 0, size
- sec
->data_allocated
);
1184 sec
->data_allocated
= size
;
1187 /* reserve at least 'size' bytes in section 'sec' from
1188 sec->data_offset. */
1189 static void *section_ptr_add(Section
*sec
, unsigned long size
)
1191 unsigned long offset
, offset1
;
1193 offset
= sec
->data_offset
;
1194 offset1
= offset
+ size
;
1195 if (offset1
> sec
->data_allocated
)
1196 section_realloc(sec
, offset1
);
1197 sec
->data_offset
= offset1
;
1198 return sec
->data
+ offset
;
1201 /* return a reference to a section, and create it if it does not
1203 Section
*find_section(TCCState
*s1
, const char *name
)
1207 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1208 sec
= s1
->sections
[i
];
1209 if (!strcmp(name
, sec
->name
))
1212 /* sections are created as PROGBITS */
1213 return new_section(s1
, name
, SHT_PROGBITS
, SHF_ALLOC
);
1216 #define SECTION_ABS ((void *)1)
1218 /* update sym->c so that it points to an external symbol in section
1219 'section' with value 'value' */
1220 static void put_extern_sym2(Sym
*sym
, Section
*section
,
1221 unsigned long value
, unsigned long size
,
1222 int can_add_underscore
)
1224 int sym_type
, sym_bind
, sh_num
, info
;
1229 if (section
== NULL
)
1231 else if (section
== SECTION_ABS
)
1234 sh_num
= section
->sh_num
;
1236 if ((sym
->type
.t
& VT_BTYPE
) == VT_FUNC
)
1237 sym_type
= STT_FUNC
;
1239 sym_type
= STT_OBJECT
;
1240 if (sym
->type
.t
& VT_STATIC
)
1241 sym_bind
= STB_LOCAL
;
1243 sym_bind
= STB_GLOBAL
;
1245 name
= get_tok_str(sym
->v
, NULL
);
1246 #ifdef CONFIG_TCC_BCHECK
1247 if (do_bounds_check
) {
1250 /* XXX: avoid doing that for statics ? */
1251 /* if bound checking is activated, we change some function
1252 names by adding the "__bound" prefix */
1255 /* XXX: we rely only on malloc hooks */
1267 strcpy(buf
, "__bound_");
1274 if (tcc_state
->leading_underscore
&& can_add_underscore
) {
1276 pstrcpy(buf1
+ 1, sizeof(buf1
) - 1, name
);
1279 info
= ELF32_ST_INFO(sym_bind
, sym_type
);
1280 sym
->c
= add_elf_sym(symtab_section
, value
, size
, info
, 0, sh_num
, name
);
1282 esym
= &((Elf32_Sym
*)symtab_section
->data
)[sym
->c
];
1283 esym
->st_value
= value
;
1284 esym
->st_size
= size
;
1285 esym
->st_shndx
= sh_num
;
1289 static void put_extern_sym(Sym
*sym
, Section
*section
,
1290 unsigned long value
, unsigned long size
)
1292 put_extern_sym2(sym
, section
, value
, size
, 1);
1295 /* add a new relocation entry to symbol 'sym' in section 's' */
1296 static void greloc(Section
*s
, Sym
*sym
, unsigned long offset
, int type
)
1299 put_extern_sym(sym
, NULL
, 0, 0);
1300 /* now we can add ELF relocation info */
1301 put_elf_reloc(symtab_section
, s
, offset
, type
, sym
->c
);
1304 static inline int isid(int c
)
1306 return (c
>= 'a' && c
<= 'z') ||
1307 (c
>= 'A' && c
<= 'Z') ||
1311 static inline int isnum(int c
)
1313 return c
>= '0' && c
<= '9';
1316 static inline int isoct(int c
)
1318 return c
>= '0' && c
<= '7';
1321 static inline int toup(int c
)
1323 if (c
>= 'a' && c
<= 'z')
1324 return c
- 'a' + 'A';
1329 static void strcat_vprintf(char *buf
, int buf_size
, const char *fmt
, va_list ap
)
1333 vsnprintf(buf
+ len
, buf_size
- len
, fmt
, ap
);
1336 static void strcat_printf(char *buf
, int buf_size
, const char *fmt
, ...)
1340 strcat_vprintf(buf
, buf_size
, fmt
, ap
);
1344 void error1(TCCState
*s1
, int is_warning
, const char *fmt
, va_list ap
)
1351 for(f
= s1
->include_stack
; f
< s1
->include_stack_ptr
; f
++)
1352 strcat_printf(buf
, sizeof(buf
), "In file included from %s:%d:\n",
1353 (*f
)->filename
, (*f
)->line_num
);
1354 if (file
->line_num
> 0) {
1355 strcat_printf(buf
, sizeof(buf
),
1356 "%s:%d: ", file
->filename
, file
->line_num
);
1358 strcat_printf(buf
, sizeof(buf
),
1359 "%s: ", file
->filename
);
1362 strcat_printf(buf
, sizeof(buf
),
1366 strcat_printf(buf
, sizeof(buf
), "warning: ");
1367 strcat_vprintf(buf
, sizeof(buf
), fmt
, ap
);
1369 if (!s1
->error_func
) {
1370 /* default case: stderr */
1371 fprintf(stderr
, "%s\n", buf
);
1373 s1
->error_func(s1
->error_opaque
, buf
);
1375 if (!is_warning
|| s1
->warn_error
)
1380 void tcc_set_error_func(TCCState
*s
, void *error_opaque
,
1381 void (*error_func
)(void *opaque
, const char *msg
))
1383 s
->error_opaque
= error_opaque
;
1384 s
->error_func
= error_func
;
1388 /* error without aborting current compilation */
1389 void error_noabort(const char *fmt
, ...)
1391 TCCState
*s1
= tcc_state
;
1395 error1(s1
, 0, fmt
, ap
);
1399 void error(const char *fmt
, ...)
1401 TCCState
*s1
= tcc_state
;
1405 error1(s1
, 0, fmt
, ap
);
1407 /* better than nothing: in some cases, we accept to handle errors */
1408 if (s1
->error_set_jmp_enabled
) {
1409 longjmp(s1
->error_jmp_buf
, 1);
1411 /* XXX: eliminate this someday */
1416 void expect(const char *msg
)
1418 error("%s expected", msg
);
1421 void warning(const char *fmt
, ...)
1423 TCCState
*s1
= tcc_state
;
1430 error1(s1
, 1, fmt
, ap
);
1437 error("'%c' expected", c
);
1441 static void test_lvalue(void)
1443 if (!(vtop
->r
& VT_LVAL
))
1447 /* allocate a new token */
1448 static TokenSym
*tok_alloc_new(TokenSym
**pts
, const char *str
, int len
)
1450 TokenSym
*ts
, **ptable
;
1453 if (tok_ident
>= SYM_FIRST_ANOM
)
1454 error("memory full");
1456 /* expand token table if needed */
1457 i
= tok_ident
- TOK_IDENT
;
1458 if ((i
% TOK_ALLOC_INCR
) == 0) {
1459 ptable
= tcc_realloc(table_ident
, (i
+ TOK_ALLOC_INCR
) * sizeof(TokenSym
*));
1461 error("memory full");
1462 table_ident
= ptable
;
1465 ts
= tcc_malloc(sizeof(TokenSym
) + len
);
1466 table_ident
[i
] = ts
;
1467 ts
->tok
= tok_ident
++;
1468 ts
->sym_define
= NULL
;
1469 ts
->sym_label
= NULL
;
1470 ts
->sym_struct
= NULL
;
1471 ts
->sym_identifier
= NULL
;
1473 ts
->hash_next
= NULL
;
1474 memcpy(ts
->str
, str
, len
);
1475 ts
->str
[len
] = '\0';
1480 #define TOK_HASH_INIT 1
1481 #define TOK_HASH_FUNC(h, c) ((h) * 263 + (c))
1483 /* find a token and add it if not found */
1484 static TokenSym
*tok_alloc(const char *str
, int len
)
1486 TokenSym
*ts
, **pts
;
1492 h
= TOK_HASH_FUNC(h
, ((unsigned char *)str
)[i
]);
1493 h
&= (TOK_HASH_SIZE
- 1);
1495 pts
= &hash_ident
[h
];
1500 if (ts
->len
== len
&& !memcmp(ts
->str
, str
, len
))
1502 pts
= &(ts
->hash_next
);
1504 return tok_alloc_new(pts
, str
, len
);
1507 /* CString handling */
1509 static void cstr_realloc(CString
*cstr
, int new_size
)
1514 size
= cstr
->size_allocated
;
1516 size
= 8; /* no need to allocate a too small first string */
1517 while (size
< new_size
)
1519 data
= tcc_realloc(cstr
->data_allocated
, size
);
1521 error("memory full");
1522 cstr
->data_allocated
= data
;
1523 cstr
->size_allocated
= size
;
1528 static inline void cstr_ccat(CString
*cstr
, int ch
)
1531 size
= cstr
->size
+ 1;
1532 if (size
> cstr
->size_allocated
)
1533 cstr_realloc(cstr
, size
);
1534 ((unsigned char *)cstr
->data
)[size
- 1] = ch
;
1538 static void cstr_cat(CString
*cstr
, const char *str
)
1550 /* add a wide char */
1551 static void cstr_wccat(CString
*cstr
, int ch
)
1554 size
= cstr
->size
+ sizeof(int);
1555 if (size
> cstr
->size_allocated
)
1556 cstr_realloc(cstr
, size
);
1557 *(int *)(((unsigned char *)cstr
->data
) + size
- sizeof(int)) = ch
;
1561 static void cstr_new(CString
*cstr
)
1563 memset(cstr
, 0, sizeof(CString
));
1566 /* free string and reset it to NULL */
1567 static void cstr_free(CString
*cstr
)
1569 tcc_free(cstr
->data_allocated
);
1573 #define cstr_reset(cstr) cstr_free(cstr)
1575 /* XXX: unicode ? */
1576 static void add_char(CString
*cstr
, int c
)
1578 if (c
== '\'' || c
== '\"' || c
== '\\') {
1579 /* XXX: could be more precise if char or string */
1580 cstr_ccat(cstr
, '\\');
1582 if (c
>= 32 && c
<= 126) {
1585 cstr_ccat(cstr
, '\\');
1587 cstr_ccat(cstr
, 'n');
1589 cstr_ccat(cstr
, '0' + ((c
>> 6) & 7));
1590 cstr_ccat(cstr
, '0' + ((c
>> 3) & 7));
1591 cstr_ccat(cstr
, '0' + (c
& 7));
1596 /* XXX: buffer overflow */
1597 /* XXX: float tokens */
1598 char *get_tok_str(int v
, CValue
*cv
)
1600 static char buf
[STRING_MAX_SIZE
+ 1];
1601 static CString cstr_buf
;
1607 /* NOTE: to go faster, we give a fixed buffer for small strings */
1608 cstr_reset(&cstr_buf
);
1609 cstr_buf
.data
= buf
;
1610 cstr_buf
.size_allocated
= sizeof(buf
);
1616 /* XXX: not quite exact, but only useful for testing */
1617 sprintf(p
, "%u", cv
->ui
);
1621 /* XXX: not quite exact, but only useful for testing */
1622 sprintf(p
, "%Lu", cv
->ull
);
1626 cstr_ccat(&cstr_buf
, '\'');
1627 add_char(&cstr_buf
, cv
->i
);
1628 cstr_ccat(&cstr_buf
, '\'');
1629 cstr_ccat(&cstr_buf
, '\0');
1633 len
= cstr
->size
- 1;
1635 add_char(&cstr_buf
, ((unsigned char *)cstr
->data
)[i
]);
1636 cstr_ccat(&cstr_buf
, '\0');
1641 cstr_ccat(&cstr_buf
, '\"');
1643 len
= cstr
->size
- 1;
1645 add_char(&cstr_buf
, ((unsigned char *)cstr
->data
)[i
]);
1647 len
= (cstr
->size
/ sizeof(int)) - 1;
1649 add_char(&cstr_buf
, ((int *)cstr
->data
)[i
]);
1651 cstr_ccat(&cstr_buf
, '\"');
1652 cstr_ccat(&cstr_buf
, '\0');
1661 return strcpy(p
, "<<=");
1663 return strcpy(p
, ">>=");
1665 if (v
< TOK_IDENT
) {
1666 /* search in two bytes table */
1680 } else if (v
< tok_ident
) {
1681 return table_ident
[v
- TOK_IDENT
]->str
;
1682 } else if (v
>= SYM_FIRST_ANOM
) {
1683 /* special name for anonymous symbol */
1684 sprintf(p
, "L.%u", v
- SYM_FIRST_ANOM
);
1686 /* should never happen */
1691 return cstr_buf
.data
;
1694 /* push, without hashing */
1695 static Sym
*sym_push2(Sym
**ps
, int v
, int t
, int c
)
1709 /* find a symbol and return its associated structure. 's' is the top
1710 of the symbol stack */
1711 static Sym
*sym_find2(Sym
*s
, int v
)
1721 /* structure lookup */
1722 static inline Sym
*struct_find(int v
)
1725 if ((unsigned)v
>= (unsigned)(tok_ident
- TOK_IDENT
))
1727 return table_ident
[v
]->sym_struct
;
1730 /* find an identifier */
1731 static inline Sym
*sym_find(int v
)
1734 if ((unsigned)v
>= (unsigned)(tok_ident
- TOK_IDENT
))
1736 return table_ident
[v
]->sym_identifier
;
1739 /* push a given symbol on the symbol stack */
1740 static Sym
*sym_push(int v
, CType
*type
, int r
, int c
)
1749 s
= sym_push2(ps
, v
, type
->t
, c
);
1750 s
->type
.ref
= type
->ref
;
1752 /* don't record fields or anonymous symbols */
1754 if (!(v
& SYM_FIELD
) && (v
& ~SYM_STRUCT
) < SYM_FIRST_ANOM
) {
1755 /* record symbol in token array */
1756 ts
= table_ident
[(v
& ~SYM_STRUCT
) - TOK_IDENT
];
1758 ps
= &ts
->sym_struct
;
1760 ps
= &ts
->sym_identifier
;
1767 /* push a global identifier */
1768 static Sym
*global_identifier_push(int v
, int t
, int c
)
1771 s
= sym_push2(&global_stack
, v
, t
, c
);
1772 /* don't record anonymous symbol */
1773 if (v
< SYM_FIRST_ANOM
) {
1774 ps
= &table_ident
[v
- TOK_IDENT
]->sym_identifier
;
1775 /* modify the top most local identifier, so that
1776 sym_identifier will point to 's' when popped */
1778 ps
= &(*ps
)->prev_tok
;
1785 /* pop symbols until top reaches 'b' */
1786 static void sym_pop(Sym
**ptop
, Sym
*b
)
1796 /* remove symbol in token array */
1798 if (!(v
& SYM_FIELD
) && (v
& ~SYM_STRUCT
) < SYM_FIRST_ANOM
) {
1799 ts
= table_ident
[(v
& ~SYM_STRUCT
) - TOK_IDENT
];
1801 ps
= &ts
->sym_struct
;
1803 ps
= &ts
->sym_identifier
;
1814 BufferedFile
*tcc_open(TCCState
*s1
, const char *filename
)
1819 fd
= open(filename
, O_RDONLY
| O_BINARY
);
1822 bf
= tcc_malloc(sizeof(BufferedFile
));
1828 bf
->buf_ptr
= bf
->buffer
;
1829 bf
->buf_end
= bf
->buffer
;
1830 bf
->buffer
[0] = CH_EOB
; /* put eob symbol */
1831 pstrcpy(bf
->filename
, sizeof(bf
->filename
), filename
);
1833 bf
->ifndef_macro
= 0;
1834 bf
->ifdef_stack_ptr
= s1
->ifdef_stack_ptr
;
1835 // printf("opening '%s'\n", filename);
1839 void tcc_close(BufferedFile
*bf
)
1841 total_lines
+= bf
->line_num
;
1846 /* fill input buffer and peek next char */
1847 static int tcc_peekc_slow(BufferedFile
*bf
)
1850 /* only tries to read if really end of buffer */
1851 if (bf
->buf_ptr
>= bf
->buf_end
) {
1853 #if defined(PARSE_DEBUG)
1858 len
= read(bf
->fd
, bf
->buffer
, len
);
1865 bf
->buf_ptr
= bf
->buffer
;
1866 bf
->buf_end
= bf
->buffer
+ len
;
1867 *bf
->buf_end
= CH_EOB
;
1869 if (bf
->buf_ptr
< bf
->buf_end
) {
1870 return bf
->buf_ptr
[0];
1872 bf
->buf_ptr
= bf
->buf_end
;
1877 /* return the current character, handling end of block if necessary
1879 static int handle_eob(void)
1881 return tcc_peekc_slow(file
);
1884 /* read next char from current input file and handle end of input buffer */
1885 static inline void inp(void)
1887 ch
= *(++(file
->buf_ptr
));
1888 /* end of buffer/file handling */
1893 /* handle '\[\r]\n' */
1894 static void handle_stray(void)
1896 while (ch
== '\\') {
1901 } else if (ch
== '\r') {
1909 error("stray '\\' in program");
1914 /* skip the stray and handle the \\n case. Output an error if
1915 incorrect char after the stray */
1916 static int handle_stray1(uint8_t *p
)
1920 if (p
>= file
->buf_end
) {
1937 /* handle just the EOB case, but not stray */
1938 #define PEEKC_EOB(c, p)\
1949 /* handle the complicated stray case */
1950 #define PEEKC(c, p)\
1955 c = handle_stray1(p);\
1960 /* input with '\[\r]\n' handling. Note that this function cannot
1961 handle other characters after '\', so you cannot call it inside
1962 strings or comments */
1963 static void minp(void)
1971 /* single line C++ comments */
1972 static uint8_t *parse_line_comment(uint8_t *p
)
1980 if (c
== '\n' || c
== CH_EOF
) {
1982 } else if (c
== '\\') {
1991 } else if (c
== '\r') {
2009 static uint8_t *parse_comment(uint8_t *p
)
2015 /* fast skip loop */
2018 if (c
== '\n' || c
== '*' || c
== '\\')
2022 if (c
== '\n' || c
== '*' || c
== '\\')
2026 /* now we can handle all the cases */
2030 } else if (c
== '*') {
2036 } else if (c
== '/') {
2037 goto end_of_comment
;
2038 } else if (c
== '\\') {
2043 /* skip '\[\r]\n', otherwise just skip the stray */
2049 } else if (c
== '\r') {
2066 /* stray, eob or eof */
2071 error("unexpected end of file in comment");
2072 } else if (c
== '\\') {
2084 /* space exlcuding newline */
2085 static inline int is_space(int ch
)
2087 return ch
== ' ' || ch
== '\t' || ch
== '\v' || ch
== '\f' || ch
== '\r';
2090 static inline void skip_spaces(void)
2092 while (is_space(ch
))
2096 /* parse a string without interpreting escapes */
2097 static uint8_t *parse_pp_string(uint8_t *p
,
2098 int sep
, CString
*str
)
2106 } else if (c
== '\\') {
2111 unterminated_string
:
2112 /* XXX: indicate line number of start of string */
2113 error("missing terminating %c character", sep
);
2114 } else if (c
== '\\') {
2115 /* escape : just skip \[\r]\n */
2120 } else if (c
== '\r') {
2123 expect("'\n' after '\r'");
2126 } else if (c
== CH_EOF
) {
2127 goto unterminated_string
;
2130 cstr_ccat(str
, '\\');
2136 } else if (c
== '\n') {
2139 } else if (c
== '\r') {
2143 cstr_ccat(str
, '\r');
2159 /* skip block of text until #else, #elif or #endif. skip also pairs of
2161 void preprocess_skip(void)
2163 int a
, start_of_line
, c
;
2190 } else if (c
== '\\') {
2191 /* XXX: incorrect: should not give an error */
2192 ch
= file
->buf_ptr
[0];
2200 p
= parse_pp_string(p
, c
, NULL
);
2209 p
= parse_comment(p
);
2210 } else if (ch
== '/') {
2211 p
= parse_line_comment(p
);
2217 if (start_of_line
) {
2222 (tok
== TOK_ELSE
|| tok
== TOK_ELIF
|| tok
== TOK_ENDIF
))
2224 if (tok
== TOK_IF
|| tok
== TOK_IFDEF
|| tok
== TOK_IFNDEF
)
2226 else if (tok
== TOK_ENDIF
)
2240 /* ParseState handling */
2242 /* XXX: currently, no include file info is stored. Thus, we cannot display
2243 accurate messages if the function or data definition spans multiple
2246 /* save current parse state in 's' */
2247 void save_parse_state(ParseState
*s
)
2249 s
->line_num
= file
->line_num
;
2250 s
->macro_ptr
= macro_ptr
;
2255 /* restore parse state from 's' */
2256 void restore_parse_state(ParseState
*s
)
2258 file
->line_num
= s
->line_num
;
2259 macro_ptr
= s
->macro_ptr
;
2264 /* return the number of additional 'ints' necessary to store the
2266 static inline int tok_ext_size(int t
)
2280 error("unsupported token");
2287 return LDOUBLE_SIZE
/ 4;
2293 /* token string handling */
2295 static inline void tok_str_new(TokenString
*s
)
2299 s
->allocated_len
= 0;
2300 s
->last_line_num
= -1;
2303 static void tok_str_free(int *str
)
2308 static int *tok_str_realloc(TokenString
*s
)
2312 if (s
->allocated_len
== 0) {
2315 len
= s
->allocated_len
* 2;
2317 str
= tcc_realloc(s
->str
, len
* sizeof(int));
2319 error("memory full");
2320 s
->allocated_len
= len
;
2325 static void tok_str_add(TokenString
*s
, int t
)
2331 if (len
>= s
->allocated_len
)
2332 str
= tok_str_realloc(s
);
2337 static void tok_str_add2(TokenString
*s
, int t
, CValue
*cv
)
2344 /* allocate space for worst case */
2345 if (len
+ TOK_MAX_SIZE
> s
->allocated_len
)
2346 str
= tok_str_realloc(s
);
2355 str
[len
++] = cv
->tab
[0];
2364 nb_words
= (sizeof(CString
) + cv
->cstr
->size
+ 3) >> 2;
2365 while ((len
+ nb_words
) > s
->allocated_len
)
2366 str
= tok_str_realloc(s
);
2367 cstr
= (CString
*)(str
+ len
);
2369 cstr
->size
= cv
->cstr
->size
;
2370 cstr
->data_allocated
= NULL
;
2371 cstr
->size_allocated
= cstr
->size
;
2372 memcpy((char *)cstr
+ sizeof(CString
),
2373 cv
->cstr
->data
, cstr
->size
);
2380 #if LDOUBLE_SIZE == 8
2383 str
[len
++] = cv
->tab
[0];
2384 str
[len
++] = cv
->tab
[1];
2386 #if LDOUBLE_SIZE == 12
2388 str
[len
++] = cv
->tab
[0];
2389 str
[len
++] = cv
->tab
[1];
2390 str
[len
++] = cv
->tab
[2];
2391 #elif LDOUBLE_SIZE != 8
2392 #error add long double size support
2401 /* add the current parse token in token string 's' */
2402 static void tok_str_add_tok(TokenString
*s
)
2406 /* save line number info */
2407 if (file
->line_num
!= s
->last_line_num
) {
2408 s
->last_line_num
= file
->line_num
;
2409 cval
.i
= s
->last_line_num
;
2410 tok_str_add2(s
, TOK_LINENUM
, &cval
);
2412 tok_str_add2(s
, tok
, &tokc
);
2415 #if LDOUBLE_SIZE == 12
2416 #define LDOUBLE_GET(p, cv) \
2420 #elif LDOUBLE_SIZE == 8
2421 #define LDOUBLE_GET(p, cv) \
2425 #error add long double size support
2429 /* get a token from an integer array and increment pointer
2430 accordingly. we code it as a macro to avoid pointer aliasing. */
2431 #define TOK_GET(t, p, cv) \
2446 cv.cstr = (CString *)p; \
2447 cv.cstr->data = (char *)p + sizeof(CString);\
2448 p += (sizeof(CString) + cv.cstr->size + 3) >> 2;\
2457 case TOK_CLDOUBLE: \
2458 LDOUBLE_GET(p, cv); \
2459 p += LDOUBLE_SIZE / 4; \
2466 /* defines handling */
2467 static inline void define_push(int v
, int macro_type
, int *str
, Sym
*first_arg
)
2471 s
= sym_push2(&define_stack
, v
, macro_type
, (int)str
);
2472 s
->next
= first_arg
;
2473 table_ident
[v
- TOK_IDENT
]->sym_define
= s
;
2476 /* undefined a define symbol. Its name is just set to zero */
2477 static void define_undef(Sym
*s
)
2481 if (v
>= TOK_IDENT
&& v
< tok_ident
)
2482 table_ident
[v
- TOK_IDENT
]->sym_define
= NULL
;
2486 static inline Sym
*define_find(int v
)
2489 if ((unsigned)v
>= (unsigned)(tok_ident
- TOK_IDENT
))
2491 return table_ident
[v
]->sym_define
;
2494 /* free define stack until top reaches 'b' */
2495 static void free_defines(Sym
*b
)
2503 /* do not free args or predefined defines */
2505 tok_str_free((int *)top
->c
);
2507 if (v
>= TOK_IDENT
&& v
< tok_ident
)
2508 table_ident
[v
- TOK_IDENT
]->sym_define
= NULL
;
2516 static Sym
*label_find(int v
)
2519 if ((unsigned)v
>= (unsigned)(tok_ident
- TOK_IDENT
))
2521 return table_ident
[v
]->sym_label
;
2524 static Sym
*label_push(Sym
**ptop
, int v
, int flags
)
2527 s
= sym_push2(ptop
, v
, 0, 0);
2529 ps
= &table_ident
[v
- TOK_IDENT
]->sym_label
;
2530 if (ptop
== &global_label_stack
) {
2531 /* modify the top most local identifier, so that
2532 sym_identifier will point to 's' when popped */
2534 ps
= &(*ps
)->prev_tok
;
2541 /* pop labels until element last is reached. Look if any labels are
2542 undefined. Define symbols if '&&label' was used. */
2543 static void label_pop(Sym
**ptop
, Sym
*slast
)
2546 for(s
= *ptop
; s
!= slast
; s
= s1
) {
2548 if (s
->r
== LABEL_DECLARED
) {
2549 warning("label '%s' declared but not used", get_tok_str(s
->v
, NULL
));
2550 } else if (s
->r
== LABEL_FORWARD
) {
2551 error("label '%s' used but not defined",
2552 get_tok_str(s
->v
, NULL
));
2555 /* define corresponding symbol. A size of
2557 put_extern_sym(s
, cur_text_section
, (long)s
->next
, 1);
2561 table_ident
[s
->v
- TOK_IDENT
]->sym_label
= s
->prev_tok
;
2567 /* eval an expression for #if/#elif */
2568 static int expr_preprocess(void)
2574 while (tok
!= TOK_LINEFEED
&& tok
!= TOK_EOF
) {
2575 next(); /* do macro subst */
2576 if (tok
== TOK_DEFINED
) {
2581 c
= define_find(tok
) != 0;
2586 } else if (tok
>= TOK_IDENT
) {
2587 /* if undefined macro */
2591 tok_str_add_tok(&str
);
2593 tok_str_add(&str
, -1); /* simulate end of file */
2594 tok_str_add(&str
, 0);
2595 /* now evaluate C constant expression */
2596 macro_ptr
= str
.str
;
2600 tok_str_free(str
.str
);
2604 #if defined(PARSE_DEBUG) || defined(PP_DEBUG)
2605 static void tok_print(int *str
)
2611 TOK_GET(t
, str
, cval
);
2614 printf(" %s", get_tok_str(t
, &cval
));
2620 /* parse after #define */
2621 static void parse_define(void)
2623 Sym
*s
, *first
, **ps
;
2624 int v
, t
, varg
, is_vaargs
, c
;
2629 error("invalid macro name '%s'", get_tok_str(tok
, &tokc
));
2630 /* XXX: should check if same macro (ANSI) */
2633 /* '(' must be just after macro definition for MACRO_FUNC */
2634 c
= file
->buf_ptr
[0];
2636 c
= handle_stray1(file
->buf_ptr
);
2641 while (tok
!= ')') {
2645 if (varg
== TOK_DOTS
) {
2646 varg
= TOK___VA_ARGS__
;
2648 } else if (tok
== TOK_DOTS
&& gnu_ext
) {
2652 if (varg
< TOK_IDENT
)
2653 error("badly punctuated parameter list");
2654 s
= sym_push2(&define_stack
, varg
| SYM_FIELD
, is_vaargs
, 0);
2665 /* EOF testing necessary for '-D' handling */
2666 while (tok
!= TOK_LINEFEED
&& tok
!= TOK_EOF
) {
2667 tok_str_add2(&str
, tok
, &tokc
);
2670 tok_str_add(&str
, 0);
2672 printf("define %s %d: ", get_tok_str(v
, NULL
), t
);
2675 define_push(v
, t
, str
.str
, first
);
2678 static inline int hash_cached_include(int type
, const char *filename
)
2680 const unsigned char *s
;
2684 h
= TOK_HASH_FUNC(h
, type
);
2687 h
= TOK_HASH_FUNC(h
, *s
);
2690 h
&= (CACHED_INCLUDES_HASH_SIZE
- 1);
2694 /* XXX: use a token or a hash table to accelerate matching ? */
2695 static CachedInclude
*search_cached_include(TCCState
*s1
,
2696 int type
, const char *filename
)
2700 h
= hash_cached_include(type
, filename
);
2701 i
= s1
->cached_includes_hash
[h
];
2705 e
= s1
->cached_includes
[i
- 1];
2706 if (e
->type
== type
&& !strcmp(e
->filename
, filename
))
2713 static inline void add_cached_include(TCCState
*s1
, int type
,
2714 const char *filename
, int ifndef_macro
)
2719 if (search_cached_include(s1
, type
, filename
))
2722 printf("adding cached '%s' %s\n", filename
, get_tok_str(ifndef_macro
, NULL
));
2724 e
= tcc_malloc(sizeof(CachedInclude
) + strlen(filename
));
2728 strcpy(e
->filename
, filename
);
2729 e
->ifndef_macro
= ifndef_macro
;
2730 dynarray_add((void ***)&s1
->cached_includes
, &s1
->nb_cached_includes
, e
);
2731 /* add in hash table */
2732 h
= hash_cached_include(type
, filename
);
2733 e
->hash_next
= s1
->cached_includes_hash
[h
];
2734 s1
->cached_includes_hash
[h
] = s1
->nb_cached_includes
;
2737 static void pragma_parse(TCCState
*s1
)
2742 if (tok
== TOK_pack
) {
2745 #pragma pack(1) // set
2746 #pragma pack() // reset to default
2747 #pragma pack(push,1) // push & set
2748 #pragma pack(pop) // restore previous
2752 if (tok
== TOK_ASM_pop
) {
2754 if (s1
->pack_stack_ptr
<= s1
->pack_stack
) {
2756 error("out of pack stack");
2758 s1
->pack_stack_ptr
--;
2762 if (tok
== TOK_ASM_push
) {
2764 if (s1
->pack_stack_ptr
>= s1
->pack_stack
+ PACK_STACK_SIZE
- 1)
2766 s1
->pack_stack_ptr
++;
2769 if (tok
!= TOK_CINT
) {
2771 error("invalid pack pragma");
2774 if (val
< 1 || val
> 16 || (val
& (val
- 1)) != 0)
2778 *s1
->pack_stack_ptr
= val
;
2784 /* is_bof is true if first non space token at beginning of file */
2785 static void preprocess(int is_bof
)
2787 TCCState
*s1
= tcc_state
;
2788 int size
, i
, c
, n
, saved_parse_flags
;
2789 char buf
[1024], *q
, *p
;
2795 saved_parse_flags
= parse_flags
;
2796 parse_flags
= PARSE_FLAG_PREPROCESS
| PARSE_FLAG_TOK_NUM
|
2797 PARSE_FLAG_LINEFEED
;
2807 s
= define_find(tok
);
2808 /* undefine symbol by putting an invalid name */
2813 case TOK_INCLUDE_NEXT
:
2814 ch
= file
->buf_ptr
[0];
2815 /* XXX: incorrect if comments : use next_nomacro with a special mode */
2820 } else if (ch
== '\"') {
2823 /* XXX: better stray handling */
2826 while (ch
!= c
&& ch
!= '\n' && ch
!= CH_EOF
) {
2827 if ((q
- buf
) < sizeof(buf
) - 1)
2834 /* eat all spaces and comments after include */
2835 /* XXX: slightly incorrect */
2836 while (ch1
!= '\n' && ch1
!= CH_EOF
)
2840 /* computed #include : either we have only strings or
2841 we have anything enclosed in '<>' */
2844 if (tok
== TOK_STR
) {
2845 while (tok
!= TOK_LINEFEED
) {
2846 if (tok
!= TOK_STR
) {
2848 error("'#include' expects \"FILENAME\" or <FILENAME>");
2850 pstrcat(buf
, sizeof(buf
), (char *)tokc
.cstr
->data
);
2856 while (tok
!= TOK_LINEFEED
) {
2857 pstrcat(buf
, sizeof(buf
), get_tok_str(tok
, &tokc
));
2861 /* check syntax and remove '<>' */
2862 if (len
< 2 || buf
[0] != '<' || buf
[len
- 1] != '>')
2863 goto include_syntax
;
2864 memmove(buf
, buf
+ 1, len
- 2);
2865 buf
[len
- 2] = '\0';
2870 e
= search_cached_include(s1
, c
, buf
);
2871 if (e
&& define_find(e
->ifndef_macro
)) {
2872 /* no need to parse the include because the 'ifndef macro'
2875 printf("%s: skipping %s\n", file
->filename
, buf
);
2879 /* first search in current dir if "header.h" */
2881 p
= strrchr(file
->filename
, '/');
2883 size
= p
+ 1 - file
->filename
;
2884 if (size
> sizeof(buf1
) - 1)
2885 size
= sizeof(buf1
) - 1;
2886 memcpy(buf1
, file
->filename
, size
);
2888 pstrcat(buf1
, sizeof(buf1
), buf
);
2889 f
= tcc_open(s1
, buf1
);
2891 if (tok
== TOK_INCLUDE_NEXT
)
2897 if (s1
->include_stack_ptr
>= s1
->include_stack
+ INCLUDE_STACK_SIZE
)
2898 error("#include recursion too deep");
2899 /* now search in all the include paths */
2900 n
= s1
->nb_include_paths
+ s1
->nb_sysinclude_paths
;
2901 for(i
= 0; i
< n
; i
++) {
2903 if (i
< s1
->nb_include_paths
)
2904 path
= s1
->include_paths
[i
];
2906 path
= s1
->sysinclude_paths
[i
- s1
->nb_include_paths
];
2907 pstrcpy(buf1
, sizeof(buf1
), path
);
2908 pstrcat(buf1
, sizeof(buf1
), "/");
2909 pstrcat(buf1
, sizeof(buf1
), buf
);
2910 f
= tcc_open(s1
, buf1
);
2912 if (tok
== TOK_INCLUDE_NEXT
)
2918 error("include file '%s' not found", buf
);
2922 printf("%s: including %s\n", file
->filename
, buf1
);
2925 pstrcpy(f
->inc_filename
, sizeof(f
->inc_filename
), buf
);
2926 /* push current file in stack */
2927 /* XXX: fix current line init */
2928 *s1
->include_stack_ptr
++ = file
;
2930 /* add include file debug info */
2932 put_stabs(file
->filename
, N_BINCL
, 0, 0, 0);
2934 tok_flags
|= TOK_FLAG_BOF
| TOK_FLAG_BOL
;
2935 ch
= file
->buf_ptr
[0];
2943 c
= expr_preprocess();
2949 if (tok
< TOK_IDENT
)
2950 error("invalid argument for '#if%sdef'", c
? "n" : "");
2954 printf("#ifndef %s\n", get_tok_str(tok
, NULL
));
2956 file
->ifndef_macro
= tok
;
2959 c
= (define_find(tok
) != 0) ^ c
;
2961 if (s1
->ifdef_stack_ptr
>= s1
->ifdef_stack
+ IFDEF_STACK_SIZE
)
2962 error("memory full");
2963 *s1
->ifdef_stack_ptr
++ = c
;
2966 if (s1
->ifdef_stack_ptr
== s1
->ifdef_stack
)
2967 error("#else without matching #if");
2968 if (s1
->ifdef_stack_ptr
[-1] & 2)
2969 error("#else after #else");
2970 c
= (s1
->ifdef_stack_ptr
[-1] ^= 3);
2973 if (s1
->ifdef_stack_ptr
== s1
->ifdef_stack
)
2974 error("#elif without matching #if");
2975 c
= s1
->ifdef_stack_ptr
[-1];
2977 error("#elif after #else");
2978 /* last #if/#elif expression was true: we skip */
2981 c
= expr_preprocess();
2982 s1
->ifdef_stack_ptr
[-1] = c
;
2992 if (s1
->ifdef_stack_ptr
<= file
->ifdef_stack_ptr
)
2993 error("#endif without matching #if");
2994 s1
->ifdef_stack_ptr
--;
2995 /* '#ifndef macro' was at the start of file. Now we check if
2996 an '#endif' is exactly at the end of file */
2997 if (file
->ifndef_macro
&&
2998 s1
->ifdef_stack_ptr
== file
->ifdef_stack_ptr
) {
2999 file
->ifndef_macro_saved
= file
->ifndef_macro
;
3000 /* need to set to zero to avoid false matches if another
3001 #ifndef at middle of file */
3002 file
->ifndef_macro
= 0;
3003 while (tok
!= TOK_LINEFEED
)
3005 tok_flags
|= TOK_FLAG_ENDIF
;
3011 if (tok
!= TOK_CINT
)
3013 file
->line_num
= tokc
.i
- 1; /* the line number will be incremented after */
3015 if (tok
!= TOK_LINEFEED
) {
3018 pstrcpy(file
->filename
, sizeof(file
->filename
),
3019 (char *)tokc
.cstr
->data
);
3025 ch
= file
->buf_ptr
[0];
3028 while (ch
!= '\n' && ch
!= CH_EOF
) {
3029 if ((q
- buf
) < sizeof(buf
) - 1)
3035 error("#error %s", buf
);
3037 warning("#warning %s", buf
);
3043 if (tok
== TOK_LINEFEED
|| tok
== '!' || tok
== TOK_CINT
) {
3044 /* '!' is ignored to allow C scripts. numbers are ignored
3045 to emulate cpp behaviour */
3047 if (!(saved_parse_flags
& PARSE_FLAG_ASM_COMMENTS
))
3048 error("invalid preprocessing directive #%s", get_tok_str(tok
, &tokc
));
3052 /* ignore other preprocess commands or #! for C scripts */
3053 while (tok
!= TOK_LINEFEED
)
3056 parse_flags
= saved_parse_flags
;
3059 /* evaluate escape codes in a string. */
3060 static void parse_escape_string(CString
*outstr
, const uint8_t *buf
, int is_long
)
3075 case '0': case '1': case '2': case '3':
3076 case '4': case '5': case '6': case '7':
3077 /* at most three octal digits */
3082 n
= n
* 8 + c
- '0';
3086 n
= n
* 8 + c
- '0';
3091 goto add_char_nonext
;
3097 if (c
>= 'a' && c
<= 'f')
3099 else if (c
>= 'A' && c
<= 'F')
3109 goto add_char_nonext
;
3133 goto invalid_escape
;
3143 if (c
>= '!' && c
<= '~')
3144 warning("unknown escape sequence: \'\\%c\'", c
);
3146 warning("unknown escape sequence: \'\\x%x\'", c
);
3153 cstr_ccat(outstr
, c
);
3155 cstr_wccat(outstr
, c
);
3157 /* add a trailing '\0' */
3159 cstr_ccat(outstr
, '\0');
3161 cstr_wccat(outstr
, '\0');
3164 /* we use 64 bit numbers */
3167 /* bn = (bn << shift) | or_val */
3168 void bn_lshift(unsigned int *bn
, int shift
, int or_val
)
3172 for(i
=0;i
<BN_SIZE
;i
++) {
3174 bn
[i
] = (v
<< shift
) | or_val
;
3175 or_val
= v
>> (32 - shift
);
3179 void bn_zero(unsigned int *bn
)
3182 for(i
=0;i
<BN_SIZE
;i
++) {
3187 /* parse number in null terminated string 'p' and return it in the
3189 void parse_number(const char *p
)
3191 int b
, t
, shift
, frac_bits
, s
, exp_val
, ch
;
3193 unsigned int bn
[BN_SIZE
];
3204 goto float_frac_parse
;
3205 } else if (t
== '0') {
3206 if (ch
== 'x' || ch
== 'X') {
3210 } else if (tcc_ext
&& (ch
== 'b' || ch
== 'B')) {
3216 /* parse all digits. cannot check octal numbers at this stage
3217 because of floating point constants */
3219 if (ch
>= 'a' && ch
<= 'f')
3221 else if (ch
>= 'A' && ch
<= 'F')
3229 if (q
>= token_buf
+ STRING_MAX_SIZE
) {
3231 error("number too long");
3237 ((ch
== 'e' || ch
== 'E') && b
== 10) ||
3238 ((ch
== 'p' || ch
== 'P') && (b
== 16 || b
== 2))) {
3240 /* NOTE: strtox should support that for hexa numbers, but
3241 non ISOC99 libcs do not support it, so we prefer to do
3243 /* hexadecimal or binary floats */
3244 /* XXX: handle overflows */
3256 } else if (t
>= 'a') {
3258 } else if (t
>= 'A') {
3263 bn_lshift(bn
, shift
, t
);
3270 if (t
>= 'a' && t
<= 'f') {
3272 } else if (t
>= 'A' && t
<= 'F') {
3274 } else if (t
>= '0' && t
<= '9') {
3280 error("invalid digit");
3281 bn_lshift(bn
, shift
, t
);
3286 if (ch
!= 'p' && ch
!= 'P')
3293 } else if (ch
== '-') {
3297 if (ch
< '0' || ch
> '9')
3298 expect("exponent digits");
3299 while (ch
>= '0' && ch
<= '9') {
3300 exp_val
= exp_val
* 10 + ch
- '0';
3303 exp_val
= exp_val
* s
;
3305 /* now we can generate the number */
3306 /* XXX: should patch directly float number */
3307 d
= (double)bn
[1] * 4294967296.0 + (double)bn
[0];
3308 d
= ldexp(d
, exp_val
- frac_bits
);
3313 /* float : should handle overflow */
3315 } else if (t
== 'L') {
3318 /* XXX: not large enough */
3319 tokc
.ld
= (long double)d
;
3325 /* decimal floats */
3327 if (q
>= token_buf
+ STRING_MAX_SIZE
)
3332 while (ch
>= '0' && ch
<= '9') {
3333 if (q
>= token_buf
+ STRING_MAX_SIZE
)
3339 if (ch
== 'e' || ch
== 'E') {
3340 if (q
>= token_buf
+ STRING_MAX_SIZE
)
3344 if (ch
== '-' || ch
== '+') {
3345 if (q
>= token_buf
+ STRING_MAX_SIZE
)
3350 if (ch
< '0' || ch
> '9')
3351 expect("exponent digits");
3352 while (ch
>= '0' && ch
<= '9') {
3353 if (q
>= token_buf
+ STRING_MAX_SIZE
)
3365 tokc
.f
= strtof(token_buf
, NULL
);
3366 } else if (t
== 'L') {
3369 tokc
.ld
= strtold(token_buf
, NULL
);
3372 tokc
.d
= strtod(token_buf
, NULL
);
3376 unsigned long long n
, n1
;
3379 /* integer number */
3382 if (b
== 10 && *q
== '0') {
3389 /* no need for checks except for base 10 / 8 errors */
3392 } else if (t
>= 'a') {
3394 } else if (t
>= 'A') {
3399 error("invalid digit");
3403 /* detect overflow */
3404 /* XXX: this test is not reliable */
3406 error("integer constant overflow");
3409 /* XXX: not exactly ANSI compliant */
3410 if ((n
& 0xffffffff00000000LL
) != 0) {
3415 } else if (n
> 0x7fffffff) {
3426 error("three 'l's in integer constant");
3429 if (tok
== TOK_CINT
)
3431 else if (tok
== TOK_CUINT
)
3435 } else if (t
== 'U') {
3437 error("two 'u's in integer constant");
3439 if (tok
== TOK_CINT
)
3441 else if (tok
== TOK_CLLONG
)
3448 if (tok
== TOK_CINT
|| tok
== TOK_CUINT
)
3456 #define PARSE2(c1, tok1, c2, tok2) \
3467 /* return next token without macro substitution */
3468 static inline void next_nomacro1(void)
3488 /* first look if it is in fact an end of buffer */
3489 if (p
>= file
->buf_end
) {
3493 if (p
>= file
->buf_end
)
3506 TCCState
*s1
= tcc_state
;
3507 if (parse_flags
& PARSE_FLAG_LINEFEED
) {
3509 } else if (s1
->include_stack_ptr
== s1
->include_stack
||
3510 !(parse_flags
& PARSE_FLAG_PREPROCESS
)) {
3511 /* no include left : end of file. */
3514 /* pop include file */
3516 /* test if previous '#endif' was after a #ifdef at
3518 if (tok_flags
& TOK_FLAG_ENDIF
) {
3520 printf("#endif %s\n", get_tok_str(file
->ifndef_macro_saved
, NULL
));
3522 add_cached_include(s1
, file
->inc_type
, file
->inc_filename
,
3523 file
->ifndef_macro_saved
);
3526 /* add end of include file debug info */
3528 put_stabd(N_EINCL
, 0, 0);
3530 /* pop include stack */
3532 s1
->include_stack_ptr
--;
3533 file
= *s1
->include_stack_ptr
;
3541 if (parse_flags
& PARSE_FLAG_LINEFEED
) {
3545 tok_flags
|= TOK_FLAG_BOL
;
3554 if ((tok_flags
& TOK_FLAG_BOL
) &&
3555 (parse_flags
& PARSE_FLAG_PREPROCESS
)) {
3557 preprocess(tok_flags
& TOK_FLAG_BOF
);
3563 tok
= TOK_TWOSHARPS
;
3565 if (parse_flags
& PARSE_FLAG_ASM_COMMENTS
) {
3566 p
= parse_line_comment(p
- 1);
3575 case 'a': case 'b': case 'c': case 'd':
3576 case 'e': case 'f': case 'g': case 'h':
3577 case 'i': case 'j': case 'k': case 'l':
3578 case 'm': case 'n': case 'o': case 'p':
3579 case 'q': case 'r': case 's': case 't':
3580 case 'u': case 'v': case 'w': case 'x':
3582 case 'A': case 'B': case 'C': case 'D':
3583 case 'E': case 'F': case 'G': case 'H':
3584 case 'I': case 'J': case 'K':
3585 case 'M': case 'N': case 'O': case 'P':
3586 case 'Q': case 'R': case 'S': case 'T':
3587 case 'U': case 'V': case 'W': case 'X':
3593 h
= TOK_HASH_FUNC(h
, c
);
3597 if (!isidnum_table
[c
])
3599 h
= TOK_HASH_FUNC(h
, c
);
3606 /* fast case : no stray found, so we have the full token
3607 and we have already hashed it */
3609 h
&= (TOK_HASH_SIZE
- 1);
3610 pts
= &hash_ident
[h
];
3615 if (ts
->len
== len
&& !memcmp(ts
->str
, p1
, len
))
3617 pts
= &(ts
->hash_next
);
3619 ts
= tok_alloc_new(pts
, p1
, len
);
3623 cstr_reset(&tokcstr
);
3626 cstr_ccat(&tokcstr
, *p1
);
3632 while (isidnum_table
[c
]) {
3633 cstr_ccat(&tokcstr
, c
);
3636 ts
= tok_alloc(tokcstr
.data
, tokcstr
.size
);
3642 if (t
!= '\\' && t
!= '\'' && t
!= '\"') {
3644 goto parse_ident_fast
;
3647 if (c
== '\'' || c
== '\"') {
3651 cstr_reset(&tokcstr
);
3652 cstr_ccat(&tokcstr
, 'L');
3653 goto parse_ident_slow
;
3657 case '0': case '1': case '2': case '3':
3658 case '4': case '5': case '6': case '7':
3661 cstr_reset(&tokcstr
);
3662 /* after the first digit, accept digits, alpha, '.' or sign if
3663 prefixed by 'eEpP' */
3667 cstr_ccat(&tokcstr
, c
);
3669 if (!(isnum(c
) || isid(c
) || c
== '.' ||
3670 ((c
== '+' || c
== '-') &&
3671 (t
== 'e' || t
== 'E' || t
== 'p' || t
== 'P'))))
3674 /* We add a trailing '\0' to ease parsing */
3675 cstr_ccat(&tokcstr
, '\0');
3676 tokc
.cstr
= &tokcstr
;
3680 /* special dot handling because it can also start a number */
3683 cstr_reset(&tokcstr
);
3684 cstr_ccat(&tokcstr
, '.');
3686 } else if (c
== '.') {
3706 /* parse the string */
3708 p
= parse_pp_string(p
, sep
, &str
);
3709 cstr_ccat(&str
, '\0');
3711 /* eval the escape (should be done as TOK_PPNUM) */
3712 cstr_reset(&tokcstr
);
3713 parse_escape_string(&tokcstr
, str
.data
, is_long
);
3718 /* XXX: make it portable */
3722 char_size
= sizeof(int);
3723 if (tokcstr
.size
<= char_size
)
3724 error("empty character constant");
3725 if (tokcstr
.size
> 2 * char_size
)
3726 warning("multi-character character constant");
3728 tokc
.i
= *(int8_t *)tokcstr
.data
;
3731 tokc
.i
= *(int *)tokcstr
.data
;
3735 tokc
.cstr
= &tokcstr
;
3749 } else if (c
== '<') {
3767 } else if (c
== '>') {
3785 } else if (c
== '=') {
3798 } else if (c
== '=') {
3811 } else if (c
== '=') {
3824 } else if (c
== '=') {
3827 } else if (c
== '>') {
3835 PARSE2('!', '!', '=', TOK_NE
)
3836 PARSE2('=', '=', '=', TOK_EQ
)
3837 PARSE2('*', '*', '=', TOK_A_MUL
)
3838 PARSE2('%', '%', '=', TOK_A_MOD
)
3839 PARSE2('^', '^', '=', TOK_A_XOR
)
3841 /* comments or operator */
3845 p
= parse_comment(p
);
3847 } else if (c
== '/') {
3848 p
= parse_line_comment(p
);
3850 } else if (c
== '=') {
3870 case '$': /* only used in assembler */
3871 case '@': /* dito */
3876 error("unrecognized character \\x%02x", c
);
3881 #if defined(PARSE_DEBUG)
3882 printf("token = %s\n", get_tok_str(tok
, &tokc
));
3886 /* return next token without macro substitution. Can read input from
3888 static void next_nomacro(void)
3894 TOK_GET(tok
, macro_ptr
, tokc
);
3895 if (tok
== TOK_LINENUM
) {
3896 file
->line_num
= tokc
.i
;
3905 /* substitute args in macro_str and return allocated string */
3906 static int *macro_arg_subst(Sym
**nested_list
, int *macro_str
, Sym
*args
)
3908 int *st
, last_tok
, t
, notfirst
;
3917 TOK_GET(t
, macro_str
, cval
);
3922 TOK_GET(t
, macro_str
, cval
);
3925 s
= sym_find2(args
, t
);
3932 cstr_ccat(&cstr
, ' ');
3933 TOK_GET(t
, st
, cval
);
3934 cstr_cat(&cstr
, get_tok_str(t
, &cval
));
3937 cstr_ccat(&cstr
, '\0');
3939 printf("stringize: %s\n", (char *)cstr
.data
);
3943 tok_str_add2(&str
, TOK_STR
, &cval
);
3946 tok_str_add2(&str
, t
, &cval
);
3948 } else if (t
>= TOK_IDENT
) {
3949 s
= sym_find2(args
, t
);
3952 /* if '##' is present before or after, no arg substitution */
3953 if (*macro_str
== TOK_TWOSHARPS
|| last_tok
== TOK_TWOSHARPS
) {
3954 /* special case for var arg macros : ## eats the
3955 ',' if empty VA_ARGS variable. */
3956 /* XXX: test of the ',' is not 100%
3957 reliable. should fix it to avoid security
3959 if (gnu_ext
&& s
->type
.t
&&
3960 last_tok
== TOK_TWOSHARPS
&&
3961 str
.len
>= 2 && str
.str
[str
.len
- 2] == ',') {
3963 /* suppress ',' '##' */
3966 /* suppress '##' and add variable */
3974 TOK_GET(t1
, st
, cval
);
3977 tok_str_add2(&str
, t1
, &cval
);
3981 /* NOTE: the stream cannot be read when macro
3982 substituing an argument */
3983 macro_subst(&str
, nested_list
, st
, 0);
3986 tok_str_add(&str
, t
);
3989 tok_str_add2(&str
, t
, &cval
);
3993 tok_str_add(&str
, 0);
3997 static char const ab_month_name
[12][4] =
3999 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
4000 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
4003 /* do macro substitution of current token with macro 's' and add
4004 result to (tok_str,tok_len). 'nested_list' is the list of all
4005 macros we got inside to avoid recursing. Return non zero if no
4006 substitution needs to be done */
4007 static int macro_subst_tok(TokenString
*tok_str
,
4008 Sym
**nested_list
, Sym
*s
, int can_read_stream
)
4010 Sym
*args
, *sa
, *sa1
;
4011 int mstr_allocated
, parlevel
, *mstr
, t
, t1
;
4018 /* if symbol is a macro, prepare substitution */
4019 /* special macros */
4020 if (tok
== TOK___LINE__
) {
4021 snprintf(buf
, sizeof(buf
), "%d", file
->line_num
);
4025 } else if (tok
== TOK___FILE__
) {
4026 cstrval
= file
->filename
;
4028 } else if (tok
== TOK___DATE__
|| tok
== TOK___TIME__
) {
4033 tm
= localtime(&ti
);
4034 if (tok
== TOK___DATE__
) {
4035 snprintf(buf
, sizeof(buf
), "%s %2d %d",
4036 ab_month_name
[tm
->tm_mon
], tm
->tm_mday
, tm
->tm_year
+ 1900);
4038 snprintf(buf
, sizeof(buf
), "%02d:%02d:%02d",
4039 tm
->tm_hour
, tm
->tm_min
, tm
->tm_sec
);
4046 cstr_cat(&cstr
, cstrval
);
4047 cstr_ccat(&cstr
, '\0');
4049 tok_str_add2(tok_str
, t1
, &cval
);
4054 if (s
->type
.t
== MACRO_FUNC
) {
4055 /* NOTE: we do not use next_nomacro to avoid eating the
4056 next token. XXX: find better solution */
4059 if (t
== 0 && can_read_stream
) {
4060 /* end of macro stream: we must look at the token
4061 after in the file */
4067 /* XXX: incorrect with comments */
4068 ch
= file
->buf_ptr
[0];
4069 while (is_space(ch
) || ch
== '\n')
4073 if (t
!= '(') /* no macro subst */
4076 /* argument macro */
4081 /* NOTE: empty args are allowed, except if no args */
4083 /* handle '()' case */
4084 if (!args
&& !sa
&& tok
== ')')
4087 error("macro '%s' used with too many args",
4088 get_tok_str(s
->v
, 0));
4091 /* NOTE: non zero sa->t indicates VA_ARGS */
4092 while ((parlevel
> 0 ||
4094 (tok
!= ',' || sa
->type
.t
))) &&
4098 else if (tok
== ')')
4100 tok_str_add2(&str
, tok
, &tokc
);
4103 tok_str_add(&str
, 0);
4104 sym_push2(&args
, sa
->v
& ~SYM_FIELD
, sa
->type
.t
, (int)str
.str
);
4107 /* special case for gcc var args: add an empty
4108 var arg argument if it is omitted */
4109 if (sa
&& sa
->type
.t
&& gnu_ext
)
4119 error("macro '%s' used with too few args",
4120 get_tok_str(s
->v
, 0));
4123 /* now subst each arg */
4124 mstr
= macro_arg_subst(nested_list
, mstr
, args
);
4129 tok_str_free((int *)sa
->c
);
4135 sym_push2(nested_list
, s
->v
, 0, 0);
4136 macro_subst(tok_str
, nested_list
, mstr
, 1);
4137 /* pop nested defined symbol */
4139 *nested_list
= sa1
->prev
;
4147 /* handle the '##' operator. Return NULL if no '##' seen. Otherwise
4148 return the resulting string (which must be freed). */
4149 static inline int *macro_twosharps(const int *macro_str
)
4152 const int *macro_ptr1
, *start_macro_ptr
, *ptr
, *saved_macro_ptr
;
4154 const char *p1
, *p2
;
4156 TokenString macro_str1
;
4159 start_macro_ptr
= macro_str
;
4160 /* we search the first '##' */
4162 macro_ptr1
= macro_str
;
4163 TOK_GET(t
, macro_str
, cval
);
4164 /* nothing more to do if end of string */
4167 if (*macro_str
== TOK_TWOSHARPS
)
4171 /* we saw '##', so we need more processing to handle it */
4173 tok_str_new(¯o_str1
);
4177 /* add all tokens seen so far */
4178 for(ptr
= start_macro_ptr
; ptr
< macro_ptr1
;) {
4179 TOK_GET(t
, ptr
, cval
);
4180 tok_str_add2(¯o_str1
, t
, &cval
);
4182 saved_macro_ptr
= macro_ptr
;
4183 /* XXX: get rid of the use of macro_ptr here */
4184 macro_ptr
= (int *)macro_str
;
4186 while (*macro_ptr
== TOK_TWOSHARPS
) {
4188 macro_ptr1
= macro_ptr
;
4191 TOK_GET(t
, macro_ptr
, cval
);
4192 /* We concatenate the two tokens if we have an
4193 identifier or a preprocessing number */
4195 p1
= get_tok_str(tok
, &tokc
);
4196 cstr_cat(&cstr
, p1
);
4197 p2
= get_tok_str(t
, &cval
);
4198 cstr_cat(&cstr
, p2
);
4199 cstr_ccat(&cstr
, '\0');
4201 if ((tok
>= TOK_IDENT
|| tok
== TOK_PPNUM
) &&
4202 (t
>= TOK_IDENT
|| t
== TOK_PPNUM
)) {
4203 if (tok
== TOK_PPNUM
) {
4204 /* if number, then create a number token */
4205 /* NOTE: no need to allocate because
4206 tok_str_add2() does it */
4209 /* if identifier, we must do a test to
4210 validate we have a correct identifier */
4211 if (t
== TOK_PPNUM
) {
4221 if (!isnum(c
) && !isid(c
))
4225 ts
= tok_alloc(cstr
.data
, strlen(cstr
.data
));
4226 tok
= ts
->tok
; /* modify current token */
4229 const char *str
= cstr
.data
;
4230 const unsigned char *q
;
4232 /* we look for a valid token */
4233 /* XXX: do more extensive checks */
4234 if (!strcmp(str
, ">>=")) {
4236 } else if (!strcmp(str
, "<<=")) {
4238 } else if (strlen(str
) == 2) {
4239 /* search in two bytes table */
4244 if (q
[0] == str
[0] && q
[1] == str
[1])
4251 /* NOTE: because get_tok_str use a static buffer,
4254 p1
= get_tok_str(tok
, &tokc
);
4255 cstr_cat(&cstr
, p1
);
4256 cstr_ccat(&cstr
, '\0');
4257 p2
= get_tok_str(t
, &cval
);
4258 warning("pasting \"%s\" and \"%s\" does not give a valid preprocessing token", cstr
.data
, p2
);
4259 /* cannot merge tokens: just add them separately */
4260 tok_str_add2(¯o_str1
, tok
, &tokc
);
4261 /* XXX: free associated memory ? */
4268 tok_str_add2(¯o_str1
, tok
, &tokc
);
4273 macro_ptr
= (int *)saved_macro_ptr
;
4275 tok_str_add(¯o_str1
, 0);
4276 return macro_str1
.str
;
4280 /* do macro substitution of macro_str and add result to
4281 (tok_str,tok_len). 'nested_list' is the list of all macros we got
4282 inside to avoid recursing. */
4283 static void macro_subst(TokenString
*tok_str
, Sym
**nested_list
,
4284 const int *macro_str
, int can_read_stream
)
4287 int *saved_macro_ptr
, *macro_str1
;
4292 /* first scan for '##' operator handling */
4294 macro_str1
= macro_twosharps(ptr
);
4298 /* NOTE: ptr == NULL can only happen if tokens are read from
4299 file stream due to a macro function call */
4302 TOK_GET(t
, ptr
, cval
);
4307 /* if nested substitution, do nothing */
4308 if (sym_find2(*nested_list
, t
))
4310 saved_macro_ptr
= macro_ptr
;
4311 macro_ptr
= (int *)ptr
;
4313 ret
= macro_subst_tok(tok_str
, nested_list
, s
, can_read_stream
);
4314 ptr
= (int *)macro_ptr
;
4315 macro_ptr
= saved_macro_ptr
;
4320 tok_str_add2(tok_str
, t
, &cval
);
4324 tok_str_free(macro_str1
);
4327 /* return next token with macro substitution */
4328 static void next(void)
4330 Sym
*nested_list
, *s
;
4336 /* if not reading from macro substituted string, then try
4337 to substitute macros */
4338 if (tok
>= TOK_IDENT
&&
4339 (parse_flags
& PARSE_FLAG_PREPROCESS
)) {
4340 s
= define_find(tok
);
4342 /* we have a macro: we try to substitute */
4345 if (macro_subst_tok(&str
, &nested_list
, s
, 1) == 0) {
4346 /* substitution done, NOTE: maybe empty */
4347 tok_str_add(&str
, 0);
4348 macro_ptr
= str
.str
;
4349 macro_ptr_allocated
= str
.str
;
4356 /* end of macro or end of unget buffer */
4357 if (unget_buffer_enabled
) {
4358 macro_ptr
= unget_saved_macro_ptr
;
4359 unget_buffer_enabled
= 0;
4361 /* end of macro string: free it */
4362 tok_str_free(macro_ptr_allocated
);
4369 /* convert preprocessor tokens into C tokens */
4370 if (tok
== TOK_PPNUM
&&
4371 (parse_flags
& PARSE_FLAG_TOK_NUM
)) {
4372 parse_number((char *)tokc
.cstr
->data
);
4376 /* push back current token and set current token to 'last_tok'. Only
4377 identifier case handled for labels. */
4378 static inline void unget_tok(int last_tok
)
4382 unget_saved_macro_ptr
= macro_ptr
;
4383 unget_buffer_enabled
= 1;
4384 q
= unget_saved_buffer
;
4387 n
= tok_ext_size(tok
) - 1;
4390 *q
= 0; /* end of token string */
4395 void swap(int *p
, int *q
)
4403 void vsetc(CType
*type
, int r
, CValue
*vc
)
4407 if (vtop
>= vstack
+ (VSTACK_SIZE
- 1))
4408 error("memory full");
4409 /* cannot let cpu flags if other instruction are generated. Also
4410 avoid leaving VT_JMP anywhere except on the top of the stack
4411 because it would complicate the code generator. */
4412 if (vtop
>= vstack
) {
4413 v
= vtop
->r
& VT_VALMASK
;
4414 if (v
== VT_CMP
|| (v
& ~1) == VT_JMP
)
4420 vtop
->r2
= VT_CONST
;
4424 /* push integer constant */
4429 vsetc(&int_type
, VT_CONST
, &cval
);
4432 /* Return a static symbol pointing to a section */
4433 static Sym
*get_sym_ref(CType
*type
, Section
*sec
,
4434 unsigned long offset
, unsigned long size
)
4440 sym
= global_identifier_push(v
, type
->t
| VT_STATIC
, 0);
4441 sym
->type
.ref
= type
->ref
;
4442 sym
->r
= VT_CONST
| VT_SYM
;
4443 put_extern_sym(sym
, sec
, offset
, size
);
4447 /* push a reference to a section offset by adding a dummy symbol */
4448 static void vpush_ref(CType
*type
, Section
*sec
, unsigned long offset
, unsigned long size
)
4453 vsetc(type
, VT_CONST
| VT_SYM
, &cval
);
4454 vtop
->sym
= get_sym_ref(type
, sec
, offset
, size
);
4457 /* define a new external reference to a symbol 'v' of type 'u' */
4458 static Sym
*external_global_sym(int v
, CType
*type
, int r
)
4464 /* push forward reference */
4465 s
= global_identifier_push(v
, type
->t
| VT_EXTERN
, 0);
4466 s
->type
.ref
= type
->ref
;
4467 s
->r
= r
| VT_CONST
| VT_SYM
;
4472 /* define a new external reference to a symbol 'v' of type 'u' */
4473 static Sym
*external_sym(int v
, CType
*type
, int r
)
4479 /* push forward reference */
4480 s
= sym_push(v
, type
, r
| VT_CONST
| VT_SYM
, 0);
4481 s
->type
.t
|= VT_EXTERN
;
4483 if (!is_compatible_types(&s
->type
, type
))
4484 error("incompatible types for redefinition of '%s'",
4485 get_tok_str(v
, NULL
));
4490 /* push a reference to global symbol v */
4491 static void vpush_global_sym(CType
*type
, int v
)
4496 sym
= external_global_sym(v
, type
, 0);
4498 vsetc(type
, VT_CONST
| VT_SYM
, &cval
);
4502 void vset(CType
*type
, int r
, int v
)
4507 vsetc(type
, r
, &cval
);
4510 void vseti(int r
, int v
)
4526 void vpushv(SValue
*v
)
4528 if (vtop
>= vstack
+ (VSTACK_SIZE
- 1))
4529 error("memory full");
4539 /* save r to the memory stack, and mark it as being free */
4540 void save_reg(int r
)
4542 int l
, saved
, size
, align
;
4546 /* modify all stack values */
4549 for(p
=vstack
;p
<=vtop
;p
++) {
4550 if ((p
->r
& VT_VALMASK
) == r
||
4551 (p
->r2
& VT_VALMASK
) == r
) {
4552 /* must save value on stack if not already done */
4554 /* NOTE: must reload 'r' because r might be equal to r2 */
4555 r
= p
->r
& VT_VALMASK
;
4556 /* store register in the stack */
4558 if ((p
->r
& VT_LVAL
) ||
4559 (!is_float(type
->t
) && (type
->t
& VT_BTYPE
) != VT_LLONG
))
4561 size
= type_size(type
, &align
);
4562 loc
= (loc
- size
) & -align
;
4563 sv
.type
.t
= type
->t
;
4564 sv
.r
= VT_LOCAL
| VT_LVAL
;
4567 #ifdef TCC_TARGET_I386
4568 /* x86 specific: need to pop fp register ST0 if saved */
4569 if (r
== TREG_ST0
) {
4570 o(0xd9dd); /* fstp %st(1) */
4573 /* special long long case */
4574 if ((type
->t
& VT_BTYPE
) == VT_LLONG
) {
4581 /* mark that stack entry as being saved on the stack */
4582 if (p
->r
& VT_LVAL
) {
4583 /* also clear the bounded flag because the
4584 relocation address of the function was stored in
4586 p
->r
= (p
->r
& ~(VT_VALMASK
| VT_BOUNDED
)) | VT_LLOCAL
;
4588 p
->r
= lvalue_type(p
->type
.t
) | VT_LOCAL
;
4596 /* find a register of class 'rc2' with at most one reference on stack.
4597 * If none, call get_reg(rc) */
4598 int get_reg_ex(int rc
, int rc2
)
4603 for(r
=0;r
<NB_REGS
;r
++) {
4604 if (reg_classes
[r
] & rc2
) {
4607 for(p
= vstack
; p
<= vtop
; p
++) {
4608 if ((p
->r
& VT_VALMASK
) == r
||
4609 (p
->r2
& VT_VALMASK
) == r
)
4619 /* find a free register of class 'rc'. If none, save one register */
4625 /* find a free register */
4626 for(r
=0;r
<NB_REGS
;r
++) {
4627 if (reg_classes
[r
] & rc
) {
4628 for(p
=vstack
;p
<=vtop
;p
++) {
4629 if ((p
->r
& VT_VALMASK
) == r
||
4630 (p
->r2
& VT_VALMASK
) == r
)
4638 /* no register left : free the first one on the stack (VERY
4639 IMPORTANT to start from the bottom to ensure that we don't
4640 spill registers used in gen_opi()) */
4641 for(p
=vstack
;p
<=vtop
;p
++) {
4642 r
= p
->r
& VT_VALMASK
;
4643 if (r
< VT_CONST
&& (reg_classes
[r
] & rc
))
4645 /* also look at second register (if long long) */
4646 r
= p
->r2
& VT_VALMASK
;
4647 if (r
< VT_CONST
&& (reg_classes
[r
] & rc
)) {
4653 /* Should never comes here */
4657 /* save registers up to (vtop - n) stack entry */
4658 void save_regs(int n
)
4663 for(p
= vstack
;p
<= p1
; p
++) {
4664 r
= p
->r
& VT_VALMASK
;
4671 /* move register 's' to 'r', and flush previous value of r to memory
4673 void move_reg(int r
, int s
)
4686 /* get address of vtop (vtop MUST BE an lvalue) */
4689 vtop
->r
&= ~VT_LVAL
;
4690 /* tricky: if saved lvalue, then we can go back to lvalue */
4691 if ((vtop
->r
& VT_VALMASK
) == VT_LLOCAL
)
4692 vtop
->r
= (vtop
->r
& ~(VT_VALMASK
| VT_LVAL_TYPE
)) | VT_LOCAL
| VT_LVAL
;
4695 #ifdef CONFIG_TCC_BCHECK
4696 /* generate lvalue bound code */
4702 vtop
->r
&= ~VT_MUSTBOUND
;
4703 /* if lvalue, then use checking code before dereferencing */
4704 if (vtop
->r
& VT_LVAL
) {
4705 /* if not VT_BOUNDED value, then make one */
4706 if (!(vtop
->r
& VT_BOUNDED
)) {
4707 lval_type
= vtop
->r
& (VT_LVAL_TYPE
| VT_LVAL
);
4708 /* must save type because we must set it to int to get pointer */
4710 vtop
->type
.t
= VT_INT
;
4713 gen_bounded_ptr_add();
4714 vtop
->r
|= lval_type
;
4717 /* then check for dereferencing */
4718 gen_bounded_ptr_deref();
4723 /* store vtop a register belonging to class 'rc'. lvalues are
4724 converted to values. Cannot be used if cannot be converted to
4725 register value (such as structures). */
4728 int r
, r2
, rc2
, bit_pos
, bit_size
, size
, align
, i
;
4729 unsigned long long ll
;
4731 /* NOTE: get_reg can modify vstack[] */
4732 if (vtop
->type
.t
& VT_BITFIELD
) {
4733 bit_pos
= (vtop
->type
.t
>> VT_STRUCT_SHIFT
) & 0x3f;
4734 bit_size
= (vtop
->type
.t
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f;
4735 /* remove bit field info to avoid loops */
4736 vtop
->type
.t
&= ~(VT_BITFIELD
| (-1 << VT_STRUCT_SHIFT
));
4737 /* generate shifts */
4738 vpushi(32 - (bit_pos
+ bit_size
));
4740 vpushi(32 - bit_size
);
4741 /* NOTE: transformed to SHR if unsigned */
4745 if (is_float(vtop
->type
.t
) &&
4746 (vtop
->r
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
) {
4749 unsigned long offset
;
4751 /* XXX: unify with initializers handling ? */
4752 /* CPUs usually cannot use float constants, so we store them
4753 generically in data segment */
4754 size
= type_size(&vtop
->type
, &align
);
4755 offset
= (data_section
->data_offset
+ align
- 1) & -align
;
4756 data_section
->data_offset
= offset
;
4757 /* XXX: not portable yet */
4758 ptr
= section_ptr_add(data_section
, size
);
4761 ptr
[i
] = vtop
->c
.tab
[i
];
4762 sym
= get_sym_ref(&vtop
->type
, data_section
, offset
, size
<< 2);
4763 vtop
->r
|= VT_LVAL
| VT_SYM
;
4767 #ifdef CONFIG_TCC_BCHECK
4768 if (vtop
->r
& VT_MUSTBOUND
)
4772 r
= vtop
->r
& VT_VALMASK
;
4773 /* need to reload if:
4775 - lvalue (need to dereference pointer)
4776 - already a register, but not in the right class */
4777 if (r
>= VT_CONST
||
4778 (vtop
->r
& VT_LVAL
) ||
4779 !(reg_classes
[r
] & rc
) ||
4780 ((vtop
->type
.t
& VT_BTYPE
) == VT_LLONG
&&
4781 !(reg_classes
[vtop
->r2
] & rc
))) {
4783 if ((vtop
->type
.t
& VT_BTYPE
) == VT_LLONG
) {
4784 /* two register type load : expand to two words
4786 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
) {
4789 vtop
->c
.ui
= ll
; /* first word */
4791 vtop
->r
= r
; /* save register value */
4792 vpushi(ll
>> 32); /* second word */
4793 } else if (r
>= VT_CONST
|| /* XXX: test to VT_CONST incorrect ? */
4794 (vtop
->r
& VT_LVAL
)) {
4795 /* We do not want to modifier the long long
4796 pointer here, so the safest (and less
4797 efficient) is to save all the other registers
4798 in the stack. XXX: totally inefficient. */
4800 /* load from memory */
4803 vtop
[-1].r
= r
; /* save register value */
4804 /* increment pointer to get second word */
4805 vtop
->type
.t
= VT_INT
;
4811 /* move registers */
4814 vtop
[-1].r
= r
; /* save register value */
4815 vtop
->r
= vtop
[-1].r2
;
4817 /* allocate second register */
4824 /* write second register */
4826 } else if ((vtop
->r
& VT_LVAL
) && !is_float(vtop
->type
.t
)) {
4828 /* lvalue of scalar type : need to use lvalue type
4829 because of possible cast */
4832 /* compute memory access type */
4833 if (vtop
->r
& VT_LVAL_BYTE
)
4835 else if (vtop
->r
& VT_LVAL_SHORT
)
4837 if (vtop
->r
& VT_LVAL_UNSIGNED
)
4841 /* restore wanted type */
4844 /* one register type load */
4849 #ifdef TCC_TARGET_C67
4850 /* uses register pairs for doubles */
4851 if ((vtop
->type
.t
& VT_BTYPE
) == VT_DOUBLE
)
4858 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
4859 void gv2(int rc1
, int rc2
)
4863 /* generate more generic register first. But VT_JMP or VT_CMP
4864 values must be generated first in all cases to avoid possible
4866 v
= vtop
[0].r
& VT_VALMASK
;
4867 if (v
!= VT_CMP
&& (v
& ~1) != VT_JMP
&& rc1
<= rc2
) {
4872 /* test if reload is needed for first register */
4873 if ((vtop
[-1].r
& VT_VALMASK
) >= VT_CONST
) {
4883 /* test if reload is needed for first register */
4884 if ((vtop
[0].r
& VT_VALMASK
) >= VT_CONST
) {
4890 /* expand long long on stack in two int registers */
4895 u
= vtop
->type
.t
& VT_UNSIGNED
;
4898 vtop
[0].r
= vtop
[-1].r2
;
4899 vtop
[0].r2
= VT_CONST
;
4900 vtop
[-1].r2
= VT_CONST
;
4901 vtop
[0].type
.t
= VT_INT
| u
;
4902 vtop
[-1].type
.t
= VT_INT
| u
;
4905 #ifdef TCC_TARGET_ARM
4906 /* expand long long on stack */
4907 void lexpand_nr(void)
4911 u
= vtop
->type
.t
& VT_UNSIGNED
;
4913 vtop
->r2
= VT_CONST
;
4914 vtop
->type
.t
= VT_INT
| u
;
4915 v
=vtop
[-1].r
& (VT_VALMASK
| VT_LVAL
);
4916 if (v
== VT_CONST
) {
4917 vtop
[-1].c
.ui
= vtop
->c
.ull
;
4918 vtop
->c
.ui
= vtop
->c
.ull
>> 32;
4920 } else if (v
== (VT_LVAL
|VT_CONST
) || v
== (VT_LVAL
|VT_LOCAL
)) {
4922 vtop
->r
= vtop
[-1].r
;
4923 } else if (v
> VT_CONST
) {
4927 vtop
->r
= vtop
[-1].r2
;
4928 vtop
[-1].r2
= VT_CONST
;
4929 vtop
[-1].type
.t
= VT_INT
| u
;
4933 /* build a long long from two ints */
4936 gv2(RC_INT
, RC_INT
);
4937 vtop
[-1].r2
= vtop
[0].r
;
4938 vtop
[-1].type
.t
= t
;
4942 /* rotate n first stack elements to the bottom
4943 I1 ... In -> I2 ... In I1 [top is right]
4951 for(i
=-n
+1;i
!=0;i
++)
4952 vtop
[i
] = vtop
[i
+1];
4956 /* rotate n first stack elements to the top
4957 I1 ... In -> In I1 ... I(n-1) [top is right]
4965 for(i
= 0;i
< n
- 1; i
++)
4966 vtop
[-i
] = vtop
[-i
- 1];
4970 #ifdef TCC_TARGET_ARM
4971 /* like vrott but in other direction
4972 In ... I1 -> I(n-1) ... I1 In [top is right]
4980 for(i
= n
- 1; i
> 0; i
--)
4981 vtop
[-i
] = vtop
[-i
+ 1];
4986 /* pop stack value */
4990 v
= vtop
->r
& VT_VALMASK
;
4991 #ifdef TCC_TARGET_I386
4992 /* for x86, we need to pop the FP stack */
4993 if (v
== TREG_ST0
&& !nocode_wanted
) {
4994 o(0xd9dd); /* fstp %st(1) */
4997 if (v
== VT_JMP
|| v
== VT_JMPI
) {
4998 /* need to put correct jump if && or || without test */
5004 /* convert stack entry to register and duplicate its value in another
5012 if ((t
& VT_BTYPE
) == VT_LLONG
) {
5019 /* stack: H L L1 H1 */
5027 /* duplicate value */
5038 load(r1
, &sv
); /* move r to r1 */
5040 /* duplicates value */
5045 /* generate CPU independent (unsigned) long long operations */
5046 void gen_opl(int op
)
5048 int t
, a
, b
, op1
, c
, i
;
5055 func
= TOK___divdi3
;
5058 func
= TOK___udivdi3
;
5061 func
= TOK___moddi3
;
5064 func
= TOK___umoddi3
;
5066 /* call generic long long function */
5067 vpush_global_sym(&func_old_type
, func
);
5072 vtop
->r2
= REG_LRET
;
5085 /* stack: L1 H1 L2 H2 */
5090 vtop
[-2] = vtop
[-3];
5093 /* stack: H1 H2 L1 L2 */
5099 /* stack: H1 H2 L1 L2 ML MH */
5102 /* stack: ML MH H1 H2 L1 L2 */
5106 /* stack: ML MH H1 L2 H2 L1 */
5111 /* stack: ML MH M1 M2 */
5114 } else if (op
== '+' || op
== '-') {
5115 /* XXX: add non carry method too (for MIPS or alpha) */
5121 /* stack: H1 H2 (L1 op L2) */
5124 gen_op(op1
+ 1); /* TOK_xxxC2 */
5127 /* stack: H1 H2 (L1 op L2) */
5130 /* stack: (L1 op L2) H1 H2 */
5132 /* stack: (L1 op L2) (H1 op H2) */
5140 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
) {
5141 t
= vtop
[-1].type
.t
;
5145 /* stack: L H shift */
5147 /* constant: simpler */
5148 /* NOTE: all comments are for SHL. the other cases are
5149 done by swaping words */
5160 if (op
!= TOK_SAR
) {
5193 /* XXX: should provide a faster fallback on x86 ? */
5196 func
= TOK___sardi3
;
5199 func
= TOK___shrdi3
;
5202 func
= TOK___shldi3
;
5208 /* compare operations */
5214 /* stack: L1 H1 L2 H2 */
5216 vtop
[-1] = vtop
[-2];
5218 /* stack: L1 L2 H1 H2 */
5221 /* when values are equal, we need to compare low words. since
5222 the jump is inverted, we invert the test too. */
5225 else if (op1
== TOK_GT
)
5227 else if (op1
== TOK_ULT
)
5229 else if (op1
== TOK_UGT
)
5234 if (op1
!= TOK_NE
) {
5238 /* generate non equal test */
5239 /* XXX: NOT PORTABLE yet */
5243 #if defined(TCC_TARGET_I386)
5244 b
= psym(0x850f, 0);
5245 #elif defined(TCC_TARGET_ARM)
5247 o(0x1A000000 | encbranch(ind
, 0, 1));
5248 #elif defined(TCC_TARGET_C67)
5249 error("not implemented");
5251 #error not supported
5255 /* compare low. Always unsigned */
5259 else if (op1
== TOK_LE
)
5261 else if (op1
== TOK_GT
)
5263 else if (op1
== TOK_GE
)
5273 /* handle integer constant optimizations and various machine
5275 void gen_opic(int op
)
5282 /* currently, we cannot do computations with forward symbols */
5283 c1
= (v1
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
5284 c2
= (v2
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
5288 case '+': v1
->c
.i
+= fc
; break;
5289 case '-': v1
->c
.i
-= fc
; break;
5290 case '&': v1
->c
.i
&= fc
; break;
5291 case '^': v1
->c
.i
^= fc
; break;
5292 case '|': v1
->c
.i
|= fc
; break;
5293 case '*': v1
->c
.i
*= fc
; break;
5300 /* if division by zero, generate explicit division */
5303 error("division by zero in constant");
5307 default: v1
->c
.i
/= fc
; break;
5308 case '%': v1
->c
.i
%= fc
; break;
5309 case TOK_UDIV
: v1
->c
.i
= (unsigned)v1
->c
.i
/ fc
; break;
5310 case TOK_UMOD
: v1
->c
.i
= (unsigned)v1
->c
.i
% fc
; break;
5313 case TOK_SHL
: v1
->c
.i
<<= fc
; break;
5314 case TOK_SHR
: v1
->c
.i
= (unsigned)v1
->c
.i
>> fc
; break;
5315 case TOK_SAR
: v1
->c
.i
>>= fc
; break;
5317 case TOK_ULT
: v1
->c
.i
= (unsigned)v1
->c
.i
< (unsigned)fc
; break;
5318 case TOK_UGE
: v1
->c
.i
= (unsigned)v1
->c
.i
>= (unsigned)fc
; break;
5319 case TOK_EQ
: v1
->c
.i
= v1
->c
.i
== fc
; break;
5320 case TOK_NE
: v1
->c
.i
= v1
->c
.i
!= fc
; break;
5321 case TOK_ULE
: v1
->c
.i
= (unsigned)v1
->c
.i
<= (unsigned)fc
; break;
5322 case TOK_UGT
: v1
->c
.i
= (unsigned)v1
->c
.i
> (unsigned)fc
; break;
5323 case TOK_LT
: v1
->c
.i
= v1
->c
.i
< fc
; break;
5324 case TOK_GE
: v1
->c
.i
= v1
->c
.i
>= fc
; break;
5325 case TOK_LE
: v1
->c
.i
= v1
->c
.i
<= fc
; break;
5326 case TOK_GT
: v1
->c
.i
= v1
->c
.i
> fc
; break;
5328 case TOK_LAND
: v1
->c
.i
= v1
->c
.i
&& fc
; break;
5329 case TOK_LOR
: v1
->c
.i
= v1
->c
.i
|| fc
; break;
5335 /* if commutative ops, put c2 as constant */
5336 if (c1
&& (op
== '+' || op
== '&' || op
== '^' ||
5337 op
== '|' || op
== '*')) {
5342 if (c2
&& (((op
== '*' || op
== '/' || op
== TOK_UDIV
||
5345 ((op
== '+' || op
== '-' || op
== '|' || op
== '^' ||
5346 op
== TOK_SHL
|| op
== TOK_SHR
|| op
== TOK_SAR
) &&
5352 } else if (c2
&& (op
== '*' || op
== TOK_PDIV
|| op
== TOK_UDIV
)) {
5353 /* try to use shifts instead of muls or divs */
5354 if (fc
> 0 && (fc
& (fc
- 1)) == 0) {
5363 else if (op
== TOK_PDIV
)
5369 } else if (c2
&& (op
== '+' || op
== '-') &&
5370 (vtop
[-1].r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) ==
5371 (VT_CONST
| VT_SYM
)) {
5372 /* symbol + constant case */
5379 if (!nocode_wanted
) {
5380 /* call low level op generator */
5389 /* generate a floating point operation with constant propagation */
5390 void gen_opif(int op
)
5398 /* currently, we cannot do computations with forward symbols */
5399 c1
= (v1
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
5400 c2
= (v2
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
5402 if (v1
->type
.t
== VT_FLOAT
) {
5405 } else if (v1
->type
.t
== VT_DOUBLE
) {
5413 /* NOTE: we only do constant propagation if finite number (not
5414 NaN or infinity) (ANSI spec) */
5415 if (!ieee_finite(f1
) || !ieee_finite(f2
))
5419 case '+': f1
+= f2
; break;
5420 case '-': f1
-= f2
; break;
5421 case '*': f1
*= f2
; break;
5425 error("division by zero in constant");
5430 /* XXX: also handles tests ? */
5434 /* XXX: overflow test ? */
5435 if (v1
->type
.t
== VT_FLOAT
) {
5437 } else if (v1
->type
.t
== VT_DOUBLE
) {
5445 if (!nocode_wanted
) {
5453 static int pointed_size(CType
*type
)
5456 return type_size(pointed_type(type
), &align
);
5459 static inline int is_null_pointer(SValue
*p
)
5461 if ((p
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) != VT_CONST
)
5463 return ((p
->type
.t
& VT_BTYPE
) == VT_INT
&& p
->c
.i
== 0) ||
5464 ((p
->type
.t
& VT_BTYPE
) == VT_LLONG
&& p
->c
.ll
== 0);
5467 static inline int is_integer_btype(int bt
)
5469 return (bt
== VT_BYTE
|| bt
== VT_SHORT
||
5470 bt
== VT_INT
|| bt
== VT_LLONG
);
5473 /* check types for comparison or substraction of pointers */
5474 static void check_comparison_pointer_types(SValue
*p1
, SValue
*p2
, int op
)
5476 CType
*type1
, *type2
, tmp_type1
, tmp_type2
;
5479 /* null pointers are accepted for all comparisons as gcc */
5480 if (is_null_pointer(p1
) || is_null_pointer(p2
))
5484 bt1
= type1
->t
& VT_BTYPE
;
5485 bt2
= type2
->t
& VT_BTYPE
;
5486 /* accept comparison between pointer and integer with a warning */
5487 if ((is_integer_btype(bt1
) || is_integer_btype(bt2
)) && op
!= '-') {
5488 warning("comparison between pointer and integer");
5492 /* both must be pointers or implicit function pointers */
5493 if (bt1
== VT_PTR
) {
5494 type1
= pointed_type(type1
);
5495 } else if (bt1
!= VT_FUNC
)
5496 goto invalid_operands
;
5498 if (bt2
== VT_PTR
) {
5499 type2
= pointed_type(type2
);
5500 } else if (bt2
!= VT_FUNC
) {
5502 error("invalid operands to binary %s", get_tok_str(op
, NULL
));
5504 if ((type1
->t
& VT_BTYPE
) == VT_VOID
||
5505 (type2
->t
& VT_BTYPE
) == VT_VOID
)
5509 tmp_type1
.t
&= ~(VT_UNSIGNED
| VT_CONSTANT
| VT_VOLATILE
);
5510 tmp_type2
.t
&= ~(VT_UNSIGNED
| VT_CONSTANT
| VT_VOLATILE
);
5511 if (!is_compatible_types(&tmp_type1
, &tmp_type2
)) {
5512 /* gcc-like error if '-' is used */
5514 goto invalid_operands
;
5516 warning("comparison of distinct pointer types lacks a cast");
5520 /* generic gen_op: handles types problems */
5523 int u
, t1
, t2
, bt1
, bt2
, t
;
5526 t1
= vtop
[-1].type
.t
;
5527 t2
= vtop
[0].type
.t
;
5528 bt1
= t1
& VT_BTYPE
;
5529 bt2
= t2
& VT_BTYPE
;
5531 if (bt1
== VT_PTR
|| bt2
== VT_PTR
) {
5532 /* at least one operand is a pointer */
5533 /* relationnal op: must be both pointers */
5534 if (op
>= TOK_ULT
&& op
<= TOK_GT
) {
5535 check_comparison_pointer_types(vtop
- 1, vtop
, op
);
5536 /* pointers are handled are unsigned */
5537 t
= VT_INT
| VT_UNSIGNED
;
5540 /* if both pointers, then it must be the '-' op */
5541 if (bt1
== VT_PTR
&& bt2
== VT_PTR
) {
5543 error("cannot use pointers here");
5544 check_comparison_pointer_types(vtop
- 1, vtop
, op
);
5545 /* XXX: check that types are compatible */
5546 u
= pointed_size(&vtop
[-1].type
);
5548 /* set to integer type */
5549 vtop
->type
.t
= VT_INT
;
5553 /* exactly one pointer : must be '+' or '-'. */
5554 if (op
!= '-' && op
!= '+')
5555 error("cannot use pointers here");
5556 /* Put pointer as first operand */
5557 if (bt2
== VT_PTR
) {
5561 type1
= vtop
[-1].type
;
5562 /* XXX: cast to int ? (long long case) */
5563 vpushi(pointed_size(&vtop
[-1].type
));
5565 #ifdef CONFIG_TCC_BCHECK
5566 /* if evaluating constant expression, no code should be
5567 generated, so no bound check */
5568 if (do_bounds_check
&& !const_wanted
) {
5569 /* if bounded pointers, we generate a special code to
5576 gen_bounded_ptr_add();
5582 /* put again type if gen_opic() swaped operands */
5585 } else if (is_float(bt1
) || is_float(bt2
)) {
5586 /* compute bigger type and do implicit casts */
5587 if (bt1
== VT_LDOUBLE
|| bt2
== VT_LDOUBLE
) {
5589 } else if (bt1
== VT_DOUBLE
|| bt2
== VT_DOUBLE
) {
5594 /* floats can only be used for a few operations */
5595 if (op
!= '+' && op
!= '-' && op
!= '*' && op
!= '/' &&
5596 (op
< TOK_ULT
|| op
> TOK_GT
))
5597 error("invalid operands for binary operation");
5599 } else if (bt1
== VT_LLONG
|| bt2
== VT_LLONG
) {
5600 /* cast to biggest op */
5602 /* convert to unsigned if it does not fit in a long long */
5603 if ((t1
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_LLONG
| VT_UNSIGNED
) ||
5604 (t2
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_LLONG
| VT_UNSIGNED
))
5608 /* integer operations */
5610 /* convert to unsigned if it does not fit in an integer */
5611 if ((t1
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
) ||
5612 (t2
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
))
5615 /* XXX: currently, some unsigned operations are explicit, so
5616 we modify them here */
5617 if (t
& VT_UNSIGNED
) {
5624 else if (op
== TOK_LT
)
5626 else if (op
== TOK_GT
)
5628 else if (op
== TOK_LE
)
5630 else if (op
== TOK_GE
)
5637 /* special case for shifts and long long: we keep the shift as
5639 if (op
== TOK_SHR
|| op
== TOK_SAR
|| op
== TOK_SHL
)
5644 else if ((t
& VT_BTYPE
) == VT_LLONG
)
5648 if (op
>= TOK_ULT
&& op
<= TOK_GT
) {
5649 /* relationnal op: the result is an int */
5650 vtop
->type
.t
= VT_INT
;
5657 /* generic itof for unsigned long long case */
5658 void gen_cvt_itof1(int t
)
5660 if ((vtop
->type
.t
& (VT_BTYPE
| VT_UNSIGNED
)) ==
5661 (VT_LLONG
| VT_UNSIGNED
)) {
5664 vpush_global_sym(&func_old_type
, TOK___ulltof
);
5665 else if (t
== VT_DOUBLE
)
5666 vpush_global_sym(&func_old_type
, TOK___ulltod
);
5668 vpush_global_sym(&func_old_type
, TOK___ulltold
);
5678 /* generic ftoi for unsigned long long case */
5679 void gen_cvt_ftoi1(int t
)
5683 if (t
== (VT_LLONG
| VT_UNSIGNED
)) {
5684 /* not handled natively */
5685 st
= vtop
->type
.t
& VT_BTYPE
;
5687 vpush_global_sym(&func_old_type
, TOK___fixunssfdi
);
5688 else if (st
== VT_DOUBLE
)
5689 vpush_global_sym(&func_old_type
, TOK___fixunsdfdi
);
5691 vpush_global_sym(&func_old_type
, TOK___fixunsxfdi
);
5696 vtop
->r2
= REG_LRET
;
5702 /* force char or short cast */
5703 void force_charshort_cast(int t
)
5707 /* XXX: add optimization if lvalue : just change type and offset */
5712 if (t
& VT_UNSIGNED
) {
5713 vpushi((1 << bits
) - 1);
5724 /* cast 'vtop' to 'type'. Casting to bitfields is forbidden. */
5725 static void gen_cast(CType
*type
)
5727 int sbt
, dbt
, sf
, df
, c
;
5729 /* special delayed cast for char/short */
5730 /* XXX: in some cases (multiple cascaded casts), it may still
5732 if (vtop
->r
& VT_MUSTCAST
) {
5733 vtop
->r
&= ~VT_MUSTCAST
;
5734 force_charshort_cast(vtop
->type
.t
);
5737 /* bitfields first get cast to ints */
5738 if (vtop
->type
.t
& VT_BITFIELD
) {
5742 dbt
= type
->t
& (VT_BTYPE
| VT_UNSIGNED
);
5743 sbt
= vtop
->type
.t
& (VT_BTYPE
| VT_UNSIGNED
);
5745 if (sbt
!= dbt
&& !nocode_wanted
) {
5748 c
= (vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
5750 /* convert from fp to fp */
5752 /* constant case: we can do it now */
5753 /* XXX: in ISOC, cannot do it if error in convert */
5754 if (dbt
== VT_FLOAT
&& sbt
== VT_DOUBLE
)
5755 vtop
->c
.f
= (float)vtop
->c
.d
;
5756 else if (dbt
== VT_FLOAT
&& sbt
== VT_LDOUBLE
)
5757 vtop
->c
.f
= (float)vtop
->c
.ld
;
5758 else if (dbt
== VT_DOUBLE
&& sbt
== VT_FLOAT
)
5759 vtop
->c
.d
= (double)vtop
->c
.f
;
5760 else if (dbt
== VT_DOUBLE
&& sbt
== VT_LDOUBLE
)
5761 vtop
->c
.d
= (double)vtop
->c
.ld
;
5762 else if (dbt
== VT_LDOUBLE
&& sbt
== VT_FLOAT
)
5763 vtop
->c
.ld
= (long double)vtop
->c
.f
;
5764 else if (dbt
== VT_LDOUBLE
&& sbt
== VT_DOUBLE
)
5765 vtop
->c
.ld
= (long double)vtop
->c
.d
;
5767 /* non constant case: generate code */
5771 /* convert int to fp */
5774 case VT_LLONG
| VT_UNSIGNED
:
5776 /* XXX: add const cases for long long */
5778 case VT_INT
| VT_UNSIGNED
:
5780 case VT_FLOAT
: vtop
->c
.f
= (float)vtop
->c
.ui
; break;
5781 case VT_DOUBLE
: vtop
->c
.d
= (double)vtop
->c
.ui
; break;
5782 case VT_LDOUBLE
: vtop
->c
.ld
= (long double)vtop
->c
.ui
; break;
5787 case VT_FLOAT
: vtop
->c
.f
= (float)vtop
->c
.i
; break;
5788 case VT_DOUBLE
: vtop
->c
.d
= (double)vtop
->c
.i
; break;
5789 case VT_LDOUBLE
: vtop
->c
.ld
= (long double)vtop
->c
.i
; break;
5795 #if !defined(TCC_TARGET_ARM)
5802 /* convert fp to int */
5803 /* we handle char/short/etc... with generic code */
5804 if (dbt
!= (VT_INT
| VT_UNSIGNED
) &&
5805 dbt
!= (VT_LLONG
| VT_UNSIGNED
) &&
5810 case VT_LLONG
| VT_UNSIGNED
:
5812 /* XXX: add const cases for long long */
5814 case VT_INT
| VT_UNSIGNED
:
5816 case VT_FLOAT
: vtop
->c
.ui
= (unsigned int)vtop
->c
.d
; break;
5817 case VT_DOUBLE
: vtop
->c
.ui
= (unsigned int)vtop
->c
.d
; break;
5818 case VT_LDOUBLE
: vtop
->c
.ui
= (unsigned int)vtop
->c
.d
; break;
5824 case VT_FLOAT
: vtop
->c
.i
= (int)vtop
->c
.d
; break;
5825 case VT_DOUBLE
: vtop
->c
.i
= (int)vtop
->c
.d
; break;
5826 case VT_LDOUBLE
: vtop
->c
.i
= (int)vtop
->c
.d
; break;
5834 if (dbt
== VT_INT
&& (type
->t
& (VT_BTYPE
| VT_UNSIGNED
)) != dbt
) {
5835 /* additional cast for char/short/bool... */
5839 } else if ((dbt
& VT_BTYPE
) == VT_LLONG
) {
5840 if ((sbt
& VT_BTYPE
) != VT_LLONG
) {
5841 /* scalar to long long */
5843 if (sbt
== (VT_INT
| VT_UNSIGNED
))
5844 vtop
->c
.ll
= vtop
->c
.ui
;
5846 vtop
->c
.ll
= vtop
->c
.i
;
5848 /* machine independent conversion */
5850 /* generate high word */
5851 if (sbt
== (VT_INT
| VT_UNSIGNED
)) {
5859 /* patch second register */
5860 vtop
[-1].r2
= vtop
->r
;
5864 } else if (dbt
== VT_BOOL
) {
5865 /* scalar to bool */
5868 } else if ((dbt
& VT_BTYPE
) == VT_BYTE
||
5869 (dbt
& VT_BTYPE
) == VT_SHORT
) {
5870 force_charshort_cast(dbt
);
5871 } else if ((dbt
& VT_BTYPE
) == VT_INT
) {
5873 if (sbt
== VT_LLONG
) {
5874 /* from long long: just take low order word */
5878 /* if lvalue and single word type, nothing to do because
5879 the lvalue already contains the real type size (see
5880 VT_LVAL_xxx constants) */
5886 /* return type size. Put alignment at 'a' */
5887 static int type_size(CType
*type
, int *a
)
5892 bt
= type
->t
& VT_BTYPE
;
5893 if (bt
== VT_STRUCT
) {
5898 } else if (bt
== VT_PTR
) {
5899 if (type
->t
& VT_ARRAY
) {
5901 return type_size(&s
->type
, a
) * s
->c
;
5906 } else if (bt
== VT_LDOUBLE
) {
5908 return LDOUBLE_SIZE
;
5909 } else if (bt
== VT_DOUBLE
|| bt
== VT_LLONG
) {
5910 #ifdef TCC_TARGET_I386
5916 } else if (bt
== VT_INT
|| bt
== VT_ENUM
|| bt
== VT_FLOAT
) {
5919 } else if (bt
== VT_SHORT
) {
5923 /* char, void, function, _Bool */
5929 /* return the pointed type of t */
5930 static inline CType
*pointed_type(CType
*type
)
5932 return &type
->ref
->type
;
5935 /* modify type so that its it is a pointer to type. */
5936 static void mk_pointer(CType
*type
)
5939 s
= sym_push(SYM_FIELD
, type
, 0, -1);
5940 type
->t
= VT_PTR
| (type
->t
& ~VT_TYPE
);
5944 /* compare function types. OLD functions match any new functions */
5945 static int is_compatible_func(CType
*type1
, CType
*type2
)
5951 if (!is_compatible_types(&s1
->type
, &s2
->type
))
5953 /* check func_call */
5956 /* XXX: not complete */
5957 if (s1
->c
== FUNC_OLD
|| s2
->c
== FUNC_OLD
)
5961 while (s1
!= NULL
) {
5964 if (!is_compatible_types(&s1
->type
, &s2
->type
))
5974 /* return true if type1 and type2 are exactly the same (including
5977 - enums are not checked as gcc __builtin_types_compatible_p ()
5979 static int is_compatible_types(CType
*type1
, CType
*type2
)
5983 t1
= type1
->t
& VT_TYPE
;
5984 t2
= type2
->t
& VT_TYPE
;
5985 /* XXX: bitfields ? */
5988 /* test more complicated cases */
5989 bt1
= t1
& VT_BTYPE
;
5990 if (bt1
== VT_PTR
) {
5991 type1
= pointed_type(type1
);
5992 type2
= pointed_type(type2
);
5993 return is_compatible_types(type1
, type2
);
5994 } else if (bt1
== VT_STRUCT
) {
5995 return (type1
->ref
== type2
->ref
);
5996 } else if (bt1
== VT_FUNC
) {
5997 return is_compatible_func(type1
, type2
);
6003 /* print a type. If 'varstr' is not NULL, then the variable is also
6004 printed in the type */
6006 /* XXX: add array and function pointers */
6007 void type_to_str(char *buf
, int buf_size
,
6008 CType
*type
, const char *varstr
)
6015 t
= type
->t
& VT_TYPE
;
6018 if (t
& VT_CONSTANT
)
6019 pstrcat(buf
, buf_size
, "const ");
6020 if (t
& VT_VOLATILE
)
6021 pstrcat(buf
, buf_size
, "volatile ");
6022 if (t
& VT_UNSIGNED
)
6023 pstrcat(buf
, buf_size
, "unsigned ");
6053 tstr
= "long double";
6055 pstrcat(buf
, buf_size
, tstr
);
6059 if (bt
== VT_STRUCT
)
6063 pstrcat(buf
, buf_size
, tstr
);
6064 v
= type
->ref
->v
& ~SYM_STRUCT
;
6065 if (v
>= SYM_FIRST_ANOM
)
6066 pstrcat(buf
, buf_size
, "<anonymous>");
6068 pstrcat(buf
, buf_size
, get_tok_str(v
, NULL
));
6072 type_to_str(buf
, buf_size
, &s
->type
, varstr
);
6073 pstrcat(buf
, buf_size
, "(");
6075 while (sa
!= NULL
) {
6076 type_to_str(buf1
, sizeof(buf1
), &sa
->type
, NULL
);
6077 pstrcat(buf
, buf_size
, buf1
);
6080 pstrcat(buf
, buf_size
, ", ");
6082 pstrcat(buf
, buf_size
, ")");
6086 pstrcpy(buf1
, sizeof(buf1
), "*");
6088 pstrcat(buf1
, sizeof(buf1
), varstr
);
6089 type_to_str(buf
, buf_size
, &s
->type
, buf1
);
6093 pstrcat(buf
, buf_size
, " ");
6094 pstrcat(buf
, buf_size
, varstr
);
6099 /* verify type compatibility to store vtop in 'dt' type, and generate
6101 static void gen_assign_cast(CType
*dt
)
6103 CType
*st
, *type1
, *type2
, tmp_type1
, tmp_type2
;
6104 char buf1
[256], buf2
[256];
6107 st
= &vtop
->type
; /* source type */
6108 dbt
= dt
->t
& VT_BTYPE
;
6109 sbt
= st
->t
& VT_BTYPE
;
6110 if (dt
->t
& VT_CONSTANT
)
6111 warning("assignment of read-only location");
6114 /* special cases for pointers */
6115 /* '0' can also be a pointer */
6116 if (is_null_pointer(vtop
))
6118 /* accept implicit pointer to integer cast with warning */
6119 if (is_integer_btype(sbt
)) {
6120 warning("assignment makes pointer from integer without a cast");
6123 type1
= pointed_type(dt
);
6124 /* a function is implicitely a function pointer */
6125 if (sbt
== VT_FUNC
) {
6126 if ((type1
->t
& VT_BTYPE
) != VT_VOID
&&
6127 !is_compatible_types(pointed_type(dt
), st
))
6134 type2
= pointed_type(st
);
6135 if ((type1
->t
& VT_BTYPE
) == VT_VOID
||
6136 (type2
->t
& VT_BTYPE
) == VT_VOID
) {
6137 /* void * can match anything */
6139 /* exact type match, except for unsigned */
6142 tmp_type1
.t
&= ~(VT_UNSIGNED
| VT_CONSTANT
| VT_VOLATILE
);
6143 tmp_type2
.t
&= ~(VT_UNSIGNED
| VT_CONSTANT
| VT_VOLATILE
);
6144 if (!is_compatible_types(&tmp_type1
, &tmp_type2
))
6147 /* check const and volatile */
6148 if ((!(type1
->t
& VT_CONSTANT
) && (type2
->t
& VT_CONSTANT
)) ||
6149 (!(type1
->t
& VT_VOLATILE
) && (type2
->t
& VT_VOLATILE
)))
6150 warning("assignment discards qualifiers from pointer target type");
6156 if (sbt
== VT_PTR
|| sbt
== VT_FUNC
) {
6157 warning("assignment makes integer from pointer without a cast");
6159 /* XXX: more tests */
6164 tmp_type1
.t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
6165 tmp_type2
.t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
6166 if (!is_compatible_types(&tmp_type1
, &tmp_type2
)) {
6168 type_to_str(buf1
, sizeof(buf1
), st
, NULL
);
6169 type_to_str(buf2
, sizeof(buf2
), dt
, NULL
);
6170 error("cannot cast '%s' to '%s'", buf1
, buf2
);
6178 /* store vtop in lvalue pushed on stack */
6181 int sbt
, dbt
, ft
, r
, t
, size
, align
, bit_size
, bit_pos
, rc
, delayed_cast
;
6183 ft
= vtop
[-1].type
.t
;
6184 sbt
= vtop
->type
.t
& VT_BTYPE
;
6185 dbt
= ft
& VT_BTYPE
;
6186 if (((sbt
== VT_INT
|| sbt
== VT_SHORT
) && dbt
== VT_BYTE
) ||
6187 (sbt
== VT_INT
&& dbt
== VT_SHORT
)) {
6188 /* optimize char/short casts */
6189 delayed_cast
= VT_MUSTCAST
;
6190 vtop
->type
.t
= ft
& VT_TYPE
;
6191 /* XXX: factorize */
6192 if (ft
& VT_CONSTANT
)
6193 warning("assignment of read-only location");
6196 if (!(ft
& VT_BITFIELD
))
6197 gen_assign_cast(&vtop
[-1].type
);
6200 if (sbt
== VT_STRUCT
) {
6201 /* if structure, only generate pointer */
6202 /* structure assignment : generate memcpy */
6203 /* XXX: optimize if small size */
6204 if (!nocode_wanted
) {
6205 size
= type_size(&vtop
->type
, &align
);
6207 vpush_global_sym(&func_old_type
, TOK_memcpy
);
6211 vtop
->type
.t
= VT_INT
;
6215 vtop
->type
.t
= VT_INT
;
6227 /* leave source on stack */
6228 } else if (ft
& VT_BITFIELD
) {
6229 /* bitfield store handling */
6230 bit_pos
= (ft
>> VT_STRUCT_SHIFT
) & 0x3f;
6231 bit_size
= (ft
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f;
6232 /* remove bit field info to avoid loops */
6233 vtop
[-1].type
.t
= ft
& ~(VT_BITFIELD
| (-1 << VT_STRUCT_SHIFT
));
6235 /* duplicate destination */
6237 vtop
[-1] = vtop
[-2];
6239 /* mask and shift source */
6240 vpushi((1 << bit_size
) - 1);
6244 /* load destination, mask and or with source */
6246 vpushi(~(((1 << bit_size
) - 1) << bit_pos
));
6252 #ifdef CONFIG_TCC_BCHECK
6253 /* bound check case */
6254 if (vtop
[-1].r
& VT_MUSTBOUND
) {
6260 if (!nocode_wanted
) {
6264 r
= gv(rc
); /* generate value */
6265 /* if lvalue was saved on stack, must read it */
6266 if ((vtop
[-1].r
& VT_VALMASK
) == VT_LLOCAL
) {
6268 t
= get_reg(RC_INT
);
6270 sv
.r
= VT_LOCAL
| VT_LVAL
;
6271 sv
.c
.ul
= vtop
[-1].c
.ul
;
6273 vtop
[-1].r
= t
| VT_LVAL
;
6276 /* two word case handling : store second register at word + 4 */
6277 if ((ft
& VT_BTYPE
) == VT_LLONG
) {
6279 /* convert to int to increment easily */
6280 vtop
->type
.t
= VT_INT
;
6286 /* XXX: it works because r2 is spilled last ! */
6287 store(vtop
->r2
, vtop
- 1);
6291 vtop
--; /* NOT vpop() because on x86 it would flush the fp stack */
6292 vtop
->r
|= delayed_cast
;
6296 /* post defines POST/PRE add. c is the token ++ or -- */
6297 void inc(int post
, int c
)
6300 vdup(); /* save lvalue */
6302 gv_dup(); /* duplicate value */
6307 vpushi(c
- TOK_MID
);
6309 vstore(); /* store value */
6311 vpop(); /* if post op, return saved value */
6314 /* Parse GNUC __attribute__ extension. Currently, the following
6315 extensions are recognized:
6316 - aligned(n) : set data/function alignment.
6317 - packed : force data alignment to 1
6318 - section(x) : generate data/code in this section.
6319 - unused : currently ignored, but may be used someday.
6320 - regparm(n) : pass function parameters in registers (i386 only)
6322 static void parse_attribute(AttributeDef
*ad
)
6326 while (tok
== TOK_ATTRIBUTE1
|| tok
== TOK_ATTRIBUTE2
) {
6330 while (tok
!= ')') {
6331 if (tok
< TOK_IDENT
)
6332 expect("attribute name");
6340 expect("section name");
6341 ad
->section
= find_section(tcc_state
, (char *)tokc
.cstr
->data
);
6350 if (n
<= 0 || (n
& (n
- 1)) != 0)
6351 error("alignment must be a positive power of two");
6364 /* currently, no need to handle it because tcc does not
6365 track unused objects */
6369 /* currently, no need to handle it because tcc does not
6370 track unused objects */
6375 ad
->func_call
= FUNC_CDECL
;
6380 ad
->func_call
= FUNC_STDCALL
;
6382 #ifdef TCC_TARGET_I386
6392 ad
->func_call
= FUNC_FASTCALL1
+ n
- 1;
6400 if (tcc_state
->warn_unsupported
)
6401 warning("'%s' attribute ignored", get_tok_str(t
, NULL
));
6402 /* skip parameters */
6403 /* XXX: skip parenthesis too */
6406 while (tok
!= ')' && tok
!= -1)
6421 /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
6422 static void struct_decl(CType
*type
, int u
)
6424 int a
, v
, size
, align
, maxalign
, c
, offset
;
6425 int bit_size
, bit_pos
, bsize
, bt
, lbit_pos
;
6430 a
= tok
; /* save decl type */
6435 /* struct already defined ? return it */
6437 expect("struct/union/enum name");
6441 error("invalid type");
6448 /* we put an undefined size for struct/union */
6449 s
= sym_push(v
| SYM_STRUCT
, &type1
, 0, -1);
6450 s
->r
= 0; /* default alignment is zero as gcc */
6451 /* put struct/union/enum name in type */
6459 error("struct/union/enum already defined");
6460 /* cannot be empty */
6462 /* non empty enums are not allowed */
6463 if (a
== TOK_ENUM
) {
6467 expect("identifier");
6473 /* enum symbols have static storage */
6474 ss
= sym_push(v
, &int_type
, VT_CONST
, c
);
6475 ss
->type
.t
|= VT_STATIC
;
6480 /* NOTE: we accept a trailing comma */
6490 while (tok
!= '}') {
6491 parse_btype(&btype
, &ad
);
6497 type_decl(&type1
, &ad
, &v
, TYPE_DIRECT
);
6498 if ((type1
.t
& VT_BTYPE
) == VT_FUNC
||
6499 (type1
.t
& (VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
| VT_INLINE
)))
6500 error("invalid type for '%s'",
6501 get_tok_str(v
, NULL
));
6505 bit_size
= expr_const();
6506 /* XXX: handle v = 0 case for messages */
6508 error("negative width in bit-field '%s'",
6509 get_tok_str(v
, NULL
));
6510 if (v
&& bit_size
== 0)
6511 error("zero width for bit-field '%s'",
6512 get_tok_str(v
, NULL
));
6514 size
= type_size(&type1
, &align
);
6516 if (align
< ad
.aligned
)
6518 } else if (ad
.packed
) {
6520 } else if (*tcc_state
->pack_stack_ptr
) {
6521 if (align
> *tcc_state
->pack_stack_ptr
)
6522 align
= *tcc_state
->pack_stack_ptr
;
6525 if (bit_size
>= 0) {
6526 bt
= type1
.t
& VT_BTYPE
;
6532 error("bitfields must have scalar type");
6534 if (bit_size
> bsize
) {
6535 error("width of '%s' exceeds its type",
6536 get_tok_str(v
, NULL
));
6537 } else if (bit_size
== bsize
) {
6538 /* no need for bit fields */
6540 } else if (bit_size
== 0) {
6541 /* XXX: what to do if only padding in a
6543 /* zero size: means to pad */
6547 /* we do not have enough room ? */
6548 if ((bit_pos
+ bit_size
) > bsize
)
6551 /* XXX: handle LSB first */
6552 type1
.t
|= VT_BITFIELD
|
6553 (bit_pos
<< VT_STRUCT_SHIFT
) |
6554 (bit_size
<< (VT_STRUCT_SHIFT
+ 6));
6555 bit_pos
+= bit_size
;
6561 /* add new memory data only if starting
6563 if (lbit_pos
== 0) {
6564 if (a
== TOK_STRUCT
) {
6565 c
= (c
+ align
- 1) & -align
;
6573 if (align
> maxalign
)
6577 printf("add field %s offset=%d",
6578 get_tok_str(v
, NULL
), offset
);
6579 if (type1
.t
& VT_BITFIELD
) {
6580 printf(" pos=%d size=%d",
6581 (type1
.t
>> VT_STRUCT_SHIFT
) & 0x3f,
6582 (type1
.t
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f);
6586 ss
= sym_push(v
| SYM_FIELD
, &type1
, 0, offset
);
6590 if (tok
== ';' || tok
== TOK_EOF
)
6597 /* store size and alignment */
6598 s
->c
= (c
+ maxalign
- 1) & -maxalign
;
6604 /* return 0 if no type declaration. otherwise, return the basic type
6607 static int parse_btype(CType
*type
, AttributeDef
*ad
)
6609 int t
, u
, type_found
, typespec_found
;
6613 memset(ad
, 0, sizeof(AttributeDef
));
6620 /* currently, we really ignore extension */
6630 if ((t
& VT_BTYPE
) != 0)
6631 error("too many basic types");
6647 if ((t
& VT_BTYPE
) == VT_DOUBLE
) {
6648 t
= (t
& ~VT_BTYPE
) | VT_LDOUBLE
;
6649 } else if ((t
& VT_BTYPE
) == VT_LONG
) {
6650 t
= (t
& ~VT_BTYPE
) | VT_LLONG
;
6664 if ((t
& VT_BTYPE
) == VT_LONG
) {
6665 t
= (t
& ~VT_BTYPE
) | VT_LDOUBLE
;
6672 struct_decl(&type1
, VT_ENUM
);
6675 type
->ref
= type1
.ref
;
6679 struct_decl(&type1
, VT_STRUCT
);
6682 /* type modifiers */
6735 /* GNUC attribute */
6736 case TOK_ATTRIBUTE1
:
6737 case TOK_ATTRIBUTE2
:
6738 parse_attribute(ad
);
6745 parse_expr_type(&type1
);
6751 if (!s
|| !(s
->type
.t
& VT_TYPEDEF
))
6753 t
|= (s
->type
.t
& ~VT_TYPEDEF
);
6754 type
->ref
= s
->type
.ref
;
6761 if ((t
& (VT_SIGNED
|VT_UNSIGNED
)) == (VT_SIGNED
|VT_UNSIGNED
))
6762 error("signed and unsigned modifier");
6763 if (tcc_state
->char_is_unsigned
) {
6764 if ((t
& (VT_SIGNED
|VT_UNSIGNED
|VT_BTYPE
)) == VT_BYTE
)
6769 /* long is never used as type */
6770 if ((t
& VT_BTYPE
) == VT_LONG
)
6771 t
= (t
& ~VT_BTYPE
) | VT_INT
;
6776 /* convert a function parameter type (array to pointer and function to
6777 function pointer) */
6778 static inline void convert_parameter_type(CType
*pt
)
6780 /* remove const and volatile qualifiers (XXX: const could be used
6781 to indicate a const function parameter */
6782 pt
->t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
6783 /* array must be transformed to pointer according to ANSI C */
6785 if ((pt
->t
& VT_BTYPE
) == VT_FUNC
) {
6790 static void post_type(CType
*type
, AttributeDef
*ad
)
6793 Sym
**plast
, *s
, *first
;
6798 /* function declaration */
6803 while (tok
!= ')') {
6804 /* read param name and compute offset */
6805 if (l
!= FUNC_OLD
) {
6806 if (!parse_btype(&pt
, &ad1
)) {
6808 error("invalid type");
6815 if ((pt
.t
& VT_BTYPE
) == VT_VOID
&& tok
== ')')
6817 type_decl(&pt
, &ad1
, &n
, TYPE_DIRECT
| TYPE_ABSTRACT
);
6818 if ((pt
.t
& VT_BTYPE
) == VT_VOID
)
6819 error("parameter declared as void");
6826 convert_parameter_type(&pt
);
6827 s
= sym_push(n
| SYM_FIELD
, &pt
, 0, 0);
6832 if (l
== FUNC_NEW
&& tok
== TOK_DOTS
) {
6839 /* if no parameters, then old type prototype */
6843 t1
= type
->t
& VT_STORAGE
;
6844 /* NOTE: const is ignored in returned type as it has a special
6845 meaning in gcc / C++ */
6846 type
->t
&= ~(VT_STORAGE
| VT_CONSTANT
);
6847 post_type(type
, ad
);
6848 /* we push a anonymous symbol which will contain the function prototype */
6849 s
= sym_push(SYM_FIELD
, type
, ad
->func_call
, l
);
6851 type
->t
= t1
| VT_FUNC
;
6853 } else if (tok
== '[') {
6854 /* array definition */
6860 error("invalid array size");
6863 /* parse next post type */
6864 t1
= type
->t
& VT_STORAGE
;
6865 type
->t
&= ~VT_STORAGE
;
6866 post_type(type
, ad
);
6868 /* we push a anonymous symbol which will contain the array
6870 s
= sym_push(SYM_FIELD
, type
, 0, n
);
6871 type
->t
= t1
| VT_ARRAY
| VT_PTR
;
6876 /* Parse a type declaration (except basic type), and return the type
6877 in 'type'. 'td' is a bitmask indicating which kind of type decl is
6878 expected. 'type' should contain the basic type. 'ad' is the
6879 attribute definition of the basic type. It can be modified by
6882 static void type_decl(CType
*type
, AttributeDef
*ad
, int *v
, int td
)
6885 CType type1
, *type2
;
6888 while (tok
== '*') {
6896 qualifiers
|= VT_CONSTANT
;
6901 qualifiers
|= VT_VOLATILE
;
6909 type
->t
|= qualifiers
;
6912 /* XXX: clarify attribute handling */
6913 if (tok
== TOK_ATTRIBUTE1
|| tok
== TOK_ATTRIBUTE2
)
6914 parse_attribute(ad
);
6916 /* recursive type */
6917 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
6918 type1
.t
= 0; /* XXX: same as int */
6921 /* XXX: this is not correct to modify 'ad' at this point, but
6922 the syntax is not clear */
6923 if (tok
== TOK_ATTRIBUTE1
|| tok
== TOK_ATTRIBUTE2
)
6924 parse_attribute(ad
);
6925 type_decl(&type1
, ad
, v
, td
);
6928 /* type identifier */
6929 if (tok
>= TOK_IDENT
&& (td
& TYPE_DIRECT
)) {
6933 if (!(td
& TYPE_ABSTRACT
))
6934 expect("identifier");
6938 post_type(type
, ad
);
6939 if (tok
== TOK_ATTRIBUTE1
|| tok
== TOK_ATTRIBUTE2
)
6940 parse_attribute(ad
);
6943 /* append type at the end of type1 */
6956 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
6957 static int lvalue_type(int t
)
6962 if (bt
== VT_BYTE
|| bt
== VT_BOOL
)
6964 else if (bt
== VT_SHORT
)
6968 if (t
& VT_UNSIGNED
)
6969 r
|= VT_LVAL_UNSIGNED
;
6973 /* indirection with full error checking and bound check */
6974 static void indir(void)
6976 if ((vtop
->type
.t
& VT_BTYPE
) != VT_PTR
)
6978 if ((vtop
->r
& VT_LVAL
) && !nocode_wanted
)
6980 vtop
->type
= *pointed_type(&vtop
->type
);
6981 /* an array is never an lvalue */
6982 if (!(vtop
->type
.t
& VT_ARRAY
)) {
6983 vtop
->r
|= lvalue_type(vtop
->type
.t
);
6984 /* if bound checking, the referenced pointer must be checked */
6985 if (do_bounds_check
)
6986 vtop
->r
|= VT_MUSTBOUND
;
6990 /* pass a parameter to a function and do type checking and casting */
6991 static void gfunc_param_typed(Sym
*func
, Sym
*arg
)
6996 func_type
= func
->c
;
6997 if (func_type
== FUNC_OLD
||
6998 (func_type
== FUNC_ELLIPSIS
&& arg
== NULL
)) {
6999 /* default casting : only need to convert float to double */
7000 if ((vtop
->type
.t
& VT_BTYPE
) == VT_FLOAT
) {
7004 } else if (arg
== NULL
) {
7005 error("too many arguments to function");
7008 type
.t
&= ~VT_CONSTANT
; /* need to do that to avoid false warning */
7009 gen_assign_cast(&type
);
7013 /* parse an expression of the form '(type)' or '(expr)' and return its
7015 static void parse_expr_type(CType
*type
)
7021 if (parse_btype(type
, &ad
)) {
7022 type_decl(type
, &ad
, &n
, TYPE_ABSTRACT
);
7029 static void parse_type(CType
*type
)
7034 if (!parse_btype(type
, &ad
)) {
7037 type_decl(type
, &ad
, &n
, TYPE_ABSTRACT
);
7040 static void vpush_tokc(int t
)
7044 vsetc(&type
, VT_CONST
, &tokc
);
7047 static void unary(void)
7049 int n
, t
, align
, size
, r
;
7054 /* XXX: GCC 2.95.3 does not generate a table although it should be
7068 vpush_tokc(VT_INT
| VT_UNSIGNED
);
7072 vpush_tokc(VT_LLONG
);
7076 vpush_tokc(VT_LLONG
| VT_UNSIGNED
);
7080 vpush_tokc(VT_FLOAT
);
7084 vpush_tokc(VT_DOUBLE
);
7088 vpush_tokc(VT_LDOUBLE
);
7091 case TOK___FUNCTION__
:
7093 goto tok_identifier
;
7099 /* special function name identifier */
7100 len
= strlen(funcname
) + 1;
7101 /* generate char[len] type */
7106 vpush_ref(&type
, data_section
, data_section
->data_offset
, len
);
7107 ptr
= section_ptr_add(data_section
, len
);
7108 memcpy(ptr
, funcname
, len
);
7116 /* string parsing */
7119 if (tcc_state
->warn_write_strings
)
7124 memset(&ad
, 0, sizeof(AttributeDef
));
7125 decl_initializer_alloc(&type
, &ad
, VT_CONST
, 2, 0, 0);
7130 if (parse_btype(&type
, &ad
)) {
7131 type_decl(&type
, &ad
, &n
, TYPE_ABSTRACT
);
7133 /* check ISOC99 compound literal */
7135 /* data is allocated locally by default */
7140 /* all except arrays are lvalues */
7141 if (!(type
.t
& VT_ARRAY
))
7142 r
|= lvalue_type(type
.t
);
7143 memset(&ad
, 0, sizeof(AttributeDef
));
7144 decl_initializer_alloc(&type
, &ad
, r
, 1, 0, 0);
7149 } else if (tok
== '{') {
7150 /* save all registers */
7152 /* statement expression : we do not accept break/continue
7153 inside as GCC does */
7154 block(NULL
, NULL
, NULL
, NULL
, 0, 1);
7169 /* functions names must be treated as function pointers,
7170 except for unary '&' and sizeof. Since we consider that
7171 functions are not lvalues, we only have to handle it
7172 there and in function calls. */
7173 /* arrays can also be used although they are not lvalues */
7174 if ((vtop
->type
.t
& VT_BTYPE
) != VT_FUNC
&&
7175 !(vtop
->type
.t
& VT_ARRAY
))
7177 mk_pointer(&vtop
->type
);
7183 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
)
7184 vtop
->c
.i
= !vtop
->c
.i
;
7185 else if ((vtop
->r
& VT_VALMASK
) == VT_CMP
)
7186 vtop
->c
.i
= vtop
->c
.i
^ 1;
7188 vseti(VT_JMP
, gtst(1, 0));
7198 /* in order to force cast, we add zero */
7200 if ((vtop
->type
.t
& VT_BTYPE
) == VT_PTR
)
7201 error("pointer not accepted for unary plus");
7211 parse_expr_type(&type
);
7215 size
= type_size(&type
, &align
);
7216 if (t
== TOK_SIZEOF
) {
7218 error("sizeof applied to an incomplete type");
7225 case TOK_builtin_types_compatible_p
:
7234 type1
.t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
7235 type2
.t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
7236 vpushi(is_compatible_types(&type1
, &type2
));
7239 case TOK_builtin_constant_p
:
7241 int saved_nocode_wanted
, res
;
7244 saved_nocode_wanted
= nocode_wanted
;
7247 res
= (vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
7249 nocode_wanted
= saved_nocode_wanted
;
7269 goto tok_identifier
;
7271 /* allow to take the address of a label */
7272 if (tok
< TOK_UIDENT
)
7273 expect("label identifier");
7274 s
= label_find(tok
);
7276 s
= label_push(&global_label_stack
, tok
, LABEL_FORWARD
);
7278 if (s
->r
== LABEL_DECLARED
)
7279 s
->r
= LABEL_FORWARD
;
7282 s
->type
.t
= VT_VOID
;
7283 mk_pointer(&s
->type
);
7284 s
->type
.t
|= VT_STATIC
;
7286 vset(&s
->type
, VT_CONST
| VT_SYM
, 0);
7295 expect("identifier");
7299 error("'%s' undeclared", get_tok_str(t
, NULL
));
7300 /* for simple function calls, we tolerate undeclared
7301 external reference to int() function */
7302 if (tcc_state
->warn_implicit_function_declaration
)
7303 warning("implicit declaration of function '%s'",
7304 get_tok_str(t
, NULL
));
7305 s
= external_global_sym(t
, &func_old_type
, 0);
7307 if ((s
->type
.t
& (VT_STATIC
| VT_INLINE
| VT_BTYPE
)) ==
7308 (VT_STATIC
| VT_INLINE
| VT_FUNC
)) {
7309 /* if referencing an inline function, then we generate a
7310 symbol to it if not already done. It will have the
7311 effect to generate code for it at the end of the
7312 compilation unit. Inline function as always
7313 generated in the text section. */
7315 put_extern_sym(s
, text_section
, 0, 0);
7316 r
= VT_SYM
| VT_CONST
;
7320 vset(&s
->type
, r
, s
->c
);
7321 /* if forward reference, we must point to s */
7322 if (vtop
->r
& VT_SYM
) {
7329 /* post operations */
7331 if (tok
== TOK_INC
|| tok
== TOK_DEC
) {
7334 } else if (tok
== '.' || tok
== TOK_ARROW
) {
7336 if (tok
== TOK_ARROW
)
7341 /* expect pointer on structure */
7342 if ((vtop
->type
.t
& VT_BTYPE
) != VT_STRUCT
)
7343 expect("struct or union");
7347 while ((s
= s
->next
) != NULL
) {
7352 error("field not found");
7353 /* add field offset to pointer */
7354 vtop
->type
= char_pointer_type
; /* change type to 'char *' */
7357 /* change type to field type, and set to lvalue */
7358 vtop
->type
= s
->type
;
7359 /* an array is never an lvalue */
7360 if (!(vtop
->type
.t
& VT_ARRAY
)) {
7361 vtop
->r
|= lvalue_type(vtop
->type
.t
);
7362 /* if bound checking, the referenced pointer must be checked */
7363 if (do_bounds_check
)
7364 vtop
->r
|= VT_MUSTBOUND
;
7367 } else if (tok
== '[') {
7373 } else if (tok
== '(') {
7379 if ((vtop
->type
.t
& VT_BTYPE
) != VT_FUNC
) {
7380 /* pointer test (no array accepted) */
7381 if ((vtop
->type
.t
& (VT_BTYPE
| VT_ARRAY
)) == VT_PTR
) {
7382 vtop
->type
= *pointed_type(&vtop
->type
);
7383 if ((vtop
->type
.t
& VT_BTYPE
) != VT_FUNC
)
7387 expect("function pointer");
7390 vtop
->r
&= ~VT_LVAL
; /* no lvalue */
7392 /* get return type */
7395 sa
= s
->next
; /* first parameter */
7397 /* compute first implicit argument if a structure is returned */
7398 if ((s
->type
.t
& VT_BTYPE
) == VT_STRUCT
) {
7399 /* get some space for the returned structure */
7400 size
= type_size(&s
->type
, &align
);
7401 loc
= (loc
- size
) & -align
;
7403 ret
.r
= VT_LOCAL
| VT_LVAL
;
7404 /* pass it as 'int' to avoid structure arg passing
7406 vseti(VT_LOCAL
, loc
);
7412 /* return in register */
7413 if (is_float(ret
.type
.t
)) {
7416 if ((ret
.type
.t
& VT_BTYPE
) == VT_LLONG
)
7425 gfunc_param_typed(s
, sa
);
7435 error("too few arguments to function");
7437 if (!nocode_wanted
) {
7438 gfunc_call(nb_args
);
7440 vtop
-= (nb_args
+ 1);
7443 vsetc(&ret
.type
, ret
.r
, &ret
.c
);
7451 static void uneq(void)
7457 (tok
>= TOK_A_MOD
&& tok
<= TOK_A_DIV
) ||
7458 tok
== TOK_A_XOR
|| tok
== TOK_A_OR
||
7459 tok
== TOK_A_SHL
|| tok
== TOK_A_SAR
) {
7474 static void expr_prod(void)
7479 while (tok
== '*' || tok
== '/' || tok
== '%') {
7487 static void expr_sum(void)
7492 while (tok
== '+' || tok
== '-') {
7500 static void expr_shift(void)
7505 while (tok
== TOK_SHL
|| tok
== TOK_SAR
) {
7513 static void expr_cmp(void)
7518 while ((tok
>= TOK_ULE
&& tok
<= TOK_GT
) ||
7519 tok
== TOK_ULT
|| tok
== TOK_UGE
) {
7527 static void expr_cmpeq(void)
7532 while (tok
== TOK_EQ
|| tok
== TOK_NE
) {
7540 static void expr_and(void)
7543 while (tok
== '&') {
7550 static void expr_xor(void)
7553 while (tok
== '^') {
7560 static void expr_or(void)
7563 while (tok
== '|') {
7570 /* XXX: fix this mess */
7571 static void expr_land_const(void)
7574 while (tok
== TOK_LAND
) {
7581 /* XXX: fix this mess */
7582 static void expr_lor_const(void)
7585 while (tok
== TOK_LOR
) {
7592 /* only used if non constant */
7593 static void expr_land(void)
7598 if (tok
== TOK_LAND
) {
7602 if (tok
!= TOK_LAND
) {
7612 static void expr_lor(void)
7617 if (tok
== TOK_LOR
) {
7621 if (tok
!= TOK_LOR
) {
7631 /* XXX: better constant handling */
7632 static void expr_eq(void)
7634 int tt
, u
, r1
, r2
, rc
, t1
, t2
, bt1
, bt2
;
7636 CType type
, type1
, type2
;
7645 if (tok
== ':' && gnu_ext
) {
7661 if (vtop
!= vstack
) {
7662 /* needed to avoid having different registers saved in
7664 if (is_float(vtop
->type
.t
))
7671 if (tok
== ':' && gnu_ext
) {
7679 sv
= *vtop
; /* save value to handle it later */
7680 vtop
--; /* no vpop so that FP stack is not flushed */
7688 bt1
= t1
& VT_BTYPE
;
7690 bt2
= t2
& VT_BTYPE
;
7691 /* cast operands to correct type according to ISOC rules */
7692 if (is_float(bt1
) || is_float(bt2
)) {
7693 if (bt1
== VT_LDOUBLE
|| bt2
== VT_LDOUBLE
) {
7694 type
.t
= VT_LDOUBLE
;
7695 } else if (bt1
== VT_DOUBLE
|| bt2
== VT_DOUBLE
) {
7700 } else if (bt1
== VT_LLONG
|| bt2
== VT_LLONG
) {
7701 /* cast to biggest op */
7703 /* convert to unsigned if it does not fit in a long long */
7704 if ((t1
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_LLONG
| VT_UNSIGNED
) ||
7705 (t2
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_LLONG
| VT_UNSIGNED
))
7706 type
.t
|= VT_UNSIGNED
;
7707 } else if (bt1
== VT_PTR
|| bt2
== VT_PTR
) {
7708 /* XXX: test pointer compatibility */
7710 } else if (bt1
== VT_STRUCT
|| bt2
== VT_STRUCT
) {
7711 /* XXX: test structure compatibility */
7713 } else if (bt1
== VT_VOID
|| bt2
== VT_VOID
) {
7714 /* NOTE: as an extension, we accept void on only one side */
7717 /* integer operations */
7719 /* convert to unsigned if it does not fit in an integer */
7720 if ((t1
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
) ||
7721 (t2
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
))
7722 type
.t
|= VT_UNSIGNED
;
7725 /* now we convert second operand */
7728 if (is_float(type
.t
)) {
7730 } else if ((type
.t
& VT_BTYPE
) == VT_LLONG
) {
7731 /* for long longs, we use fixed registers to avoid having
7732 to handle a complicated move */
7737 /* this is horrible, but we must also convert first
7741 /* put again first value and cast it */
7752 static void gexpr(void)
7763 /* parse an expression and return its type without any side effect. */
7764 static void expr_type(CType
*type
)
7766 int saved_nocode_wanted
;
7768 saved_nocode_wanted
= nocode_wanted
;
7773 nocode_wanted
= saved_nocode_wanted
;
7776 /* parse a unary expression and return its type without any side
7778 static void unary_type(CType
*type
)
7790 /* parse a constant expression and return value in vtop. */
7791 static void expr_const1(void)
7800 /* parse an integer constant and return its value. */
7801 static int expr_const(void)
7805 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) != VT_CONST
)
7806 expect("constant expression");
7812 /* return the label token if current token is a label, otherwise
7814 static int is_label(void)
7818 /* fast test first */
7819 if (tok
< TOK_UIDENT
)
7821 /* no need to save tokc because tok is an identifier */
7828 unget_tok(last_tok
);
7833 static void block(int *bsym
, int *csym
, int *case_sym
, int *def_sym
,
7834 int case_reg
, int is_expr
)
7839 /* generate line number info */
7841 (last_line_num
!= file
->line_num
|| last_ind
!= ind
)) {
7842 put_stabn(N_SLINE
, 0, file
->line_num
, ind
- func_ind
);
7844 last_line_num
= file
->line_num
;
7848 /* default return value is (void) */
7850 vtop
->type
.t
= VT_VOID
;
7853 if (tok
== TOK_IF
) {
7860 block(bsym
, csym
, case_sym
, def_sym
, case_reg
, 0);
7862 if (c
== TOK_ELSE
) {
7866 block(bsym
, csym
, case_sym
, def_sym
, case_reg
, 0);
7867 gsym(d
); /* patch else jmp */
7870 } else if (tok
== TOK_WHILE
) {
7878 block(&a
, &b
, case_sym
, def_sym
, case_reg
, 0);
7882 } else if (tok
== '{') {
7886 /* record local declaration stack position */
7888 llabel
= local_label_stack
;
7889 /* handle local labels declarations */
7890 if (tok
== TOK_LABEL
) {
7893 if (tok
< TOK_UIDENT
)
7894 expect("label identifier");
7895 label_push(&local_label_stack
, tok
, LABEL_DECLARED
);
7905 while (tok
!= '}') {
7910 block(bsym
, csym
, case_sym
, def_sym
, case_reg
, is_expr
);
7913 /* pop locally defined labels */
7914 label_pop(&local_label_stack
, llabel
);
7915 /* pop locally defined symbols */
7916 sym_pop(&local_stack
, s
);
7918 } else if (tok
== TOK_RETURN
) {
7922 gen_assign_cast(&func_vt
);
7923 if ((func_vt
.t
& VT_BTYPE
) == VT_STRUCT
) {
7925 /* if returning structure, must copy it to implicit
7926 first pointer arg location */
7929 vset(&type
, VT_LOCAL
| VT_LVAL
, func_vc
);
7932 /* copy structure value to pointer */
7934 } else if (is_float(func_vt
.t
)) {
7939 vtop
--; /* NOT vpop() because on x86 it would flush the fp stack */
7942 rsym
= gjmp(rsym
); /* jmp */
7943 } else if (tok
== TOK_BREAK
) {
7946 error("cannot break");
7947 *bsym
= gjmp(*bsym
);
7950 } else if (tok
== TOK_CONTINUE
) {
7953 error("cannot continue");
7954 *csym
= gjmp(*csym
);
7957 } else if (tok
== TOK_FOR
) {
7984 block(&a
, &b
, case_sym
, def_sym
, case_reg
, 0);
7989 if (tok
== TOK_DO
) {
7994 block(&a
, &b
, case_sym
, def_sym
, case_reg
, 0);
8005 if (tok
== TOK_SWITCH
) {
8009 /* XXX: other types than integer */
8010 case_reg
= gv(RC_INT
);
8014 b
= gjmp(0); /* jump to first case */
8016 block(&a
, csym
, &b
, &c
, case_reg
, 0);
8017 /* if no default, jmp after switch */
8025 if (tok
== TOK_CASE
) {
8032 if (gnu_ext
&& tok
== TOK_DOTS
) {
8036 warning("empty case range");
8038 /* since a case is like a label, we must skip it with a jmp */
8045 *case_sym
= gtst(1, 0);
8048 *case_sym
= gtst(1, 0);
8052 *case_sym
= gtst(1, *case_sym
);
8057 goto block_after_label
;
8059 if (tok
== TOK_DEFAULT
) {
8065 error("too many 'default'");
8068 goto block_after_label
;
8070 if (tok
== TOK_GOTO
) {
8072 if (tok
== '*' && gnu_ext
) {
8076 if ((vtop
->type
.t
& VT_BTYPE
) != VT_PTR
)
8079 } else if (tok
>= TOK_UIDENT
) {
8080 s
= label_find(tok
);
8081 /* put forward definition if needed */
8083 s
= label_push(&global_label_stack
, tok
, LABEL_FORWARD
);
8085 if (s
->r
== LABEL_DECLARED
)
8086 s
->r
= LABEL_FORWARD
;
8088 /* label already defined */
8089 if (s
->r
& LABEL_FORWARD
)
8090 s
->next
= (void *)gjmp((long)s
->next
);
8092 gjmp_addr((long)s
->next
);
8095 expect("label identifier");
8098 } else if (tok
== TOK_ASM1
|| tok
== TOK_ASM2
|| tok
== TOK_ASM3
) {
8106 if (s
->r
== LABEL_DEFINED
)
8107 error("duplicate label '%s'", get_tok_str(s
->v
, NULL
));
8108 gsym((long)s
->next
);
8109 s
->r
= LABEL_DEFINED
;
8111 s
= label_push(&global_label_stack
, b
, LABEL_DEFINED
);
8113 s
->next
= (void *)ind
;
8114 /* we accept this, but it is a mistake */
8117 warning("deprecated use of label at end of compound statement");
8121 block(bsym
, csym
, case_sym
, def_sym
, case_reg
, is_expr
);
8124 /* expression case */
8139 /* t is the array or struct type. c is the array or struct
8140 address. cur_index/cur_field is the pointer to the current
8141 value. 'size_only' is true if only size info is needed (only used
8143 static void decl_designator(CType
*type
, Section
*sec
, unsigned long c
,
8144 int *cur_index
, Sym
**cur_field
,
8148 int notfirst
, index
, index_last
, align
, l
, nb_elems
, elem_size
;
8154 if (gnu_ext
&& (l
= is_label()) != 0)
8156 while (tok
== '[' || tok
== '.') {
8158 if (!(type
->t
& VT_ARRAY
))
8159 expect("array type");
8162 index
= expr_const();
8163 if (index
< 0 || (s
->c
>= 0 && index
>= s
->c
))
8164 expect("invalid index");
8165 if (tok
== TOK_DOTS
&& gnu_ext
) {
8167 index_last
= expr_const();
8168 if (index_last
< 0 ||
8169 (s
->c
>= 0 && index_last
>= s
->c
) ||
8171 expect("invalid index");
8177 *cur_index
= index_last
;
8178 type
= pointed_type(type
);
8179 elem_size
= type_size(type
, &align
);
8180 c
+= index
* elem_size
;
8181 /* NOTE: we only support ranges for last designator */
8182 nb_elems
= index_last
- index
+ 1;
8183 if (nb_elems
!= 1) {
8192 if ((type
->t
& VT_BTYPE
) != VT_STRUCT
)
8193 expect("struct/union type");
8206 /* XXX: fix this mess by using explicit storage field */
8208 type1
.t
|= (type
->t
& ~VT_TYPE
);
8222 if (type
->t
& VT_ARRAY
) {
8224 type
= pointed_type(type
);
8225 c
+= index
* type_size(type
, &align
);
8229 error("too many field init");
8230 /* XXX: fix this mess by using explicit storage field */
8232 type1
.t
|= (type
->t
& ~VT_TYPE
);
8237 decl_initializer(type
, sec
, c
, 0, size_only
);
8239 /* XXX: make it more general */
8240 if (!size_only
&& nb_elems
> 1) {
8241 unsigned long c_end
;
8246 error("range init not supported yet for dynamic storage");
8247 c_end
= c
+ nb_elems
* elem_size
;
8248 if (c_end
> sec
->data_allocated
)
8249 section_realloc(sec
, c_end
);
8250 src
= sec
->data
+ c
;
8252 for(i
= 1; i
< nb_elems
; i
++) {
8254 memcpy(dst
, src
, elem_size
);
8260 #define EXPR_CONST 1
8263 /* store a value or an expression directly in global data or in local array */
8264 static void init_putv(CType
*type
, Section
*sec
, unsigned long c
,
8265 int v
, int expr_type
)
8267 int saved_global_expr
, bt
, bit_pos
, bit_size
;
8269 unsigned long long bit_mask
;
8277 /* compound literals must be allocated globally in this case */
8278 saved_global_expr
= global_expr
;
8281 global_expr
= saved_global_expr
;
8282 /* NOTE: symbols are accepted */
8283 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
)) != VT_CONST
)
8284 error("initializer element is not constant");
8292 dtype
.t
&= ~VT_CONSTANT
; /* need to do that to avoid false warning */
8295 /* XXX: not portable */
8296 /* XXX: generate error if incorrect relocation */
8297 gen_assign_cast(&dtype
);
8298 bt
= type
->t
& VT_BTYPE
;
8299 ptr
= sec
->data
+ c
;
8300 /* XXX: make code faster ? */
8301 if (!(type
->t
& VT_BITFIELD
)) {
8306 bit_pos
= (vtop
->type
.t
>> VT_STRUCT_SHIFT
) & 0x3f;
8307 bit_size
= (vtop
->type
.t
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f;
8308 bit_mask
= (1LL << bit_size
) - 1;
8310 if ((vtop
->r
& VT_SYM
) &&
8316 (bt
== VT_INT
&& bit_size
!= 32)))
8317 error("initializer element is not computable at load time");
8320 *(char *)ptr
|= (vtop
->c
.i
& bit_mask
) << bit_pos
;
8323 *(short *)ptr
|= (vtop
->c
.i
& bit_mask
) << bit_pos
;
8326 *(double *)ptr
= vtop
->c
.d
;
8329 *(long double *)ptr
= vtop
->c
.ld
;
8332 *(long long *)ptr
|= (vtop
->c
.ll
& bit_mask
) << bit_pos
;
8335 if (vtop
->r
& VT_SYM
) {
8336 greloc(sec
, vtop
->sym
, c
, R_DATA_32
);
8338 *(int *)ptr
|= (vtop
->c
.i
& bit_mask
) << bit_pos
;
8343 vset(&dtype
, VT_LOCAL
, c
);
8350 /* put zeros for variable based init */
8351 static void init_putz(CType
*t
, Section
*sec
, unsigned long c
, int size
)
8354 /* nothing to do because globals are already set to zero */
8356 vpush_global_sym(&func_old_type
, TOK_memset
);
8364 /* 't' contains the type and storage info. 'c' is the offset of the
8365 object in section 'sec'. If 'sec' is NULL, it means stack based
8366 allocation. 'first' is true if array '{' must be read (multi
8367 dimension implicit array init handling). 'size_only' is true if
8368 size only evaluation is wanted (only for arrays). */
8369 static void decl_initializer(CType
*type
, Section
*sec
, unsigned long c
,
8370 int first
, int size_only
)
8372 int index
, array_length
, n
, no_oblock
, nb
, parlevel
, i
;
8373 int size1
, align1
, expr_type
;
8377 if (type
->t
& VT_ARRAY
) {
8381 t1
= pointed_type(type
);
8382 size1
= type_size(t1
, &align1
);
8385 if ((first
&& tok
!= TOK_LSTR
&& tok
!= TOK_STR
) ||
8391 /* only parse strings here if correct type (otherwise: handle
8392 them as ((w)char *) expressions */
8393 if ((tok
== TOK_LSTR
&&
8394 (t1
->t
& VT_BTYPE
) == VT_INT
) ||
8396 (t1
->t
& VT_BTYPE
) == VT_BYTE
)) {
8397 while (tok
== TOK_STR
|| tok
== TOK_LSTR
) {
8402 /* compute maximum number of chars wanted */
8404 cstr_len
= cstr
->size
;
8406 cstr_len
= cstr
->size
/ sizeof(int);
8409 if (n
>= 0 && nb
> (n
- array_length
))
8410 nb
= n
- array_length
;
8413 warning("initializer-string for array is too long");
8414 /* in order to go faster for common case (char
8415 string in global variable, we handle it
8417 if (sec
&& tok
== TOK_STR
&& size1
== 1) {
8418 memcpy(sec
->data
+ c
+ array_length
, cstr
->data
, nb
);
8422 ch
= ((unsigned char *)cstr
->data
)[i
];
8424 ch
= ((int *)cstr
->data
)[i
];
8425 init_putv(t1
, sec
, c
+ (array_length
+ i
) * size1
,
8433 /* only add trailing zero if enough storage (no
8434 warning in this case since it is standard) */
8435 if (n
< 0 || array_length
< n
) {
8437 init_putv(t1
, sec
, c
+ (array_length
* size1
), 0, EXPR_VAL
);
8443 while (tok
!= '}') {
8444 decl_designator(type
, sec
, c
, &index
, NULL
, size_only
);
8445 if (n
>= 0 && index
>= n
)
8446 error("index too large");
8447 /* must put zero in holes (note that doing it that way
8448 ensures that it even works with designators) */
8449 if (!size_only
&& array_length
< index
) {
8450 init_putz(t1
, sec
, c
+ array_length
* size1
,
8451 (index
- array_length
) * size1
);
8454 if (index
> array_length
)
8455 array_length
= index
;
8456 /* special test for multi dimensional arrays (may not
8457 be strictly correct if designators are used at the
8459 if (index
>= n
&& no_oblock
)
8468 /* put zeros at the end */
8469 if (!size_only
&& n
>= 0 && array_length
< n
) {
8470 init_putz(t1
, sec
, c
+ array_length
* size1
,
8471 (n
- array_length
) * size1
);
8473 /* patch type size if needed */
8475 s
->c
= array_length
;
8476 } else if ((type
->t
& VT_BTYPE
) == VT_STRUCT
&&
8477 (sec
|| !first
|| tok
== '{')) {
8480 /* NOTE: the previous test is a specific case for automatic
8481 struct/union init */
8482 /* XXX: union needs only one init */
8484 /* XXX: this test is incorrect for local initializers
8485 beginning with ( without {. It would be much more difficult
8486 to do it correctly (ideally, the expression parser should
8487 be used in all cases) */
8493 while (tok
== '(') {
8497 if (!parse_btype(&type1
, &ad1
))
8499 type_decl(&type1
, &ad1
, &n
, TYPE_ABSTRACT
);
8501 if (!is_assignable_types(type
, &type1
))
8502 error("invalid type for cast");
8507 if (first
|| tok
== '{') {
8516 while (tok
!= '}') {
8517 decl_designator(type
, sec
, c
, NULL
, &f
, size_only
);
8519 if (!size_only
&& array_length
< index
) {
8520 init_putz(type
, sec
, c
+ array_length
,
8521 index
- array_length
);
8523 index
= index
+ type_size(&f
->type
, &align1
);
8524 if (index
> array_length
)
8525 array_length
= index
;
8527 if (no_oblock
&& f
== NULL
)
8533 /* put zeros at the end */
8534 if (!size_only
&& array_length
< n
) {
8535 init_putz(type
, sec
, c
+ array_length
,
8544 } else if (tok
== '{') {
8546 decl_initializer(type
, sec
, c
, first
, size_only
);
8548 } else if (size_only
) {
8549 /* just skip expression */
8551 while ((parlevel
> 0 || (tok
!= '}' && tok
!= ',')) &&
8555 else if (tok
== ')')
8560 /* currently, we always use constant expression for globals
8561 (may change for scripting case) */
8562 expr_type
= EXPR_CONST
;
8564 expr_type
= EXPR_ANY
;
8565 init_putv(type
, sec
, c
, 0, expr_type
);
8569 /* parse an initializer for type 't' if 'has_init' is non zero, and
8570 allocate space in local or global data space ('r' is either
8571 VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
8572 variable 'v' of scope 'scope' is declared before initializers are
8573 parsed. If 'v' is zero, then a reference to the new object is put
8574 in the value stack. If 'has_init' is 2, a special parsing is done
8575 to handle string constants. */
8576 static void decl_initializer_alloc(CType
*type
, AttributeDef
*ad
, int r
,
8577 int has_init
, int v
, int scope
)
8579 int size
, align
, addr
, data_offset
;
8581 ParseState saved_parse_state
;
8582 TokenString init_str
;
8585 size
= type_size(type
, &align
);
8586 /* If unknown size, we must evaluate it before
8587 evaluating initializers because
8588 initializers can generate global data too
8589 (e.g. string pointers or ISOC99 compound
8590 literals). It also simplifies local
8591 initializers handling */
8592 tok_str_new(&init_str
);
8595 error("unknown type size");
8596 /* get all init string */
8597 if (has_init
== 2) {
8598 /* only get strings */
8599 while (tok
== TOK_STR
|| tok
== TOK_LSTR
) {
8600 tok_str_add_tok(&init_str
);
8605 while (level
> 0 || (tok
!= ',' && tok
!= ';')) {
8607 error("unexpected end of file in initializer");
8608 tok_str_add_tok(&init_str
);
8611 else if (tok
== '}') {
8619 tok_str_add(&init_str
, -1);
8620 tok_str_add(&init_str
, 0);
8623 save_parse_state(&saved_parse_state
);
8625 macro_ptr
= init_str
.str
;
8627 decl_initializer(type
, NULL
, 0, 1, 1);
8628 /* prepare second initializer parsing */
8629 macro_ptr
= init_str
.str
;
8632 /* if still unknown size, error */
8633 size
= type_size(type
, &align
);
8635 error("unknown type size");
8637 /* take into account specified alignment if bigger */
8639 if (ad
->aligned
> align
)
8640 align
= ad
->aligned
;
8641 } else if (ad
->packed
) {
8644 if ((r
& VT_VALMASK
) == VT_LOCAL
) {
8646 if (do_bounds_check
&& (type
->t
& VT_ARRAY
))
8648 loc
= (loc
- size
) & -align
;
8650 /* handles bounds */
8651 /* XXX: currently, since we do only one pass, we cannot track
8652 '&' operators, so we add only arrays */
8653 if (do_bounds_check
&& (type
->t
& VT_ARRAY
)) {
8654 unsigned long *bounds_ptr
;
8655 /* add padding between regions */
8657 /* then add local bound info */
8658 bounds_ptr
= section_ptr_add(lbounds_section
, 2 * sizeof(unsigned long));
8659 bounds_ptr
[0] = addr
;
8660 bounds_ptr
[1] = size
;
8663 /* local variable */
8664 sym_push(v
, type
, r
, addr
);
8666 /* push local reference */
8667 vset(type
, r
, addr
);
8673 if (v
&& scope
== VT_CONST
) {
8674 /* see if the symbol was already defined */
8677 if (!is_compatible_types(&sym
->type
, type
))
8678 error("incompatible types for redefinition of '%s'",
8679 get_tok_str(v
, NULL
));
8680 if (sym
->type
.t
& VT_EXTERN
) {
8681 /* if the variable is extern, it was not allocated */
8682 sym
->type
.t
&= ~VT_EXTERN
;
8683 /* set array size if it was ommited in extern
8685 if ((sym
->type
.t
& VT_ARRAY
) &&
8686 sym
->type
.ref
->c
< 0 &&
8688 sym
->type
.ref
->c
= type
->ref
->c
;
8690 /* we accept several definitions of the same
8691 global variable. this is tricky, because we
8692 must play with the SHN_COMMON type of the symbol */
8693 /* XXX: should check if the variable was already
8694 initialized. It is incorrect to initialized it
8696 /* no init data, we won't add more to the symbol */
8703 /* allocate symbol in corresponding section */
8708 else if (tcc_state
->nocommon
)
8712 data_offset
= sec
->data_offset
;
8713 data_offset
= (data_offset
+ align
- 1) & -align
;
8715 /* very important to increment global pointer at this time
8716 because initializers themselves can create new initializers */
8717 data_offset
+= size
;
8718 /* add padding if bound check */
8719 if (do_bounds_check
)
8721 sec
->data_offset
= data_offset
;
8722 /* allocate section space to put the data */
8723 if (sec
->sh_type
!= SHT_NOBITS
&&
8724 data_offset
> sec
->data_allocated
)
8725 section_realloc(sec
, data_offset
);
8726 /* align section if needed */
8727 if (align
> sec
->sh_addralign
)
8728 sec
->sh_addralign
= align
;
8730 addr
= 0; /* avoid warning */
8734 if (scope
== VT_CONST
) {
8739 sym
= sym_push(v
, type
, r
| VT_SYM
, 0);
8741 /* update symbol definition */
8743 put_extern_sym(sym
, sec
, addr
, size
);
8746 /* put a common area */
8747 put_extern_sym(sym
, NULL
, align
, size
);
8748 /* XXX: find a nicer way */
8749 esym
= &((Elf32_Sym
*)symtab_section
->data
)[sym
->c
];
8750 esym
->st_shndx
= SHN_COMMON
;
8755 /* push global reference */
8756 sym
= get_sym_ref(type
, sec
, addr
, size
);
8758 vsetc(type
, VT_CONST
| VT_SYM
, &cval
);
8762 /* handles bounds now because the symbol must be defined
8763 before for the relocation */
8764 if (do_bounds_check
) {
8765 unsigned long *bounds_ptr
;
8767 greloc(bounds_section
, sym
, bounds_section
->data_offset
, R_DATA_32
);
8768 /* then add global bound info */
8769 bounds_ptr
= section_ptr_add(bounds_section
, 2 * sizeof(long));
8770 bounds_ptr
[0] = 0; /* relocated */
8771 bounds_ptr
[1] = size
;
8775 decl_initializer(type
, sec
, addr
, 1, 0);
8776 /* restore parse state if needed */
8778 tok_str_free(init_str
.str
);
8779 restore_parse_state(&saved_parse_state
);
8785 void put_func_debug(Sym
*sym
)
8790 /* XXX: we put here a dummy type */
8791 snprintf(buf
, sizeof(buf
), "%s:%c1",
8792 funcname
, sym
->type
.t
& VT_STATIC
? 'f' : 'F');
8793 put_stabs_r(buf
, N_FUN
, 0, file
->line_num
, 0,
8794 cur_text_section
, sym
->c
);
8799 /* parse an old style function declaration list */
8800 /* XXX: check multiple parameter */
8801 static void func_decl_list(Sym
*func_sym
)
8808 /* parse each declaration */
8809 while (tok
!= '{' && tok
!= ';' && tok
!= ',' && tok
!= TOK_EOF
) {
8810 if (!parse_btype(&btype
, &ad
))
8811 expect("declaration list");
8812 if (((btype
.t
& VT_BTYPE
) == VT_ENUM
||
8813 (btype
.t
& VT_BTYPE
) == VT_STRUCT
) &&
8815 /* we accept no variable after */
8819 type_decl(&type
, &ad
, &v
, TYPE_DIRECT
);
8820 /* find parameter in function parameter list */
8823 if ((s
->v
& ~SYM_FIELD
) == v
)
8827 error("declaration for parameter '%s' but no such parameter",
8828 get_tok_str(v
, NULL
));
8830 /* check that no storage specifier except 'register' was given */
8831 if (type
.t
& VT_STORAGE
)
8832 error("storage class specified for '%s'", get_tok_str(v
, NULL
));
8833 convert_parameter_type(&type
);
8834 /* we can add the type (NOTE: it could be local to the function) */
8836 /* accept other parameters */
8847 /* parse a function defined by symbol 'sym' and generate its code in
8848 'cur_text_section' */
8849 static void gen_function(Sym
*sym
)
8851 ind
= cur_text_section
->data_offset
;
8852 /* NOTE: we patch the symbol size later */
8853 put_extern_sym(sym
, cur_text_section
, ind
, 0);
8854 funcname
= get_tok_str(sym
->v
, NULL
);
8856 /* put debug symbol */
8858 put_func_debug(sym
);
8859 /* push a dummy symbol to enable local sym storage */
8860 sym_push2(&local_stack
, SYM_FIELD
, 0, 0);
8861 gfunc_prolog(&sym
->type
);
8863 block(NULL
, NULL
, NULL
, NULL
, 0, 0);
8866 cur_text_section
->data_offset
= ind
;
8867 label_pop(&global_label_stack
, NULL
);
8868 sym_pop(&local_stack
, NULL
); /* reset local stack */
8869 /* end of function */
8870 /* patch symbol size */
8871 ((Elf32_Sym
*)symtab_section
->data
)[sym
->c
].st_size
=
8874 put_stabn(N_FUN
, 0, 0, ind
- func_ind
);
8876 funcname
= ""; /* for safety */
8877 func_vt
.t
= VT_VOID
; /* for safety */
8878 ind
= 0; /* for safety */
8881 static void gen_inline_functions(void)
8885 int *str
, inline_generated
;
8887 /* iterate while inline function are referenced */
8889 inline_generated
= 0;
8890 for(sym
= global_stack
; sym
!= NULL
; sym
= sym
->prev
) {
8892 if (((type
->t
& VT_BTYPE
) == VT_FUNC
) &&
8893 (type
->t
& (VT_STATIC
| VT_INLINE
)) ==
8894 (VT_STATIC
| VT_INLINE
) &&
8896 /* the function was used: generate its code and
8897 convert it to a normal function */
8898 str
= (int *)sym
->r
;
8899 sym
->r
= VT_SYM
| VT_CONST
;
8900 type
->t
&= ~VT_INLINE
;
8904 cur_text_section
= text_section
;
8906 macro_ptr
= NULL
; /* fail safe */
8909 inline_generated
= 1;
8912 if (!inline_generated
)
8916 /* free all remaining inline function tokens */
8917 for(sym
= global_stack
; sym
!= NULL
; sym
= sym
->prev
) {
8919 if (((type
->t
& VT_BTYPE
) == VT_FUNC
) &&
8920 (type
->t
& (VT_STATIC
| VT_INLINE
)) ==
8921 (VT_STATIC
| VT_INLINE
)) {
8922 str
= (int *)sym
->r
;
8924 sym
->r
= 0; /* fail safe */
8929 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
8930 static void decl(int l
)
8938 if (!parse_btype(&btype
, &ad
)) {
8939 /* skip redundant ';' */
8940 /* XXX: find more elegant solution */
8945 if (l
== VT_CONST
&&
8946 (tok
== TOK_ASM1
|| tok
== TOK_ASM2
|| tok
== TOK_ASM3
)) {
8947 /* global asm block */
8951 /* special test for old K&R protos without explicit int
8952 type. Only accepted when defining global data */
8953 if (l
== VT_LOCAL
|| tok
< TOK_DEFINE
)
8957 if (((btype
.t
& VT_BTYPE
) == VT_ENUM
||
8958 (btype
.t
& VT_BTYPE
) == VT_STRUCT
) &&
8960 /* we accept no variable after */
8964 while (1) { /* iterate thru each declaration */
8966 type_decl(&type
, &ad
, &v
, TYPE_DIRECT
);
8970 type_to_str(buf
, sizeof(buf
), t
, get_tok_str(v
, NULL
));
8971 printf("type = '%s'\n", buf
);
8974 if ((type
.t
& VT_BTYPE
) == VT_FUNC
) {
8975 /* if old style function prototype, we accept a
8978 if (sym
->c
== FUNC_OLD
)
8979 func_decl_list(sym
);
8984 error("cannot use local functions");
8985 if (!(type
.t
& VT_FUNC
))
8986 expect("function definition");
8988 /* reject abstract declarators in function definition */
8990 while ((sym
= sym
->next
) != NULL
)
8991 if (!(sym
->v
& ~SYM_FIELD
))
8992 expect("identifier");
8994 /* XXX: cannot do better now: convert extern line to static inline */
8995 if ((type
.t
& (VT_EXTERN
| VT_INLINE
)) == (VT_EXTERN
| VT_INLINE
))
8996 type
.t
= (type
.t
& ~VT_EXTERN
) | VT_STATIC
;
9000 if ((sym
->type
.t
& VT_BTYPE
) != VT_FUNC
)
9002 /* specific case: if not func_call defined, we put
9003 the one of the prototype */
9004 /* XXX: should have default value */
9005 if (sym
->type
.ref
->r
!= FUNC_CDECL
&&
9006 type
.ref
->r
== FUNC_CDECL
)
9007 type
.ref
->r
= sym
->type
.ref
->r
;
9008 if (!is_compatible_types(&sym
->type
, &type
)) {
9010 error("incompatible types for redefinition of '%s'",
9011 get_tok_str(v
, NULL
));
9013 /* if symbol is already defined, then put complete type */
9016 /* put function symbol */
9017 sym
= global_identifier_push(v
, type
.t
, 0);
9018 sym
->type
.ref
= type
.ref
;
9021 /* static inline functions are just recorded as a kind
9022 of macro. Their code will be emitted at the end of
9023 the compilation unit only if they are used */
9024 if ((type
.t
& (VT_INLINE
| VT_STATIC
)) ==
9025 (VT_INLINE
| VT_STATIC
)) {
9026 TokenString func_str
;
9029 tok_str_new(&func_str
);
9035 error("unexpected end of file");
9036 tok_str_add_tok(&func_str
);
9041 } else if (t
== '}') {
9043 if (block_level
== 0)
9047 tok_str_add(&func_str
, -1);
9048 tok_str_add(&func_str
, 0);
9049 sym
->r
= (int)func_str
.str
;
9051 /* compute text section */
9052 cur_text_section
= ad
.section
;
9053 if (!cur_text_section
)
9054 cur_text_section
= text_section
;
9055 sym
->r
= VT_SYM
| VT_CONST
;
9057 #ifdef TCC_TARGET_PE
9059 ((Elf32_Sym
*)symtab_section
->data
)[sym
->c
].st_other
|= 1;
9065 if (btype
.t
& VT_TYPEDEF
) {
9066 /* save typedefed type */
9067 /* XXX: test storage specifiers ? */
9068 sym
= sym_push(v
, &type
, 0, 0);
9069 sym
->type
.t
|= VT_TYPEDEF
;
9070 } else if ((type
.t
& VT_BTYPE
) == VT_FUNC
) {
9071 /* external function definition */
9072 /* specific case for func_call attribute */
9074 type
.ref
->r
= ad
.func_call
;
9075 external_sym(v
, &type
, 0);
9077 /* not lvalue if array */
9079 if (!(type
.t
& VT_ARRAY
))
9080 r
|= lvalue_type(type
.t
);
9081 has_init
= (tok
== '=');
9082 if ((btype
.t
& VT_EXTERN
) ||
9083 ((type
.t
& VT_ARRAY
) && (type
.t
& VT_STATIC
) &&
9084 !has_init
&& l
== VT_CONST
&& type
.ref
->c
< 0)) {
9085 /* external variable */
9086 /* NOTE: as GCC, uninitialized global static
9087 arrays of null size are considered as
9089 external_sym(v
, &type
, r
);
9091 if (type
.t
& VT_STATIC
)
9097 decl_initializer_alloc(&type
, &ad
, r
,
9111 /* better than nothing, but needs extension to handle '-E' option
9113 static void preprocess_init(TCCState
*s1
)
9115 s1
->include_stack_ptr
= s1
->include_stack
;
9116 /* XXX: move that before to avoid having to initialize
9117 file->ifdef_stack_ptr ? */
9118 s1
->ifdef_stack_ptr
= s1
->ifdef_stack
;
9119 file
->ifdef_stack_ptr
= s1
->ifdef_stack_ptr
;
9121 /* XXX: not ANSI compliant: bound checking says error */
9123 s1
->pack_stack
[0] = 0;
9124 s1
->pack_stack_ptr
= s1
->pack_stack
;
9127 /* compile the C file opened in 'file'. Return non zero if errors. */
9128 static int tcc_compile(TCCState
*s1
)
9132 volatile int section_sym
;
9135 printf("%s: **** new file\n", file
->filename
);
9137 preprocess_init(s1
);
9140 anon_sym
= SYM_FIRST_ANOM
;
9142 /* file info: full path + filename */
9143 section_sym
= 0; /* avoid warning */
9145 section_sym
= put_elf_sym(symtab_section
, 0, 0,
9146 ELF32_ST_INFO(STB_LOCAL
, STT_SECTION
), 0,
9147 text_section
->sh_num
, NULL
);
9148 getcwd(buf
, sizeof(buf
));
9149 pstrcat(buf
, sizeof(buf
), "/");
9150 put_stabs_r(buf
, N_SO
, 0, 0,
9151 text_section
->data_offset
, text_section
, section_sym
);
9152 put_stabs_r(file
->filename
, N_SO
, 0, 0,
9153 text_section
->data_offset
, text_section
, section_sym
);
9155 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
9156 symbols can be safely used */
9157 put_elf_sym(symtab_section
, 0, 0,
9158 ELF32_ST_INFO(STB_LOCAL
, STT_FILE
), 0,
9159 SHN_ABS
, file
->filename
);
9161 /* define some often used types */
9162 int_type
.t
= VT_INT
;
9164 char_pointer_type
.t
= VT_BYTE
;
9165 mk_pointer(&char_pointer_type
);
9167 func_old_type
.t
= VT_FUNC
;
9168 func_old_type
.ref
= sym_push(SYM_FIELD
, &int_type
, FUNC_CDECL
, FUNC_OLD
);
9171 /* define 'void *alloca(unsigned int)' builtin function */
9176 sym
= sym_push(p
, mk_pointer(VT_VOID
), FUNC_CDECL
, FUNC_NEW
);
9177 s1
= sym_push(SYM_FIELD
, VT_UNSIGNED
| VT_INT
, 0, 0);
9180 sym_push(TOK_alloca
, VT_FUNC
| (p
<< VT_STRUCT_SHIFT
), VT_CONST
, 0);
9184 define_start
= define_stack
;
9186 if (setjmp(s1
->error_jmp_buf
) == 0) {
9188 s1
->error_set_jmp_enabled
= 1;
9190 ch
= file
->buf_ptr
[0];
9191 tok_flags
= TOK_FLAG_BOL
| TOK_FLAG_BOF
;
9192 parse_flags
= PARSE_FLAG_PREPROCESS
| PARSE_FLAG_TOK_NUM
;
9196 expect("declaration");
9198 /* end of translation unit info */
9200 put_stabs_r(NULL
, N_SO
, 0, 0,
9201 text_section
->data_offset
, text_section
, section_sym
);
9204 s1
->error_set_jmp_enabled
= 0;
9206 /* reset define stack, but leave -Dsymbols (may be incorrect if
9207 they are undefined) */
9208 free_defines(define_start
);
9210 gen_inline_functions();
9212 sym_pop(&global_stack
, NULL
);
9214 return s1
->nb_errors
!= 0 ? -1 : 0;
9218 int tcc_compile_string(TCCState
*s
, const char *str
)
9220 BufferedFile bf1
, *bf
= &bf1
;
9224 /* init file structure */
9226 /* XXX: avoid copying */
9228 buf
= tcc_malloc(len
+ 1);
9231 memcpy(buf
, str
, len
);
9234 bf
->buf_end
= buf
+ len
;
9235 pstrcpy(bf
->filename
, sizeof(bf
->filename
), "<string>");
9239 ret
= tcc_compile(s
);
9243 /* currently, no need to close */
9248 /* define a preprocessor symbol. A value can also be provided with the '=' operator */
9249 void tcc_define_symbol(TCCState
*s1
, const char *sym
, const char *value
)
9251 BufferedFile bf1
, *bf
= &bf1
;
9253 pstrcpy(bf
->buffer
, IO_BUF_SIZE
, sym
);
9254 pstrcat(bf
->buffer
, IO_BUF_SIZE
, " ");
9258 pstrcat(bf
->buffer
, IO_BUF_SIZE
, value
);
9260 /* init file structure */
9262 bf
->buf_ptr
= bf
->buffer
;
9263 bf
->buf_end
= bf
->buffer
+ strlen(bf
->buffer
);
9264 *bf
->buf_end
= CH_EOB
;
9265 bf
->filename
[0] = '\0';
9269 s1
->include_stack_ptr
= s1
->include_stack
;
9271 /* parse with define parser */
9272 ch
= file
->buf_ptr
[0];
9278 /* undefine a preprocessor symbol */
9279 void tcc_undefine_symbol(TCCState
*s1
, const char *sym
)
9283 ts
= tok_alloc(sym
, strlen(sym
));
9284 s
= define_find(ts
->tok
);
9285 /* undefine symbol by putting an invalid name */
9290 #ifdef CONFIG_TCC_ASM
9292 #ifdef TCC_TARGET_I386
9293 #include "i386-asm.c"
9298 static void asm_instr(void)
9300 error("inline asm() not supported");
9302 static void asm_global_instr(void)
9304 error("inline asm() not supported");
9310 #ifdef TCC_TARGET_COFF
9311 #include "tcccoff.c"
9314 #ifdef TCC_TARGET_PE
9318 /* print the position in the source file of PC value 'pc' by reading
9319 the stabs debug information */
9320 static void rt_printline(unsigned long wanted_pc
)
9322 Stab_Sym
*sym
, *sym_end
;
9323 char func_name
[128], last_func_name
[128];
9324 unsigned long func_addr
, last_pc
, pc
;
9325 const char *incl_files
[INCLUDE_STACK_SIZE
];
9326 int incl_index
, len
, last_line_num
, i
;
9327 const char *str
, *p
;
9329 fprintf(stderr
, "0x%08lx:", wanted_pc
);
9331 func_name
[0] = '\0';
9334 last_func_name
[0] = '\0';
9335 last_pc
= 0xffffffff;
9337 sym
= (Stab_Sym
*)stab_section
->data
+ 1;
9338 sym_end
= (Stab_Sym
*)(stab_section
->data
+ stab_section
->data_offset
);
9339 while (sym
< sym_end
) {
9340 switch(sym
->n_type
) {
9341 /* function start or end */
9343 if (sym
->n_strx
== 0) {
9344 /* we test if between last line and end of function */
9345 pc
= sym
->n_value
+ func_addr
;
9346 if (wanted_pc
>= last_pc
&& wanted_pc
< pc
)
9348 func_name
[0] = '\0';
9351 str
= stabstr_section
->data
+ sym
->n_strx
;
9352 p
= strchr(str
, ':');
9354 pstrcpy(func_name
, sizeof(func_name
), str
);
9357 if (len
> sizeof(func_name
) - 1)
9358 len
= sizeof(func_name
) - 1;
9359 memcpy(func_name
, str
, len
);
9360 func_name
[len
] = '\0';
9362 func_addr
= sym
->n_value
;
9365 /* line number info */
9367 pc
= sym
->n_value
+ func_addr
;
9368 if (wanted_pc
>= last_pc
&& wanted_pc
< pc
)
9371 last_line_num
= sym
->n_desc
;
9373 strcpy(last_func_name
, func_name
);
9377 str
= stabstr_section
->data
+ sym
->n_strx
;
9379 if (incl_index
< INCLUDE_STACK_SIZE
) {
9380 incl_files
[incl_index
++] = str
;
9388 if (sym
->n_strx
== 0) {
9389 incl_index
= 0; /* end of translation unit */
9391 str
= stabstr_section
->data
+ sym
->n_strx
;
9392 /* do not add path */
9394 if (len
> 0 && str
[len
- 1] != '/')
9402 /* second pass: we try symtab symbols (no line number info) */
9405 Elf32_Sym
*sym
, *sym_end
;
9408 sym_end
= (Elf32_Sym
*)(symtab_section
->data
+ symtab_section
->data_offset
);
9409 for(sym
= (Elf32_Sym
*)symtab_section
->data
+ 1;
9412 type
= ELF32_ST_TYPE(sym
->st_info
);
9413 if (type
== STT_FUNC
) {
9414 if (wanted_pc
>= sym
->st_value
&&
9415 wanted_pc
< sym
->st_value
+ sym
->st_size
) {
9416 pstrcpy(last_func_name
, sizeof(last_func_name
),
9417 strtab_section
->data
+ sym
->st_name
);
9423 /* did not find any info: */
9424 fprintf(stderr
, " ???\n");
9427 if (last_func_name
[0] != '\0') {
9428 fprintf(stderr
, " %s()", last_func_name
);
9430 if (incl_index
> 0) {
9431 fprintf(stderr
, " (%s:%d",
9432 incl_files
[incl_index
- 1], last_line_num
);
9433 for(i
= incl_index
- 2; i
>= 0; i
--)
9434 fprintf(stderr
, ", included from %s", incl_files
[i
]);
9435 fprintf(stderr
, ")");
9437 fprintf(stderr
, "\n");
9440 #if !defined(WIN32) && !defined(CONFIG_TCCBOOT)
9444 /* fix for glibc 2.1 */
9450 /* return the PC at frame level 'level'. Return non zero if not found */
9451 static int rt_get_caller_pc(unsigned long *paddr
,
9452 ucontext_t
*uc
, int level
)
9458 #if defined(__FreeBSD__)
9459 *paddr
= uc
->uc_mcontext
.mc_eip
;
9460 #elif defined(__dietlibc__)
9461 *paddr
= uc
->uc_mcontext
.eip
;
9463 *paddr
= uc
->uc_mcontext
.gregs
[REG_EIP
];
9467 #if defined(__FreeBSD__)
9468 fp
= uc
->uc_mcontext
.mc_ebp
;
9469 #elif defined(__dietlibc__)
9470 fp
= uc
->uc_mcontext
.ebp
;
9472 fp
= uc
->uc_mcontext
.gregs
[REG_EBP
];
9474 for(i
=1;i
<level
;i
++) {
9475 /* XXX: check address validity with program info */
9476 if (fp
<= 0x1000 || fp
>= 0xc0000000)
9478 fp
= ((unsigned long *)fp
)[0];
9480 *paddr
= ((unsigned long *)fp
)[1];
9486 #warning add arch specific rt_get_caller_pc()
9488 static int rt_get_caller_pc(unsigned long *paddr
,
9489 ucontext_t
*uc
, int level
)
9495 /* emit a run time error at position 'pc' */
9496 void rt_error(ucontext_t
*uc
, const char *fmt
, ...)
9503 fprintf(stderr
, "Runtime error: ");
9504 vfprintf(stderr
, fmt
, ap
);
9505 fprintf(stderr
, "\n");
9506 for(i
=0;i
<num_callers
;i
++) {
9507 if (rt_get_caller_pc(&pc
, uc
, i
) < 0)
9510 fprintf(stderr
, "at ");
9512 fprintf(stderr
, "by ");
9519 /* signal handler for fatal errors */
9520 static void sig_error(int signum
, siginfo_t
*siginf
, void *puc
)
9522 ucontext_t
*uc
= puc
;
9526 switch(siginf
->si_code
) {
9529 rt_error(uc
, "division by zero");
9532 rt_error(uc
, "floating point exception");
9538 if (rt_bound_error_msg
&& *rt_bound_error_msg
)
9539 rt_error(uc
, *rt_bound_error_msg
);
9541 rt_error(uc
, "dereferencing invalid pointer");
9544 rt_error(uc
, "illegal instruction");
9547 rt_error(uc
, "abort() called");
9550 rt_error(uc
, "caught signal %d", signum
);
9557 /* do all relocations (needed before using tcc_get_symbol()) */
9558 int tcc_relocate(TCCState
*s1
)
9565 #ifdef TCC_TARGET_PE
9568 tcc_add_runtime(s1
);
9571 relocate_common_syms();
9573 tcc_add_linker_symbols(s1
);
9575 build_got_entries(s1
);
9577 /* compute relocation address : section are relocated in place. We
9578 also alloc the bss space */
9579 for(i
= 1; i
< s1
->nb_sections
; i
++) {
9580 s
= s1
->sections
[i
];
9581 if (s
->sh_flags
& SHF_ALLOC
) {
9582 if (s
->sh_type
== SHT_NOBITS
)
9583 s
->data
= tcc_mallocz(s
->data_offset
);
9584 s
->sh_addr
= (unsigned long)s
->data
;
9588 relocate_syms(s1
, 1);
9590 if (s1
->nb_errors
!= 0)
9593 /* relocate each section */
9594 for(i
= 1; i
< s1
->nb_sections
; i
++) {
9595 s
= s1
->sections
[i
];
9597 relocate_section(s1
, s
);
9602 /* launch the compiled program with the given arguments */
9603 int tcc_run(TCCState
*s1
, int argc
, char **argv
)
9605 int (*prog_main
)(int, char **);
9607 if (tcc_relocate(s1
) < 0)
9610 prog_main
= tcc_get_symbol_err(s1
, "main");
9613 #if defined(WIN32) || defined(CONFIG_TCCBOOT)
9614 error("debug mode currently not available for Windows");
9616 struct sigaction sigact
;
9617 /* install TCC signal handlers to print debug info on fatal
9619 sigact
.sa_flags
= SA_SIGINFO
| SA_RESETHAND
;
9620 sigact
.sa_sigaction
= sig_error
;
9621 sigemptyset(&sigact
.sa_mask
);
9622 sigaction(SIGFPE
, &sigact
, NULL
);
9623 sigaction(SIGILL
, &sigact
, NULL
);
9624 sigaction(SIGSEGV
, &sigact
, NULL
);
9625 sigaction(SIGBUS
, &sigact
, NULL
);
9626 sigaction(SIGABRT
, &sigact
, NULL
);
9630 #ifdef CONFIG_TCC_BCHECK
9631 if (do_bounds_check
) {
9632 void (*bound_init
)(void);
9634 /* set error function */
9635 rt_bound_error_msg
= (void *)tcc_get_symbol_err(s1
,
9636 "__bound_error_msg");
9638 /* XXX: use .init section so that it also work in binary ? */
9639 bound_init
= (void *)tcc_get_symbol_err(s1
, "__bound_init");
9643 return (*prog_main
)(argc
, argv
);
9646 TCCState
*tcc_new(void)
9653 s
= tcc_mallocz(sizeof(TCCState
));
9657 s
->output_type
= TCC_OUTPUT_MEMORY
;
9659 /* init isid table */
9661 isidnum_table
[i
] = isid(i
) || isnum(i
);
9663 /* add all tokens */
9665 memset(hash_ident
, 0, TOK_HASH_SIZE
* sizeof(TokenSym
*));
9667 tok_ident
= TOK_IDENT
;
9676 ts
= tok_alloc(p
, r
- p
- 1);
9680 /* we add dummy defines for some special macros to speed up tests
9681 and to have working defined() */
9682 define_push(TOK___LINE__
, MACRO_OBJ
, NULL
, NULL
);
9683 define_push(TOK___FILE__
, MACRO_OBJ
, NULL
, NULL
);
9684 define_push(TOK___DATE__
, MACRO_OBJ
, NULL
, NULL
);
9685 define_push(TOK___TIME__
, MACRO_OBJ
, NULL
, NULL
);
9687 /* standard defines */
9688 tcc_define_symbol(s
, "__STDC__", NULL
);
9689 #if defined(TCC_TARGET_I386)
9690 tcc_define_symbol(s
, "__i386__", NULL
);
9692 #if defined(TCC_TARGET_ARM)
9693 tcc_define_symbol(s
, "__ARM_ARCH_4__", NULL
);
9694 tcc_define_symbol(s
, "__arm_elf__", NULL
);
9695 tcc_define_symbol(s
, "__arm_elf", NULL
);
9696 tcc_define_symbol(s
, "arm_elf", NULL
);
9697 tcc_define_symbol(s
, "__arm__", NULL
);
9698 tcc_define_symbol(s
, "__arm", NULL
);
9699 tcc_define_symbol(s
, "arm", NULL
);
9700 tcc_define_symbol(s
, "__APCS_32__", NULL
);
9703 tcc_define_symbol(s
, "__linux__", NULL
);
9704 tcc_define_symbol(s
, "linux", NULL
);
9706 /* tiny C specific defines */
9707 tcc_define_symbol(s
, "__TINYC__", NULL
);
9709 /* tiny C & gcc defines */
9710 tcc_define_symbol(s
, "__SIZE_TYPE__", "unsigned int");
9711 tcc_define_symbol(s
, "__PTRDIFF_TYPE__", "int");
9712 tcc_define_symbol(s
, "__WCHAR_TYPE__", "int");
9714 /* default library paths */
9715 #ifdef TCC_TARGET_PE
9718 snprintf(buf
, sizeof(buf
), "%s/lib", tcc_lib_path
);
9719 tcc_add_library_path(s
, buf
);
9722 tcc_add_library_path(s
, "/usr/local/lib");
9723 tcc_add_library_path(s
, "/usr/lib");
9724 tcc_add_library_path(s
, "/lib");
9727 /* no section zero */
9728 dynarray_add((void ***)&s
->sections
, &s
->nb_sections
, NULL
);
9730 /* create standard sections */
9731 text_section
= new_section(s
, ".text", SHT_PROGBITS
, SHF_ALLOC
| SHF_EXECINSTR
);
9732 data_section
= new_section(s
, ".data", SHT_PROGBITS
, SHF_ALLOC
| SHF_WRITE
);
9733 bss_section
= new_section(s
, ".bss", SHT_NOBITS
, SHF_ALLOC
| SHF_WRITE
);
9735 /* symbols are always generated for linking stage */
9736 symtab_section
= new_symtab(s
, ".symtab", SHT_SYMTAB
, 0,
9738 ".hashtab", SHF_PRIVATE
);
9739 strtab_section
= symtab_section
->link
;
9741 /* private symbol table for dynamic symbols */
9742 s
->dynsymtab_section
= new_symtab(s
, ".dynsymtab", SHT_SYMTAB
, SHF_PRIVATE
,
9744 ".dynhashtab", SHF_PRIVATE
);
9745 s
->alacarte_link
= 1;
9747 #ifdef CHAR_IS_UNSIGNED
9748 s
->char_is_unsigned
= 1;
9750 #ifdef TCC_TARGET_PE
9751 s
->leading_underscore
= 1;
9756 void tcc_delete(TCCState
*s1
)
9760 /* free -D defines */
9764 n
= tok_ident
- TOK_IDENT
;
9765 for(i
= 0; i
< n
; i
++)
9766 tcc_free(table_ident
[i
]);
9767 tcc_free(table_ident
);
9769 /* free all sections */
9771 free_section(symtab_section
->hash
);
9773 free_section(s1
->dynsymtab_section
->hash
);
9774 free_section(s1
->dynsymtab_section
->link
);
9775 free_section(s1
->dynsymtab_section
);
9777 for(i
= 1; i
< s1
->nb_sections
; i
++)
9778 free_section(s1
->sections
[i
]);
9779 tcc_free(s1
->sections
);
9781 /* free loaded dlls array */
9782 for(i
= 0; i
< s1
->nb_loaded_dlls
; i
++)
9783 tcc_free(s1
->loaded_dlls
[i
]);
9784 tcc_free(s1
->loaded_dlls
);
9787 for(i
= 0; i
< s1
->nb_library_paths
; i
++)
9788 tcc_free(s1
->library_paths
[i
]);
9789 tcc_free(s1
->library_paths
);
9791 /* cached includes */
9792 for(i
= 0; i
< s1
->nb_cached_includes
; i
++)
9793 tcc_free(s1
->cached_includes
[i
]);
9794 tcc_free(s1
->cached_includes
);
9796 for(i
= 0; i
< s1
->nb_include_paths
; i
++)
9797 tcc_free(s1
->include_paths
[i
]);
9798 tcc_free(s1
->include_paths
);
9800 for(i
= 0; i
< s1
->nb_sysinclude_paths
; i
++)
9801 tcc_free(s1
->sysinclude_paths
[i
]);
9802 tcc_free(s1
->sysinclude_paths
);
9807 int tcc_add_include_path(TCCState
*s1
, const char *pathname
)
9811 pathname1
= tcc_strdup(pathname
);
9812 dynarray_add((void ***)&s1
->include_paths
, &s1
->nb_include_paths
, pathname1
);
9816 int tcc_add_sysinclude_path(TCCState
*s1
, const char *pathname
)
9820 pathname1
= tcc_strdup(pathname
);
9821 dynarray_add((void ***)&s1
->sysinclude_paths
, &s1
->nb_sysinclude_paths
, pathname1
);
9825 static int tcc_add_file_internal(TCCState
*s1
, const char *filename
, int flags
)
9827 const char *ext
, *filename1
;
9830 BufferedFile
*saved_file
;
9832 /* find source file type with extension */
9833 filename1
= strrchr(filename
, '/');
9837 filename1
= filename
;
9838 ext
= strrchr(filename1
, '.');
9844 file
= tcc_open(s1
, filename
);
9846 if (flags
& AFF_PRINT_ERROR
) {
9847 error_noabort("file '%s' not found", filename
);
9853 if (!ext
|| !strcmp(ext
, "c")) {
9854 /* C file assumed */
9855 ret
= tcc_compile(s1
);
9857 #ifdef CONFIG_TCC_ASM
9858 if (!strcmp(ext
, "S")) {
9859 /* preprocessed assembler */
9860 ret
= tcc_assemble(s1
, 1);
9861 } else if (!strcmp(ext
, "s")) {
9862 /* non preprocessed assembler */
9863 ret
= tcc_assemble(s1
, 0);
9866 #ifdef TCC_TARGET_PE
9867 if (!strcmp(ext
, "def")) {
9868 ret
= pe_load_def_file(s1
, fdopen(file
->fd
, "rb"));
9873 /* assume executable format: auto guess file type */
9874 ret
= read(fd
, &ehdr
, sizeof(ehdr
));
9875 lseek(fd
, 0, SEEK_SET
);
9877 error_noabort("could not read header");
9879 } else if (ret
!= sizeof(ehdr
)) {
9880 goto try_load_script
;
9883 if (ehdr
.e_ident
[0] == ELFMAG0
&&
9884 ehdr
.e_ident
[1] == ELFMAG1
&&
9885 ehdr
.e_ident
[2] == ELFMAG2
&&
9886 ehdr
.e_ident
[3] == ELFMAG3
) {
9887 file
->line_num
= 0; /* do not display line number if error */
9888 if (ehdr
.e_type
== ET_REL
) {
9889 ret
= tcc_load_object_file(s1
, fd
, 0);
9890 } else if (ehdr
.e_type
== ET_DYN
) {
9891 if (s1
->output_type
== TCC_OUTPUT_MEMORY
) {
9892 #ifdef TCC_TARGET_PE
9896 h
= dlopen(filename
, RTLD_GLOBAL
| RTLD_LAZY
);
9903 ret
= tcc_load_dll(s1
, fd
, filename
,
9904 (flags
& AFF_REFERENCED_DLL
) != 0);
9907 error_noabort("unrecognized ELF file");
9910 } else if (memcmp((char *)&ehdr
, ARMAG
, 8) == 0) {
9911 file
->line_num
= 0; /* do not display line number if error */
9912 ret
= tcc_load_archive(s1
, fd
);
9914 #ifdef TCC_TARGET_COFF
9915 if (*(uint16_t *)(&ehdr
) == COFF_C67_MAGIC
) {
9916 ret
= tcc_load_coff(s1
, fd
);
9920 /* as GNU ld, consider it is an ld script if not recognized */
9922 ret
= tcc_load_ldscript(s1
);
9924 error_noabort("unrecognized file type");
9939 int tcc_add_file(TCCState
*s
, const char *filename
)
9941 return tcc_add_file_internal(s
, filename
, AFF_PRINT_ERROR
);
9944 int tcc_add_library_path(TCCState
*s
, const char *pathname
)
9948 pathname1
= tcc_strdup(pathname
);
9949 dynarray_add((void ***)&s
->library_paths
, &s
->nb_library_paths
, pathname1
);
9953 /* find and load a dll. Return non zero if not found */
9954 /* XXX: add '-rpath' option support ? */
9955 static int tcc_add_dll(TCCState
*s
, const char *filename
, int flags
)
9960 for(i
= 0; i
< s
->nb_library_paths
; i
++) {
9961 snprintf(buf
, sizeof(buf
), "%s/%s",
9962 s
->library_paths
[i
], filename
);
9963 if (tcc_add_file_internal(s
, buf
, flags
) == 0)
9969 /* the library name is the same as the argument of the '-l' option */
9970 int tcc_add_library(TCCState
*s
, const char *libraryname
)
9975 /* first we look for the dynamic library if not static linking */
9976 if (!s
->static_link
) {
9977 #ifdef TCC_TARGET_PE
9978 snprintf(buf
, sizeof(buf
), "%s.def", libraryname
);
9980 snprintf(buf
, sizeof(buf
), "lib%s.so", libraryname
);
9982 if (tcc_add_dll(s
, buf
, 0) == 0)
9986 /* then we look for the static library */
9987 for(i
= 0; i
< s
->nb_library_paths
; i
++) {
9988 snprintf(buf
, sizeof(buf
), "%s/lib%s.a",
9989 s
->library_paths
[i
], libraryname
);
9990 if (tcc_add_file_internal(s
, buf
, 0) == 0)
9996 int tcc_add_symbol(TCCState
*s
, const char *name
, unsigned long val
)
9998 add_elf_sym(symtab_section
, val
, 0,
9999 ELF32_ST_INFO(STB_GLOBAL
, STT_NOTYPE
), 0,
10004 int tcc_set_output_type(TCCState
*s
, int output_type
)
10006 s
->output_type
= output_type
;
10008 if (!s
->nostdinc
) {
10011 /* default include paths */
10012 /* XXX: reverse order needed if -isystem support */
10013 #ifndef TCC_TARGET_PE
10014 tcc_add_sysinclude_path(s
, "/usr/local/include");
10015 tcc_add_sysinclude_path(s
, "/usr/include");
10017 snprintf(buf
, sizeof(buf
), "%s/include", tcc_lib_path
);
10018 tcc_add_sysinclude_path(s
, buf
);
10019 #ifdef TCC_TARGET_PE
10020 snprintf(buf
, sizeof(buf
), "%s/include/winapi", tcc_lib_path
);
10021 tcc_add_sysinclude_path(s
, buf
);
10025 /* if bound checking, then add corresponding sections */
10026 #ifdef CONFIG_TCC_BCHECK
10027 if (do_bounds_check
) {
10028 /* define symbol */
10029 tcc_define_symbol(s
, "__BOUNDS_CHECKING_ON", NULL
);
10030 /* create bounds sections */
10031 bounds_section
= new_section(s
, ".bounds",
10032 SHT_PROGBITS
, SHF_ALLOC
);
10033 lbounds_section
= new_section(s
, ".lbounds",
10034 SHT_PROGBITS
, SHF_ALLOC
);
10038 if (s
->char_is_unsigned
) {
10039 tcc_define_symbol(s
, "__CHAR_UNSIGNED__", NULL
);
10042 /* add debug sections */
10045 stab_section
= new_section(s
, ".stab", SHT_PROGBITS
, 0);
10046 stab_section
->sh_entsize
= sizeof(Stab_Sym
);
10047 stabstr_section
= new_section(s
, ".stabstr", SHT_STRTAB
, 0);
10048 put_elf_str(stabstr_section
, "");
10049 stab_section
->link
= stabstr_section
;
10050 /* put first entry */
10051 put_stabs("", 0, 0, 0, 0);
10054 /* add libc crt1/crti objects */
10055 #ifndef TCC_TARGET_PE
10056 if ((output_type
== TCC_OUTPUT_EXE
|| output_type
== TCC_OUTPUT_DLL
) &&
10058 if (output_type
!= TCC_OUTPUT_DLL
)
10059 tcc_add_file(s
, CONFIG_TCC_CRT_PREFIX
"/crt1.o");
10060 tcc_add_file(s
, CONFIG_TCC_CRT_PREFIX
"/crti.o");
10066 #define WD_ALL 0x0001 /* warning is activated when using -Wall */
10067 #define FD_INVERT 0x0002 /* invert value before storing */
10069 typedef struct FlagDef
{
10075 static const FlagDef warning_defs
[] = {
10076 { offsetof(TCCState
, warn_unsupported
), 0, "unsupported" },
10077 { offsetof(TCCState
, warn_write_strings
), 0, "write-strings" },
10078 { offsetof(TCCState
, warn_error
), 0, "error" },
10079 { offsetof(TCCState
, warn_implicit_function_declaration
), WD_ALL
,
10080 "implicit-function-declaration" },
10083 static int set_flag(TCCState
*s
, const FlagDef
*flags
, int nb_flags
,
10084 const char *name
, int value
)
10091 if (r
[0] == 'n' && r
[1] == 'o' && r
[2] == '-') {
10095 for(i
= 0, p
= flags
; i
< nb_flags
; i
++, p
++) {
10096 if (!strcmp(r
, p
->name
))
10101 if (p
->flags
& FD_INVERT
)
10103 *(int *)((uint8_t *)s
+ p
->offset
) = value
;
10108 /* set/reset a warning */
10109 int tcc_set_warning(TCCState
*s
, const char *warning_name
, int value
)
10114 if (!strcmp(warning_name
, "all")) {
10115 for(i
= 0, p
= warning_defs
; i
< countof(warning_defs
); i
++, p
++) {
10116 if (p
->flags
& WD_ALL
)
10117 *(int *)((uint8_t *)s
+ p
->offset
) = 1;
10121 return set_flag(s
, warning_defs
, countof(warning_defs
),
10122 warning_name
, value
);
10126 static const FlagDef flag_defs
[] = {
10127 { offsetof(TCCState
, char_is_unsigned
), 0, "unsigned-char" },
10128 { offsetof(TCCState
, char_is_unsigned
), FD_INVERT
, "signed-char" },
10129 { offsetof(TCCState
, nocommon
), FD_INVERT
, "common" },
10130 { offsetof(TCCState
, leading_underscore
), 0, "leading-underscore" },
10133 /* set/reset a flag */
10134 int tcc_set_flag(TCCState
*s
, const char *flag_name
, int value
)
10136 return set_flag(s
, flag_defs
, countof(flag_defs
),
10140 #if !defined(LIBTCC)
10142 /* extract the basename of a file */
10143 static const char *tcc_basename(const char *name
)
10146 p
= strrchr(name
, '/');
10149 p
= strrchr(name
, '\\');
10158 static int64_t getclock_us(void)
10163 return (tb
.time
* 1000LL + tb
.millitm
) * 1000LL;
10166 gettimeofday(&tv
, NULL
);
10167 return tv
.tv_sec
* 1000000LL + tv
.tv_usec
;
10173 printf("tcc version " TCC_VERSION
" - Tiny C Compiler - Copyright (C) 2001-2005 Fabrice Bellard\n"
10174 "usage: tcc [-v] [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
10175 " [-Wwarn] [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-static]\n"
10176 " [infile1 infile2...] [-run infile args...]\n"
10178 "General options:\n"
10179 " -v display current version\n"
10180 " -c compile only - generate an object file\n"
10181 " -o outfile set output filename\n"
10182 " -Bdir set tcc internal library path\n"
10183 " -bench output compilation statistics\n"
10184 " -run run compiled source\n"
10185 " -fflag set or reset (with 'no-' prefix) 'flag' (see man page)\n"
10186 " -Wwarning set or reset (with 'no-' prefix) 'warning' (see man page)\n"
10187 " -w disable all warnings\n"
10188 "Preprocessor options:\n"
10189 " -Idir add include path 'dir'\n"
10190 " -Dsym[=val] define 'sym' with value 'val'\n"
10191 " -Usym undefine 'sym'\n"
10192 "Linker options:\n"
10193 " -Ldir add library path 'dir'\n"
10194 " -llib link with dynamic or static library 'lib'\n"
10195 " -shared generate a shared library\n"
10196 " -static static linking\n"
10197 " -rdynamic export all global symbols to dynamic linker\n"
10198 " -r relocatable output\n"
10199 "Debugger options:\n"
10200 " -g generate runtime debug info\n"
10201 #ifdef CONFIG_TCC_BCHECK
10202 " -b compile with built-in memory and bounds checker (implies -g)\n"
10204 " -bt N show N callers in stack traces\n"
10208 #define TCC_OPTION_HAS_ARG 0x0001
10209 #define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
10211 typedef struct TCCOption
{
10239 TCC_OPTION_nostdinc
,
10240 TCC_OPTION_nostdlib
,
10241 TCC_OPTION_print_search_dirs
,
10242 TCC_OPTION_rdynamic
,
10249 static const TCCOption tcc_options
[] = {
10250 { "h", TCC_OPTION_HELP
, 0 },
10251 { "?", TCC_OPTION_HELP
, 0 },
10252 { "I", TCC_OPTION_I
, TCC_OPTION_HAS_ARG
},
10253 { "D", TCC_OPTION_D
, TCC_OPTION_HAS_ARG
},
10254 { "U", TCC_OPTION_U
, TCC_OPTION_HAS_ARG
},
10255 { "L", TCC_OPTION_L
, TCC_OPTION_HAS_ARG
},
10256 { "B", TCC_OPTION_B
, TCC_OPTION_HAS_ARG
},
10257 { "l", TCC_OPTION_l
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10258 { "bench", TCC_OPTION_bench
, 0 },
10259 { "bt", TCC_OPTION_bt
, TCC_OPTION_HAS_ARG
},
10260 #ifdef CONFIG_TCC_BCHECK
10261 { "b", TCC_OPTION_b
, 0 },
10263 { "g", TCC_OPTION_g
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10264 { "c", TCC_OPTION_c
, 0 },
10265 { "static", TCC_OPTION_static
, 0 },
10266 { "shared", TCC_OPTION_shared
, 0 },
10267 { "o", TCC_OPTION_o
, TCC_OPTION_HAS_ARG
},
10268 { "run", TCC_OPTION_run
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10269 { "rdynamic", TCC_OPTION_rdynamic
, 0 },
10270 { "r", TCC_OPTION_r
, 0 },
10271 { "Wl,", TCC_OPTION_Wl
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10272 { "W", TCC_OPTION_W
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10273 { "O", TCC_OPTION_O
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10274 { "m", TCC_OPTION_m
, TCC_OPTION_HAS_ARG
},
10275 { "f", TCC_OPTION_f
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10276 { "nostdinc", TCC_OPTION_nostdinc
, 0 },
10277 { "nostdlib", TCC_OPTION_nostdlib
, 0 },
10278 { "print-search-dirs", TCC_OPTION_print_search_dirs
, 0 },
10279 { "v", TCC_OPTION_v
, 0 },
10280 { "w", TCC_OPTION_w
, 0 },
10281 { "pipe", TCC_OPTION_pipe
, 0},
10285 /* convert 'str' into an array of space separated strings */
10286 static int expand_args(char ***pargv
, const char *str
)
10295 while (is_space(*str
))
10300 while (*str
!= '\0' && !is_space(*str
))
10303 arg
= tcc_malloc(len
+ 1);
10304 memcpy(arg
, s1
, len
);
10306 dynarray_add((void ***)&argv
, &argc
, arg
);
10312 static char **files
;
10313 static int nb_files
, nb_libraries
;
10314 static int multiple_files
;
10315 static int print_search_dirs
;
10316 static int output_type
;
10317 static int reloc_output
;
10318 static const char *outfile
;
10320 int parse_args(TCCState
*s
, int argc
, char **argv
)
10323 const TCCOption
*popt
;
10324 const char *optarg
, *p1
, *r1
;
10329 if (optind
>= argc
) {
10330 if (nb_files
== 0 && !print_search_dirs
)
10335 r
= argv
[optind
++];
10337 /* add a new file */
10338 dynarray_add((void ***)&files
, &nb_files
, r
);
10339 if (!multiple_files
) {
10341 /* argv[0] will be this file */
10345 /* find option in table (match only the first chars */
10346 popt
= tcc_options
;
10350 error("invalid option -- '%s'", r
);
10363 if (popt
->flags
& TCC_OPTION_HAS_ARG
) {
10364 if (*r1
!= '\0' || (popt
->flags
& TCC_OPTION_NOSEP
)) {
10367 if (optind
>= argc
)
10368 error("argument to '%s' is missing", r
);
10369 optarg
= argv
[optind
++];
10377 switch(popt
->index
) {
10378 case TCC_OPTION_HELP
:
10383 if (tcc_add_include_path(s
, optarg
) < 0)
10384 error("too many include paths");
10389 sym
= (char *)optarg
;
10390 value
= strchr(sym
, '=');
10395 tcc_define_symbol(s
, sym
, value
);
10399 tcc_undefine_symbol(s
, optarg
);
10402 tcc_add_library_path(s
, optarg
);
10405 /* set tcc utilities path (mainly for tcc development) */
10406 tcc_lib_path
= optarg
;
10409 dynarray_add((void ***)&files
, &nb_files
, r
);
10412 case TCC_OPTION_bench
:
10415 case TCC_OPTION_bt
:
10416 num_callers
= atoi(optarg
);
10418 #ifdef CONFIG_TCC_BCHECK
10420 do_bounds_check
= 1;
10428 multiple_files
= 1;
10429 output_type
= TCC_OUTPUT_OBJ
;
10431 case TCC_OPTION_static
:
10432 s
->static_link
= 1;
10434 case TCC_OPTION_shared
:
10435 output_type
= TCC_OUTPUT_DLL
;
10438 multiple_files
= 1;
10442 /* generate a .o merging several output files */
10444 output_type
= TCC_OUTPUT_OBJ
;
10446 case TCC_OPTION_nostdinc
:
10449 case TCC_OPTION_nostdlib
:
10452 case TCC_OPTION_print_search_dirs
:
10453 print_search_dirs
= 1;
10455 case TCC_OPTION_run
:
10459 argc1
= expand_args(&argv1
, optarg
);
10461 parse_args(s
, argc1
, argv1
);
10463 multiple_files
= 0;
10464 output_type
= TCC_OUTPUT_MEMORY
;
10468 printf("tcc version %s\n", TCC_VERSION
);
10471 if (tcc_set_flag(s
, optarg
, 1) < 0 && s
->warn_unsupported
)
10472 goto unsupported_option
;
10475 if (tcc_set_warning(s
, optarg
, 1) < 0 &&
10476 s
->warn_unsupported
)
10477 goto unsupported_option
;
10482 case TCC_OPTION_rdynamic
:
10485 case TCC_OPTION_Wl
:
10488 if (strstart(optarg
, "-Ttext,", &p
)) {
10489 s
->text_addr
= strtoul(p
, NULL
, 16);
10490 s
->has_text_addr
= 1;
10491 } else if (strstart(optarg
, "--oformat,", &p
)) {
10492 if (strstart(p
, "elf32-", NULL
)) {
10493 s
->output_format
= TCC_OUTPUT_FORMAT_ELF
;
10494 } else if (!strcmp(p
, "binary")) {
10495 s
->output_format
= TCC_OUTPUT_FORMAT_BINARY
;
10497 #ifdef TCC_TARGET_COFF
10498 if (!strcmp(p
, "coff")) {
10499 s
->output_format
= TCC_OUTPUT_FORMAT_COFF
;
10503 error("target %s not found", p
);
10506 error("unsupported linker option '%s'", optarg
);
10511 if (s
->warn_unsupported
) {
10512 unsupported_option
:
10513 warning("unsupported option '%s'", r
);
10522 int main(int argc
, char **argv
)
10526 int nb_objfiles
, ret
, optind
;
10527 char objfilename
[1024];
10528 int64_t start_time
= 0;
10531 /* on win32, we suppose the lib and includes are at the location
10534 static char path
[1024];
10537 GetModuleFileNameA(NULL
, path
, sizeof path
);
10538 p
= d
= strlwr(path
);
10541 if (*d
== '\\') *d
= '/', p
= d
;
10545 tcc_lib_path
= path
;
10550 output_type
= TCC_OUTPUT_EXE
;
10552 multiple_files
= 1;
10557 print_search_dirs
= 0;
10559 optind
= parse_args(s
, argc
- 1, argv
+ 1) + 1;
10561 if (print_search_dirs
) {
10562 /* enough for Linux kernel */
10563 printf("install: %s/\n", tcc_lib_path
);
10567 nb_objfiles
= nb_files
- nb_libraries
;
10569 /* if outfile provided without other options, we output an
10571 if (outfile
&& output_type
== TCC_OUTPUT_MEMORY
)
10572 output_type
= TCC_OUTPUT_EXE
;
10574 /* check -c consistency : only single file handled. XXX: checks file type */
10575 if (output_type
== TCC_OUTPUT_OBJ
&& !reloc_output
) {
10576 /* accepts only a single input file */
10577 if (nb_objfiles
!= 1)
10578 error("cannot specify multiple files with -c");
10579 if (nb_libraries
!= 0)
10580 error("cannot specify libraries with -c");
10583 if (output_type
!= TCC_OUTPUT_MEMORY
) {
10585 /* compute default outfile name */
10586 pstrcpy(objfilename
, sizeof(objfilename
) - 1,
10588 tcc_basename(files
[0]));
10589 #ifdef TCC_TARGET_PE
10590 pe_guess_outfile(objfilename
, output_type
);
10592 if (output_type
== TCC_OUTPUT_OBJ
&& !reloc_output
) {
10593 char *ext
= strrchr(objfilename
, '.');
10595 goto default_outfile
;
10596 /* add .o extension */
10597 strcpy(ext
+ 1, "o");
10600 pstrcpy(objfilename
, sizeof(objfilename
), "a.out");
10603 outfile
= objfilename
;
10608 start_time
= getclock_us();
10611 tcc_set_output_type(s
, output_type
);
10613 /* compile or add each files or library */
10614 for(i
= 0;i
< nb_files
; i
++) {
10615 const char *filename
;
10617 filename
= files
[i
];
10618 if (filename
[0] == '-') {
10619 if (tcc_add_library(s
, filename
+ 2) < 0)
10620 error("cannot find %s", filename
);
10622 if (tcc_add_file(s
, filename
) < 0) {
10629 /* free all files */
10634 total_time
= (double)(getclock_us() - start_time
) / 1000000.0;
10635 if (total_time
< 0.001)
10636 total_time
= 0.001;
10637 if (total_bytes
< 1)
10639 printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
10640 tok_ident
- TOK_IDENT
, total_lines
, total_bytes
,
10641 total_time
, (int)(total_lines
/ total_time
),
10642 total_bytes
/ total_time
/ 1000000.0);
10645 if (s
->output_type
== TCC_OUTPUT_MEMORY
) {
10646 ret
= tcc_run(s
, argc
- optind
, argv
+ optind
);
10648 #ifdef TCC_TARGET_PE
10649 if (s
->output_type
!= TCC_OUTPUT_OBJ
) {
10650 ret
= tcc_output_pe(s
, outfile
);
10654 tcc_output_file(s
, outfile
);
10658 /* XXX: cannot do it with bound checking because of the malloc hooks */
10659 if (!do_bounds_check
)
10664 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size
, mem_max_size
);