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
);
768 struct macro_level
*prev
;
772 static void macro_subst(TokenString
*tok_str
, Sym
**nested_list
,
773 const int *macro_str
, struct macro_level
**can_read_stream
);
775 void force_charshort_cast(int t
);
776 static void gen_cast(CType
*type
);
778 static Sym
*sym_find(int v
);
779 static Sym
*sym_push(int v
, CType
*type
, int r
, int c
);
782 static int type_size(CType
*type
, int *a
);
783 static inline CType
*pointed_type(CType
*type
);
784 static int pointed_size(CType
*type
);
785 static int lvalue_type(int t
);
786 static int parse_btype(CType
*type
, AttributeDef
*ad
);
787 static void type_decl(CType
*type
, AttributeDef
*ad
, int *v
, int td
);
788 static int is_compatible_types(CType
*type1
, CType
*type2
);
790 int ieee_finite(double d
);
791 void error(const char *fmt
, ...);
795 void lexpand_nr(void);
796 static void vpush_global_sym(CType
*type
, int v
);
797 void vset(CType
*type
, int r
, int v
);
798 void type_to_str(char *buf
, int buf_size
,
799 CType
*type
, const char *varstr
);
800 char *get_tok_str(int v
, CValue
*cv
);
801 static Sym
*get_sym_ref(CType
*type
, Section
*sec
,
802 unsigned long offset
, unsigned long size
);
803 static Sym
*external_global_sym(int v
, CType
*type
, int r
);
805 /* section generation */
806 static void section_realloc(Section
*sec
, unsigned long new_size
);
807 static void *section_ptr_add(Section
*sec
, unsigned long size
);
808 static void put_extern_sym(Sym
*sym
, Section
*section
,
809 unsigned long value
, unsigned long size
);
810 static void greloc(Section
*s
, Sym
*sym
, unsigned long addr
, int type
);
811 static int put_elf_str(Section
*s
, const char *sym
);
812 static int put_elf_sym(Section
*s
,
813 unsigned long value
, unsigned long size
,
814 int info
, int other
, int shndx
, const char *name
);
815 static int add_elf_sym(Section
*s
, unsigned long value
, unsigned long size
,
816 int info
, int other
, int sh_num
, const char *name
);
817 static void put_elf_reloc(Section
*symtab
, Section
*s
, unsigned long offset
,
818 int type
, int symbol
);
819 static void put_stabs(const char *str
, int type
, int other
, int desc
,
820 unsigned long value
);
821 static void put_stabs_r(const char *str
, int type
, int other
, int desc
,
822 unsigned long value
, Section
*sec
, int sym_index
);
823 static void put_stabn(int type
, int other
, int desc
, int value
);
824 static void put_stabd(int type
, int other
, int desc
);
825 static int tcc_add_dll(TCCState
*s
, const char *filename
, int flags
);
827 #define AFF_PRINT_ERROR 0x0001 /* print error if file not found */
828 #define AFF_REFERENCED_DLL 0x0002 /* load a referenced dll from another dll */
829 static int tcc_add_file_internal(TCCState
*s
, const char *filename
, int flags
);
832 int tcc_output_coff(TCCState
*s1
, FILE *f
);
835 void *resolve_sym(TCCState
*s1
, const char *sym
, int type
);
836 int pe_load_def_file(struct TCCState
*s1
, FILE *fp
);
837 void pe_setup_paths(struct TCCState
*s1
, int *p_output_type
, const char **p_outfile
, char *first_file
);
838 unsigned long pe_add_runtime(struct TCCState
*s1
);
839 int tcc_output_pe(struct TCCState
*s1
, const char *filename
);
843 #ifdef CONFIG_TCC_ASM
845 typedef struct ExprValue
{
850 #define MAX_ASM_OPERANDS 30
852 typedef struct ASMOperand
{
853 int id
; /* GCC 3 optionnal identifier (0 if number only supported */
855 char asm_str
[16]; /* computed asm string for operand */
856 SValue
*vt
; /* C value of the expression */
857 int ref_index
; /* if >= 0, gives reference to a output constraint */
858 int input_index
; /* if >= 0, gives reference to an input constraint */
859 int priority
; /* priority, used to assign registers */
860 int reg
; /* if >= 0, register number used for this operand */
861 int is_llong
; /* true if double register value */
862 int is_memory
; /* true if memory operand */
863 int is_rw
; /* for '+' modifier */
866 static void asm_expr(TCCState
*s1
, ExprValue
*pe
);
867 static int asm_int_expr(TCCState
*s1
);
868 static int find_constraint(ASMOperand
*operands
, int nb_operands
,
869 const char *name
, const char **pp
);
871 static int tcc_assemble(TCCState
*s1
, int do_preprocess
);
875 static void asm_instr(void);
876 static void asm_global_instr(void);
878 /* true if float/double/long double type */
879 static inline int is_float(int t
)
883 return bt
== VT_LDOUBLE
|| bt
== VT_DOUBLE
|| bt
== VT_FLOAT
;
886 #ifdef TCC_TARGET_I386
887 #include "i386-gen.c"
890 #ifdef TCC_TARGET_ARM
894 #ifdef TCC_TARGET_C67
898 #ifdef CONFIG_TCC_STATIC
900 #define RTLD_LAZY 0x001
901 #define RTLD_NOW 0x002
902 #define RTLD_GLOBAL 0x100
903 #define RTLD_DEFAULT NULL
905 /* dummy function for profiling */
906 void *dlopen(const char *filename
, int flag
)
911 const char *dlerror(void)
916 typedef struct TCCSyms
{
921 #define TCCSYM(a) { #a, &a, },
923 /* add the symbol you want here if no dynamic linking is done */
924 static TCCSyms tcc_syms
[] = {
925 #if !defined(CONFIG_TCCBOOT)
934 void *resolve_sym(TCCState
*s1
, const char *symbol
, int type
)
938 while (p
->str
!= NULL
) {
939 if (!strcmp(p
->str
, symbol
))
946 #elif !defined(WIN32)
950 void *resolve_sym(TCCState
*s1
, const char *sym
, int type
)
952 return dlsym(RTLD_DEFAULT
, sym
);
957 /********************************************************/
959 /* we use our own 'finite' function to avoid potential problems with
960 non standard math libs */
961 /* XXX: endianness dependent */
962 int ieee_finite(double d
)
965 return ((unsigned)((p
[1] | 0x800fffff) + 1)) >> 31;
968 /* copy a string and truncate it. */
969 static char *pstrcpy(char *buf
, int buf_size
, const char *s
)
976 q_end
= buf
+ buf_size
- 1;
988 /* strcat and truncate. */
989 static char *pstrcat(char *buf
, int buf_size
, const char *s
)
994 pstrcpy(buf
+ len
, buf_size
- len
, s
);
998 static int strstart(const char *str
, const char *val
, const char **ptr
)
1003 while (*q
!= '\0') {
1014 /* memory management */
1020 static inline void tcc_free(void *ptr
)
1023 mem_cur_size
-= malloc_usable_size(ptr
);
1028 static void *tcc_malloc(unsigned long size
)
1033 error("memory full");
1035 mem_cur_size
+= malloc_usable_size(ptr
);
1036 if (mem_cur_size
> mem_max_size
)
1037 mem_max_size
= mem_cur_size
;
1042 static void *tcc_mallocz(unsigned long size
)
1045 ptr
= tcc_malloc(size
);
1046 memset(ptr
, 0, size
);
1050 static inline void *tcc_realloc(void *ptr
, unsigned long size
)
1054 mem_cur_size
-= malloc_usable_size(ptr
);
1056 ptr1
= realloc(ptr
, size
);
1058 /* NOTE: count not correct if alloc error, but not critical */
1059 mem_cur_size
+= malloc_usable_size(ptr1
);
1060 if (mem_cur_size
> mem_max_size
)
1061 mem_max_size
= mem_cur_size
;
1066 static char *tcc_strdup(const char *str
)
1069 ptr
= tcc_malloc(strlen(str
) + 1);
1074 #define free(p) use_tcc_free(p)
1075 #define malloc(s) use_tcc_malloc(s)
1076 #define realloc(p, s) use_tcc_realloc(p, s)
1078 static void dynarray_add(void ***ptab
, int *nb_ptr
, void *data
)
1085 /* every power of two we double array size */
1086 if ((nb
& (nb
- 1)) == 0) {
1091 pp
= tcc_realloc(pp
, nb_alloc
* sizeof(void *));
1093 error("memory full");
1100 /* symbol allocator */
1101 static Sym
*__sym_malloc(void)
1103 Sym
*sym_pool
, *sym
, *last_sym
;
1106 sym_pool
= tcc_malloc(SYM_POOL_NB
* sizeof(Sym
));
1108 last_sym
= sym_free_first
;
1110 for(i
= 0; i
< SYM_POOL_NB
; i
++) {
1111 sym
->next
= last_sym
;
1115 sym_free_first
= last_sym
;
1119 static inline Sym
*sym_malloc(void)
1122 sym
= sym_free_first
;
1124 sym
= __sym_malloc();
1125 sym_free_first
= sym
->next
;
1129 static inline void sym_free(Sym
*sym
)
1131 sym
->next
= sym_free_first
;
1132 sym_free_first
= sym
;
1135 Section
*new_section(TCCState
*s1
, const char *name
, int sh_type
, int sh_flags
)
1139 sec
= tcc_mallocz(sizeof(Section
) + strlen(name
));
1140 strcpy(sec
->name
, name
);
1141 sec
->sh_type
= sh_type
;
1142 sec
->sh_flags
= sh_flags
;
1149 sec
->sh_addralign
= 4;
1152 sec
->sh_addralign
= 1;
1155 sec
->sh_addralign
= 32; /* default conservative alignment */
1159 /* only add section if not private */
1160 if (!(sh_flags
& SHF_PRIVATE
)) {
1161 sec
->sh_num
= s1
->nb_sections
;
1162 dynarray_add((void ***)&s1
->sections
, &s1
->nb_sections
, sec
);
1167 static void free_section(Section
*s
)
1173 /* realloc section and set its content to zero */
1174 static void section_realloc(Section
*sec
, unsigned long new_size
)
1177 unsigned char *data
;
1179 size
= sec
->data_allocated
;
1182 while (size
< new_size
)
1184 data
= tcc_realloc(sec
->data
, size
);
1186 error("memory full");
1187 memset(data
+ sec
->data_allocated
, 0, size
- sec
->data_allocated
);
1189 sec
->data_allocated
= size
;
1192 /* reserve at least 'size' bytes in section 'sec' from
1193 sec->data_offset. */
1194 static void *section_ptr_add(Section
*sec
, unsigned long size
)
1196 unsigned long offset
, offset1
;
1198 offset
= sec
->data_offset
;
1199 offset1
= offset
+ size
;
1200 if (offset1
> sec
->data_allocated
)
1201 section_realloc(sec
, offset1
);
1202 sec
->data_offset
= offset1
;
1203 return sec
->data
+ offset
;
1206 /* return a reference to a section, and create it if it does not
1208 Section
*find_section(TCCState
*s1
, const char *name
)
1212 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1213 sec
= s1
->sections
[i
];
1214 if (!strcmp(name
, sec
->name
))
1217 /* sections are created as PROGBITS */
1218 return new_section(s1
, name
, SHT_PROGBITS
, SHF_ALLOC
);
1221 #define SECTION_ABS ((void *)1)
1223 /* update sym->c so that it points to an external symbol in section
1224 'section' with value 'value' */
1225 static void put_extern_sym2(Sym
*sym
, Section
*section
,
1226 unsigned long value
, unsigned long size
,
1227 int can_add_underscore
)
1229 int sym_type
, sym_bind
, sh_num
, info
;
1234 if (section
== NULL
)
1236 else if (section
== SECTION_ABS
)
1239 sh_num
= section
->sh_num
;
1241 if ((sym
->type
.t
& VT_BTYPE
) == VT_FUNC
)
1242 sym_type
= STT_FUNC
;
1244 sym_type
= STT_OBJECT
;
1245 if (sym
->type
.t
& VT_STATIC
)
1246 sym_bind
= STB_LOCAL
;
1248 sym_bind
= STB_GLOBAL
;
1250 name
= get_tok_str(sym
->v
, NULL
);
1251 #ifdef CONFIG_TCC_BCHECK
1252 if (do_bounds_check
) {
1255 /* XXX: avoid doing that for statics ? */
1256 /* if bound checking is activated, we change some function
1257 names by adding the "__bound" prefix */
1260 /* XXX: we rely only on malloc hooks */
1272 strcpy(buf
, "__bound_");
1279 if (tcc_state
->leading_underscore
&& can_add_underscore
) {
1281 pstrcpy(buf1
+ 1, sizeof(buf1
) - 1, name
);
1284 info
= ELF32_ST_INFO(sym_bind
, sym_type
);
1285 sym
->c
= add_elf_sym(symtab_section
, value
, size
, info
, 0, sh_num
, name
);
1287 esym
= &((Elf32_Sym
*)symtab_section
->data
)[sym
->c
];
1288 esym
->st_value
= value
;
1289 esym
->st_size
= size
;
1290 esym
->st_shndx
= sh_num
;
1294 static void put_extern_sym(Sym
*sym
, Section
*section
,
1295 unsigned long value
, unsigned long size
)
1297 put_extern_sym2(sym
, section
, value
, size
, 1);
1300 /* add a new relocation entry to symbol 'sym' in section 's' */
1301 static void greloc(Section
*s
, Sym
*sym
, unsigned long offset
, int type
)
1304 put_extern_sym(sym
, NULL
, 0, 0);
1305 /* now we can add ELF relocation info */
1306 put_elf_reloc(symtab_section
, s
, offset
, type
, sym
->c
);
1309 static inline int isid(int c
)
1311 return (c
>= 'a' && c
<= 'z') ||
1312 (c
>= 'A' && c
<= 'Z') ||
1316 static inline int isnum(int c
)
1318 return c
>= '0' && c
<= '9';
1321 static inline int isoct(int c
)
1323 return c
>= '0' && c
<= '7';
1326 static inline int toup(int c
)
1328 if (c
>= 'a' && c
<= 'z')
1329 return c
- 'a' + 'A';
1334 static void strcat_vprintf(char *buf
, int buf_size
, const char *fmt
, va_list ap
)
1338 vsnprintf(buf
+ len
, buf_size
- len
, fmt
, ap
);
1341 static void strcat_printf(char *buf
, int buf_size
, const char *fmt
, ...)
1345 strcat_vprintf(buf
, buf_size
, fmt
, ap
);
1349 void error1(TCCState
*s1
, int is_warning
, const char *fmt
, va_list ap
)
1356 for(f
= s1
->include_stack
; f
< s1
->include_stack_ptr
; f
++)
1357 strcat_printf(buf
, sizeof(buf
), "In file included from %s:%d:\n",
1358 (*f
)->filename
, (*f
)->line_num
);
1359 if (file
->line_num
> 0) {
1360 strcat_printf(buf
, sizeof(buf
),
1361 "%s:%d: ", file
->filename
, file
->line_num
);
1363 strcat_printf(buf
, sizeof(buf
),
1364 "%s: ", file
->filename
);
1367 strcat_printf(buf
, sizeof(buf
),
1371 strcat_printf(buf
, sizeof(buf
), "warning: ");
1372 strcat_vprintf(buf
, sizeof(buf
), fmt
, ap
);
1374 if (!s1
->error_func
) {
1375 /* default case: stderr */
1376 fprintf(stderr
, "%s\n", buf
);
1378 s1
->error_func(s1
->error_opaque
, buf
);
1380 if (!is_warning
|| s1
->warn_error
)
1385 void tcc_set_error_func(TCCState
*s
, void *error_opaque
,
1386 void (*error_func
)(void *opaque
, const char *msg
))
1388 s
->error_opaque
= error_opaque
;
1389 s
->error_func
= error_func
;
1393 /* error without aborting current compilation */
1394 void error_noabort(const char *fmt
, ...)
1396 TCCState
*s1
= tcc_state
;
1400 error1(s1
, 0, fmt
, ap
);
1404 void error(const char *fmt
, ...)
1406 TCCState
*s1
= tcc_state
;
1410 error1(s1
, 0, fmt
, ap
);
1412 /* better than nothing: in some cases, we accept to handle errors */
1413 if (s1
->error_set_jmp_enabled
) {
1414 longjmp(s1
->error_jmp_buf
, 1);
1416 /* XXX: eliminate this someday */
1421 void expect(const char *msg
)
1423 error("%s expected", msg
);
1426 void warning(const char *fmt
, ...)
1428 TCCState
*s1
= tcc_state
;
1435 error1(s1
, 1, fmt
, ap
);
1442 error("'%c' expected", c
);
1446 static void test_lvalue(void)
1448 if (!(vtop
->r
& VT_LVAL
))
1452 /* allocate a new token */
1453 static TokenSym
*tok_alloc_new(TokenSym
**pts
, const char *str
, int len
)
1455 TokenSym
*ts
, **ptable
;
1458 if (tok_ident
>= SYM_FIRST_ANOM
)
1459 error("memory full");
1461 /* expand token table if needed */
1462 i
= tok_ident
- TOK_IDENT
;
1463 if ((i
% TOK_ALLOC_INCR
) == 0) {
1464 ptable
= tcc_realloc(table_ident
, (i
+ TOK_ALLOC_INCR
) * sizeof(TokenSym
*));
1466 error("memory full");
1467 table_ident
= ptable
;
1470 ts
= tcc_malloc(sizeof(TokenSym
) + len
);
1471 table_ident
[i
] = ts
;
1472 ts
->tok
= tok_ident
++;
1473 ts
->sym_define
= NULL
;
1474 ts
->sym_label
= NULL
;
1475 ts
->sym_struct
= NULL
;
1476 ts
->sym_identifier
= NULL
;
1478 ts
->hash_next
= NULL
;
1479 memcpy(ts
->str
, str
, len
);
1480 ts
->str
[len
] = '\0';
1485 #define TOK_HASH_INIT 1
1486 #define TOK_HASH_FUNC(h, c) ((h) * 263 + (c))
1488 /* find a token and add it if not found */
1489 static TokenSym
*tok_alloc(const char *str
, int len
)
1491 TokenSym
*ts
, **pts
;
1497 h
= TOK_HASH_FUNC(h
, ((unsigned char *)str
)[i
]);
1498 h
&= (TOK_HASH_SIZE
- 1);
1500 pts
= &hash_ident
[h
];
1505 if (ts
->len
== len
&& !memcmp(ts
->str
, str
, len
))
1507 pts
= &(ts
->hash_next
);
1509 return tok_alloc_new(pts
, str
, len
);
1512 /* CString handling */
1514 static void cstr_realloc(CString
*cstr
, int new_size
)
1519 size
= cstr
->size_allocated
;
1521 size
= 8; /* no need to allocate a too small first string */
1522 while (size
< new_size
)
1524 data
= tcc_realloc(cstr
->data_allocated
, size
);
1526 error("memory full");
1527 cstr
->data_allocated
= data
;
1528 cstr
->size_allocated
= size
;
1533 static inline void cstr_ccat(CString
*cstr
, int ch
)
1536 size
= cstr
->size
+ 1;
1537 if (size
> cstr
->size_allocated
)
1538 cstr_realloc(cstr
, size
);
1539 ((unsigned char *)cstr
->data
)[size
- 1] = ch
;
1543 static void cstr_cat(CString
*cstr
, const char *str
)
1555 /* add a wide char */
1556 static void cstr_wccat(CString
*cstr
, int ch
)
1559 size
= cstr
->size
+ sizeof(int);
1560 if (size
> cstr
->size_allocated
)
1561 cstr_realloc(cstr
, size
);
1562 *(int *)(((unsigned char *)cstr
->data
) + size
- sizeof(int)) = ch
;
1566 static void cstr_new(CString
*cstr
)
1568 memset(cstr
, 0, sizeof(CString
));
1571 /* free string and reset it to NULL */
1572 static void cstr_free(CString
*cstr
)
1574 tcc_free(cstr
->data_allocated
);
1578 #define cstr_reset(cstr) cstr_free(cstr)
1580 /* XXX: unicode ? */
1581 static void add_char(CString
*cstr
, int c
)
1583 if (c
== '\'' || c
== '\"' || c
== '\\') {
1584 /* XXX: could be more precise if char or string */
1585 cstr_ccat(cstr
, '\\');
1587 if (c
>= 32 && c
<= 126) {
1590 cstr_ccat(cstr
, '\\');
1592 cstr_ccat(cstr
, 'n');
1594 cstr_ccat(cstr
, '0' + ((c
>> 6) & 7));
1595 cstr_ccat(cstr
, '0' + ((c
>> 3) & 7));
1596 cstr_ccat(cstr
, '0' + (c
& 7));
1601 /* XXX: buffer overflow */
1602 /* XXX: float tokens */
1603 char *get_tok_str(int v
, CValue
*cv
)
1605 static char buf
[STRING_MAX_SIZE
+ 1];
1606 static CString cstr_buf
;
1612 /* NOTE: to go faster, we give a fixed buffer for small strings */
1613 cstr_reset(&cstr_buf
);
1614 cstr_buf
.data
= buf
;
1615 cstr_buf
.size_allocated
= sizeof(buf
);
1621 /* XXX: not quite exact, but only useful for testing */
1622 sprintf(p
, "%u", cv
->ui
);
1626 /* XXX: not quite exact, but only useful for testing */
1627 sprintf(p
, "%Lu", cv
->ull
);
1631 cstr_ccat(&cstr_buf
, '\'');
1632 add_char(&cstr_buf
, cv
->i
);
1633 cstr_ccat(&cstr_buf
, '\'');
1634 cstr_ccat(&cstr_buf
, '\0');
1638 len
= cstr
->size
- 1;
1640 add_char(&cstr_buf
, ((unsigned char *)cstr
->data
)[i
]);
1641 cstr_ccat(&cstr_buf
, '\0');
1646 cstr_ccat(&cstr_buf
, '\"');
1648 len
= cstr
->size
- 1;
1650 add_char(&cstr_buf
, ((unsigned char *)cstr
->data
)[i
]);
1652 len
= (cstr
->size
/ sizeof(int)) - 1;
1654 add_char(&cstr_buf
, ((int *)cstr
->data
)[i
]);
1656 cstr_ccat(&cstr_buf
, '\"');
1657 cstr_ccat(&cstr_buf
, '\0');
1666 return strcpy(p
, "<<=");
1668 return strcpy(p
, ">>=");
1670 if (v
< TOK_IDENT
) {
1671 /* search in two bytes table */
1685 } else if (v
< tok_ident
) {
1686 return table_ident
[v
- TOK_IDENT
]->str
;
1687 } else if (v
>= SYM_FIRST_ANOM
) {
1688 /* special name for anonymous symbol */
1689 sprintf(p
, "L.%u", v
- SYM_FIRST_ANOM
);
1691 /* should never happen */
1696 return cstr_buf
.data
;
1699 /* push, without hashing */
1700 static Sym
*sym_push2(Sym
**ps
, int v
, int t
, int c
)
1714 /* find a symbol and return its associated structure. 's' is the top
1715 of the symbol stack */
1716 static Sym
*sym_find2(Sym
*s
, int v
)
1726 /* structure lookup */
1727 static inline Sym
*struct_find(int v
)
1730 if ((unsigned)v
>= (unsigned)(tok_ident
- TOK_IDENT
))
1732 return table_ident
[v
]->sym_struct
;
1735 /* find an identifier */
1736 static inline Sym
*sym_find(int v
)
1739 if ((unsigned)v
>= (unsigned)(tok_ident
- TOK_IDENT
))
1741 return table_ident
[v
]->sym_identifier
;
1744 /* push a given symbol on the symbol stack */
1745 static Sym
*sym_push(int v
, CType
*type
, int r
, int c
)
1754 s
= sym_push2(ps
, v
, type
->t
, c
);
1755 s
->type
.ref
= type
->ref
;
1757 /* don't record fields or anonymous symbols */
1759 if (!(v
& SYM_FIELD
) && (v
& ~SYM_STRUCT
) < SYM_FIRST_ANOM
) {
1760 /* record symbol in token array */
1761 ts
= table_ident
[(v
& ~SYM_STRUCT
) - TOK_IDENT
];
1763 ps
= &ts
->sym_struct
;
1765 ps
= &ts
->sym_identifier
;
1772 /* push a global identifier */
1773 static Sym
*global_identifier_push(int v
, int t
, int c
)
1776 s
= sym_push2(&global_stack
, v
, t
, c
);
1777 /* don't record anonymous symbol */
1778 if (v
< SYM_FIRST_ANOM
) {
1779 ps
= &table_ident
[v
- TOK_IDENT
]->sym_identifier
;
1780 /* modify the top most local identifier, so that
1781 sym_identifier will point to 's' when popped */
1783 ps
= &(*ps
)->prev_tok
;
1790 /* pop symbols until top reaches 'b' */
1791 static void sym_pop(Sym
**ptop
, Sym
*b
)
1801 /* remove symbol in token array */
1803 if (!(v
& SYM_FIELD
) && (v
& ~SYM_STRUCT
) < SYM_FIRST_ANOM
) {
1804 ts
= table_ident
[(v
& ~SYM_STRUCT
) - TOK_IDENT
];
1806 ps
= &ts
->sym_struct
;
1808 ps
= &ts
->sym_identifier
;
1819 BufferedFile
*tcc_open(TCCState
*s1
, const char *filename
)
1824 fd
= open(filename
, O_RDONLY
| O_BINARY
);
1827 bf
= tcc_malloc(sizeof(BufferedFile
));
1833 bf
->buf_ptr
= bf
->buffer
;
1834 bf
->buf_end
= bf
->buffer
;
1835 bf
->buffer
[0] = CH_EOB
; /* put eob symbol */
1836 pstrcpy(bf
->filename
, sizeof(bf
->filename
), filename
);
1838 bf
->ifndef_macro
= 0;
1839 bf
->ifdef_stack_ptr
= s1
->ifdef_stack_ptr
;
1840 // printf("opening '%s'\n", filename);
1844 void tcc_close(BufferedFile
*bf
)
1846 total_lines
+= bf
->line_num
;
1851 /* fill input buffer and peek next char */
1852 static int tcc_peekc_slow(BufferedFile
*bf
)
1855 /* only tries to read if really end of buffer */
1856 if (bf
->buf_ptr
>= bf
->buf_end
) {
1858 #if defined(PARSE_DEBUG)
1863 len
= read(bf
->fd
, bf
->buffer
, len
);
1870 bf
->buf_ptr
= bf
->buffer
;
1871 bf
->buf_end
= bf
->buffer
+ len
;
1872 *bf
->buf_end
= CH_EOB
;
1874 if (bf
->buf_ptr
< bf
->buf_end
) {
1875 return bf
->buf_ptr
[0];
1877 bf
->buf_ptr
= bf
->buf_end
;
1882 /* return the current character, handling end of block if necessary
1884 static int handle_eob(void)
1886 return tcc_peekc_slow(file
);
1889 /* read next char from current input file and handle end of input buffer */
1890 static inline void inp(void)
1892 ch
= *(++(file
->buf_ptr
));
1893 /* end of buffer/file handling */
1898 /* handle '\[\r]\n' */
1899 static void handle_stray(void)
1901 while (ch
== '\\') {
1906 } else if (ch
== '\r') {
1914 error("stray '\\' in program");
1919 /* skip the stray and handle the \\n case. Output an error if
1920 incorrect char after the stray */
1921 static int handle_stray1(uint8_t *p
)
1925 if (p
>= file
->buf_end
) {
1942 /* handle just the EOB case, but not stray */
1943 #define PEEKC_EOB(c, p)\
1954 /* handle the complicated stray case */
1955 #define PEEKC(c, p)\
1960 c = handle_stray1(p);\
1965 /* input with '\[\r]\n' handling. Note that this function cannot
1966 handle other characters after '\', so you cannot call it inside
1967 strings or comments */
1968 static void minp(void)
1976 /* single line C++ comments */
1977 static uint8_t *parse_line_comment(uint8_t *p
)
1985 if (c
== '\n' || c
== CH_EOF
) {
1987 } else if (c
== '\\') {
1996 } else if (c
== '\r') {
2014 static uint8_t *parse_comment(uint8_t *p
)
2020 /* fast skip loop */
2023 if (c
== '\n' || c
== '*' || c
== '\\')
2027 if (c
== '\n' || c
== '*' || c
== '\\')
2031 /* now we can handle all the cases */
2035 } else if (c
== '*') {
2041 } else if (c
== '/') {
2042 goto end_of_comment
;
2043 } else if (c
== '\\') {
2048 /* skip '\[\r]\n', otherwise just skip the stray */
2054 } else if (c
== '\r') {
2071 /* stray, eob or eof */
2076 error("unexpected end of file in comment");
2077 } else if (c
== '\\') {
2089 /* space exlcuding newline */
2090 static inline int is_space(int ch
)
2092 return ch
== ' ' || ch
== '\t' || ch
== '\v' || ch
== '\f' || ch
== '\r';
2095 static inline void skip_spaces(void)
2097 while (is_space(ch
))
2101 /* parse a string without interpreting escapes */
2102 static uint8_t *parse_pp_string(uint8_t *p
,
2103 int sep
, CString
*str
)
2111 } else if (c
== '\\') {
2116 unterminated_string
:
2117 /* XXX: indicate line number of start of string */
2118 error("missing terminating %c character", sep
);
2119 } else if (c
== '\\') {
2120 /* escape : just skip \[\r]\n */
2125 } else if (c
== '\r') {
2128 expect("'\n' after '\r'");
2131 } else if (c
== CH_EOF
) {
2132 goto unterminated_string
;
2135 cstr_ccat(str
, '\\');
2141 } else if (c
== '\n') {
2144 } else if (c
== '\r') {
2148 cstr_ccat(str
, '\r');
2164 /* skip block of text until #else, #elif or #endif. skip also pairs of
2166 void preprocess_skip(void)
2168 int a
, start_of_line
, c
;
2195 } else if (c
== '\\') {
2196 /* XXX: incorrect: should not give an error */
2197 ch
= file
->buf_ptr
[0];
2205 p
= parse_pp_string(p
, c
, NULL
);
2214 p
= parse_comment(p
);
2215 } else if (ch
== '/') {
2216 p
= parse_line_comment(p
);
2222 if (start_of_line
) {
2227 (tok
== TOK_ELSE
|| tok
== TOK_ELIF
|| tok
== TOK_ENDIF
))
2229 if (tok
== TOK_IF
|| tok
== TOK_IFDEF
|| tok
== TOK_IFNDEF
)
2231 else if (tok
== TOK_ENDIF
)
2245 /* ParseState handling */
2247 /* XXX: currently, no include file info is stored. Thus, we cannot display
2248 accurate messages if the function or data definition spans multiple
2251 /* save current parse state in 's' */
2252 void save_parse_state(ParseState
*s
)
2254 s
->line_num
= file
->line_num
;
2255 s
->macro_ptr
= macro_ptr
;
2260 /* restore parse state from 's' */
2261 void restore_parse_state(ParseState
*s
)
2263 file
->line_num
= s
->line_num
;
2264 macro_ptr
= s
->macro_ptr
;
2269 /* return the number of additional 'ints' necessary to store the
2271 static inline int tok_ext_size(int t
)
2285 error("unsupported token");
2292 return LDOUBLE_SIZE
/ 4;
2298 /* token string handling */
2300 static inline void tok_str_new(TokenString
*s
)
2304 s
->allocated_len
= 0;
2305 s
->last_line_num
= -1;
2308 static void tok_str_free(int *str
)
2313 static int *tok_str_realloc(TokenString
*s
)
2317 if (s
->allocated_len
== 0) {
2320 len
= s
->allocated_len
* 2;
2322 str
= tcc_realloc(s
->str
, len
* sizeof(int));
2324 error("memory full");
2325 s
->allocated_len
= len
;
2330 static void tok_str_add(TokenString
*s
, int t
)
2336 if (len
>= s
->allocated_len
)
2337 str
= tok_str_realloc(s
);
2342 static void tok_str_add2(TokenString
*s
, int t
, CValue
*cv
)
2349 /* allocate space for worst case */
2350 if (len
+ TOK_MAX_SIZE
> s
->allocated_len
)
2351 str
= tok_str_realloc(s
);
2360 str
[len
++] = cv
->tab
[0];
2369 nb_words
= (sizeof(CString
) + cv
->cstr
->size
+ 3) >> 2;
2370 while ((len
+ nb_words
) > s
->allocated_len
)
2371 str
= tok_str_realloc(s
);
2372 cstr
= (CString
*)(str
+ len
);
2374 cstr
->size
= cv
->cstr
->size
;
2375 cstr
->data_allocated
= NULL
;
2376 cstr
->size_allocated
= cstr
->size
;
2377 memcpy((char *)cstr
+ sizeof(CString
),
2378 cv
->cstr
->data
, cstr
->size
);
2385 #if LDOUBLE_SIZE == 8
2388 str
[len
++] = cv
->tab
[0];
2389 str
[len
++] = cv
->tab
[1];
2391 #if LDOUBLE_SIZE == 12
2393 str
[len
++] = cv
->tab
[0];
2394 str
[len
++] = cv
->tab
[1];
2395 str
[len
++] = cv
->tab
[2];
2396 #elif LDOUBLE_SIZE != 8
2397 #error add long double size support
2406 /* add the current parse token in token string 's' */
2407 static void tok_str_add_tok(TokenString
*s
)
2411 /* save line number info */
2412 if (file
->line_num
!= s
->last_line_num
) {
2413 s
->last_line_num
= file
->line_num
;
2414 cval
.i
= s
->last_line_num
;
2415 tok_str_add2(s
, TOK_LINENUM
, &cval
);
2417 tok_str_add2(s
, tok
, &tokc
);
2420 #if LDOUBLE_SIZE == 12
2421 #define LDOUBLE_GET(p, cv) \
2425 #elif LDOUBLE_SIZE == 8
2426 #define LDOUBLE_GET(p, cv) \
2430 #error add long double size support
2434 /* get a token from an integer array and increment pointer
2435 accordingly. we code it as a macro to avoid pointer aliasing. */
2436 #define TOK_GET(t, p, cv) \
2451 cv.cstr = (CString *)p; \
2452 cv.cstr->data = (char *)p + sizeof(CString);\
2453 p += (sizeof(CString) + cv.cstr->size + 3) >> 2;\
2462 case TOK_CLDOUBLE: \
2463 LDOUBLE_GET(p, cv); \
2464 p += LDOUBLE_SIZE / 4; \
2471 /* defines handling */
2472 static inline void define_push(int v
, int macro_type
, int *str
, Sym
*first_arg
)
2476 s
= sym_push2(&define_stack
, v
, macro_type
, (int)str
);
2477 s
->next
= first_arg
;
2478 table_ident
[v
- TOK_IDENT
]->sym_define
= s
;
2481 /* undefined a define symbol. Its name is just set to zero */
2482 static void define_undef(Sym
*s
)
2486 if (v
>= TOK_IDENT
&& v
< tok_ident
)
2487 table_ident
[v
- TOK_IDENT
]->sym_define
= NULL
;
2491 static inline Sym
*define_find(int v
)
2494 if ((unsigned)v
>= (unsigned)(tok_ident
- TOK_IDENT
))
2496 return table_ident
[v
]->sym_define
;
2499 /* free define stack until top reaches 'b' */
2500 static void free_defines(Sym
*b
)
2508 /* do not free args or predefined defines */
2510 tok_str_free((int *)top
->c
);
2512 if (v
>= TOK_IDENT
&& v
< tok_ident
)
2513 table_ident
[v
- TOK_IDENT
]->sym_define
= NULL
;
2521 static Sym
*label_find(int v
)
2524 if ((unsigned)v
>= (unsigned)(tok_ident
- TOK_IDENT
))
2526 return table_ident
[v
]->sym_label
;
2529 static Sym
*label_push(Sym
**ptop
, int v
, int flags
)
2532 s
= sym_push2(ptop
, v
, 0, 0);
2534 ps
= &table_ident
[v
- TOK_IDENT
]->sym_label
;
2535 if (ptop
== &global_label_stack
) {
2536 /* modify the top most local identifier, so that
2537 sym_identifier will point to 's' when popped */
2539 ps
= &(*ps
)->prev_tok
;
2546 /* pop labels until element last is reached. Look if any labels are
2547 undefined. Define symbols if '&&label' was used. */
2548 static void label_pop(Sym
**ptop
, Sym
*slast
)
2551 for(s
= *ptop
; s
!= slast
; s
= s1
) {
2553 if (s
->r
== LABEL_DECLARED
) {
2554 warning("label '%s' declared but not used", get_tok_str(s
->v
, NULL
));
2555 } else if (s
->r
== LABEL_FORWARD
) {
2556 error("label '%s' used but not defined",
2557 get_tok_str(s
->v
, NULL
));
2560 /* define corresponding symbol. A size of
2562 put_extern_sym(s
, cur_text_section
, (long)s
->next
, 1);
2566 table_ident
[s
->v
- TOK_IDENT
]->sym_label
= s
->prev_tok
;
2572 /* eval an expression for #if/#elif */
2573 static int expr_preprocess(void)
2579 while (tok
!= TOK_LINEFEED
&& tok
!= TOK_EOF
) {
2580 next(); /* do macro subst */
2581 if (tok
== TOK_DEFINED
) {
2586 c
= define_find(tok
) != 0;
2591 } else if (tok
>= TOK_IDENT
) {
2592 /* if undefined macro */
2596 tok_str_add_tok(&str
);
2598 tok_str_add(&str
, -1); /* simulate end of file */
2599 tok_str_add(&str
, 0);
2600 /* now evaluate C constant expression */
2601 macro_ptr
= str
.str
;
2605 tok_str_free(str
.str
);
2609 #if defined(PARSE_DEBUG) || defined(PP_DEBUG)
2610 static void tok_print(int *str
)
2616 TOK_GET(t
, str
, cval
);
2619 printf(" %s", get_tok_str(t
, &cval
));
2625 /* parse after #define */
2626 static void parse_define(void)
2628 Sym
*s
, *first
, **ps
;
2629 int v
, t
, varg
, is_vaargs
, c
;
2634 error("invalid macro name '%s'", get_tok_str(tok
, &tokc
));
2635 /* XXX: should check if same macro (ANSI) */
2638 /* '(' must be just after macro definition for MACRO_FUNC */
2639 c
= file
->buf_ptr
[0];
2641 c
= handle_stray1(file
->buf_ptr
);
2646 while (tok
!= ')') {
2650 if (varg
== TOK_DOTS
) {
2651 varg
= TOK___VA_ARGS__
;
2653 } else if (tok
== TOK_DOTS
&& gnu_ext
) {
2657 if (varg
< TOK_IDENT
)
2658 error("badly punctuated parameter list");
2659 s
= sym_push2(&define_stack
, varg
| SYM_FIELD
, is_vaargs
, 0);
2670 /* EOF testing necessary for '-D' handling */
2671 while (tok
!= TOK_LINEFEED
&& tok
!= TOK_EOF
) {
2672 tok_str_add2(&str
, tok
, &tokc
);
2675 tok_str_add(&str
, 0);
2677 printf("define %s %d: ", get_tok_str(v
, NULL
), t
);
2680 define_push(v
, t
, str
.str
, first
);
2683 static inline int hash_cached_include(int type
, const char *filename
)
2685 const unsigned char *s
;
2689 h
= TOK_HASH_FUNC(h
, type
);
2692 h
= TOK_HASH_FUNC(h
, *s
);
2695 h
&= (CACHED_INCLUDES_HASH_SIZE
- 1);
2699 /* XXX: use a token or a hash table to accelerate matching ? */
2700 static CachedInclude
*search_cached_include(TCCState
*s1
,
2701 int type
, const char *filename
)
2705 h
= hash_cached_include(type
, filename
);
2706 i
= s1
->cached_includes_hash
[h
];
2710 e
= s1
->cached_includes
[i
- 1];
2711 if (e
->type
== type
&& !strcmp(e
->filename
, filename
))
2718 static inline void add_cached_include(TCCState
*s1
, int type
,
2719 const char *filename
, int ifndef_macro
)
2724 if (search_cached_include(s1
, type
, filename
))
2727 printf("adding cached '%s' %s\n", filename
, get_tok_str(ifndef_macro
, NULL
));
2729 e
= tcc_malloc(sizeof(CachedInclude
) + strlen(filename
));
2733 strcpy(e
->filename
, filename
);
2734 e
->ifndef_macro
= ifndef_macro
;
2735 dynarray_add((void ***)&s1
->cached_includes
, &s1
->nb_cached_includes
, e
);
2736 /* add in hash table */
2737 h
= hash_cached_include(type
, filename
);
2738 e
->hash_next
= s1
->cached_includes_hash
[h
];
2739 s1
->cached_includes_hash
[h
] = s1
->nb_cached_includes
;
2742 static void pragma_parse(TCCState
*s1
)
2747 if (tok
== TOK_pack
) {
2750 #pragma pack(1) // set
2751 #pragma pack() // reset to default
2752 #pragma pack(push,1) // push & set
2753 #pragma pack(pop) // restore previous
2757 if (tok
== TOK_ASM_pop
) {
2759 if (s1
->pack_stack_ptr
<= s1
->pack_stack
) {
2761 error("out of pack stack");
2763 s1
->pack_stack_ptr
--;
2767 if (tok
== TOK_ASM_push
) {
2769 if (s1
->pack_stack_ptr
>= s1
->pack_stack
+ PACK_STACK_SIZE
- 1)
2771 s1
->pack_stack_ptr
++;
2774 if (tok
!= TOK_CINT
) {
2776 error("invalid pack pragma");
2779 if (val
< 1 || val
> 16 || (val
& (val
- 1)) != 0)
2783 *s1
->pack_stack_ptr
= val
;
2789 /* is_bof is true if first non space token at beginning of file */
2790 static void preprocess(int is_bof
)
2792 TCCState
*s1
= tcc_state
;
2793 int size
, i
, c
, n
, saved_parse_flags
;
2794 char buf
[1024], *q
, *p
;
2800 saved_parse_flags
= parse_flags
;
2801 parse_flags
= PARSE_FLAG_PREPROCESS
| PARSE_FLAG_TOK_NUM
|
2802 PARSE_FLAG_LINEFEED
;
2812 s
= define_find(tok
);
2813 /* undefine symbol by putting an invalid name */
2818 case TOK_INCLUDE_NEXT
:
2819 ch
= file
->buf_ptr
[0];
2820 /* XXX: incorrect if comments : use next_nomacro with a special mode */
2825 } else if (ch
== '\"') {
2828 /* XXX: better stray handling */
2831 while (ch
!= c
&& ch
!= '\n' && ch
!= CH_EOF
) {
2832 if ((q
- buf
) < sizeof(buf
) - 1)
2839 /* eat all spaces and comments after include */
2840 /* XXX: slightly incorrect */
2841 while (ch1
!= '\n' && ch1
!= CH_EOF
)
2845 /* computed #include : either we have only strings or
2846 we have anything enclosed in '<>' */
2849 if (tok
== TOK_STR
) {
2850 while (tok
!= TOK_LINEFEED
) {
2851 if (tok
!= TOK_STR
) {
2853 error("'#include' expects \"FILENAME\" or <FILENAME>");
2855 pstrcat(buf
, sizeof(buf
), (char *)tokc
.cstr
->data
);
2861 while (tok
!= TOK_LINEFEED
) {
2862 pstrcat(buf
, sizeof(buf
), get_tok_str(tok
, &tokc
));
2866 /* check syntax and remove '<>' */
2867 if (len
< 2 || buf
[0] != '<' || buf
[len
- 1] != '>')
2868 goto include_syntax
;
2869 memmove(buf
, buf
+ 1, len
- 2);
2870 buf
[len
- 2] = '\0';
2875 e
= search_cached_include(s1
, c
, buf
);
2876 if (e
&& define_find(e
->ifndef_macro
)) {
2877 /* no need to parse the include because the 'ifndef macro'
2880 printf("%s: skipping %s\n", file
->filename
, buf
);
2884 /* first search in current dir if "header.h" */
2886 p
= strrchr(file
->filename
, '/');
2888 size
= p
+ 1 - file
->filename
;
2889 if (size
> sizeof(buf1
) - 1)
2890 size
= sizeof(buf1
) - 1;
2891 memcpy(buf1
, file
->filename
, size
);
2893 pstrcat(buf1
, sizeof(buf1
), buf
);
2894 f
= tcc_open(s1
, buf1
);
2896 if (tok
== TOK_INCLUDE_NEXT
)
2902 if (s1
->include_stack_ptr
>= s1
->include_stack
+ INCLUDE_STACK_SIZE
)
2903 error("#include recursion too deep");
2904 /* now search in all the include paths */
2905 n
= s1
->nb_include_paths
+ s1
->nb_sysinclude_paths
;
2906 for(i
= 0; i
< n
; i
++) {
2908 if (i
< s1
->nb_include_paths
)
2909 path
= s1
->include_paths
[i
];
2911 path
= s1
->sysinclude_paths
[i
- s1
->nb_include_paths
];
2912 pstrcpy(buf1
, sizeof(buf1
), path
);
2913 pstrcat(buf1
, sizeof(buf1
), "/");
2914 pstrcat(buf1
, sizeof(buf1
), buf
);
2915 f
= tcc_open(s1
, buf1
);
2917 if (tok
== TOK_INCLUDE_NEXT
)
2923 error("include file '%s' not found", buf
);
2927 printf("%s: including %s\n", file
->filename
, buf1
);
2930 pstrcpy(f
->inc_filename
, sizeof(f
->inc_filename
), buf
);
2931 /* push current file in stack */
2932 /* XXX: fix current line init */
2933 *s1
->include_stack_ptr
++ = file
;
2935 /* add include file debug info */
2937 put_stabs(file
->filename
, N_BINCL
, 0, 0, 0);
2939 tok_flags
|= TOK_FLAG_BOF
| TOK_FLAG_BOL
;
2940 ch
= file
->buf_ptr
[0];
2948 c
= expr_preprocess();
2954 if (tok
< TOK_IDENT
)
2955 error("invalid argument for '#if%sdef'", c
? "n" : "");
2959 printf("#ifndef %s\n", get_tok_str(tok
, NULL
));
2961 file
->ifndef_macro
= tok
;
2964 c
= (define_find(tok
) != 0) ^ c
;
2966 if (s1
->ifdef_stack_ptr
>= s1
->ifdef_stack
+ IFDEF_STACK_SIZE
)
2967 error("memory full");
2968 *s1
->ifdef_stack_ptr
++ = c
;
2971 if (s1
->ifdef_stack_ptr
== s1
->ifdef_stack
)
2972 error("#else without matching #if");
2973 if (s1
->ifdef_stack_ptr
[-1] & 2)
2974 error("#else after #else");
2975 c
= (s1
->ifdef_stack_ptr
[-1] ^= 3);
2978 if (s1
->ifdef_stack_ptr
== s1
->ifdef_stack
)
2979 error("#elif without matching #if");
2980 c
= s1
->ifdef_stack_ptr
[-1];
2982 error("#elif after #else");
2983 /* last #if/#elif expression was true: we skip */
2986 c
= expr_preprocess();
2987 s1
->ifdef_stack_ptr
[-1] = c
;
2997 if (s1
->ifdef_stack_ptr
<= file
->ifdef_stack_ptr
)
2998 error("#endif without matching #if");
2999 s1
->ifdef_stack_ptr
--;
3000 /* '#ifndef macro' was at the start of file. Now we check if
3001 an '#endif' is exactly at the end of file */
3002 if (file
->ifndef_macro
&&
3003 s1
->ifdef_stack_ptr
== file
->ifdef_stack_ptr
) {
3004 file
->ifndef_macro_saved
= file
->ifndef_macro
;
3005 /* need to set to zero to avoid false matches if another
3006 #ifndef at middle of file */
3007 file
->ifndef_macro
= 0;
3008 while (tok
!= TOK_LINEFEED
)
3010 tok_flags
|= TOK_FLAG_ENDIF
;
3016 if (tok
!= TOK_CINT
)
3018 file
->line_num
= tokc
.i
- 1; /* the line number will be incremented after */
3020 if (tok
!= TOK_LINEFEED
) {
3023 pstrcpy(file
->filename
, sizeof(file
->filename
),
3024 (char *)tokc
.cstr
->data
);
3030 ch
= file
->buf_ptr
[0];
3033 while (ch
!= '\n' && ch
!= CH_EOF
) {
3034 if ((q
- buf
) < sizeof(buf
) - 1)
3040 error("#error %s", buf
);
3042 warning("#warning %s", buf
);
3048 if (tok
== TOK_LINEFEED
|| tok
== '!' || tok
== TOK_CINT
) {
3049 /* '!' is ignored to allow C scripts. numbers are ignored
3050 to emulate cpp behaviour */
3052 if (!(saved_parse_flags
& PARSE_FLAG_ASM_COMMENTS
))
3053 error("invalid preprocessing directive #%s", get_tok_str(tok
, &tokc
));
3057 /* ignore other preprocess commands or #! for C scripts */
3058 while (tok
!= TOK_LINEFEED
)
3061 parse_flags
= saved_parse_flags
;
3064 /* evaluate escape codes in a string. */
3065 static void parse_escape_string(CString
*outstr
, const uint8_t *buf
, int is_long
)
3080 case '0': case '1': case '2': case '3':
3081 case '4': case '5': case '6': case '7':
3082 /* at most three octal digits */
3087 n
= n
* 8 + c
- '0';
3091 n
= n
* 8 + c
- '0';
3096 goto add_char_nonext
;
3102 if (c
>= 'a' && c
<= 'f')
3104 else if (c
>= 'A' && c
<= 'F')
3114 goto add_char_nonext
;
3138 goto invalid_escape
;
3148 if (c
>= '!' && c
<= '~')
3149 warning("unknown escape sequence: \'\\%c\'", c
);
3151 warning("unknown escape sequence: \'\\x%x\'", c
);
3158 cstr_ccat(outstr
, c
);
3160 cstr_wccat(outstr
, c
);
3162 /* add a trailing '\0' */
3164 cstr_ccat(outstr
, '\0');
3166 cstr_wccat(outstr
, '\0');
3169 /* we use 64 bit numbers */
3172 /* bn = (bn << shift) | or_val */
3173 void bn_lshift(unsigned int *bn
, int shift
, int or_val
)
3177 for(i
=0;i
<BN_SIZE
;i
++) {
3179 bn
[i
] = (v
<< shift
) | or_val
;
3180 or_val
= v
>> (32 - shift
);
3184 void bn_zero(unsigned int *bn
)
3187 for(i
=0;i
<BN_SIZE
;i
++) {
3192 /* parse number in null terminated string 'p' and return it in the
3194 void parse_number(const char *p
)
3196 int b
, t
, shift
, frac_bits
, s
, exp_val
, ch
;
3198 unsigned int bn
[BN_SIZE
];
3209 goto float_frac_parse
;
3210 } else if (t
== '0') {
3211 if (ch
== 'x' || ch
== 'X') {
3215 } else if (tcc_ext
&& (ch
== 'b' || ch
== 'B')) {
3221 /* parse all digits. cannot check octal numbers at this stage
3222 because of floating point constants */
3224 if (ch
>= 'a' && ch
<= 'f')
3226 else if (ch
>= 'A' && ch
<= 'F')
3234 if (q
>= token_buf
+ STRING_MAX_SIZE
) {
3236 error("number too long");
3242 ((ch
== 'e' || ch
== 'E') && b
== 10) ||
3243 ((ch
== 'p' || ch
== 'P') && (b
== 16 || b
== 2))) {
3245 /* NOTE: strtox should support that for hexa numbers, but
3246 non ISOC99 libcs do not support it, so we prefer to do
3248 /* hexadecimal or binary floats */
3249 /* XXX: handle overflows */
3261 } else if (t
>= 'a') {
3263 } else if (t
>= 'A') {
3268 bn_lshift(bn
, shift
, t
);
3275 if (t
>= 'a' && t
<= 'f') {
3277 } else if (t
>= 'A' && t
<= 'F') {
3279 } else if (t
>= '0' && t
<= '9') {
3285 error("invalid digit");
3286 bn_lshift(bn
, shift
, t
);
3291 if (ch
!= 'p' && ch
!= 'P')
3298 } else if (ch
== '-') {
3302 if (ch
< '0' || ch
> '9')
3303 expect("exponent digits");
3304 while (ch
>= '0' && ch
<= '9') {
3305 exp_val
= exp_val
* 10 + ch
- '0';
3308 exp_val
= exp_val
* s
;
3310 /* now we can generate the number */
3311 /* XXX: should patch directly float number */
3312 d
= (double)bn
[1] * 4294967296.0 + (double)bn
[0];
3313 d
= ldexp(d
, exp_val
- frac_bits
);
3318 /* float : should handle overflow */
3320 } else if (t
== 'L') {
3323 /* XXX: not large enough */
3324 tokc
.ld
= (long double)d
;
3330 /* decimal floats */
3332 if (q
>= token_buf
+ STRING_MAX_SIZE
)
3337 while (ch
>= '0' && ch
<= '9') {
3338 if (q
>= token_buf
+ STRING_MAX_SIZE
)
3344 if (ch
== 'e' || ch
== 'E') {
3345 if (q
>= token_buf
+ STRING_MAX_SIZE
)
3349 if (ch
== '-' || ch
== '+') {
3350 if (q
>= token_buf
+ STRING_MAX_SIZE
)
3355 if (ch
< '0' || ch
> '9')
3356 expect("exponent digits");
3357 while (ch
>= '0' && ch
<= '9') {
3358 if (q
>= token_buf
+ STRING_MAX_SIZE
)
3370 tokc
.f
= strtof(token_buf
, NULL
);
3371 } else if (t
== 'L') {
3374 tokc
.ld
= strtold(token_buf
, NULL
);
3377 tokc
.d
= strtod(token_buf
, NULL
);
3381 unsigned long long n
, n1
;
3384 /* integer number */
3387 if (b
== 10 && *q
== '0') {
3394 /* no need for checks except for base 10 / 8 errors */
3397 } else if (t
>= 'a') {
3399 } else if (t
>= 'A') {
3404 error("invalid digit");
3408 /* detect overflow */
3409 /* XXX: this test is not reliable */
3411 error("integer constant overflow");
3414 /* XXX: not exactly ANSI compliant */
3415 if ((n
& 0xffffffff00000000LL
) != 0) {
3420 } else if (n
> 0x7fffffff) {
3431 error("three 'l's in integer constant");
3434 if (tok
== TOK_CINT
)
3436 else if (tok
== TOK_CUINT
)
3440 } else if (t
== 'U') {
3442 error("two 'u's in integer constant");
3444 if (tok
== TOK_CINT
)
3446 else if (tok
== TOK_CLLONG
)
3453 if (tok
== TOK_CINT
|| tok
== TOK_CUINT
)
3461 #define PARSE2(c1, tok1, c2, tok2) \
3472 /* return next token without macro substitution */
3473 static inline void next_nomacro1(void)
3493 /* first look if it is in fact an end of buffer */
3494 if (p
>= file
->buf_end
) {
3498 if (p
>= file
->buf_end
)
3511 TCCState
*s1
= tcc_state
;
3512 if (parse_flags
& PARSE_FLAG_LINEFEED
) {
3514 } else if (s1
->include_stack_ptr
== s1
->include_stack
||
3515 !(parse_flags
& PARSE_FLAG_PREPROCESS
)) {
3516 /* no include left : end of file. */
3519 /* pop include file */
3521 /* test if previous '#endif' was after a #ifdef at
3523 if (tok_flags
& TOK_FLAG_ENDIF
) {
3525 printf("#endif %s\n", get_tok_str(file
->ifndef_macro_saved
, NULL
));
3527 add_cached_include(s1
, file
->inc_type
, file
->inc_filename
,
3528 file
->ifndef_macro_saved
);
3531 /* add end of include file debug info */
3533 put_stabd(N_EINCL
, 0, 0);
3535 /* pop include stack */
3537 s1
->include_stack_ptr
--;
3538 file
= *s1
->include_stack_ptr
;
3546 if (parse_flags
& PARSE_FLAG_LINEFEED
) {
3550 tok_flags
|= TOK_FLAG_BOL
;
3559 if ((tok_flags
& TOK_FLAG_BOL
) &&
3560 (parse_flags
& PARSE_FLAG_PREPROCESS
)) {
3562 preprocess(tok_flags
& TOK_FLAG_BOF
);
3568 tok
= TOK_TWOSHARPS
;
3570 if (parse_flags
& PARSE_FLAG_ASM_COMMENTS
) {
3571 p
= parse_line_comment(p
- 1);
3580 case 'a': case 'b': case 'c': case 'd':
3581 case 'e': case 'f': case 'g': case 'h':
3582 case 'i': case 'j': case 'k': case 'l':
3583 case 'm': case 'n': case 'o': case 'p':
3584 case 'q': case 'r': case 's': case 't':
3585 case 'u': case 'v': case 'w': case 'x':
3587 case 'A': case 'B': case 'C': case 'D':
3588 case 'E': case 'F': case 'G': case 'H':
3589 case 'I': case 'J': case 'K':
3590 case 'M': case 'N': case 'O': case 'P':
3591 case 'Q': case 'R': case 'S': case 'T':
3592 case 'U': case 'V': case 'W': case 'X':
3598 h
= TOK_HASH_FUNC(h
, c
);
3602 if (!isidnum_table
[c
])
3604 h
= TOK_HASH_FUNC(h
, c
);
3611 /* fast case : no stray found, so we have the full token
3612 and we have already hashed it */
3614 h
&= (TOK_HASH_SIZE
- 1);
3615 pts
= &hash_ident
[h
];
3620 if (ts
->len
== len
&& !memcmp(ts
->str
, p1
, len
))
3622 pts
= &(ts
->hash_next
);
3624 ts
= tok_alloc_new(pts
, p1
, len
);
3628 cstr_reset(&tokcstr
);
3631 cstr_ccat(&tokcstr
, *p1
);
3637 while (isidnum_table
[c
]) {
3638 cstr_ccat(&tokcstr
, c
);
3641 ts
= tok_alloc(tokcstr
.data
, tokcstr
.size
);
3647 if (t
!= '\\' && t
!= '\'' && t
!= '\"') {
3649 goto parse_ident_fast
;
3652 if (c
== '\'' || c
== '\"') {
3656 cstr_reset(&tokcstr
);
3657 cstr_ccat(&tokcstr
, 'L');
3658 goto parse_ident_slow
;
3662 case '0': case '1': case '2': case '3':
3663 case '4': case '5': case '6': case '7':
3666 cstr_reset(&tokcstr
);
3667 /* after the first digit, accept digits, alpha, '.' or sign if
3668 prefixed by 'eEpP' */
3672 cstr_ccat(&tokcstr
, c
);
3674 if (!(isnum(c
) || isid(c
) || c
== '.' ||
3675 ((c
== '+' || c
== '-') &&
3676 (t
== 'e' || t
== 'E' || t
== 'p' || t
== 'P'))))
3679 /* We add a trailing '\0' to ease parsing */
3680 cstr_ccat(&tokcstr
, '\0');
3681 tokc
.cstr
= &tokcstr
;
3685 /* special dot handling because it can also start a number */
3688 cstr_reset(&tokcstr
);
3689 cstr_ccat(&tokcstr
, '.');
3691 } else if (c
== '.') {
3711 /* parse the string */
3713 p
= parse_pp_string(p
, sep
, &str
);
3714 cstr_ccat(&str
, '\0');
3716 /* eval the escape (should be done as TOK_PPNUM) */
3717 cstr_reset(&tokcstr
);
3718 parse_escape_string(&tokcstr
, str
.data
, is_long
);
3723 /* XXX: make it portable */
3727 char_size
= sizeof(int);
3728 if (tokcstr
.size
<= char_size
)
3729 error("empty character constant");
3730 if (tokcstr
.size
> 2 * char_size
)
3731 warning("multi-character character constant");
3733 tokc
.i
= *(int8_t *)tokcstr
.data
;
3736 tokc
.i
= *(int *)tokcstr
.data
;
3740 tokc
.cstr
= &tokcstr
;
3754 } else if (c
== '<') {
3772 } else if (c
== '>') {
3790 } else if (c
== '=') {
3803 } else if (c
== '=') {
3816 } else if (c
== '=') {
3829 } else if (c
== '=') {
3832 } else if (c
== '>') {
3840 PARSE2('!', '!', '=', TOK_NE
)
3841 PARSE2('=', '=', '=', TOK_EQ
)
3842 PARSE2('*', '*', '=', TOK_A_MUL
)
3843 PARSE2('%', '%', '=', TOK_A_MOD
)
3844 PARSE2('^', '^', '=', TOK_A_XOR
)
3846 /* comments or operator */
3850 p
= parse_comment(p
);
3852 } else if (c
== '/') {
3853 p
= parse_line_comment(p
);
3855 } else if (c
== '=') {
3875 case '$': /* only used in assembler */
3876 case '@': /* dito */
3881 error("unrecognized character \\x%02x", c
);
3886 #if defined(PARSE_DEBUG)
3887 printf("token = %s\n", get_tok_str(tok
, &tokc
));
3891 /* return next token without macro substitution. Can read input from
3893 static void next_nomacro(void)
3899 TOK_GET(tok
, macro_ptr
, tokc
);
3900 if (tok
== TOK_LINENUM
) {
3901 file
->line_num
= tokc
.i
;
3910 /* substitute args in macro_str and return allocated string */
3911 static int *macro_arg_subst(Sym
**nested_list
, int *macro_str
, Sym
*args
)
3913 int *st
, last_tok
, t
, notfirst
;
3922 TOK_GET(t
, macro_str
, cval
);
3927 TOK_GET(t
, macro_str
, cval
);
3930 s
= sym_find2(args
, t
);
3937 cstr_ccat(&cstr
, ' ');
3938 TOK_GET(t
, st
, cval
);
3939 cstr_cat(&cstr
, get_tok_str(t
, &cval
));
3942 cstr_ccat(&cstr
, '\0');
3944 printf("stringize: %s\n", (char *)cstr
.data
);
3948 tok_str_add2(&str
, TOK_STR
, &cval
);
3951 tok_str_add2(&str
, t
, &cval
);
3953 } else if (t
>= TOK_IDENT
) {
3954 s
= sym_find2(args
, t
);
3957 /* if '##' is present before or after, no arg substitution */
3958 if (*macro_str
== TOK_TWOSHARPS
|| last_tok
== TOK_TWOSHARPS
) {
3959 /* special case for var arg macros : ## eats the
3960 ',' if empty VA_ARGS variable. */
3961 /* XXX: test of the ',' is not 100%
3962 reliable. should fix it to avoid security
3964 if (gnu_ext
&& s
->type
.t
&&
3965 last_tok
== TOK_TWOSHARPS
&&
3966 str
.len
>= 2 && str
.str
[str
.len
- 2] == ',') {
3968 /* suppress ',' '##' */
3971 /* suppress '##' and add variable */
3979 TOK_GET(t1
, st
, cval
);
3982 tok_str_add2(&str
, t1
, &cval
);
3986 /* NOTE: the stream cannot be read when macro
3987 substituing an argument */
3988 macro_subst(&str
, nested_list
, st
, NULL
);
3991 tok_str_add(&str
, t
);
3994 tok_str_add2(&str
, t
, &cval
);
3998 tok_str_add(&str
, 0);
4002 static char const ab_month_name
[12][4] =
4004 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
4005 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
4008 /* do macro substitution of current token with macro 's' and add
4009 result to (tok_str,tok_len). 'nested_list' is the list of all
4010 macros we got inside to avoid recursing. Return non zero if no
4011 substitution needs to be done */
4012 static int macro_subst_tok(TokenString
*tok_str
,
4013 Sym
**nested_list
, Sym
*s
, struct macro_level
**can_read_stream
)
4015 Sym
*args
, *sa
, *sa1
;
4016 int mstr_allocated
, parlevel
, *mstr
, t
, t1
;
4023 /* if symbol is a macro, prepare substitution */
4024 /* special macros */
4025 if (tok
== TOK___LINE__
) {
4026 snprintf(buf
, sizeof(buf
), "%d", file
->line_num
);
4030 } else if (tok
== TOK___FILE__
) {
4031 cstrval
= file
->filename
;
4033 } else if (tok
== TOK___DATE__
|| tok
== TOK___TIME__
) {
4038 tm
= localtime(&ti
);
4039 if (tok
== TOK___DATE__
) {
4040 snprintf(buf
, sizeof(buf
), "%s %2d %d",
4041 ab_month_name
[tm
->tm_mon
], tm
->tm_mday
, tm
->tm_year
+ 1900);
4043 snprintf(buf
, sizeof(buf
), "%02d:%02d:%02d",
4044 tm
->tm_hour
, tm
->tm_min
, tm
->tm_sec
);
4051 cstr_cat(&cstr
, cstrval
);
4052 cstr_ccat(&cstr
, '\0');
4054 tok_str_add2(tok_str
, t1
, &cval
);
4059 if (s
->type
.t
== MACRO_FUNC
) {
4060 /* NOTE: we do not use next_nomacro to avoid eating the
4061 next token. XXX: find better solution */
4065 if (t
== 0 && can_read_stream
) {
4066 /* end of macro stream: we must look at the token
4067 after in the file */
4068 struct macro_level
*ml
= *can_read_stream
;
4074 *can_read_stream
= ml
-> prev
;
4079 /* XXX: incorrect with comments */
4080 ch
= file
->buf_ptr
[0];
4081 while (is_space(ch
) || ch
== '\n')
4085 if (t
!= '(') /* no macro subst */
4088 /* argument macro */
4093 /* NOTE: empty args are allowed, except if no args */
4095 /* handle '()' case */
4096 if (!args
&& !sa
&& tok
== ')')
4099 error("macro '%s' used with too many args",
4100 get_tok_str(s
->v
, 0));
4103 /* NOTE: non zero sa->t indicates VA_ARGS */
4104 while ((parlevel
> 0 ||
4106 (tok
!= ',' || sa
->type
.t
))) &&
4110 else if (tok
== ')')
4112 tok_str_add2(&str
, tok
, &tokc
);
4115 tok_str_add(&str
, 0);
4116 sym_push2(&args
, sa
->v
& ~SYM_FIELD
, sa
->type
.t
, (int)str
.str
);
4119 /* special case for gcc var args: add an empty
4120 var arg argument if it is omitted */
4121 if (sa
&& sa
->type
.t
&& gnu_ext
)
4131 error("macro '%s' used with too few args",
4132 get_tok_str(s
->v
, 0));
4135 /* now subst each arg */
4136 mstr
= macro_arg_subst(nested_list
, mstr
, args
);
4141 tok_str_free((int *)sa
->c
);
4147 sym_push2(nested_list
, s
->v
, 0, 0);
4148 macro_subst(tok_str
, nested_list
, mstr
, can_read_stream
);
4149 /* pop nested defined symbol */
4151 *nested_list
= sa1
->prev
;
4159 /* handle the '##' operator. Return NULL if no '##' seen. Otherwise
4160 return the resulting string (which must be freed). */
4161 static inline int *macro_twosharps(const int *macro_str
)
4164 const int *macro_ptr1
, *start_macro_ptr
, *ptr
, *saved_macro_ptr
;
4166 const char *p1
, *p2
;
4168 TokenString macro_str1
;
4171 start_macro_ptr
= macro_str
;
4172 /* we search the first '##' */
4174 macro_ptr1
= macro_str
;
4175 TOK_GET(t
, macro_str
, cval
);
4176 /* nothing more to do if end of string */
4179 if (*macro_str
== TOK_TWOSHARPS
)
4183 /* we saw '##', so we need more processing to handle it */
4185 tok_str_new(¯o_str1
);
4189 /* add all tokens seen so far */
4190 for(ptr
= start_macro_ptr
; ptr
< macro_ptr1
;) {
4191 TOK_GET(t
, ptr
, cval
);
4192 tok_str_add2(¯o_str1
, t
, &cval
);
4194 saved_macro_ptr
= macro_ptr
;
4195 /* XXX: get rid of the use of macro_ptr here */
4196 macro_ptr
= (int *)macro_str
;
4198 while (*macro_ptr
== TOK_TWOSHARPS
) {
4200 macro_ptr1
= macro_ptr
;
4203 TOK_GET(t
, macro_ptr
, cval
);
4204 /* We concatenate the two tokens if we have an
4205 identifier or a preprocessing number */
4207 p1
= get_tok_str(tok
, &tokc
);
4208 cstr_cat(&cstr
, p1
);
4209 p2
= get_tok_str(t
, &cval
);
4210 cstr_cat(&cstr
, p2
);
4211 cstr_ccat(&cstr
, '\0');
4213 if ((tok
>= TOK_IDENT
|| tok
== TOK_PPNUM
) &&
4214 (t
>= TOK_IDENT
|| t
== TOK_PPNUM
)) {
4215 if (tok
== TOK_PPNUM
) {
4216 /* if number, then create a number token */
4217 /* NOTE: no need to allocate because
4218 tok_str_add2() does it */
4221 /* if identifier, we must do a test to
4222 validate we have a correct identifier */
4223 if (t
== TOK_PPNUM
) {
4233 if (!isnum(c
) && !isid(c
))
4237 ts
= tok_alloc(cstr
.data
, strlen(cstr
.data
));
4238 tok
= ts
->tok
; /* modify current token */
4241 const char *str
= cstr
.data
;
4242 const unsigned char *q
;
4244 /* we look for a valid token */
4245 /* XXX: do more extensive checks */
4246 if (!strcmp(str
, ">>=")) {
4248 } else if (!strcmp(str
, "<<=")) {
4250 } else if (strlen(str
) == 2) {
4251 /* search in two bytes table */
4256 if (q
[0] == str
[0] && q
[1] == str
[1])
4263 /* NOTE: because get_tok_str use a static buffer,
4266 p1
= get_tok_str(tok
, &tokc
);
4267 cstr_cat(&cstr
, p1
);
4268 cstr_ccat(&cstr
, '\0');
4269 p2
= get_tok_str(t
, &cval
);
4270 warning("pasting \"%s\" and \"%s\" does not give a valid preprocessing token", cstr
.data
, p2
);
4271 /* cannot merge tokens: just add them separately */
4272 tok_str_add2(¯o_str1
, tok
, &tokc
);
4273 /* XXX: free associated memory ? */
4280 tok_str_add2(¯o_str1
, tok
, &tokc
);
4285 macro_ptr
= (int *)saved_macro_ptr
;
4287 tok_str_add(¯o_str1
, 0);
4288 return macro_str1
.str
;
4292 /* do macro substitution of macro_str and add result to
4293 (tok_str,tok_len). 'nested_list' is the list of all macros we got
4294 inside to avoid recursing. */
4295 static void macro_subst(TokenString
*tok_str
, Sym
**nested_list
,
4296 const int *macro_str
, struct macro_level
** can_read_stream
)
4303 struct macro_level ml
;
4305 /* first scan for '##' operator handling */
4307 macro_str1
= macro_twosharps(ptr
);
4311 /* NOTE: ptr == NULL can only happen if tokens are read from
4312 file stream due to a macro function call */
4315 TOK_GET(t
, ptr
, cval
);
4320 /* if nested substitution, do nothing */
4321 if (sym_find2(*nested_list
, t
))
4324 if (can_read_stream
)
4325 ml
.prev
= *can_read_stream
, *can_read_stream
= &ml
;
4326 macro_ptr
= (int *)ptr
;
4328 ret
= macro_subst_tok(tok_str
, nested_list
, s
, can_read_stream
);
4329 ptr
= (int *)macro_ptr
;
4331 if (can_read_stream
&& *can_read_stream
== &ml
)
4332 *can_read_stream
= ml
.prev
;
4337 tok_str_add2(tok_str
, t
, &cval
);
4341 tok_str_free(macro_str1
);
4344 /* return next token with macro substitution */
4345 static void next(void)
4347 Sym
*nested_list
, *s
;
4349 struct macro_level
*ml
;
4354 /* if not reading from macro substituted string, then try
4355 to substitute macros */
4356 if (tok
>= TOK_IDENT
&&
4357 (parse_flags
& PARSE_FLAG_PREPROCESS
)) {
4358 s
= define_find(tok
);
4360 /* we have a macro: we try to substitute */
4364 if (macro_subst_tok(&str
, &nested_list
, s
, &ml
) == 0) {
4365 /* substitution done, NOTE: maybe empty */
4366 tok_str_add(&str
, 0);
4367 macro_ptr
= str
.str
;
4368 macro_ptr_allocated
= str
.str
;
4375 /* end of macro or end of unget buffer */
4376 if (unget_buffer_enabled
) {
4377 macro_ptr
= unget_saved_macro_ptr
;
4378 unget_buffer_enabled
= 0;
4380 /* end of macro string: free it */
4381 tok_str_free(macro_ptr_allocated
);
4388 /* convert preprocessor tokens into C tokens */
4389 if (tok
== TOK_PPNUM
&&
4390 (parse_flags
& PARSE_FLAG_TOK_NUM
)) {
4391 parse_number((char *)tokc
.cstr
->data
);
4395 /* push back current token and set current token to 'last_tok'. Only
4396 identifier case handled for labels. */
4397 static inline void unget_tok(int last_tok
)
4401 unget_saved_macro_ptr
= macro_ptr
;
4402 unget_buffer_enabled
= 1;
4403 q
= unget_saved_buffer
;
4406 n
= tok_ext_size(tok
) - 1;
4409 *q
= 0; /* end of token string */
4414 void swap(int *p
, int *q
)
4422 void vsetc(CType
*type
, int r
, CValue
*vc
)
4426 if (vtop
>= vstack
+ (VSTACK_SIZE
- 1))
4427 error("memory full");
4428 /* cannot let cpu flags if other instruction are generated. Also
4429 avoid leaving VT_JMP anywhere except on the top of the stack
4430 because it would complicate the code generator. */
4431 if (vtop
>= vstack
) {
4432 v
= vtop
->r
& VT_VALMASK
;
4433 if (v
== VT_CMP
|| (v
& ~1) == VT_JMP
)
4439 vtop
->r2
= VT_CONST
;
4443 /* push integer constant */
4448 vsetc(&int_type
, VT_CONST
, &cval
);
4451 /* Return a static symbol pointing to a section */
4452 static Sym
*get_sym_ref(CType
*type
, Section
*sec
,
4453 unsigned long offset
, unsigned long size
)
4459 sym
= global_identifier_push(v
, type
->t
| VT_STATIC
, 0);
4460 sym
->type
.ref
= type
->ref
;
4461 sym
->r
= VT_CONST
| VT_SYM
;
4462 put_extern_sym(sym
, sec
, offset
, size
);
4466 /* push a reference to a section offset by adding a dummy symbol */
4467 static void vpush_ref(CType
*type
, Section
*sec
, unsigned long offset
, unsigned long size
)
4472 vsetc(type
, VT_CONST
| VT_SYM
, &cval
);
4473 vtop
->sym
= get_sym_ref(type
, sec
, offset
, size
);
4476 /* define a new external reference to a symbol 'v' of type 'u' */
4477 static Sym
*external_global_sym(int v
, CType
*type
, int r
)
4483 /* push forward reference */
4484 s
= global_identifier_push(v
, type
->t
| VT_EXTERN
, 0);
4485 s
->type
.ref
= type
->ref
;
4486 s
->r
= r
| VT_CONST
| VT_SYM
;
4491 /* define a new external reference to a symbol 'v' of type 'u' */
4492 static Sym
*external_sym(int v
, CType
*type
, int r
)
4498 /* push forward reference */
4499 s
= sym_push(v
, type
, r
| VT_CONST
| VT_SYM
, 0);
4500 s
->type
.t
|= VT_EXTERN
;
4502 if (!is_compatible_types(&s
->type
, type
))
4503 error("incompatible types for redefinition of '%s'",
4504 get_tok_str(v
, NULL
));
4509 /* push a reference to global symbol v */
4510 static void vpush_global_sym(CType
*type
, int v
)
4515 sym
= external_global_sym(v
, type
, 0);
4517 vsetc(type
, VT_CONST
| VT_SYM
, &cval
);
4521 void vset(CType
*type
, int r
, int v
)
4526 vsetc(type
, r
, &cval
);
4529 void vseti(int r
, int v
)
4545 void vpushv(SValue
*v
)
4547 if (vtop
>= vstack
+ (VSTACK_SIZE
- 1))
4548 error("memory full");
4558 /* save r to the memory stack, and mark it as being free */
4559 void save_reg(int r
)
4561 int l
, saved
, size
, align
;
4565 /* modify all stack values */
4568 for(p
=vstack
;p
<=vtop
;p
++) {
4569 if ((p
->r
& VT_VALMASK
) == r
||
4570 (p
->r2
& VT_VALMASK
) == r
) {
4571 /* must save value on stack if not already done */
4573 /* NOTE: must reload 'r' because r might be equal to r2 */
4574 r
= p
->r
& VT_VALMASK
;
4575 /* store register in the stack */
4577 if ((p
->r
& VT_LVAL
) ||
4578 (!is_float(type
->t
) && (type
->t
& VT_BTYPE
) != VT_LLONG
))
4580 size
= type_size(type
, &align
);
4581 loc
= (loc
- size
) & -align
;
4582 sv
.type
.t
= type
->t
;
4583 sv
.r
= VT_LOCAL
| VT_LVAL
;
4586 #ifdef TCC_TARGET_I386
4587 /* x86 specific: need to pop fp register ST0 if saved */
4588 if (r
== TREG_ST0
) {
4589 o(0xd9dd); /* fstp %st(1) */
4592 /* special long long case */
4593 if ((type
->t
& VT_BTYPE
) == VT_LLONG
) {
4600 /* mark that stack entry as being saved on the stack */
4601 if (p
->r
& VT_LVAL
) {
4602 /* also clear the bounded flag because the
4603 relocation address of the function was stored in
4605 p
->r
= (p
->r
& ~(VT_VALMASK
| VT_BOUNDED
)) | VT_LLOCAL
;
4607 p
->r
= lvalue_type(p
->type
.t
) | VT_LOCAL
;
4615 /* find a register of class 'rc2' with at most one reference on stack.
4616 * If none, call get_reg(rc) */
4617 int get_reg_ex(int rc
, int rc2
)
4622 for(r
=0;r
<NB_REGS
;r
++) {
4623 if (reg_classes
[r
] & rc2
) {
4626 for(p
= vstack
; p
<= vtop
; p
++) {
4627 if ((p
->r
& VT_VALMASK
) == r
||
4628 (p
->r2
& VT_VALMASK
) == r
)
4638 /* find a free register of class 'rc'. If none, save one register */
4644 /* find a free register */
4645 for(r
=0;r
<NB_REGS
;r
++) {
4646 if (reg_classes
[r
] & rc
) {
4647 for(p
=vstack
;p
<=vtop
;p
++) {
4648 if ((p
->r
& VT_VALMASK
) == r
||
4649 (p
->r2
& VT_VALMASK
) == r
)
4657 /* no register left : free the first one on the stack (VERY
4658 IMPORTANT to start from the bottom to ensure that we don't
4659 spill registers used in gen_opi()) */
4660 for(p
=vstack
;p
<=vtop
;p
++) {
4661 r
= p
->r
& VT_VALMASK
;
4662 if (r
< VT_CONST
&& (reg_classes
[r
] & rc
))
4664 /* also look at second register (if long long) */
4665 r
= p
->r2
& VT_VALMASK
;
4666 if (r
< VT_CONST
&& (reg_classes
[r
] & rc
)) {
4672 /* Should never comes here */
4676 /* save registers up to (vtop - n) stack entry */
4677 void save_regs(int n
)
4682 for(p
= vstack
;p
<= p1
; p
++) {
4683 r
= p
->r
& VT_VALMASK
;
4690 /* move register 's' to 'r', and flush previous value of r to memory
4692 void move_reg(int r
, int s
)
4705 /* get address of vtop (vtop MUST BE an lvalue) */
4708 vtop
->r
&= ~VT_LVAL
;
4709 /* tricky: if saved lvalue, then we can go back to lvalue */
4710 if ((vtop
->r
& VT_VALMASK
) == VT_LLOCAL
)
4711 vtop
->r
= (vtop
->r
& ~(VT_VALMASK
| VT_LVAL_TYPE
)) | VT_LOCAL
| VT_LVAL
;
4714 #ifdef CONFIG_TCC_BCHECK
4715 /* generate lvalue bound code */
4721 vtop
->r
&= ~VT_MUSTBOUND
;
4722 /* if lvalue, then use checking code before dereferencing */
4723 if (vtop
->r
& VT_LVAL
) {
4724 /* if not VT_BOUNDED value, then make one */
4725 if (!(vtop
->r
& VT_BOUNDED
)) {
4726 lval_type
= vtop
->r
& (VT_LVAL_TYPE
| VT_LVAL
);
4727 /* must save type because we must set it to int to get pointer */
4729 vtop
->type
.t
= VT_INT
;
4732 gen_bounded_ptr_add();
4733 vtop
->r
|= lval_type
;
4736 /* then check for dereferencing */
4737 gen_bounded_ptr_deref();
4742 /* store vtop a register belonging to class 'rc'. lvalues are
4743 converted to values. Cannot be used if cannot be converted to
4744 register value (such as structures). */
4747 int r
, r2
, rc2
, bit_pos
, bit_size
, size
, align
, i
;
4748 unsigned long long ll
;
4750 /* NOTE: get_reg can modify vstack[] */
4751 if (vtop
->type
.t
& VT_BITFIELD
) {
4752 bit_pos
= (vtop
->type
.t
>> VT_STRUCT_SHIFT
) & 0x3f;
4753 bit_size
= (vtop
->type
.t
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f;
4754 /* remove bit field info to avoid loops */
4755 vtop
->type
.t
&= ~(VT_BITFIELD
| (-1 << VT_STRUCT_SHIFT
));
4756 /* generate shifts */
4757 vpushi(32 - (bit_pos
+ bit_size
));
4759 vpushi(32 - bit_size
);
4760 /* NOTE: transformed to SHR if unsigned */
4764 if (is_float(vtop
->type
.t
) &&
4765 (vtop
->r
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
) {
4768 unsigned long offset
;
4770 /* XXX: unify with initializers handling ? */
4771 /* CPUs usually cannot use float constants, so we store them
4772 generically in data segment */
4773 size
= type_size(&vtop
->type
, &align
);
4774 offset
= (data_section
->data_offset
+ align
- 1) & -align
;
4775 data_section
->data_offset
= offset
;
4776 /* XXX: not portable yet */
4777 ptr
= section_ptr_add(data_section
, size
);
4780 ptr
[i
] = vtop
->c
.tab
[i
];
4781 sym
= get_sym_ref(&vtop
->type
, data_section
, offset
, size
<< 2);
4782 vtop
->r
|= VT_LVAL
| VT_SYM
;
4786 #ifdef CONFIG_TCC_BCHECK
4787 if (vtop
->r
& VT_MUSTBOUND
)
4791 r
= vtop
->r
& VT_VALMASK
;
4792 /* need to reload if:
4794 - lvalue (need to dereference pointer)
4795 - already a register, but not in the right class */
4796 if (r
>= VT_CONST
||
4797 (vtop
->r
& VT_LVAL
) ||
4798 !(reg_classes
[r
] & rc
) ||
4799 ((vtop
->type
.t
& VT_BTYPE
) == VT_LLONG
&&
4800 !(reg_classes
[vtop
->r2
] & rc
))) {
4802 if ((vtop
->type
.t
& VT_BTYPE
) == VT_LLONG
) {
4803 /* two register type load : expand to two words
4805 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
) {
4808 vtop
->c
.ui
= ll
; /* first word */
4810 vtop
->r
= r
; /* save register value */
4811 vpushi(ll
>> 32); /* second word */
4812 } else if (r
>= VT_CONST
|| /* XXX: test to VT_CONST incorrect ? */
4813 (vtop
->r
& VT_LVAL
)) {
4814 /* We do not want to modifier the long long
4815 pointer here, so the safest (and less
4816 efficient) is to save all the other registers
4817 in the stack. XXX: totally inefficient. */
4819 /* load from memory */
4822 vtop
[-1].r
= r
; /* save register value */
4823 /* increment pointer to get second word */
4824 vtop
->type
.t
= VT_INT
;
4830 /* move registers */
4833 vtop
[-1].r
= r
; /* save register value */
4834 vtop
->r
= vtop
[-1].r2
;
4836 /* allocate second register */
4843 /* write second register */
4845 } else if ((vtop
->r
& VT_LVAL
) && !is_float(vtop
->type
.t
)) {
4847 /* lvalue of scalar type : need to use lvalue type
4848 because of possible cast */
4851 /* compute memory access type */
4852 if (vtop
->r
& VT_LVAL_BYTE
)
4854 else if (vtop
->r
& VT_LVAL_SHORT
)
4856 if (vtop
->r
& VT_LVAL_UNSIGNED
)
4860 /* restore wanted type */
4863 /* one register type load */
4868 #ifdef TCC_TARGET_C67
4869 /* uses register pairs for doubles */
4870 if ((vtop
->type
.t
& VT_BTYPE
) == VT_DOUBLE
)
4877 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
4878 void gv2(int rc1
, int rc2
)
4882 /* generate more generic register first. But VT_JMP or VT_CMP
4883 values must be generated first in all cases to avoid possible
4885 v
= vtop
[0].r
& VT_VALMASK
;
4886 if (v
!= VT_CMP
&& (v
& ~1) != VT_JMP
&& rc1
<= rc2
) {
4891 /* test if reload is needed for first register */
4892 if ((vtop
[-1].r
& VT_VALMASK
) >= VT_CONST
) {
4902 /* test if reload is needed for first register */
4903 if ((vtop
[0].r
& VT_VALMASK
) >= VT_CONST
) {
4909 /* expand long long on stack in two int registers */
4914 u
= vtop
->type
.t
& VT_UNSIGNED
;
4917 vtop
[0].r
= vtop
[-1].r2
;
4918 vtop
[0].r2
= VT_CONST
;
4919 vtop
[-1].r2
= VT_CONST
;
4920 vtop
[0].type
.t
= VT_INT
| u
;
4921 vtop
[-1].type
.t
= VT_INT
| u
;
4924 #ifdef TCC_TARGET_ARM
4925 /* expand long long on stack */
4926 void lexpand_nr(void)
4930 u
= vtop
->type
.t
& VT_UNSIGNED
;
4932 vtop
->r2
= VT_CONST
;
4933 vtop
->type
.t
= VT_INT
| u
;
4934 v
=vtop
[-1].r
& (VT_VALMASK
| VT_LVAL
);
4935 if (v
== VT_CONST
) {
4936 vtop
[-1].c
.ui
= vtop
->c
.ull
;
4937 vtop
->c
.ui
= vtop
->c
.ull
>> 32;
4939 } else if (v
== (VT_LVAL
|VT_CONST
) || v
== (VT_LVAL
|VT_LOCAL
)) {
4941 vtop
->r
= vtop
[-1].r
;
4942 } else if (v
> VT_CONST
) {
4946 vtop
->r
= vtop
[-1].r2
;
4947 vtop
[-1].r2
= VT_CONST
;
4948 vtop
[-1].type
.t
= VT_INT
| u
;
4952 /* build a long long from two ints */
4955 gv2(RC_INT
, RC_INT
);
4956 vtop
[-1].r2
= vtop
[0].r
;
4957 vtop
[-1].type
.t
= t
;
4961 /* rotate n first stack elements to the bottom
4962 I1 ... In -> I2 ... In I1 [top is right]
4970 for(i
=-n
+1;i
!=0;i
++)
4971 vtop
[i
] = vtop
[i
+1];
4975 /* rotate n first stack elements to the top
4976 I1 ... In -> In I1 ... I(n-1) [top is right]
4984 for(i
= 0;i
< n
- 1; i
++)
4985 vtop
[-i
] = vtop
[-i
- 1];
4989 #ifdef TCC_TARGET_ARM
4990 /* like vrott but in other direction
4991 In ... I1 -> I(n-1) ... I1 In [top is right]
4999 for(i
= n
- 1; i
> 0; i
--)
5000 vtop
[-i
] = vtop
[-i
+ 1];
5005 /* pop stack value */
5009 v
= vtop
->r
& VT_VALMASK
;
5010 #ifdef TCC_TARGET_I386
5011 /* for x86, we need to pop the FP stack */
5012 if (v
== TREG_ST0
&& !nocode_wanted
) {
5013 o(0xd9dd); /* fstp %st(1) */
5016 if (v
== VT_JMP
|| v
== VT_JMPI
) {
5017 /* need to put correct jump if && or || without test */
5023 /* convert stack entry to register and duplicate its value in another
5031 if ((t
& VT_BTYPE
) == VT_LLONG
) {
5038 /* stack: H L L1 H1 */
5046 /* duplicate value */
5057 load(r1
, &sv
); /* move r to r1 */
5059 /* duplicates value */
5064 /* generate CPU independent (unsigned) long long operations */
5065 void gen_opl(int op
)
5067 int t
, a
, b
, op1
, c
, i
;
5074 func
= TOK___divdi3
;
5077 func
= TOK___udivdi3
;
5080 func
= TOK___moddi3
;
5083 func
= TOK___umoddi3
;
5085 /* call generic long long function */
5086 vpush_global_sym(&func_old_type
, func
);
5091 vtop
->r2
= REG_LRET
;
5104 /* stack: L1 H1 L2 H2 */
5109 vtop
[-2] = vtop
[-3];
5112 /* stack: H1 H2 L1 L2 */
5118 /* stack: H1 H2 L1 L2 ML MH */
5121 /* stack: ML MH H1 H2 L1 L2 */
5125 /* stack: ML MH H1 L2 H2 L1 */
5130 /* stack: ML MH M1 M2 */
5133 } else if (op
== '+' || op
== '-') {
5134 /* XXX: add non carry method too (for MIPS or alpha) */
5140 /* stack: H1 H2 (L1 op L2) */
5143 gen_op(op1
+ 1); /* TOK_xxxC2 */
5146 /* stack: H1 H2 (L1 op L2) */
5149 /* stack: (L1 op L2) H1 H2 */
5151 /* stack: (L1 op L2) (H1 op H2) */
5159 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
) {
5160 t
= vtop
[-1].type
.t
;
5164 /* stack: L H shift */
5166 /* constant: simpler */
5167 /* NOTE: all comments are for SHL. the other cases are
5168 done by swaping words */
5179 if (op
!= TOK_SAR
) {
5212 /* XXX: should provide a faster fallback on x86 ? */
5215 func
= TOK___sardi3
;
5218 func
= TOK___shrdi3
;
5221 func
= TOK___shldi3
;
5227 /* compare operations */
5233 /* stack: L1 H1 L2 H2 */
5235 vtop
[-1] = vtop
[-2];
5237 /* stack: L1 L2 H1 H2 */
5240 /* when values are equal, we need to compare low words. since
5241 the jump is inverted, we invert the test too. */
5244 else if (op1
== TOK_GT
)
5246 else if (op1
== TOK_ULT
)
5248 else if (op1
== TOK_UGT
)
5253 if (op1
!= TOK_NE
) {
5257 /* generate non equal test */
5258 /* XXX: NOT PORTABLE yet */
5262 #if defined(TCC_TARGET_I386)
5263 b
= psym(0x850f, 0);
5264 #elif defined(TCC_TARGET_ARM)
5266 o(0x1A000000 | encbranch(ind
, 0, 1));
5267 #elif defined(TCC_TARGET_C67)
5268 error("not implemented");
5270 #error not supported
5274 /* compare low. Always unsigned */
5278 else if (op1
== TOK_LE
)
5280 else if (op1
== TOK_GT
)
5282 else if (op1
== TOK_GE
)
5292 /* handle integer constant optimizations and various machine
5294 void gen_opic(int op
)
5301 /* currently, we cannot do computations with forward symbols */
5302 c1
= (v1
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
5303 c2
= (v2
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
5307 case '+': v1
->c
.i
+= fc
; break;
5308 case '-': v1
->c
.i
-= fc
; break;
5309 case '&': v1
->c
.i
&= fc
; break;
5310 case '^': v1
->c
.i
^= fc
; break;
5311 case '|': v1
->c
.i
|= fc
; break;
5312 case '*': v1
->c
.i
*= fc
; break;
5319 /* if division by zero, generate explicit division */
5322 error("division by zero in constant");
5326 default: v1
->c
.i
/= fc
; break;
5327 case '%': v1
->c
.i
%= fc
; break;
5328 case TOK_UDIV
: v1
->c
.i
= (unsigned)v1
->c
.i
/ fc
; break;
5329 case TOK_UMOD
: v1
->c
.i
= (unsigned)v1
->c
.i
% fc
; break;
5332 case TOK_SHL
: v1
->c
.i
<<= fc
; break;
5333 case TOK_SHR
: v1
->c
.i
= (unsigned)v1
->c
.i
>> fc
; break;
5334 case TOK_SAR
: v1
->c
.i
>>= fc
; break;
5336 case TOK_ULT
: v1
->c
.i
= (unsigned)v1
->c
.i
< (unsigned)fc
; break;
5337 case TOK_UGE
: v1
->c
.i
= (unsigned)v1
->c
.i
>= (unsigned)fc
; break;
5338 case TOK_EQ
: v1
->c
.i
= v1
->c
.i
== fc
; break;
5339 case TOK_NE
: v1
->c
.i
= v1
->c
.i
!= fc
; break;
5340 case TOK_ULE
: v1
->c
.i
= (unsigned)v1
->c
.i
<= (unsigned)fc
; break;
5341 case TOK_UGT
: v1
->c
.i
= (unsigned)v1
->c
.i
> (unsigned)fc
; break;
5342 case TOK_LT
: v1
->c
.i
= v1
->c
.i
< fc
; break;
5343 case TOK_GE
: v1
->c
.i
= v1
->c
.i
>= fc
; break;
5344 case TOK_LE
: v1
->c
.i
= v1
->c
.i
<= fc
; break;
5345 case TOK_GT
: v1
->c
.i
= v1
->c
.i
> fc
; break;
5347 case TOK_LAND
: v1
->c
.i
= v1
->c
.i
&& fc
; break;
5348 case TOK_LOR
: v1
->c
.i
= v1
->c
.i
|| fc
; break;
5354 /* if commutative ops, put c2 as constant */
5355 if (c1
&& (op
== '+' || op
== '&' || op
== '^' ||
5356 op
== '|' || op
== '*')) {
5361 if (c2
&& (((op
== '*' || op
== '/' || op
== TOK_UDIV
||
5364 ((op
== '+' || op
== '-' || op
== '|' || op
== '^' ||
5365 op
== TOK_SHL
|| op
== TOK_SHR
|| op
== TOK_SAR
) &&
5371 } else if (c2
&& (op
== '*' || op
== TOK_PDIV
|| op
== TOK_UDIV
)) {
5372 /* try to use shifts instead of muls or divs */
5373 if (fc
> 0 && (fc
& (fc
- 1)) == 0) {
5382 else if (op
== TOK_PDIV
)
5388 } else if (c2
&& (op
== '+' || op
== '-') &&
5389 (vtop
[-1].r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) ==
5390 (VT_CONST
| VT_SYM
)) {
5391 /* symbol + constant case */
5398 if (!nocode_wanted
) {
5399 /* call low level op generator */
5408 /* generate a floating point operation with constant propagation */
5409 void gen_opif(int op
)
5417 /* currently, we cannot do computations with forward symbols */
5418 c1
= (v1
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
5419 c2
= (v2
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
5421 if (v1
->type
.t
== VT_FLOAT
) {
5424 } else if (v1
->type
.t
== VT_DOUBLE
) {
5432 /* NOTE: we only do constant propagation if finite number (not
5433 NaN or infinity) (ANSI spec) */
5434 if (!ieee_finite(f1
) || !ieee_finite(f2
))
5438 case '+': f1
+= f2
; break;
5439 case '-': f1
-= f2
; break;
5440 case '*': f1
*= f2
; break;
5444 error("division by zero in constant");
5449 /* XXX: also handles tests ? */
5453 /* XXX: overflow test ? */
5454 if (v1
->type
.t
== VT_FLOAT
) {
5456 } else if (v1
->type
.t
== VT_DOUBLE
) {
5464 if (!nocode_wanted
) {
5472 static int pointed_size(CType
*type
)
5475 return type_size(pointed_type(type
), &align
);
5478 static inline int is_null_pointer(SValue
*p
)
5480 if ((p
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) != VT_CONST
)
5482 return ((p
->type
.t
& VT_BTYPE
) == VT_INT
&& p
->c
.i
== 0) ||
5483 ((p
->type
.t
& VT_BTYPE
) == VT_LLONG
&& p
->c
.ll
== 0);
5486 static inline int is_integer_btype(int bt
)
5488 return (bt
== VT_BYTE
|| bt
== VT_SHORT
||
5489 bt
== VT_INT
|| bt
== VT_LLONG
);
5492 /* check types for comparison or substraction of pointers */
5493 static void check_comparison_pointer_types(SValue
*p1
, SValue
*p2
, int op
)
5495 CType
*type1
, *type2
, tmp_type1
, tmp_type2
;
5498 /* null pointers are accepted for all comparisons as gcc */
5499 if (is_null_pointer(p1
) || is_null_pointer(p2
))
5503 bt1
= type1
->t
& VT_BTYPE
;
5504 bt2
= type2
->t
& VT_BTYPE
;
5505 /* accept comparison between pointer and integer with a warning */
5506 if ((is_integer_btype(bt1
) || is_integer_btype(bt2
)) && op
!= '-') {
5507 warning("comparison between pointer and integer");
5511 /* both must be pointers or implicit function pointers */
5512 if (bt1
== VT_PTR
) {
5513 type1
= pointed_type(type1
);
5514 } else if (bt1
!= VT_FUNC
)
5515 goto invalid_operands
;
5517 if (bt2
== VT_PTR
) {
5518 type2
= pointed_type(type2
);
5519 } else if (bt2
!= VT_FUNC
) {
5521 error("invalid operands to binary %s", get_tok_str(op
, NULL
));
5523 if ((type1
->t
& VT_BTYPE
) == VT_VOID
||
5524 (type2
->t
& VT_BTYPE
) == VT_VOID
)
5528 tmp_type1
.t
&= ~(VT_UNSIGNED
| VT_CONSTANT
| VT_VOLATILE
);
5529 tmp_type2
.t
&= ~(VT_UNSIGNED
| VT_CONSTANT
| VT_VOLATILE
);
5530 if (!is_compatible_types(&tmp_type1
, &tmp_type2
)) {
5531 /* gcc-like error if '-' is used */
5533 goto invalid_operands
;
5535 warning("comparison of distinct pointer types lacks a cast");
5539 /* generic gen_op: handles types problems */
5542 int u
, t1
, t2
, bt1
, bt2
, t
;
5545 t1
= vtop
[-1].type
.t
;
5546 t2
= vtop
[0].type
.t
;
5547 bt1
= t1
& VT_BTYPE
;
5548 bt2
= t2
& VT_BTYPE
;
5550 if (bt1
== VT_PTR
|| bt2
== VT_PTR
) {
5551 /* at least one operand is a pointer */
5552 /* relationnal op: must be both pointers */
5553 if (op
>= TOK_ULT
&& op
<= TOK_GT
) {
5554 check_comparison_pointer_types(vtop
- 1, vtop
, op
);
5555 /* pointers are handled are unsigned */
5556 t
= VT_INT
| VT_UNSIGNED
;
5559 /* if both pointers, then it must be the '-' op */
5560 if (bt1
== VT_PTR
&& bt2
== VT_PTR
) {
5562 error("cannot use pointers here");
5563 check_comparison_pointer_types(vtop
- 1, vtop
, op
);
5564 /* XXX: check that types are compatible */
5565 u
= pointed_size(&vtop
[-1].type
);
5567 /* set to integer type */
5568 vtop
->type
.t
= VT_INT
;
5572 /* exactly one pointer : must be '+' or '-'. */
5573 if (op
!= '-' && op
!= '+')
5574 error("cannot use pointers here");
5575 /* Put pointer as first operand */
5576 if (bt2
== VT_PTR
) {
5580 type1
= vtop
[-1].type
;
5581 /* XXX: cast to int ? (long long case) */
5582 vpushi(pointed_size(&vtop
[-1].type
));
5584 #ifdef CONFIG_TCC_BCHECK
5585 /* if evaluating constant expression, no code should be
5586 generated, so no bound check */
5587 if (do_bounds_check
&& !const_wanted
) {
5588 /* if bounded pointers, we generate a special code to
5595 gen_bounded_ptr_add();
5601 /* put again type if gen_opic() swaped operands */
5604 } else if (is_float(bt1
) || is_float(bt2
)) {
5605 /* compute bigger type and do implicit casts */
5606 if (bt1
== VT_LDOUBLE
|| bt2
== VT_LDOUBLE
) {
5608 } else if (bt1
== VT_DOUBLE
|| bt2
== VT_DOUBLE
) {
5613 /* floats can only be used for a few operations */
5614 if (op
!= '+' && op
!= '-' && op
!= '*' && op
!= '/' &&
5615 (op
< TOK_ULT
|| op
> TOK_GT
))
5616 error("invalid operands for binary operation");
5618 } else if (bt1
== VT_LLONG
|| bt2
== VT_LLONG
) {
5619 /* cast to biggest op */
5621 /* convert to unsigned if it does not fit in a long long */
5622 if ((t1
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_LLONG
| VT_UNSIGNED
) ||
5623 (t2
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_LLONG
| VT_UNSIGNED
))
5627 /* integer operations */
5629 /* convert to unsigned if it does not fit in an integer */
5630 if ((t1
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
) ||
5631 (t2
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
))
5634 /* XXX: currently, some unsigned operations are explicit, so
5635 we modify them here */
5636 if (t
& VT_UNSIGNED
) {
5643 else if (op
== TOK_LT
)
5645 else if (op
== TOK_GT
)
5647 else if (op
== TOK_LE
)
5649 else if (op
== TOK_GE
)
5656 /* special case for shifts and long long: we keep the shift as
5658 if (op
== TOK_SHR
|| op
== TOK_SAR
|| op
== TOK_SHL
)
5663 else if ((t
& VT_BTYPE
) == VT_LLONG
)
5667 if (op
>= TOK_ULT
&& op
<= TOK_GT
) {
5668 /* relationnal op: the result is an int */
5669 vtop
->type
.t
= VT_INT
;
5676 /* generic itof for unsigned long long case */
5677 void gen_cvt_itof1(int t
)
5679 if ((vtop
->type
.t
& (VT_BTYPE
| VT_UNSIGNED
)) ==
5680 (VT_LLONG
| VT_UNSIGNED
)) {
5683 vpush_global_sym(&func_old_type
, TOK___ulltof
);
5684 else if (t
== VT_DOUBLE
)
5685 vpush_global_sym(&func_old_type
, TOK___ulltod
);
5687 vpush_global_sym(&func_old_type
, TOK___ulltold
);
5697 /* generic ftoi for unsigned long long case */
5698 void gen_cvt_ftoi1(int t
)
5702 if (t
== (VT_LLONG
| VT_UNSIGNED
)) {
5703 /* not handled natively */
5704 st
= vtop
->type
.t
& VT_BTYPE
;
5706 vpush_global_sym(&func_old_type
, TOK___fixunssfdi
);
5707 else if (st
== VT_DOUBLE
)
5708 vpush_global_sym(&func_old_type
, TOK___fixunsdfdi
);
5710 vpush_global_sym(&func_old_type
, TOK___fixunsxfdi
);
5715 vtop
->r2
= REG_LRET
;
5721 /* force char or short cast */
5722 void force_charshort_cast(int t
)
5726 /* XXX: add optimization if lvalue : just change type and offset */
5731 if (t
& VT_UNSIGNED
) {
5732 vpushi((1 << bits
) - 1);
5743 /* cast 'vtop' to 'type'. Casting to bitfields is forbidden. */
5744 static void gen_cast(CType
*type
)
5746 int sbt
, dbt
, sf
, df
, c
;
5748 /* special delayed cast for char/short */
5749 /* XXX: in some cases (multiple cascaded casts), it may still
5751 if (vtop
->r
& VT_MUSTCAST
) {
5752 vtop
->r
&= ~VT_MUSTCAST
;
5753 force_charshort_cast(vtop
->type
.t
);
5756 /* bitfields first get cast to ints */
5757 if (vtop
->type
.t
& VT_BITFIELD
) {
5761 dbt
= type
->t
& (VT_BTYPE
| VT_UNSIGNED
);
5762 sbt
= vtop
->type
.t
& (VT_BTYPE
| VT_UNSIGNED
);
5764 if (sbt
!= dbt
&& !nocode_wanted
) {
5767 c
= (vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
5769 /* convert from fp to fp */
5771 /* constant case: we can do it now */
5772 /* XXX: in ISOC, cannot do it if error in convert */
5773 if (dbt
== VT_FLOAT
&& sbt
== VT_DOUBLE
)
5774 vtop
->c
.f
= (float)vtop
->c
.d
;
5775 else if (dbt
== VT_FLOAT
&& sbt
== VT_LDOUBLE
)
5776 vtop
->c
.f
= (float)vtop
->c
.ld
;
5777 else if (dbt
== VT_DOUBLE
&& sbt
== VT_FLOAT
)
5778 vtop
->c
.d
= (double)vtop
->c
.f
;
5779 else if (dbt
== VT_DOUBLE
&& sbt
== VT_LDOUBLE
)
5780 vtop
->c
.d
= (double)vtop
->c
.ld
;
5781 else if (dbt
== VT_LDOUBLE
&& sbt
== VT_FLOAT
)
5782 vtop
->c
.ld
= (long double)vtop
->c
.f
;
5783 else if (dbt
== VT_LDOUBLE
&& sbt
== VT_DOUBLE
)
5784 vtop
->c
.ld
= (long double)vtop
->c
.d
;
5786 /* non constant case: generate code */
5790 /* convert int to fp */
5793 case VT_LLONG
| VT_UNSIGNED
:
5795 /* XXX: add const cases for long long */
5797 case VT_INT
| VT_UNSIGNED
:
5799 case VT_FLOAT
: vtop
->c
.f
= (float)vtop
->c
.ui
; break;
5800 case VT_DOUBLE
: vtop
->c
.d
= (double)vtop
->c
.ui
; break;
5801 case VT_LDOUBLE
: vtop
->c
.ld
= (long double)vtop
->c
.ui
; break;
5806 case VT_FLOAT
: vtop
->c
.f
= (float)vtop
->c
.i
; break;
5807 case VT_DOUBLE
: vtop
->c
.d
= (double)vtop
->c
.i
; break;
5808 case VT_LDOUBLE
: vtop
->c
.ld
= (long double)vtop
->c
.i
; break;
5814 #if !defined(TCC_TARGET_ARM)
5821 /* convert fp to int */
5822 /* we handle char/short/etc... with generic code */
5823 if (dbt
!= (VT_INT
| VT_UNSIGNED
) &&
5824 dbt
!= (VT_LLONG
| VT_UNSIGNED
) &&
5829 case VT_LLONG
| VT_UNSIGNED
:
5831 /* XXX: add const cases for long long */
5833 case VT_INT
| VT_UNSIGNED
:
5835 case VT_FLOAT
: vtop
->c
.ui
= (unsigned int)vtop
->c
.d
; break;
5836 case VT_DOUBLE
: vtop
->c
.ui
= (unsigned int)vtop
->c
.d
; break;
5837 case VT_LDOUBLE
: vtop
->c
.ui
= (unsigned int)vtop
->c
.d
; break;
5843 case VT_FLOAT
: vtop
->c
.i
= (int)vtop
->c
.d
; break;
5844 case VT_DOUBLE
: vtop
->c
.i
= (int)vtop
->c
.d
; break;
5845 case VT_LDOUBLE
: vtop
->c
.i
= (int)vtop
->c
.d
; break;
5853 if (dbt
== VT_INT
&& (type
->t
& (VT_BTYPE
| VT_UNSIGNED
)) != dbt
) {
5854 /* additional cast for char/short/bool... */
5858 } else if ((dbt
& VT_BTYPE
) == VT_LLONG
) {
5859 if ((sbt
& VT_BTYPE
) != VT_LLONG
) {
5860 /* scalar to long long */
5862 if (sbt
== (VT_INT
| VT_UNSIGNED
))
5863 vtop
->c
.ll
= vtop
->c
.ui
;
5865 vtop
->c
.ll
= vtop
->c
.i
;
5867 /* machine independent conversion */
5869 /* generate high word */
5870 if (sbt
== (VT_INT
| VT_UNSIGNED
)) {
5878 /* patch second register */
5879 vtop
[-1].r2
= vtop
->r
;
5883 } else if (dbt
== VT_BOOL
) {
5884 /* scalar to bool */
5887 } else if ((dbt
& VT_BTYPE
) == VT_BYTE
||
5888 (dbt
& VT_BTYPE
) == VT_SHORT
) {
5889 force_charshort_cast(dbt
);
5890 } else if ((dbt
& VT_BTYPE
) == VT_INT
) {
5892 if (sbt
== VT_LLONG
) {
5893 /* from long long: just take low order word */
5897 /* if lvalue and single word type, nothing to do because
5898 the lvalue already contains the real type size (see
5899 VT_LVAL_xxx constants) */
5905 /* return type size. Put alignment at 'a' */
5906 static int type_size(CType
*type
, int *a
)
5911 bt
= type
->t
& VT_BTYPE
;
5912 if (bt
== VT_STRUCT
) {
5917 } else if (bt
== VT_PTR
) {
5918 if (type
->t
& VT_ARRAY
) {
5920 return type_size(&s
->type
, a
) * s
->c
;
5925 } else if (bt
== VT_LDOUBLE
) {
5927 return LDOUBLE_SIZE
;
5928 } else if (bt
== VT_DOUBLE
|| bt
== VT_LLONG
) {
5929 #ifdef TCC_TARGET_I386
5935 } else if (bt
== VT_INT
|| bt
== VT_ENUM
|| bt
== VT_FLOAT
) {
5938 } else if (bt
== VT_SHORT
) {
5942 /* char, void, function, _Bool */
5948 /* return the pointed type of t */
5949 static inline CType
*pointed_type(CType
*type
)
5951 return &type
->ref
->type
;
5954 /* modify type so that its it is a pointer to type. */
5955 static void mk_pointer(CType
*type
)
5958 s
= sym_push(SYM_FIELD
, type
, 0, -1);
5959 type
->t
= VT_PTR
| (type
->t
& ~VT_TYPE
);
5963 /* compare function types. OLD functions match any new functions */
5964 static int is_compatible_func(CType
*type1
, CType
*type2
)
5970 if (!is_compatible_types(&s1
->type
, &s2
->type
))
5972 /* check func_call */
5975 /* XXX: not complete */
5976 if (s1
->c
== FUNC_OLD
|| s2
->c
== FUNC_OLD
)
5980 while (s1
!= NULL
) {
5983 if (!is_compatible_types(&s1
->type
, &s2
->type
))
5993 /* return true if type1 and type2 are exactly the same (including
5996 - enums are not checked as gcc __builtin_types_compatible_p ()
5998 static int is_compatible_types(CType
*type1
, CType
*type2
)
6002 t1
= type1
->t
& VT_TYPE
;
6003 t2
= type2
->t
& VT_TYPE
;
6004 /* XXX: bitfields ? */
6007 /* test more complicated cases */
6008 bt1
= t1
& VT_BTYPE
;
6009 if (bt1
== VT_PTR
) {
6010 type1
= pointed_type(type1
);
6011 type2
= pointed_type(type2
);
6012 return is_compatible_types(type1
, type2
);
6013 } else if (bt1
== VT_STRUCT
) {
6014 return (type1
->ref
== type2
->ref
);
6015 } else if (bt1
== VT_FUNC
) {
6016 return is_compatible_func(type1
, type2
);
6022 /* print a type. If 'varstr' is not NULL, then the variable is also
6023 printed in the type */
6025 /* XXX: add array and function pointers */
6026 void type_to_str(char *buf
, int buf_size
,
6027 CType
*type
, const char *varstr
)
6034 t
= type
->t
& VT_TYPE
;
6037 if (t
& VT_CONSTANT
)
6038 pstrcat(buf
, buf_size
, "const ");
6039 if (t
& VT_VOLATILE
)
6040 pstrcat(buf
, buf_size
, "volatile ");
6041 if (t
& VT_UNSIGNED
)
6042 pstrcat(buf
, buf_size
, "unsigned ");
6072 tstr
= "long double";
6074 pstrcat(buf
, buf_size
, tstr
);
6078 if (bt
== VT_STRUCT
)
6082 pstrcat(buf
, buf_size
, tstr
);
6083 v
= type
->ref
->v
& ~SYM_STRUCT
;
6084 if (v
>= SYM_FIRST_ANOM
)
6085 pstrcat(buf
, buf_size
, "<anonymous>");
6087 pstrcat(buf
, buf_size
, get_tok_str(v
, NULL
));
6091 type_to_str(buf
, buf_size
, &s
->type
, varstr
);
6092 pstrcat(buf
, buf_size
, "(");
6094 while (sa
!= NULL
) {
6095 type_to_str(buf1
, sizeof(buf1
), &sa
->type
, NULL
);
6096 pstrcat(buf
, buf_size
, buf1
);
6099 pstrcat(buf
, buf_size
, ", ");
6101 pstrcat(buf
, buf_size
, ")");
6105 pstrcpy(buf1
, sizeof(buf1
), "*");
6107 pstrcat(buf1
, sizeof(buf1
), varstr
);
6108 type_to_str(buf
, buf_size
, &s
->type
, buf1
);
6112 pstrcat(buf
, buf_size
, " ");
6113 pstrcat(buf
, buf_size
, varstr
);
6118 /* verify type compatibility to store vtop in 'dt' type, and generate
6120 static void gen_assign_cast(CType
*dt
)
6122 CType
*st
, *type1
, *type2
, tmp_type1
, tmp_type2
;
6123 char buf1
[256], buf2
[256];
6126 st
= &vtop
->type
; /* source type */
6127 dbt
= dt
->t
& VT_BTYPE
;
6128 sbt
= st
->t
& VT_BTYPE
;
6129 if (dt
->t
& VT_CONSTANT
)
6130 warning("assignment of read-only location");
6133 /* special cases for pointers */
6134 /* '0' can also be a pointer */
6135 if (is_null_pointer(vtop
))
6137 /* accept implicit pointer to integer cast with warning */
6138 if (is_integer_btype(sbt
)) {
6139 warning("assignment makes pointer from integer without a cast");
6142 type1
= pointed_type(dt
);
6143 /* a function is implicitely a function pointer */
6144 if (sbt
== VT_FUNC
) {
6145 if ((type1
->t
& VT_BTYPE
) != VT_VOID
&&
6146 !is_compatible_types(pointed_type(dt
), st
))
6153 type2
= pointed_type(st
);
6154 if ((type1
->t
& VT_BTYPE
) == VT_VOID
||
6155 (type2
->t
& VT_BTYPE
) == VT_VOID
) {
6156 /* void * can match anything */
6158 /* exact type match, except for unsigned */
6161 tmp_type1
.t
&= ~(VT_UNSIGNED
| VT_CONSTANT
| VT_VOLATILE
);
6162 tmp_type2
.t
&= ~(VT_UNSIGNED
| VT_CONSTANT
| VT_VOLATILE
);
6163 if (!is_compatible_types(&tmp_type1
, &tmp_type2
))
6166 /* check const and volatile */
6167 if ((!(type1
->t
& VT_CONSTANT
) && (type2
->t
& VT_CONSTANT
)) ||
6168 (!(type1
->t
& VT_VOLATILE
) && (type2
->t
& VT_VOLATILE
)))
6169 warning("assignment discards qualifiers from pointer target type");
6175 if (sbt
== VT_PTR
|| sbt
== VT_FUNC
) {
6176 warning("assignment makes integer from pointer without a cast");
6178 /* XXX: more tests */
6183 tmp_type1
.t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
6184 tmp_type2
.t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
6185 if (!is_compatible_types(&tmp_type1
, &tmp_type2
)) {
6187 type_to_str(buf1
, sizeof(buf1
), st
, NULL
);
6188 type_to_str(buf2
, sizeof(buf2
), dt
, NULL
);
6189 error("cannot cast '%s' to '%s'", buf1
, buf2
);
6197 /* store vtop in lvalue pushed on stack */
6200 int sbt
, dbt
, ft
, r
, t
, size
, align
, bit_size
, bit_pos
, rc
, delayed_cast
;
6202 ft
= vtop
[-1].type
.t
;
6203 sbt
= vtop
->type
.t
& VT_BTYPE
;
6204 dbt
= ft
& VT_BTYPE
;
6205 if (((sbt
== VT_INT
|| sbt
== VT_SHORT
) && dbt
== VT_BYTE
) ||
6206 (sbt
== VT_INT
&& dbt
== VT_SHORT
)) {
6207 /* optimize char/short casts */
6208 delayed_cast
= VT_MUSTCAST
;
6209 vtop
->type
.t
= ft
& VT_TYPE
;
6210 /* XXX: factorize */
6211 if (ft
& VT_CONSTANT
)
6212 warning("assignment of read-only location");
6215 if (!(ft
& VT_BITFIELD
))
6216 gen_assign_cast(&vtop
[-1].type
);
6219 if (sbt
== VT_STRUCT
) {
6220 /* if structure, only generate pointer */
6221 /* structure assignment : generate memcpy */
6222 /* XXX: optimize if small size */
6223 if (!nocode_wanted
) {
6224 size
= type_size(&vtop
->type
, &align
);
6226 vpush_global_sym(&func_old_type
, TOK_memcpy
);
6230 vtop
->type
.t
= VT_INT
;
6234 vtop
->type
.t
= VT_INT
;
6246 /* leave source on stack */
6247 } else if (ft
& VT_BITFIELD
) {
6248 /* bitfield store handling */
6249 bit_pos
= (ft
>> VT_STRUCT_SHIFT
) & 0x3f;
6250 bit_size
= (ft
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f;
6251 /* remove bit field info to avoid loops */
6252 vtop
[-1].type
.t
= ft
& ~(VT_BITFIELD
| (-1 << VT_STRUCT_SHIFT
));
6254 /* duplicate destination */
6256 vtop
[-1] = vtop
[-2];
6258 /* mask and shift source */
6259 vpushi((1 << bit_size
) - 1);
6263 /* load destination, mask and or with source */
6265 vpushi(~(((1 << bit_size
) - 1) << bit_pos
));
6271 #ifdef CONFIG_TCC_BCHECK
6272 /* bound check case */
6273 if (vtop
[-1].r
& VT_MUSTBOUND
) {
6279 if (!nocode_wanted
) {
6283 r
= gv(rc
); /* generate value */
6284 /* if lvalue was saved on stack, must read it */
6285 if ((vtop
[-1].r
& VT_VALMASK
) == VT_LLOCAL
) {
6287 t
= get_reg(RC_INT
);
6289 sv
.r
= VT_LOCAL
| VT_LVAL
;
6290 sv
.c
.ul
= vtop
[-1].c
.ul
;
6292 vtop
[-1].r
= t
| VT_LVAL
;
6295 /* two word case handling : store second register at word + 4 */
6296 if ((ft
& VT_BTYPE
) == VT_LLONG
) {
6298 /* convert to int to increment easily */
6299 vtop
->type
.t
= VT_INT
;
6305 /* XXX: it works because r2 is spilled last ! */
6306 store(vtop
->r2
, vtop
- 1);
6310 vtop
--; /* NOT vpop() because on x86 it would flush the fp stack */
6311 vtop
->r
|= delayed_cast
;
6315 /* post defines POST/PRE add. c is the token ++ or -- */
6316 void inc(int post
, int c
)
6319 vdup(); /* save lvalue */
6321 gv_dup(); /* duplicate value */
6326 vpushi(c
- TOK_MID
);
6328 vstore(); /* store value */
6330 vpop(); /* if post op, return saved value */
6333 /* Parse GNUC __attribute__ extension. Currently, the following
6334 extensions are recognized:
6335 - aligned(n) : set data/function alignment.
6336 - packed : force data alignment to 1
6337 - section(x) : generate data/code in this section.
6338 - unused : currently ignored, but may be used someday.
6339 - regparm(n) : pass function parameters in registers (i386 only)
6341 static void parse_attribute(AttributeDef
*ad
)
6345 while (tok
== TOK_ATTRIBUTE1
|| tok
== TOK_ATTRIBUTE2
) {
6349 while (tok
!= ')') {
6350 if (tok
< TOK_IDENT
)
6351 expect("attribute name");
6359 expect("section name");
6360 ad
->section
= find_section(tcc_state
, (char *)tokc
.cstr
->data
);
6369 if (n
<= 0 || (n
& (n
- 1)) != 0)
6370 error("alignment must be a positive power of two");
6383 /* currently, no need to handle it because tcc does not
6384 track unused objects */
6388 /* currently, no need to handle it because tcc does not
6389 track unused objects */
6394 ad
->func_call
= FUNC_CDECL
;
6399 ad
->func_call
= FUNC_STDCALL
;
6401 #ifdef TCC_TARGET_I386
6411 ad
->func_call
= FUNC_FASTCALL1
+ n
- 1;
6419 if (tcc_state
->warn_unsupported
)
6420 warning("'%s' attribute ignored", get_tok_str(t
, NULL
));
6421 /* skip parameters */
6422 /* XXX: skip parenthesis too */
6425 while (tok
!= ')' && tok
!= -1)
6440 /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
6441 static void struct_decl(CType
*type
, int u
)
6443 int a
, v
, size
, align
, maxalign
, c
, offset
;
6444 int bit_size
, bit_pos
, bsize
, bt
, lbit_pos
;
6449 a
= tok
; /* save decl type */
6454 /* struct already defined ? return it */
6456 expect("struct/union/enum name");
6460 error("invalid type");
6467 /* we put an undefined size for struct/union */
6468 s
= sym_push(v
| SYM_STRUCT
, &type1
, 0, -1);
6469 s
->r
= 0; /* default alignment is zero as gcc */
6470 /* put struct/union/enum name in type */
6478 error("struct/union/enum already defined");
6479 /* cannot be empty */
6481 /* non empty enums are not allowed */
6482 if (a
== TOK_ENUM
) {
6486 expect("identifier");
6492 /* enum symbols have static storage */
6493 ss
= sym_push(v
, &int_type
, VT_CONST
, c
);
6494 ss
->type
.t
|= VT_STATIC
;
6499 /* NOTE: we accept a trailing comma */
6509 while (tok
!= '}') {
6510 parse_btype(&btype
, &ad
);
6516 type_decl(&type1
, &ad
, &v
, TYPE_DIRECT
);
6517 if ((type1
.t
& VT_BTYPE
) == VT_FUNC
||
6518 (type1
.t
& (VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
| VT_INLINE
)))
6519 error("invalid type for '%s'",
6520 get_tok_str(v
, NULL
));
6524 bit_size
= expr_const();
6525 /* XXX: handle v = 0 case for messages */
6527 error("negative width in bit-field '%s'",
6528 get_tok_str(v
, NULL
));
6529 if (v
&& bit_size
== 0)
6530 error("zero width for bit-field '%s'",
6531 get_tok_str(v
, NULL
));
6533 size
= type_size(&type1
, &align
);
6535 if (align
< ad
.aligned
)
6537 } else if (ad
.packed
) {
6539 } else if (*tcc_state
->pack_stack_ptr
) {
6540 if (align
> *tcc_state
->pack_stack_ptr
)
6541 align
= *tcc_state
->pack_stack_ptr
;
6544 if (bit_size
>= 0) {
6545 bt
= type1
.t
& VT_BTYPE
;
6551 error("bitfields must have scalar type");
6553 if (bit_size
> bsize
) {
6554 error("width of '%s' exceeds its type",
6555 get_tok_str(v
, NULL
));
6556 } else if (bit_size
== bsize
) {
6557 /* no need for bit fields */
6559 } else if (bit_size
== 0) {
6560 /* XXX: what to do if only padding in a
6562 /* zero size: means to pad */
6566 /* we do not have enough room ? */
6567 if ((bit_pos
+ bit_size
) > bsize
)
6570 /* XXX: handle LSB first */
6571 type1
.t
|= VT_BITFIELD
|
6572 (bit_pos
<< VT_STRUCT_SHIFT
) |
6573 (bit_size
<< (VT_STRUCT_SHIFT
+ 6));
6574 bit_pos
+= bit_size
;
6580 /* add new memory data only if starting
6582 if (lbit_pos
== 0) {
6583 if (a
== TOK_STRUCT
) {
6584 c
= (c
+ align
- 1) & -align
;
6592 if (align
> maxalign
)
6596 printf("add field %s offset=%d",
6597 get_tok_str(v
, NULL
), offset
);
6598 if (type1
.t
& VT_BITFIELD
) {
6599 printf(" pos=%d size=%d",
6600 (type1
.t
>> VT_STRUCT_SHIFT
) & 0x3f,
6601 (type1
.t
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f);
6605 ss
= sym_push(v
| SYM_FIELD
, &type1
, 0, offset
);
6609 if (tok
== ';' || tok
== TOK_EOF
)
6616 /* store size and alignment */
6617 s
->c
= (c
+ maxalign
- 1) & -maxalign
;
6623 /* return 0 if no type declaration. otherwise, return the basic type
6626 static int parse_btype(CType
*type
, AttributeDef
*ad
)
6628 int t
, u
, type_found
, typespec_found
;
6632 memset(ad
, 0, sizeof(AttributeDef
));
6639 /* currently, we really ignore extension */
6649 if ((t
& VT_BTYPE
) != 0)
6650 error("too many basic types");
6666 if ((t
& VT_BTYPE
) == VT_DOUBLE
) {
6667 t
= (t
& ~VT_BTYPE
) | VT_LDOUBLE
;
6668 } else if ((t
& VT_BTYPE
) == VT_LONG
) {
6669 t
= (t
& ~VT_BTYPE
) | VT_LLONG
;
6683 if ((t
& VT_BTYPE
) == VT_LONG
) {
6684 t
= (t
& ~VT_BTYPE
) | VT_LDOUBLE
;
6691 struct_decl(&type1
, VT_ENUM
);
6694 type
->ref
= type1
.ref
;
6698 struct_decl(&type1
, VT_STRUCT
);
6701 /* type modifiers */
6754 /* GNUC attribute */
6755 case TOK_ATTRIBUTE1
:
6756 case TOK_ATTRIBUTE2
:
6757 parse_attribute(ad
);
6764 parse_expr_type(&type1
);
6770 if (!s
|| !(s
->type
.t
& VT_TYPEDEF
))
6772 t
|= (s
->type
.t
& ~VT_TYPEDEF
);
6773 type
->ref
= s
->type
.ref
;
6780 if ((t
& (VT_SIGNED
|VT_UNSIGNED
)) == (VT_SIGNED
|VT_UNSIGNED
))
6781 error("signed and unsigned modifier");
6782 if (tcc_state
->char_is_unsigned
) {
6783 if ((t
& (VT_SIGNED
|VT_UNSIGNED
|VT_BTYPE
)) == VT_BYTE
)
6788 /* long is never used as type */
6789 if ((t
& VT_BTYPE
) == VT_LONG
)
6790 t
= (t
& ~VT_BTYPE
) | VT_INT
;
6795 /* convert a function parameter type (array to pointer and function to
6796 function pointer) */
6797 static inline void convert_parameter_type(CType
*pt
)
6799 /* remove const and volatile qualifiers (XXX: const could be used
6800 to indicate a const function parameter */
6801 pt
->t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
6802 /* array must be transformed to pointer according to ANSI C */
6804 if ((pt
->t
& VT_BTYPE
) == VT_FUNC
) {
6809 static void post_type(CType
*type
, AttributeDef
*ad
)
6812 Sym
**plast
, *s
, *first
;
6817 /* function declaration */
6822 while (tok
!= ')') {
6823 /* read param name and compute offset */
6824 if (l
!= FUNC_OLD
) {
6825 if (!parse_btype(&pt
, &ad1
)) {
6827 error("invalid type");
6834 if ((pt
.t
& VT_BTYPE
) == VT_VOID
&& tok
== ')')
6836 type_decl(&pt
, &ad1
, &n
, TYPE_DIRECT
| TYPE_ABSTRACT
);
6837 if ((pt
.t
& VT_BTYPE
) == VT_VOID
)
6838 error("parameter declared as void");
6845 convert_parameter_type(&pt
);
6846 s
= sym_push(n
| SYM_FIELD
, &pt
, 0, 0);
6851 if (l
== FUNC_NEW
&& tok
== TOK_DOTS
) {
6858 /* if no parameters, then old type prototype */
6862 t1
= type
->t
& VT_STORAGE
;
6863 /* NOTE: const is ignored in returned type as it has a special
6864 meaning in gcc / C++ */
6865 type
->t
&= ~(VT_STORAGE
| VT_CONSTANT
);
6866 post_type(type
, ad
);
6867 /* we push a anonymous symbol which will contain the function prototype */
6868 s
= sym_push(SYM_FIELD
, type
, ad
->func_call
, l
);
6870 type
->t
= t1
| VT_FUNC
;
6872 } else if (tok
== '[') {
6873 /* array definition */
6879 error("invalid array size");
6882 /* parse next post type */
6883 t1
= type
->t
& VT_STORAGE
;
6884 type
->t
&= ~VT_STORAGE
;
6885 post_type(type
, ad
);
6887 /* we push a anonymous symbol which will contain the array
6889 s
= sym_push(SYM_FIELD
, type
, 0, n
);
6890 type
->t
= t1
| VT_ARRAY
| VT_PTR
;
6895 /* Parse a type declaration (except basic type), and return the type
6896 in 'type'. 'td' is a bitmask indicating which kind of type decl is
6897 expected. 'type' should contain the basic type. 'ad' is the
6898 attribute definition of the basic type. It can be modified by
6901 static void type_decl(CType
*type
, AttributeDef
*ad
, int *v
, int td
)
6904 CType type1
, *type2
;
6907 while (tok
== '*') {
6915 qualifiers
|= VT_CONSTANT
;
6920 qualifiers
|= VT_VOLATILE
;
6928 type
->t
|= qualifiers
;
6931 /* XXX: clarify attribute handling */
6932 if (tok
== TOK_ATTRIBUTE1
|| tok
== TOK_ATTRIBUTE2
)
6933 parse_attribute(ad
);
6935 /* recursive type */
6936 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
6937 type1
.t
= 0; /* XXX: same as int */
6940 /* XXX: this is not correct to modify 'ad' at this point, but
6941 the syntax is not clear */
6942 if (tok
== TOK_ATTRIBUTE1
|| tok
== TOK_ATTRIBUTE2
)
6943 parse_attribute(ad
);
6944 type_decl(&type1
, ad
, v
, td
);
6947 /* type identifier */
6948 if (tok
>= TOK_IDENT
&& (td
& TYPE_DIRECT
)) {
6952 if (!(td
& TYPE_ABSTRACT
))
6953 expect("identifier");
6957 post_type(type
, ad
);
6958 if (tok
== TOK_ATTRIBUTE1
|| tok
== TOK_ATTRIBUTE2
)
6959 parse_attribute(ad
);
6962 /* append type at the end of type1 */
6975 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
6976 static int lvalue_type(int t
)
6981 if (bt
== VT_BYTE
|| bt
== VT_BOOL
)
6983 else if (bt
== VT_SHORT
)
6987 if (t
& VT_UNSIGNED
)
6988 r
|= VT_LVAL_UNSIGNED
;
6992 /* indirection with full error checking and bound check */
6993 static void indir(void)
6995 if ((vtop
->type
.t
& VT_BTYPE
) != VT_PTR
)
6997 if ((vtop
->r
& VT_LVAL
) && !nocode_wanted
)
6999 vtop
->type
= *pointed_type(&vtop
->type
);
7000 /* an array is never an lvalue */
7001 if (!(vtop
->type
.t
& VT_ARRAY
)) {
7002 vtop
->r
|= lvalue_type(vtop
->type
.t
);
7003 /* if bound checking, the referenced pointer must be checked */
7004 if (do_bounds_check
)
7005 vtop
->r
|= VT_MUSTBOUND
;
7009 /* pass a parameter to a function and do type checking and casting */
7010 static void gfunc_param_typed(Sym
*func
, Sym
*arg
)
7015 func_type
= func
->c
;
7016 if (func_type
== FUNC_OLD
||
7017 (func_type
== FUNC_ELLIPSIS
&& arg
== NULL
)) {
7018 /* default casting : only need to convert float to double */
7019 if ((vtop
->type
.t
& VT_BTYPE
) == VT_FLOAT
) {
7023 } else if (arg
== NULL
) {
7024 error("too many arguments to function");
7027 type
.t
&= ~VT_CONSTANT
; /* need to do that to avoid false warning */
7028 gen_assign_cast(&type
);
7032 /* parse an expression of the form '(type)' or '(expr)' and return its
7034 static void parse_expr_type(CType
*type
)
7040 if (parse_btype(type
, &ad
)) {
7041 type_decl(type
, &ad
, &n
, TYPE_ABSTRACT
);
7048 static void parse_type(CType
*type
)
7053 if (!parse_btype(type
, &ad
)) {
7056 type_decl(type
, &ad
, &n
, TYPE_ABSTRACT
);
7059 static void vpush_tokc(int t
)
7063 vsetc(&type
, VT_CONST
, &tokc
);
7066 static void unary(void)
7068 int n
, t
, align
, size
, r
;
7073 /* XXX: GCC 2.95.3 does not generate a table although it should be
7087 vpush_tokc(VT_INT
| VT_UNSIGNED
);
7091 vpush_tokc(VT_LLONG
);
7095 vpush_tokc(VT_LLONG
| VT_UNSIGNED
);
7099 vpush_tokc(VT_FLOAT
);
7103 vpush_tokc(VT_DOUBLE
);
7107 vpush_tokc(VT_LDOUBLE
);
7110 case TOK___FUNCTION__
:
7112 goto tok_identifier
;
7118 /* special function name identifier */
7119 len
= strlen(funcname
) + 1;
7120 /* generate char[len] type */
7125 vpush_ref(&type
, data_section
, data_section
->data_offset
, len
);
7126 ptr
= section_ptr_add(data_section
, len
);
7127 memcpy(ptr
, funcname
, len
);
7135 /* string parsing */
7138 if (tcc_state
->warn_write_strings
)
7143 memset(&ad
, 0, sizeof(AttributeDef
));
7144 decl_initializer_alloc(&type
, &ad
, VT_CONST
, 2, 0, 0);
7149 if (parse_btype(&type
, &ad
)) {
7150 type_decl(&type
, &ad
, &n
, TYPE_ABSTRACT
);
7152 /* check ISOC99 compound literal */
7154 /* data is allocated locally by default */
7159 /* all except arrays are lvalues */
7160 if (!(type
.t
& VT_ARRAY
))
7161 r
|= lvalue_type(type
.t
);
7162 memset(&ad
, 0, sizeof(AttributeDef
));
7163 decl_initializer_alloc(&type
, &ad
, r
, 1, 0, 0);
7168 } else if (tok
== '{') {
7169 /* save all registers */
7171 /* statement expression : we do not accept break/continue
7172 inside as GCC does */
7173 block(NULL
, NULL
, NULL
, NULL
, 0, 1);
7188 /* functions names must be treated as function pointers,
7189 except for unary '&' and sizeof. Since we consider that
7190 functions are not lvalues, we only have to handle it
7191 there and in function calls. */
7192 /* arrays can also be used although they are not lvalues */
7193 if ((vtop
->type
.t
& VT_BTYPE
) != VT_FUNC
&&
7194 !(vtop
->type
.t
& VT_ARRAY
))
7196 mk_pointer(&vtop
->type
);
7202 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
)
7203 vtop
->c
.i
= !vtop
->c
.i
;
7204 else if ((vtop
->r
& VT_VALMASK
) == VT_CMP
)
7205 vtop
->c
.i
= vtop
->c
.i
^ 1;
7207 vseti(VT_JMP
, gtst(1, 0));
7217 /* in order to force cast, we add zero */
7219 if ((vtop
->type
.t
& VT_BTYPE
) == VT_PTR
)
7220 error("pointer not accepted for unary plus");
7230 parse_expr_type(&type
);
7234 size
= type_size(&type
, &align
);
7235 if (t
== TOK_SIZEOF
) {
7237 error("sizeof applied to an incomplete type");
7244 case TOK_builtin_types_compatible_p
:
7253 type1
.t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
7254 type2
.t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
7255 vpushi(is_compatible_types(&type1
, &type2
));
7258 case TOK_builtin_constant_p
:
7260 int saved_nocode_wanted
, res
;
7263 saved_nocode_wanted
= nocode_wanted
;
7266 res
= (vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
7268 nocode_wanted
= saved_nocode_wanted
;
7288 goto tok_identifier
;
7290 /* allow to take the address of a label */
7291 if (tok
< TOK_UIDENT
)
7292 expect("label identifier");
7293 s
= label_find(tok
);
7295 s
= label_push(&global_label_stack
, tok
, LABEL_FORWARD
);
7297 if (s
->r
== LABEL_DECLARED
)
7298 s
->r
= LABEL_FORWARD
;
7301 s
->type
.t
= VT_VOID
;
7302 mk_pointer(&s
->type
);
7303 s
->type
.t
|= VT_STATIC
;
7305 vset(&s
->type
, VT_CONST
| VT_SYM
, 0);
7314 expect("identifier");
7318 error("'%s' undeclared", get_tok_str(t
, NULL
));
7319 /* for simple function calls, we tolerate undeclared
7320 external reference to int() function */
7321 if (tcc_state
->warn_implicit_function_declaration
)
7322 warning("implicit declaration of function '%s'",
7323 get_tok_str(t
, NULL
));
7324 s
= external_global_sym(t
, &func_old_type
, 0);
7326 if ((s
->type
.t
& (VT_STATIC
| VT_INLINE
| VT_BTYPE
)) ==
7327 (VT_STATIC
| VT_INLINE
| VT_FUNC
)) {
7328 /* if referencing an inline function, then we generate a
7329 symbol to it if not already done. It will have the
7330 effect to generate code for it at the end of the
7331 compilation unit. Inline function as always
7332 generated in the text section. */
7334 put_extern_sym(s
, text_section
, 0, 0);
7335 r
= VT_SYM
| VT_CONST
;
7339 vset(&s
->type
, r
, s
->c
);
7340 /* if forward reference, we must point to s */
7341 if (vtop
->r
& VT_SYM
) {
7348 /* post operations */
7350 if (tok
== TOK_INC
|| tok
== TOK_DEC
) {
7353 } else if (tok
== '.' || tok
== TOK_ARROW
) {
7355 if (tok
== TOK_ARROW
)
7360 /* expect pointer on structure */
7361 if ((vtop
->type
.t
& VT_BTYPE
) != VT_STRUCT
)
7362 expect("struct or union");
7366 while ((s
= s
->next
) != NULL
) {
7371 error("field not found");
7372 /* add field offset to pointer */
7373 vtop
->type
= char_pointer_type
; /* change type to 'char *' */
7376 /* change type to field type, and set to lvalue */
7377 vtop
->type
= s
->type
;
7378 /* an array is never an lvalue */
7379 if (!(vtop
->type
.t
& VT_ARRAY
)) {
7380 vtop
->r
|= lvalue_type(vtop
->type
.t
);
7381 /* if bound checking, the referenced pointer must be checked */
7382 if (do_bounds_check
)
7383 vtop
->r
|= VT_MUSTBOUND
;
7386 } else if (tok
== '[') {
7392 } else if (tok
== '(') {
7398 if ((vtop
->type
.t
& VT_BTYPE
) != VT_FUNC
) {
7399 /* pointer test (no array accepted) */
7400 if ((vtop
->type
.t
& (VT_BTYPE
| VT_ARRAY
)) == VT_PTR
) {
7401 vtop
->type
= *pointed_type(&vtop
->type
);
7402 if ((vtop
->type
.t
& VT_BTYPE
) != VT_FUNC
)
7406 expect("function pointer");
7409 vtop
->r
&= ~VT_LVAL
; /* no lvalue */
7411 /* get return type */
7414 sa
= s
->next
; /* first parameter */
7416 /* compute first implicit argument if a structure is returned */
7417 if ((s
->type
.t
& VT_BTYPE
) == VT_STRUCT
) {
7418 /* get some space for the returned structure */
7419 size
= type_size(&s
->type
, &align
);
7420 loc
= (loc
- size
) & -align
;
7422 ret
.r
= VT_LOCAL
| VT_LVAL
;
7423 /* pass it as 'int' to avoid structure arg passing
7425 vseti(VT_LOCAL
, loc
);
7431 /* return in register */
7432 if (is_float(ret
.type
.t
)) {
7435 if ((ret
.type
.t
& VT_BTYPE
) == VT_LLONG
)
7444 gfunc_param_typed(s
, sa
);
7454 error("too few arguments to function");
7456 if (!nocode_wanted
) {
7457 gfunc_call(nb_args
);
7459 vtop
-= (nb_args
+ 1);
7462 vsetc(&ret
.type
, ret
.r
, &ret
.c
);
7470 static void uneq(void)
7476 (tok
>= TOK_A_MOD
&& tok
<= TOK_A_DIV
) ||
7477 tok
== TOK_A_XOR
|| tok
== TOK_A_OR
||
7478 tok
== TOK_A_SHL
|| tok
== TOK_A_SAR
) {
7493 static void expr_prod(void)
7498 while (tok
== '*' || tok
== '/' || tok
== '%') {
7506 static void expr_sum(void)
7511 while (tok
== '+' || tok
== '-') {
7519 static void expr_shift(void)
7524 while (tok
== TOK_SHL
|| tok
== TOK_SAR
) {
7532 static void expr_cmp(void)
7537 while ((tok
>= TOK_ULE
&& tok
<= TOK_GT
) ||
7538 tok
== TOK_ULT
|| tok
== TOK_UGE
) {
7546 static void expr_cmpeq(void)
7551 while (tok
== TOK_EQ
|| tok
== TOK_NE
) {
7559 static void expr_and(void)
7562 while (tok
== '&') {
7569 static void expr_xor(void)
7572 while (tok
== '^') {
7579 static void expr_or(void)
7582 while (tok
== '|') {
7589 /* XXX: fix this mess */
7590 static void expr_land_const(void)
7593 while (tok
== TOK_LAND
) {
7600 /* XXX: fix this mess */
7601 static void expr_lor_const(void)
7604 while (tok
== TOK_LOR
) {
7611 /* only used if non constant */
7612 static void expr_land(void)
7617 if (tok
== TOK_LAND
) {
7621 if (tok
!= TOK_LAND
) {
7631 static void expr_lor(void)
7636 if (tok
== TOK_LOR
) {
7640 if (tok
!= TOK_LOR
) {
7650 /* XXX: better constant handling */
7651 static void expr_eq(void)
7653 int tt
, u
, r1
, r2
, rc
, t1
, t2
, bt1
, bt2
;
7655 CType type
, type1
, type2
;
7664 if (tok
== ':' && gnu_ext
) {
7680 if (vtop
!= vstack
) {
7681 /* needed to avoid having different registers saved in
7683 if (is_float(vtop
->type
.t
))
7690 if (tok
== ':' && gnu_ext
) {
7698 sv
= *vtop
; /* save value to handle it later */
7699 vtop
--; /* no vpop so that FP stack is not flushed */
7707 bt1
= t1
& VT_BTYPE
;
7709 bt2
= t2
& VT_BTYPE
;
7710 /* cast operands to correct type according to ISOC rules */
7711 if (is_float(bt1
) || is_float(bt2
)) {
7712 if (bt1
== VT_LDOUBLE
|| bt2
== VT_LDOUBLE
) {
7713 type
.t
= VT_LDOUBLE
;
7714 } else if (bt1
== VT_DOUBLE
|| bt2
== VT_DOUBLE
) {
7719 } else if (bt1
== VT_LLONG
|| bt2
== VT_LLONG
) {
7720 /* cast to biggest op */
7722 /* convert to unsigned if it does not fit in a long long */
7723 if ((t1
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_LLONG
| VT_UNSIGNED
) ||
7724 (t2
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_LLONG
| VT_UNSIGNED
))
7725 type
.t
|= VT_UNSIGNED
;
7726 } else if (bt1
== VT_PTR
|| bt2
== VT_PTR
) {
7727 /* XXX: test pointer compatibility */
7729 } else if (bt1
== VT_STRUCT
|| bt2
== VT_STRUCT
) {
7730 /* XXX: test structure compatibility */
7732 } else if (bt1
== VT_VOID
|| bt2
== VT_VOID
) {
7733 /* NOTE: as an extension, we accept void on only one side */
7736 /* integer operations */
7738 /* convert to unsigned if it does not fit in an integer */
7739 if ((t1
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
) ||
7740 (t2
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
))
7741 type
.t
|= VT_UNSIGNED
;
7744 /* now we convert second operand */
7747 if (is_float(type
.t
)) {
7749 } else if ((type
.t
& VT_BTYPE
) == VT_LLONG
) {
7750 /* for long longs, we use fixed registers to avoid having
7751 to handle a complicated move */
7756 /* this is horrible, but we must also convert first
7760 /* put again first value and cast it */
7771 static void gexpr(void)
7782 /* parse an expression and return its type without any side effect. */
7783 static void expr_type(CType
*type
)
7785 int saved_nocode_wanted
;
7787 saved_nocode_wanted
= nocode_wanted
;
7792 nocode_wanted
= saved_nocode_wanted
;
7795 /* parse a unary expression and return its type without any side
7797 static void unary_type(CType
*type
)
7809 /* parse a constant expression and return value in vtop. */
7810 static void expr_const1(void)
7819 /* parse an integer constant and return its value. */
7820 static int expr_const(void)
7824 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) != VT_CONST
)
7825 expect("constant expression");
7831 /* return the label token if current token is a label, otherwise
7833 static int is_label(void)
7837 /* fast test first */
7838 if (tok
< TOK_UIDENT
)
7840 /* no need to save tokc because tok is an identifier */
7847 unget_tok(last_tok
);
7852 static void block(int *bsym
, int *csym
, int *case_sym
, int *def_sym
,
7853 int case_reg
, int is_expr
)
7858 /* generate line number info */
7860 (last_line_num
!= file
->line_num
|| last_ind
!= ind
)) {
7861 put_stabn(N_SLINE
, 0, file
->line_num
, ind
- func_ind
);
7863 last_line_num
= file
->line_num
;
7867 /* default return value is (void) */
7869 vtop
->type
.t
= VT_VOID
;
7872 if (tok
== TOK_IF
) {
7879 block(bsym
, csym
, case_sym
, def_sym
, case_reg
, 0);
7881 if (c
== TOK_ELSE
) {
7885 block(bsym
, csym
, case_sym
, def_sym
, case_reg
, 0);
7886 gsym(d
); /* patch else jmp */
7889 } else if (tok
== TOK_WHILE
) {
7897 block(&a
, &b
, case_sym
, def_sym
, case_reg
, 0);
7901 } else if (tok
== '{') {
7905 /* record local declaration stack position */
7907 llabel
= local_label_stack
;
7908 /* handle local labels declarations */
7909 if (tok
== TOK_LABEL
) {
7912 if (tok
< TOK_UIDENT
)
7913 expect("label identifier");
7914 label_push(&local_label_stack
, tok
, LABEL_DECLARED
);
7924 while (tok
!= '}') {
7929 block(bsym
, csym
, case_sym
, def_sym
, case_reg
, is_expr
);
7932 /* pop locally defined labels */
7933 label_pop(&local_label_stack
, llabel
);
7934 /* pop locally defined symbols */
7935 sym_pop(&local_stack
, s
);
7937 } else if (tok
== TOK_RETURN
) {
7941 gen_assign_cast(&func_vt
);
7942 if ((func_vt
.t
& VT_BTYPE
) == VT_STRUCT
) {
7944 /* if returning structure, must copy it to implicit
7945 first pointer arg location */
7948 vset(&type
, VT_LOCAL
| VT_LVAL
, func_vc
);
7951 /* copy structure value to pointer */
7953 } else if (is_float(func_vt
.t
)) {
7958 vtop
--; /* NOT vpop() because on x86 it would flush the fp stack */
7961 rsym
= gjmp(rsym
); /* jmp */
7962 } else if (tok
== TOK_BREAK
) {
7965 error("cannot break");
7966 *bsym
= gjmp(*bsym
);
7969 } else if (tok
== TOK_CONTINUE
) {
7972 error("cannot continue");
7973 *csym
= gjmp(*csym
);
7976 } else if (tok
== TOK_FOR
) {
8003 block(&a
, &b
, case_sym
, def_sym
, case_reg
, 0);
8008 if (tok
== TOK_DO
) {
8013 block(&a
, &b
, case_sym
, def_sym
, case_reg
, 0);
8024 if (tok
== TOK_SWITCH
) {
8028 /* XXX: other types than integer */
8029 case_reg
= gv(RC_INT
);
8033 b
= gjmp(0); /* jump to first case */
8035 block(&a
, csym
, &b
, &c
, case_reg
, 0);
8036 /* if no default, jmp after switch */
8044 if (tok
== TOK_CASE
) {
8051 if (gnu_ext
&& tok
== TOK_DOTS
) {
8055 warning("empty case range");
8057 /* since a case is like a label, we must skip it with a jmp */
8064 *case_sym
= gtst(1, 0);
8067 *case_sym
= gtst(1, 0);
8071 *case_sym
= gtst(1, *case_sym
);
8076 goto block_after_label
;
8078 if (tok
== TOK_DEFAULT
) {
8084 error("too many 'default'");
8087 goto block_after_label
;
8089 if (tok
== TOK_GOTO
) {
8091 if (tok
== '*' && gnu_ext
) {
8095 if ((vtop
->type
.t
& VT_BTYPE
) != VT_PTR
)
8098 } else if (tok
>= TOK_UIDENT
) {
8099 s
= label_find(tok
);
8100 /* put forward definition if needed */
8102 s
= label_push(&global_label_stack
, tok
, LABEL_FORWARD
);
8104 if (s
->r
== LABEL_DECLARED
)
8105 s
->r
= LABEL_FORWARD
;
8107 /* label already defined */
8108 if (s
->r
& LABEL_FORWARD
)
8109 s
->next
= (void *)gjmp((long)s
->next
);
8111 gjmp_addr((long)s
->next
);
8114 expect("label identifier");
8117 } else if (tok
== TOK_ASM1
|| tok
== TOK_ASM2
|| tok
== TOK_ASM3
) {
8125 if (s
->r
== LABEL_DEFINED
)
8126 error("duplicate label '%s'", get_tok_str(s
->v
, NULL
));
8127 gsym((long)s
->next
);
8128 s
->r
= LABEL_DEFINED
;
8130 s
= label_push(&global_label_stack
, b
, LABEL_DEFINED
);
8132 s
->next
= (void *)ind
;
8133 /* we accept this, but it is a mistake */
8136 warning("deprecated use of label at end of compound statement");
8140 block(bsym
, csym
, case_sym
, def_sym
, case_reg
, is_expr
);
8143 /* expression case */
8158 /* t is the array or struct type. c is the array or struct
8159 address. cur_index/cur_field is the pointer to the current
8160 value. 'size_only' is true if only size info is needed (only used
8162 static void decl_designator(CType
*type
, Section
*sec
, unsigned long c
,
8163 int *cur_index
, Sym
**cur_field
,
8167 int notfirst
, index
, index_last
, align
, l
, nb_elems
, elem_size
;
8173 if (gnu_ext
&& (l
= is_label()) != 0)
8175 while (tok
== '[' || tok
== '.') {
8177 if (!(type
->t
& VT_ARRAY
))
8178 expect("array type");
8181 index
= expr_const();
8182 if (index
< 0 || (s
->c
>= 0 && index
>= s
->c
))
8183 expect("invalid index");
8184 if (tok
== TOK_DOTS
&& gnu_ext
) {
8186 index_last
= expr_const();
8187 if (index_last
< 0 ||
8188 (s
->c
>= 0 && index_last
>= s
->c
) ||
8190 expect("invalid index");
8196 *cur_index
= index_last
;
8197 type
= pointed_type(type
);
8198 elem_size
= type_size(type
, &align
);
8199 c
+= index
* elem_size
;
8200 /* NOTE: we only support ranges for last designator */
8201 nb_elems
= index_last
- index
+ 1;
8202 if (nb_elems
!= 1) {
8211 if ((type
->t
& VT_BTYPE
) != VT_STRUCT
)
8212 expect("struct/union type");
8225 /* XXX: fix this mess by using explicit storage field */
8227 type1
.t
|= (type
->t
& ~VT_TYPE
);
8241 if (type
->t
& VT_ARRAY
) {
8243 type
= pointed_type(type
);
8244 c
+= index
* type_size(type
, &align
);
8248 error("too many field init");
8249 /* XXX: fix this mess by using explicit storage field */
8251 type1
.t
|= (type
->t
& ~VT_TYPE
);
8256 decl_initializer(type
, sec
, c
, 0, size_only
);
8258 /* XXX: make it more general */
8259 if (!size_only
&& nb_elems
> 1) {
8260 unsigned long c_end
;
8265 error("range init not supported yet for dynamic storage");
8266 c_end
= c
+ nb_elems
* elem_size
;
8267 if (c_end
> sec
->data_allocated
)
8268 section_realloc(sec
, c_end
);
8269 src
= sec
->data
+ c
;
8271 for(i
= 1; i
< nb_elems
; i
++) {
8273 memcpy(dst
, src
, elem_size
);
8279 #define EXPR_CONST 1
8282 /* store a value or an expression directly in global data or in local array */
8283 static void init_putv(CType
*type
, Section
*sec
, unsigned long c
,
8284 int v
, int expr_type
)
8286 int saved_global_expr
, bt
, bit_pos
, bit_size
;
8288 unsigned long long bit_mask
;
8296 /* compound literals must be allocated globally in this case */
8297 saved_global_expr
= global_expr
;
8300 global_expr
= saved_global_expr
;
8301 /* NOTE: symbols are accepted */
8302 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
)) != VT_CONST
)
8303 error("initializer element is not constant");
8311 dtype
.t
&= ~VT_CONSTANT
; /* need to do that to avoid false warning */
8314 /* XXX: not portable */
8315 /* XXX: generate error if incorrect relocation */
8316 gen_assign_cast(&dtype
);
8317 bt
= type
->t
& VT_BTYPE
;
8318 ptr
= sec
->data
+ c
;
8319 /* XXX: make code faster ? */
8320 if (!(type
->t
& VT_BITFIELD
)) {
8325 bit_pos
= (vtop
->type
.t
>> VT_STRUCT_SHIFT
) & 0x3f;
8326 bit_size
= (vtop
->type
.t
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f;
8327 bit_mask
= (1LL << bit_size
) - 1;
8329 if ((vtop
->r
& VT_SYM
) &&
8335 (bt
== VT_INT
&& bit_size
!= 32)))
8336 error("initializer element is not computable at load time");
8339 *(char *)ptr
|= (vtop
->c
.i
& bit_mask
) << bit_pos
;
8342 *(short *)ptr
|= (vtop
->c
.i
& bit_mask
) << bit_pos
;
8345 *(double *)ptr
= vtop
->c
.d
;
8348 *(long double *)ptr
= vtop
->c
.ld
;
8351 *(long long *)ptr
|= (vtop
->c
.ll
& bit_mask
) << bit_pos
;
8354 if (vtop
->r
& VT_SYM
) {
8355 greloc(sec
, vtop
->sym
, c
, R_DATA_32
);
8357 *(int *)ptr
|= (vtop
->c
.i
& bit_mask
) << bit_pos
;
8362 vset(&dtype
, VT_LOCAL
, c
);
8369 /* put zeros for variable based init */
8370 static void init_putz(CType
*t
, Section
*sec
, unsigned long c
, int size
)
8373 /* nothing to do because globals are already set to zero */
8375 vpush_global_sym(&func_old_type
, TOK_memset
);
8383 /* 't' contains the type and storage info. 'c' is the offset of the
8384 object in section 'sec'. If 'sec' is NULL, it means stack based
8385 allocation. 'first' is true if array '{' must be read (multi
8386 dimension implicit array init handling). 'size_only' is true if
8387 size only evaluation is wanted (only for arrays). */
8388 static void decl_initializer(CType
*type
, Section
*sec
, unsigned long c
,
8389 int first
, int size_only
)
8391 int index
, array_length
, n
, no_oblock
, nb
, parlevel
, i
;
8392 int size1
, align1
, expr_type
;
8396 if (type
->t
& VT_ARRAY
) {
8400 t1
= pointed_type(type
);
8401 size1
= type_size(t1
, &align1
);
8404 if ((first
&& tok
!= TOK_LSTR
&& tok
!= TOK_STR
) ||
8410 /* only parse strings here if correct type (otherwise: handle
8411 them as ((w)char *) expressions */
8412 if ((tok
== TOK_LSTR
&&
8413 (t1
->t
& VT_BTYPE
) == VT_INT
) ||
8415 (t1
->t
& VT_BTYPE
) == VT_BYTE
)) {
8416 while (tok
== TOK_STR
|| tok
== TOK_LSTR
) {
8421 /* compute maximum number of chars wanted */
8423 cstr_len
= cstr
->size
;
8425 cstr_len
= cstr
->size
/ sizeof(int);
8428 if (n
>= 0 && nb
> (n
- array_length
))
8429 nb
= n
- array_length
;
8432 warning("initializer-string for array is too long");
8433 /* in order to go faster for common case (char
8434 string in global variable, we handle it
8436 if (sec
&& tok
== TOK_STR
&& size1
== 1) {
8437 memcpy(sec
->data
+ c
+ array_length
, cstr
->data
, nb
);
8441 ch
= ((unsigned char *)cstr
->data
)[i
];
8443 ch
= ((int *)cstr
->data
)[i
];
8444 init_putv(t1
, sec
, c
+ (array_length
+ i
) * size1
,
8452 /* only add trailing zero if enough storage (no
8453 warning in this case since it is standard) */
8454 if (n
< 0 || array_length
< n
) {
8456 init_putv(t1
, sec
, c
+ (array_length
* size1
), 0, EXPR_VAL
);
8462 while (tok
!= '}') {
8463 decl_designator(type
, sec
, c
, &index
, NULL
, size_only
);
8464 if (n
>= 0 && index
>= n
)
8465 error("index too large");
8466 /* must put zero in holes (note that doing it that way
8467 ensures that it even works with designators) */
8468 if (!size_only
&& array_length
< index
) {
8469 init_putz(t1
, sec
, c
+ array_length
* size1
,
8470 (index
- array_length
) * size1
);
8473 if (index
> array_length
)
8474 array_length
= index
;
8475 /* special test for multi dimensional arrays (may not
8476 be strictly correct if designators are used at the
8478 if (index
>= n
&& no_oblock
)
8487 /* put zeros at the end */
8488 if (!size_only
&& n
>= 0 && array_length
< n
) {
8489 init_putz(t1
, sec
, c
+ array_length
* size1
,
8490 (n
- array_length
) * size1
);
8492 /* patch type size if needed */
8494 s
->c
= array_length
;
8495 } else if ((type
->t
& VT_BTYPE
) == VT_STRUCT
&&
8496 (sec
|| !first
|| tok
== '{')) {
8499 /* NOTE: the previous test is a specific case for automatic
8500 struct/union init */
8501 /* XXX: union needs only one init */
8503 /* XXX: this test is incorrect for local initializers
8504 beginning with ( without {. It would be much more difficult
8505 to do it correctly (ideally, the expression parser should
8506 be used in all cases) */
8512 while (tok
== '(') {
8516 if (!parse_btype(&type1
, &ad1
))
8518 type_decl(&type1
, &ad1
, &n
, TYPE_ABSTRACT
);
8520 if (!is_assignable_types(type
, &type1
))
8521 error("invalid type for cast");
8526 if (first
|| tok
== '{') {
8535 while (tok
!= '}') {
8536 decl_designator(type
, sec
, c
, NULL
, &f
, size_only
);
8538 if (!size_only
&& array_length
< index
) {
8539 init_putz(type
, sec
, c
+ array_length
,
8540 index
- array_length
);
8542 index
= index
+ type_size(&f
->type
, &align1
);
8543 if (index
> array_length
)
8544 array_length
= index
;
8546 if (no_oblock
&& f
== NULL
)
8552 /* put zeros at the end */
8553 if (!size_only
&& array_length
< n
) {
8554 init_putz(type
, sec
, c
+ array_length
,
8563 } else if (tok
== '{') {
8565 decl_initializer(type
, sec
, c
, first
, size_only
);
8567 } else if (size_only
) {
8568 /* just skip expression */
8570 while ((parlevel
> 0 || (tok
!= '}' && tok
!= ',')) &&
8574 else if (tok
== ')')
8579 /* currently, we always use constant expression for globals
8580 (may change for scripting case) */
8581 expr_type
= EXPR_CONST
;
8583 expr_type
= EXPR_ANY
;
8584 init_putv(type
, sec
, c
, 0, expr_type
);
8588 /* parse an initializer for type 't' if 'has_init' is non zero, and
8589 allocate space in local or global data space ('r' is either
8590 VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
8591 variable 'v' of scope 'scope' is declared before initializers are
8592 parsed. If 'v' is zero, then a reference to the new object is put
8593 in the value stack. If 'has_init' is 2, a special parsing is done
8594 to handle string constants. */
8595 static void decl_initializer_alloc(CType
*type
, AttributeDef
*ad
, int r
,
8596 int has_init
, int v
, int scope
)
8598 int size
, align
, addr
, data_offset
;
8600 ParseState saved_parse_state
;
8601 TokenString init_str
;
8604 size
= type_size(type
, &align
);
8605 /* If unknown size, we must evaluate it before
8606 evaluating initializers because
8607 initializers can generate global data too
8608 (e.g. string pointers or ISOC99 compound
8609 literals). It also simplifies local
8610 initializers handling */
8611 tok_str_new(&init_str
);
8614 error("unknown type size");
8615 /* get all init string */
8616 if (has_init
== 2) {
8617 /* only get strings */
8618 while (tok
== TOK_STR
|| tok
== TOK_LSTR
) {
8619 tok_str_add_tok(&init_str
);
8624 while (level
> 0 || (tok
!= ',' && tok
!= ';')) {
8626 error("unexpected end of file in initializer");
8627 tok_str_add_tok(&init_str
);
8630 else if (tok
== '}') {
8638 tok_str_add(&init_str
, -1);
8639 tok_str_add(&init_str
, 0);
8642 save_parse_state(&saved_parse_state
);
8644 macro_ptr
= init_str
.str
;
8646 decl_initializer(type
, NULL
, 0, 1, 1);
8647 /* prepare second initializer parsing */
8648 macro_ptr
= init_str
.str
;
8651 /* if still unknown size, error */
8652 size
= type_size(type
, &align
);
8654 error("unknown type size");
8656 /* take into account specified alignment if bigger */
8658 if (ad
->aligned
> align
)
8659 align
= ad
->aligned
;
8660 } else if (ad
->packed
) {
8663 if ((r
& VT_VALMASK
) == VT_LOCAL
) {
8665 if (do_bounds_check
&& (type
->t
& VT_ARRAY
))
8667 loc
= (loc
- size
) & -align
;
8669 /* handles bounds */
8670 /* XXX: currently, since we do only one pass, we cannot track
8671 '&' operators, so we add only arrays */
8672 if (do_bounds_check
&& (type
->t
& VT_ARRAY
)) {
8673 unsigned long *bounds_ptr
;
8674 /* add padding between regions */
8676 /* then add local bound info */
8677 bounds_ptr
= section_ptr_add(lbounds_section
, 2 * sizeof(unsigned long));
8678 bounds_ptr
[0] = addr
;
8679 bounds_ptr
[1] = size
;
8682 /* local variable */
8683 sym_push(v
, type
, r
, addr
);
8685 /* push local reference */
8686 vset(type
, r
, addr
);
8692 if (v
&& scope
== VT_CONST
) {
8693 /* see if the symbol was already defined */
8696 if (!is_compatible_types(&sym
->type
, type
))
8697 error("incompatible types for redefinition of '%s'",
8698 get_tok_str(v
, NULL
));
8699 if (sym
->type
.t
& VT_EXTERN
) {
8700 /* if the variable is extern, it was not allocated */
8701 sym
->type
.t
&= ~VT_EXTERN
;
8702 /* set array size if it was ommited in extern
8704 if ((sym
->type
.t
& VT_ARRAY
) &&
8705 sym
->type
.ref
->c
< 0 &&
8707 sym
->type
.ref
->c
= type
->ref
->c
;
8709 /* we accept several definitions of the same
8710 global variable. this is tricky, because we
8711 must play with the SHN_COMMON type of the symbol */
8712 /* XXX: should check if the variable was already
8713 initialized. It is incorrect to initialized it
8715 /* no init data, we won't add more to the symbol */
8722 /* allocate symbol in corresponding section */
8727 else if (tcc_state
->nocommon
)
8731 data_offset
= sec
->data_offset
;
8732 data_offset
= (data_offset
+ align
- 1) & -align
;
8734 /* very important to increment global pointer at this time
8735 because initializers themselves can create new initializers */
8736 data_offset
+= size
;
8737 /* add padding if bound check */
8738 if (do_bounds_check
)
8740 sec
->data_offset
= data_offset
;
8741 /* allocate section space to put the data */
8742 if (sec
->sh_type
!= SHT_NOBITS
&&
8743 data_offset
> sec
->data_allocated
)
8744 section_realloc(sec
, data_offset
);
8745 /* align section if needed */
8746 if (align
> sec
->sh_addralign
)
8747 sec
->sh_addralign
= align
;
8749 addr
= 0; /* avoid warning */
8753 if (scope
== VT_CONST
) {
8758 sym
= sym_push(v
, type
, r
| VT_SYM
, 0);
8760 /* update symbol definition */
8762 put_extern_sym(sym
, sec
, addr
, size
);
8765 /* put a common area */
8766 put_extern_sym(sym
, NULL
, align
, size
);
8767 /* XXX: find a nicer way */
8768 esym
= &((Elf32_Sym
*)symtab_section
->data
)[sym
->c
];
8769 esym
->st_shndx
= SHN_COMMON
;
8774 /* push global reference */
8775 sym
= get_sym_ref(type
, sec
, addr
, size
);
8777 vsetc(type
, VT_CONST
| VT_SYM
, &cval
);
8781 /* handles bounds now because the symbol must be defined
8782 before for the relocation */
8783 if (do_bounds_check
) {
8784 unsigned long *bounds_ptr
;
8786 greloc(bounds_section
, sym
, bounds_section
->data_offset
, R_DATA_32
);
8787 /* then add global bound info */
8788 bounds_ptr
= section_ptr_add(bounds_section
, 2 * sizeof(long));
8789 bounds_ptr
[0] = 0; /* relocated */
8790 bounds_ptr
[1] = size
;
8794 decl_initializer(type
, sec
, addr
, 1, 0);
8795 /* restore parse state if needed */
8797 tok_str_free(init_str
.str
);
8798 restore_parse_state(&saved_parse_state
);
8804 void put_func_debug(Sym
*sym
)
8809 /* XXX: we put here a dummy type */
8810 snprintf(buf
, sizeof(buf
), "%s:%c1",
8811 funcname
, sym
->type
.t
& VT_STATIC
? 'f' : 'F');
8812 put_stabs_r(buf
, N_FUN
, 0, file
->line_num
, 0,
8813 cur_text_section
, sym
->c
);
8818 /* parse an old style function declaration list */
8819 /* XXX: check multiple parameter */
8820 static void func_decl_list(Sym
*func_sym
)
8827 /* parse each declaration */
8828 while (tok
!= '{' && tok
!= ';' && tok
!= ',' && tok
!= TOK_EOF
) {
8829 if (!parse_btype(&btype
, &ad
))
8830 expect("declaration list");
8831 if (((btype
.t
& VT_BTYPE
) == VT_ENUM
||
8832 (btype
.t
& VT_BTYPE
) == VT_STRUCT
) &&
8834 /* we accept no variable after */
8838 type_decl(&type
, &ad
, &v
, TYPE_DIRECT
);
8839 /* find parameter in function parameter list */
8842 if ((s
->v
& ~SYM_FIELD
) == v
)
8846 error("declaration for parameter '%s' but no such parameter",
8847 get_tok_str(v
, NULL
));
8849 /* check that no storage specifier except 'register' was given */
8850 if (type
.t
& VT_STORAGE
)
8851 error("storage class specified for '%s'", get_tok_str(v
, NULL
));
8852 convert_parameter_type(&type
);
8853 /* we can add the type (NOTE: it could be local to the function) */
8855 /* accept other parameters */
8866 /* parse a function defined by symbol 'sym' and generate its code in
8867 'cur_text_section' */
8868 static void gen_function(Sym
*sym
)
8870 ind
= cur_text_section
->data_offset
;
8871 /* NOTE: we patch the symbol size later */
8872 put_extern_sym(sym
, cur_text_section
, ind
, 0);
8873 funcname
= get_tok_str(sym
->v
, NULL
);
8875 /* put debug symbol */
8877 put_func_debug(sym
);
8878 /* push a dummy symbol to enable local sym storage */
8879 sym_push2(&local_stack
, SYM_FIELD
, 0, 0);
8880 gfunc_prolog(&sym
->type
);
8882 block(NULL
, NULL
, NULL
, NULL
, 0, 0);
8885 cur_text_section
->data_offset
= ind
;
8886 label_pop(&global_label_stack
, NULL
);
8887 sym_pop(&local_stack
, NULL
); /* reset local stack */
8888 /* end of function */
8889 /* patch symbol size */
8890 ((Elf32_Sym
*)symtab_section
->data
)[sym
->c
].st_size
=
8893 put_stabn(N_FUN
, 0, 0, ind
- func_ind
);
8895 funcname
= ""; /* for safety */
8896 func_vt
.t
= VT_VOID
; /* for safety */
8897 ind
= 0; /* for safety */
8900 static void gen_inline_functions(void)
8904 int *str
, inline_generated
;
8906 /* iterate while inline function are referenced */
8908 inline_generated
= 0;
8909 for(sym
= global_stack
; sym
!= NULL
; sym
= sym
->prev
) {
8911 if (((type
->t
& VT_BTYPE
) == VT_FUNC
) &&
8912 (type
->t
& (VT_STATIC
| VT_INLINE
)) ==
8913 (VT_STATIC
| VT_INLINE
) &&
8915 /* the function was used: generate its code and
8916 convert it to a normal function */
8917 str
= (int *)sym
->r
;
8918 sym
->r
= VT_SYM
| VT_CONST
;
8919 type
->t
&= ~VT_INLINE
;
8923 cur_text_section
= text_section
;
8925 macro_ptr
= NULL
; /* fail safe */
8928 inline_generated
= 1;
8931 if (!inline_generated
)
8935 /* free all remaining inline function tokens */
8936 for(sym
= global_stack
; sym
!= NULL
; sym
= sym
->prev
) {
8938 if (((type
->t
& VT_BTYPE
) == VT_FUNC
) &&
8939 (type
->t
& (VT_STATIC
| VT_INLINE
)) ==
8940 (VT_STATIC
| VT_INLINE
)) {
8941 str
= (int *)sym
->r
;
8943 sym
->r
= 0; /* fail safe */
8948 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
8949 static void decl(int l
)
8957 if (!parse_btype(&btype
, &ad
)) {
8958 /* skip redundant ';' */
8959 /* XXX: find more elegant solution */
8964 if (l
== VT_CONST
&&
8965 (tok
== TOK_ASM1
|| tok
== TOK_ASM2
|| tok
== TOK_ASM3
)) {
8966 /* global asm block */
8970 /* special test for old K&R protos without explicit int
8971 type. Only accepted when defining global data */
8972 if (l
== VT_LOCAL
|| tok
< TOK_DEFINE
)
8976 if (((btype
.t
& VT_BTYPE
) == VT_ENUM
||
8977 (btype
.t
& VT_BTYPE
) == VT_STRUCT
) &&
8979 /* we accept no variable after */
8983 while (1) { /* iterate thru each declaration */
8985 type_decl(&type
, &ad
, &v
, TYPE_DIRECT
);
8989 type_to_str(buf
, sizeof(buf
), t
, get_tok_str(v
, NULL
));
8990 printf("type = '%s'\n", buf
);
8993 if ((type
.t
& VT_BTYPE
) == VT_FUNC
) {
8994 /* if old style function prototype, we accept a
8997 if (sym
->c
== FUNC_OLD
)
8998 func_decl_list(sym
);
9003 error("cannot use local functions");
9004 if (!(type
.t
& VT_FUNC
))
9005 expect("function definition");
9007 /* reject abstract declarators in function definition */
9009 while ((sym
= sym
->next
) != NULL
)
9010 if (!(sym
->v
& ~SYM_FIELD
))
9011 expect("identifier");
9013 /* XXX: cannot do better now: convert extern line to static inline */
9014 if ((type
.t
& (VT_EXTERN
| VT_INLINE
)) == (VT_EXTERN
| VT_INLINE
))
9015 type
.t
= (type
.t
& ~VT_EXTERN
) | VT_STATIC
;
9019 if ((sym
->type
.t
& VT_BTYPE
) != VT_FUNC
)
9021 /* specific case: if not func_call defined, we put
9022 the one of the prototype */
9023 /* XXX: should have default value */
9024 if (sym
->type
.ref
->r
!= FUNC_CDECL
&&
9025 type
.ref
->r
== FUNC_CDECL
)
9026 type
.ref
->r
= sym
->type
.ref
->r
;
9027 if (!is_compatible_types(&sym
->type
, &type
)) {
9029 error("incompatible types for redefinition of '%s'",
9030 get_tok_str(v
, NULL
));
9032 /* if symbol is already defined, then put complete type */
9035 /* put function symbol */
9036 sym
= global_identifier_push(v
, type
.t
, 0);
9037 sym
->type
.ref
= type
.ref
;
9040 /* static inline functions are just recorded as a kind
9041 of macro. Their code will be emitted at the end of
9042 the compilation unit only if they are used */
9043 if ((type
.t
& (VT_INLINE
| VT_STATIC
)) ==
9044 (VT_INLINE
| VT_STATIC
)) {
9045 TokenString func_str
;
9048 tok_str_new(&func_str
);
9054 error("unexpected end of file");
9055 tok_str_add_tok(&func_str
);
9060 } else if (t
== '}') {
9062 if (block_level
== 0)
9066 tok_str_add(&func_str
, -1);
9067 tok_str_add(&func_str
, 0);
9068 sym
->r
= (int)func_str
.str
;
9070 /* compute text section */
9071 cur_text_section
= ad
.section
;
9072 if (!cur_text_section
)
9073 cur_text_section
= text_section
;
9074 sym
->r
= VT_SYM
| VT_CONST
;
9076 #ifdef TCC_TARGET_PE
9078 ((Elf32_Sym
*)symtab_section
->data
)[sym
->c
].st_other
|= 1;
9084 if (btype
.t
& VT_TYPEDEF
) {
9085 /* save typedefed type */
9086 /* XXX: test storage specifiers ? */
9087 sym
= sym_push(v
, &type
, 0, 0);
9088 sym
->type
.t
|= VT_TYPEDEF
;
9089 } else if ((type
.t
& VT_BTYPE
) == VT_FUNC
) {
9090 /* external function definition */
9091 /* specific case for func_call attribute */
9093 type
.ref
->r
= ad
.func_call
;
9094 external_sym(v
, &type
, 0);
9096 /* not lvalue if array */
9098 if (!(type
.t
& VT_ARRAY
))
9099 r
|= lvalue_type(type
.t
);
9100 has_init
= (tok
== '=');
9101 if ((btype
.t
& VT_EXTERN
) ||
9102 ((type
.t
& VT_ARRAY
) && (type
.t
& VT_STATIC
) &&
9103 !has_init
&& l
== VT_CONST
&& type
.ref
->c
< 0)) {
9104 /* external variable */
9105 /* NOTE: as GCC, uninitialized global static
9106 arrays of null size are considered as
9108 external_sym(v
, &type
, r
);
9110 if (type
.t
& VT_STATIC
)
9116 decl_initializer_alloc(&type
, &ad
, r
,
9130 /* better than nothing, but needs extension to handle '-E' option
9132 static void preprocess_init(TCCState
*s1
)
9134 s1
->include_stack_ptr
= s1
->include_stack
;
9135 /* XXX: move that before to avoid having to initialize
9136 file->ifdef_stack_ptr ? */
9137 s1
->ifdef_stack_ptr
= s1
->ifdef_stack
;
9138 file
->ifdef_stack_ptr
= s1
->ifdef_stack_ptr
;
9140 /* XXX: not ANSI compliant: bound checking says error */
9142 s1
->pack_stack
[0] = 0;
9143 s1
->pack_stack_ptr
= s1
->pack_stack
;
9146 /* compile the C file opened in 'file'. Return non zero if errors. */
9147 static int tcc_compile(TCCState
*s1
)
9151 volatile int section_sym
;
9154 printf("%s: **** new file\n", file
->filename
);
9156 preprocess_init(s1
);
9159 anon_sym
= SYM_FIRST_ANOM
;
9161 /* file info: full path + filename */
9162 section_sym
= 0; /* avoid warning */
9164 section_sym
= put_elf_sym(symtab_section
, 0, 0,
9165 ELF32_ST_INFO(STB_LOCAL
, STT_SECTION
), 0,
9166 text_section
->sh_num
, NULL
);
9167 getcwd(buf
, sizeof(buf
));
9168 pstrcat(buf
, sizeof(buf
), "/");
9169 put_stabs_r(buf
, N_SO
, 0, 0,
9170 text_section
->data_offset
, text_section
, section_sym
);
9171 put_stabs_r(file
->filename
, N_SO
, 0, 0,
9172 text_section
->data_offset
, text_section
, section_sym
);
9174 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
9175 symbols can be safely used */
9176 put_elf_sym(symtab_section
, 0, 0,
9177 ELF32_ST_INFO(STB_LOCAL
, STT_FILE
), 0,
9178 SHN_ABS
, file
->filename
);
9180 /* define some often used types */
9181 int_type
.t
= VT_INT
;
9183 char_pointer_type
.t
= VT_BYTE
;
9184 mk_pointer(&char_pointer_type
);
9186 func_old_type
.t
= VT_FUNC
;
9187 func_old_type
.ref
= sym_push(SYM_FIELD
, &int_type
, FUNC_CDECL
, FUNC_OLD
);
9190 /* define 'void *alloca(unsigned int)' builtin function */
9195 sym
= sym_push(p
, mk_pointer(VT_VOID
), FUNC_CDECL
, FUNC_NEW
);
9196 s1
= sym_push(SYM_FIELD
, VT_UNSIGNED
| VT_INT
, 0, 0);
9199 sym_push(TOK_alloca
, VT_FUNC
| (p
<< VT_STRUCT_SHIFT
), VT_CONST
, 0);
9203 define_start
= define_stack
;
9205 if (setjmp(s1
->error_jmp_buf
) == 0) {
9207 s1
->error_set_jmp_enabled
= 1;
9209 ch
= file
->buf_ptr
[0];
9210 tok_flags
= TOK_FLAG_BOL
| TOK_FLAG_BOF
;
9211 parse_flags
= PARSE_FLAG_PREPROCESS
| PARSE_FLAG_TOK_NUM
;
9215 expect("declaration");
9217 /* end of translation unit info */
9219 put_stabs_r(NULL
, N_SO
, 0, 0,
9220 text_section
->data_offset
, text_section
, section_sym
);
9223 s1
->error_set_jmp_enabled
= 0;
9225 /* reset define stack, but leave -Dsymbols (may be incorrect if
9226 they are undefined) */
9227 free_defines(define_start
);
9229 gen_inline_functions();
9231 sym_pop(&global_stack
, NULL
);
9233 return s1
->nb_errors
!= 0 ? -1 : 0;
9237 int tcc_compile_string(TCCState
*s
, const char *str
)
9239 BufferedFile bf1
, *bf
= &bf1
;
9243 /* init file structure */
9245 /* XXX: avoid copying */
9247 buf
= tcc_malloc(len
+ 1);
9250 memcpy(buf
, str
, len
);
9253 bf
->buf_end
= buf
+ len
;
9254 pstrcpy(bf
->filename
, sizeof(bf
->filename
), "<string>");
9258 ret
= tcc_compile(s
);
9262 /* currently, no need to close */
9267 /* define a preprocessor symbol. A value can also be provided with the '=' operator */
9268 void tcc_define_symbol(TCCState
*s1
, const char *sym
, const char *value
)
9270 BufferedFile bf1
, *bf
= &bf1
;
9272 pstrcpy(bf
->buffer
, IO_BUF_SIZE
, sym
);
9273 pstrcat(bf
->buffer
, IO_BUF_SIZE
, " ");
9277 pstrcat(bf
->buffer
, IO_BUF_SIZE
, value
);
9279 /* init file structure */
9281 bf
->buf_ptr
= bf
->buffer
;
9282 bf
->buf_end
= bf
->buffer
+ strlen(bf
->buffer
);
9283 *bf
->buf_end
= CH_EOB
;
9284 bf
->filename
[0] = '\0';
9288 s1
->include_stack_ptr
= s1
->include_stack
;
9290 /* parse with define parser */
9291 ch
= file
->buf_ptr
[0];
9297 /* undefine a preprocessor symbol */
9298 void tcc_undefine_symbol(TCCState
*s1
, const char *sym
)
9302 ts
= tok_alloc(sym
, strlen(sym
));
9303 s
= define_find(ts
->tok
);
9304 /* undefine symbol by putting an invalid name */
9309 #ifdef CONFIG_TCC_ASM
9311 #ifdef TCC_TARGET_I386
9312 #include "i386-asm.c"
9317 static void asm_instr(void)
9319 error("inline asm() not supported");
9321 static void asm_global_instr(void)
9323 error("inline asm() not supported");
9329 #ifdef TCC_TARGET_COFF
9330 #include "tcccoff.c"
9333 #ifdef TCC_TARGET_PE
9337 /* print the position in the source file of PC value 'pc' by reading
9338 the stabs debug information */
9339 static void rt_printline(unsigned long wanted_pc
)
9341 Stab_Sym
*sym
, *sym_end
;
9342 char func_name
[128], last_func_name
[128];
9343 unsigned long func_addr
, last_pc
, pc
;
9344 const char *incl_files
[INCLUDE_STACK_SIZE
];
9345 int incl_index
, len
, last_line_num
, i
;
9346 const char *str
, *p
;
9348 fprintf(stderr
, "0x%08lx:", wanted_pc
);
9350 func_name
[0] = '\0';
9353 last_func_name
[0] = '\0';
9354 last_pc
= 0xffffffff;
9356 sym
= (Stab_Sym
*)stab_section
->data
+ 1;
9357 sym_end
= (Stab_Sym
*)(stab_section
->data
+ stab_section
->data_offset
);
9358 while (sym
< sym_end
) {
9359 switch(sym
->n_type
) {
9360 /* function start or end */
9362 if (sym
->n_strx
== 0) {
9363 /* we test if between last line and end of function */
9364 pc
= sym
->n_value
+ func_addr
;
9365 if (wanted_pc
>= last_pc
&& wanted_pc
< pc
)
9367 func_name
[0] = '\0';
9370 str
= stabstr_section
->data
+ sym
->n_strx
;
9371 p
= strchr(str
, ':');
9373 pstrcpy(func_name
, sizeof(func_name
), str
);
9376 if (len
> sizeof(func_name
) - 1)
9377 len
= sizeof(func_name
) - 1;
9378 memcpy(func_name
, str
, len
);
9379 func_name
[len
] = '\0';
9381 func_addr
= sym
->n_value
;
9384 /* line number info */
9386 pc
= sym
->n_value
+ func_addr
;
9387 if (wanted_pc
>= last_pc
&& wanted_pc
< pc
)
9390 last_line_num
= sym
->n_desc
;
9392 strcpy(last_func_name
, func_name
);
9396 str
= stabstr_section
->data
+ sym
->n_strx
;
9398 if (incl_index
< INCLUDE_STACK_SIZE
) {
9399 incl_files
[incl_index
++] = str
;
9407 if (sym
->n_strx
== 0) {
9408 incl_index
= 0; /* end of translation unit */
9410 str
= stabstr_section
->data
+ sym
->n_strx
;
9411 /* do not add path */
9413 if (len
> 0 && str
[len
- 1] != '/')
9421 /* second pass: we try symtab symbols (no line number info) */
9424 Elf32_Sym
*sym
, *sym_end
;
9427 sym_end
= (Elf32_Sym
*)(symtab_section
->data
+ symtab_section
->data_offset
);
9428 for(sym
= (Elf32_Sym
*)symtab_section
->data
+ 1;
9431 type
= ELF32_ST_TYPE(sym
->st_info
);
9432 if (type
== STT_FUNC
) {
9433 if (wanted_pc
>= sym
->st_value
&&
9434 wanted_pc
< sym
->st_value
+ sym
->st_size
) {
9435 pstrcpy(last_func_name
, sizeof(last_func_name
),
9436 strtab_section
->data
+ sym
->st_name
);
9442 /* did not find any info: */
9443 fprintf(stderr
, " ???\n");
9446 if (last_func_name
[0] != '\0') {
9447 fprintf(stderr
, " %s()", last_func_name
);
9449 if (incl_index
> 0) {
9450 fprintf(stderr
, " (%s:%d",
9451 incl_files
[incl_index
- 1], last_line_num
);
9452 for(i
= incl_index
- 2; i
>= 0; i
--)
9453 fprintf(stderr
, ", included from %s", incl_files
[i
]);
9454 fprintf(stderr
, ")");
9456 fprintf(stderr
, "\n");
9459 #if !defined(WIN32) && !defined(CONFIG_TCCBOOT)
9463 /* fix for glibc 2.1 */
9469 /* return the PC at frame level 'level'. Return non zero if not found */
9470 static int rt_get_caller_pc(unsigned long *paddr
,
9471 ucontext_t
*uc
, int level
)
9477 #if defined(__FreeBSD__)
9478 *paddr
= uc
->uc_mcontext
.mc_eip
;
9479 #elif defined(__dietlibc__)
9480 *paddr
= uc
->uc_mcontext
.eip
;
9482 *paddr
= uc
->uc_mcontext
.gregs
[REG_EIP
];
9486 #if defined(__FreeBSD__)
9487 fp
= uc
->uc_mcontext
.mc_ebp
;
9488 #elif defined(__dietlibc__)
9489 fp
= uc
->uc_mcontext
.ebp
;
9491 fp
= uc
->uc_mcontext
.gregs
[REG_EBP
];
9493 for(i
=1;i
<level
;i
++) {
9494 /* XXX: check address validity with program info */
9495 if (fp
<= 0x1000 || fp
>= 0xc0000000)
9497 fp
= ((unsigned long *)fp
)[0];
9499 *paddr
= ((unsigned long *)fp
)[1];
9505 #warning add arch specific rt_get_caller_pc()
9507 static int rt_get_caller_pc(unsigned long *paddr
,
9508 ucontext_t
*uc
, int level
)
9514 /* emit a run time error at position 'pc' */
9515 void rt_error(ucontext_t
*uc
, const char *fmt
, ...)
9522 fprintf(stderr
, "Runtime error: ");
9523 vfprintf(stderr
, fmt
, ap
);
9524 fprintf(stderr
, "\n");
9525 for(i
=0;i
<num_callers
;i
++) {
9526 if (rt_get_caller_pc(&pc
, uc
, i
) < 0)
9529 fprintf(stderr
, "at ");
9531 fprintf(stderr
, "by ");
9538 /* signal handler for fatal errors */
9539 static void sig_error(int signum
, siginfo_t
*siginf
, void *puc
)
9541 ucontext_t
*uc
= puc
;
9545 switch(siginf
->si_code
) {
9548 rt_error(uc
, "division by zero");
9551 rt_error(uc
, "floating point exception");
9557 if (rt_bound_error_msg
&& *rt_bound_error_msg
)
9558 rt_error(uc
, *rt_bound_error_msg
);
9560 rt_error(uc
, "dereferencing invalid pointer");
9563 rt_error(uc
, "illegal instruction");
9566 rt_error(uc
, "abort() called");
9569 rt_error(uc
, "caught signal %d", signum
);
9576 /* do all relocations (needed before using tcc_get_symbol()) */
9577 int tcc_relocate(TCCState
*s1
)
9584 #ifdef TCC_TARGET_PE
9587 tcc_add_runtime(s1
);
9590 relocate_common_syms();
9592 tcc_add_linker_symbols(s1
);
9594 build_got_entries(s1
);
9596 /* compute relocation address : section are relocated in place. We
9597 also alloc the bss space */
9598 for(i
= 1; i
< s1
->nb_sections
; i
++) {
9599 s
= s1
->sections
[i
];
9600 if (s
->sh_flags
& SHF_ALLOC
) {
9601 if (s
->sh_type
== SHT_NOBITS
)
9602 s
->data
= tcc_mallocz(s
->data_offset
);
9603 s
->sh_addr
= (unsigned long)s
->data
;
9607 relocate_syms(s1
, 1);
9609 if (s1
->nb_errors
!= 0)
9612 /* relocate each section */
9613 for(i
= 1; i
< s1
->nb_sections
; i
++) {
9614 s
= s1
->sections
[i
];
9616 relocate_section(s1
, s
);
9621 /* launch the compiled program with the given arguments */
9622 int tcc_run(TCCState
*s1
, int argc
, char **argv
)
9624 int (*prog_main
)(int, char **);
9626 if (tcc_relocate(s1
) < 0)
9629 prog_main
= tcc_get_symbol_err(s1
, "main");
9632 #if defined(WIN32) || defined(CONFIG_TCCBOOT)
9633 error("debug mode currently not available for Windows");
9635 struct sigaction sigact
;
9636 /* install TCC signal handlers to print debug info on fatal
9638 sigact
.sa_flags
= SA_SIGINFO
| SA_RESETHAND
;
9639 sigact
.sa_sigaction
= sig_error
;
9640 sigemptyset(&sigact
.sa_mask
);
9641 sigaction(SIGFPE
, &sigact
, NULL
);
9642 sigaction(SIGILL
, &sigact
, NULL
);
9643 sigaction(SIGSEGV
, &sigact
, NULL
);
9644 sigaction(SIGBUS
, &sigact
, NULL
);
9645 sigaction(SIGABRT
, &sigact
, NULL
);
9649 #ifdef CONFIG_TCC_BCHECK
9650 if (do_bounds_check
) {
9651 void (*bound_init
)(void);
9653 /* set error function */
9654 rt_bound_error_msg
= (void *)tcc_get_symbol_err(s1
,
9655 "__bound_error_msg");
9657 /* XXX: use .init section so that it also work in binary ? */
9658 bound_init
= (void *)tcc_get_symbol_err(s1
, "__bound_init");
9662 return (*prog_main
)(argc
, argv
);
9665 TCCState
*tcc_new(void)
9672 s
= tcc_mallocz(sizeof(TCCState
));
9676 s
->output_type
= TCC_OUTPUT_MEMORY
;
9678 /* init isid table */
9680 isidnum_table
[i
] = isid(i
) || isnum(i
);
9682 /* add all tokens */
9684 memset(hash_ident
, 0, TOK_HASH_SIZE
* sizeof(TokenSym
*));
9686 tok_ident
= TOK_IDENT
;
9695 ts
= tok_alloc(p
, r
- p
- 1);
9699 /* we add dummy defines for some special macros to speed up tests
9700 and to have working defined() */
9701 define_push(TOK___LINE__
, MACRO_OBJ
, NULL
, NULL
);
9702 define_push(TOK___FILE__
, MACRO_OBJ
, NULL
, NULL
);
9703 define_push(TOK___DATE__
, MACRO_OBJ
, NULL
, NULL
);
9704 define_push(TOK___TIME__
, MACRO_OBJ
, NULL
, NULL
);
9706 /* standard defines */
9707 tcc_define_symbol(s
, "__STDC__", NULL
);
9708 #if defined(TCC_TARGET_I386)
9709 tcc_define_symbol(s
, "__i386__", NULL
);
9711 #if defined(TCC_TARGET_ARM)
9712 tcc_define_symbol(s
, "__ARM_ARCH_4__", NULL
);
9713 tcc_define_symbol(s
, "__arm_elf__", NULL
);
9714 tcc_define_symbol(s
, "__arm_elf", NULL
);
9715 tcc_define_symbol(s
, "arm_elf", NULL
);
9716 tcc_define_symbol(s
, "__arm__", NULL
);
9717 tcc_define_symbol(s
, "__arm", NULL
);
9718 tcc_define_symbol(s
, "arm", NULL
);
9719 tcc_define_symbol(s
, "__APCS_32__", NULL
);
9722 tcc_define_symbol(s
, "__linux__", NULL
);
9723 tcc_define_symbol(s
, "linux", NULL
);
9725 /* tiny C specific defines */
9726 tcc_define_symbol(s
, "__TINYC__", NULL
);
9728 /* tiny C & gcc defines */
9729 tcc_define_symbol(s
, "__SIZE_TYPE__", "unsigned int");
9730 tcc_define_symbol(s
, "__PTRDIFF_TYPE__", "int");
9731 tcc_define_symbol(s
, "__WCHAR_TYPE__", "int");
9733 /* default library paths */
9734 #ifdef TCC_TARGET_PE
9737 snprintf(buf
, sizeof(buf
), "%s/lib", tcc_lib_path
);
9738 tcc_add_library_path(s
, buf
);
9741 tcc_add_library_path(s
, "/usr/local/lib");
9742 tcc_add_library_path(s
, "/usr/lib");
9743 tcc_add_library_path(s
, "/lib");
9746 /* no section zero */
9747 dynarray_add((void ***)&s
->sections
, &s
->nb_sections
, NULL
);
9749 /* create standard sections */
9750 text_section
= new_section(s
, ".text", SHT_PROGBITS
, SHF_ALLOC
| SHF_EXECINSTR
);
9751 data_section
= new_section(s
, ".data", SHT_PROGBITS
, SHF_ALLOC
| SHF_WRITE
);
9752 bss_section
= new_section(s
, ".bss", SHT_NOBITS
, SHF_ALLOC
| SHF_WRITE
);
9754 /* symbols are always generated for linking stage */
9755 symtab_section
= new_symtab(s
, ".symtab", SHT_SYMTAB
, 0,
9757 ".hashtab", SHF_PRIVATE
);
9758 strtab_section
= symtab_section
->link
;
9760 /* private symbol table for dynamic symbols */
9761 s
->dynsymtab_section
= new_symtab(s
, ".dynsymtab", SHT_SYMTAB
, SHF_PRIVATE
,
9763 ".dynhashtab", SHF_PRIVATE
);
9764 s
->alacarte_link
= 1;
9766 #ifdef CHAR_IS_UNSIGNED
9767 s
->char_is_unsigned
= 1;
9769 #if defined(TCC_TARGET_PE) && 0
9770 /* XXX: currently the PE linker is not ready to support that */
9771 s
->leading_underscore
= 1;
9776 void tcc_delete(TCCState
*s1
)
9780 /* free -D defines */
9784 n
= tok_ident
- TOK_IDENT
;
9785 for(i
= 0; i
< n
; i
++)
9786 tcc_free(table_ident
[i
]);
9787 tcc_free(table_ident
);
9789 /* free all sections */
9791 free_section(symtab_section
->hash
);
9793 free_section(s1
->dynsymtab_section
->hash
);
9794 free_section(s1
->dynsymtab_section
->link
);
9795 free_section(s1
->dynsymtab_section
);
9797 for(i
= 1; i
< s1
->nb_sections
; i
++)
9798 free_section(s1
->sections
[i
]);
9799 tcc_free(s1
->sections
);
9801 /* free loaded dlls array */
9802 for(i
= 0; i
< s1
->nb_loaded_dlls
; i
++)
9803 tcc_free(s1
->loaded_dlls
[i
]);
9804 tcc_free(s1
->loaded_dlls
);
9807 for(i
= 0; i
< s1
->nb_library_paths
; i
++)
9808 tcc_free(s1
->library_paths
[i
]);
9809 tcc_free(s1
->library_paths
);
9811 /* cached includes */
9812 for(i
= 0; i
< s1
->nb_cached_includes
; i
++)
9813 tcc_free(s1
->cached_includes
[i
]);
9814 tcc_free(s1
->cached_includes
);
9816 for(i
= 0; i
< s1
->nb_include_paths
; i
++)
9817 tcc_free(s1
->include_paths
[i
]);
9818 tcc_free(s1
->include_paths
);
9820 for(i
= 0; i
< s1
->nb_sysinclude_paths
; i
++)
9821 tcc_free(s1
->sysinclude_paths
[i
]);
9822 tcc_free(s1
->sysinclude_paths
);
9827 int tcc_add_include_path(TCCState
*s1
, const char *pathname
)
9831 pathname1
= tcc_strdup(pathname
);
9832 dynarray_add((void ***)&s1
->include_paths
, &s1
->nb_include_paths
, pathname1
);
9836 int tcc_add_sysinclude_path(TCCState
*s1
, const char *pathname
)
9840 pathname1
= tcc_strdup(pathname
);
9841 dynarray_add((void ***)&s1
->sysinclude_paths
, &s1
->nb_sysinclude_paths
, pathname1
);
9845 static int tcc_add_file_internal(TCCState
*s1
, const char *filename
, int flags
)
9847 const char *ext
, *filename1
;
9850 BufferedFile
*saved_file
;
9852 /* find source file type with extension */
9853 filename1
= strrchr(filename
, '/');
9857 filename1
= filename
;
9858 ext
= strrchr(filename1
, '.');
9864 file
= tcc_open(s1
, filename
);
9866 if (flags
& AFF_PRINT_ERROR
) {
9867 error_noabort("file '%s' not found", filename
);
9873 if (!ext
|| !strcmp(ext
, "c")) {
9874 /* C file assumed */
9875 ret
= tcc_compile(s1
);
9877 #ifdef CONFIG_TCC_ASM
9878 if (!strcmp(ext
, "S")) {
9879 /* preprocessed assembler */
9880 ret
= tcc_assemble(s1
, 1);
9881 } else if (!strcmp(ext
, "s")) {
9882 /* non preprocessed assembler */
9883 ret
= tcc_assemble(s1
, 0);
9886 #ifdef TCC_TARGET_PE
9887 if (!strcmp(ext
, "def")) {
9888 ret
= pe_load_def_file(s1
, fdopen(file
->fd
, "rb"));
9893 /* assume executable format: auto guess file type */
9894 ret
= read(fd
, &ehdr
, sizeof(ehdr
));
9895 lseek(fd
, 0, SEEK_SET
);
9897 error_noabort("could not read header");
9899 } else if (ret
!= sizeof(ehdr
)) {
9900 goto try_load_script
;
9903 if (ehdr
.e_ident
[0] == ELFMAG0
&&
9904 ehdr
.e_ident
[1] == ELFMAG1
&&
9905 ehdr
.e_ident
[2] == ELFMAG2
&&
9906 ehdr
.e_ident
[3] == ELFMAG3
) {
9907 file
->line_num
= 0; /* do not display line number if error */
9908 if (ehdr
.e_type
== ET_REL
) {
9909 ret
= tcc_load_object_file(s1
, fd
, 0);
9910 } else if (ehdr
.e_type
== ET_DYN
) {
9911 if (s1
->output_type
== TCC_OUTPUT_MEMORY
) {
9912 #ifdef TCC_TARGET_PE
9916 h
= dlopen(filename
, RTLD_GLOBAL
| RTLD_LAZY
);
9923 ret
= tcc_load_dll(s1
, fd
, filename
,
9924 (flags
& AFF_REFERENCED_DLL
) != 0);
9927 error_noabort("unrecognized ELF file");
9930 } else if (memcmp((char *)&ehdr
, ARMAG
, 8) == 0) {
9931 file
->line_num
= 0; /* do not display line number if error */
9932 ret
= tcc_load_archive(s1
, fd
);
9934 #ifdef TCC_TARGET_COFF
9935 if (*(uint16_t *)(&ehdr
) == COFF_C67_MAGIC
) {
9936 ret
= tcc_load_coff(s1
, fd
);
9940 /* as GNU ld, consider it is an ld script if not recognized */
9942 ret
= tcc_load_ldscript(s1
);
9944 error_noabort("unrecognized file type");
9959 int tcc_add_file(TCCState
*s
, const char *filename
)
9961 return tcc_add_file_internal(s
, filename
, AFF_PRINT_ERROR
);
9964 int tcc_add_library_path(TCCState
*s
, const char *pathname
)
9968 pathname1
= tcc_strdup(pathname
);
9969 dynarray_add((void ***)&s
->library_paths
, &s
->nb_library_paths
, pathname1
);
9973 /* find and load a dll. Return non zero if not found */
9974 /* XXX: add '-rpath' option support ? */
9975 static int tcc_add_dll(TCCState
*s
, const char *filename
, int flags
)
9980 for(i
= 0; i
< s
->nb_library_paths
; i
++) {
9981 snprintf(buf
, sizeof(buf
), "%s/%s",
9982 s
->library_paths
[i
], filename
);
9983 if (tcc_add_file_internal(s
, buf
, flags
) == 0)
9989 /* the library name is the same as the argument of the '-l' option */
9990 int tcc_add_library(TCCState
*s
, const char *libraryname
)
9995 /* first we look for the dynamic library if not static linking */
9996 if (!s
->static_link
) {
9997 #ifdef TCC_TARGET_PE
9998 snprintf(buf
, sizeof(buf
), "%s.def", libraryname
);
10000 snprintf(buf
, sizeof(buf
), "lib%s.so", libraryname
);
10002 if (tcc_add_dll(s
, buf
, 0) == 0)
10006 /* then we look for the static library */
10007 for(i
= 0; i
< s
->nb_library_paths
; i
++) {
10008 snprintf(buf
, sizeof(buf
), "%s/lib%s.a",
10009 s
->library_paths
[i
], libraryname
);
10010 if (tcc_add_file_internal(s
, buf
, 0) == 0)
10016 int tcc_add_symbol(TCCState
*s
, const char *name
, unsigned long val
)
10018 add_elf_sym(symtab_section
, val
, 0,
10019 ELF32_ST_INFO(STB_GLOBAL
, STT_NOTYPE
), 0,
10024 int tcc_set_output_type(TCCState
*s
, int output_type
)
10026 s
->output_type
= output_type
;
10028 if (!s
->nostdinc
) {
10031 /* default include paths */
10032 /* XXX: reverse order needed if -isystem support */
10033 #ifndef TCC_TARGET_PE
10034 tcc_add_sysinclude_path(s
, "/usr/local/include");
10035 tcc_add_sysinclude_path(s
, "/usr/include");
10037 snprintf(buf
, sizeof(buf
), "%s/include", tcc_lib_path
);
10038 tcc_add_sysinclude_path(s
, buf
);
10039 #ifdef TCC_TARGET_PE
10040 snprintf(buf
, sizeof(buf
), "%s/include/winapi", tcc_lib_path
);
10041 tcc_add_sysinclude_path(s
, buf
);
10045 /* if bound checking, then add corresponding sections */
10046 #ifdef CONFIG_TCC_BCHECK
10047 if (do_bounds_check
) {
10048 /* define symbol */
10049 tcc_define_symbol(s
, "__BOUNDS_CHECKING_ON", NULL
);
10050 /* create bounds sections */
10051 bounds_section
= new_section(s
, ".bounds",
10052 SHT_PROGBITS
, SHF_ALLOC
);
10053 lbounds_section
= new_section(s
, ".lbounds",
10054 SHT_PROGBITS
, SHF_ALLOC
);
10058 if (s
->char_is_unsigned
) {
10059 tcc_define_symbol(s
, "__CHAR_UNSIGNED__", NULL
);
10062 /* add debug sections */
10065 stab_section
= new_section(s
, ".stab", SHT_PROGBITS
, 0);
10066 stab_section
->sh_entsize
= sizeof(Stab_Sym
);
10067 stabstr_section
= new_section(s
, ".stabstr", SHT_STRTAB
, 0);
10068 put_elf_str(stabstr_section
, "");
10069 stab_section
->link
= stabstr_section
;
10070 /* put first entry */
10071 put_stabs("", 0, 0, 0, 0);
10074 /* add libc crt1/crti objects */
10075 #ifndef TCC_TARGET_PE
10076 if ((output_type
== TCC_OUTPUT_EXE
|| output_type
== TCC_OUTPUT_DLL
) &&
10078 if (output_type
!= TCC_OUTPUT_DLL
)
10079 tcc_add_file(s
, CONFIG_TCC_CRT_PREFIX
"/crt1.o");
10080 tcc_add_file(s
, CONFIG_TCC_CRT_PREFIX
"/crti.o");
10086 #define WD_ALL 0x0001 /* warning is activated when using -Wall */
10087 #define FD_INVERT 0x0002 /* invert value before storing */
10089 typedef struct FlagDef
{
10095 static const FlagDef warning_defs
[] = {
10096 { offsetof(TCCState
, warn_unsupported
), 0, "unsupported" },
10097 { offsetof(TCCState
, warn_write_strings
), 0, "write-strings" },
10098 { offsetof(TCCState
, warn_error
), 0, "error" },
10099 { offsetof(TCCState
, warn_implicit_function_declaration
), WD_ALL
,
10100 "implicit-function-declaration" },
10103 static int set_flag(TCCState
*s
, const FlagDef
*flags
, int nb_flags
,
10104 const char *name
, int value
)
10111 if (r
[0] == 'n' && r
[1] == 'o' && r
[2] == '-') {
10115 for(i
= 0, p
= flags
; i
< nb_flags
; i
++, p
++) {
10116 if (!strcmp(r
, p
->name
))
10121 if (p
->flags
& FD_INVERT
)
10123 *(int *)((uint8_t *)s
+ p
->offset
) = value
;
10128 /* set/reset a warning */
10129 int tcc_set_warning(TCCState
*s
, const char *warning_name
, int value
)
10134 if (!strcmp(warning_name
, "all")) {
10135 for(i
= 0, p
= warning_defs
; i
< countof(warning_defs
); i
++, p
++) {
10136 if (p
->flags
& WD_ALL
)
10137 *(int *)((uint8_t *)s
+ p
->offset
) = 1;
10141 return set_flag(s
, warning_defs
, countof(warning_defs
),
10142 warning_name
, value
);
10146 static const FlagDef flag_defs
[] = {
10147 { offsetof(TCCState
, char_is_unsigned
), 0, "unsigned-char" },
10148 { offsetof(TCCState
, char_is_unsigned
), FD_INVERT
, "signed-char" },
10149 { offsetof(TCCState
, nocommon
), FD_INVERT
, "common" },
10150 { offsetof(TCCState
, leading_underscore
), 0, "leading-underscore" },
10153 /* set/reset a flag */
10154 int tcc_set_flag(TCCState
*s
, const char *flag_name
, int value
)
10156 return set_flag(s
, flag_defs
, countof(flag_defs
),
10160 #if !defined(LIBTCC)
10162 /* extract the basename of a file */
10163 static const char *tcc_basename(const char *name
)
10166 p
= strrchr(name
, '/');
10169 p
= strrchr(name
, '\\');
10178 static int64_t getclock_us(void)
10183 return (tb
.time
* 1000LL + tb
.millitm
) * 1000LL;
10186 gettimeofday(&tv
, NULL
);
10187 return tv
.tv_sec
* 1000000LL + tv
.tv_usec
;
10193 printf("tcc version " TCC_VERSION
" - Tiny C Compiler - Copyright (C) 2001-2005 Fabrice Bellard\n"
10194 "usage: tcc [-v] [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
10195 " [-Wwarn] [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-static]\n"
10196 " [infile1 infile2...] [-run infile args...]\n"
10198 "General options:\n"
10199 " -v display current version\n"
10200 " -c compile only - generate an object file\n"
10201 " -o outfile set output filename\n"
10202 " -Bdir set tcc internal library path\n"
10203 " -bench output compilation statistics\n"
10204 " -run run compiled source\n"
10205 " -fflag set or reset (with 'no-' prefix) 'flag' (see man page)\n"
10206 " -Wwarning set or reset (with 'no-' prefix) 'warning' (see man page)\n"
10207 " -w disable all warnings\n"
10208 "Preprocessor options:\n"
10209 " -Idir add include path 'dir'\n"
10210 " -Dsym[=val] define 'sym' with value 'val'\n"
10211 " -Usym undefine 'sym'\n"
10212 "Linker options:\n"
10213 " -Ldir add library path 'dir'\n"
10214 " -llib link with dynamic or static library 'lib'\n"
10215 " -shared generate a shared library\n"
10216 " -static static linking\n"
10217 " -rdynamic export all global symbols to dynamic linker\n"
10218 " -r relocatable output\n"
10219 "Debugger options:\n"
10220 " -g generate runtime debug info\n"
10221 #ifdef CONFIG_TCC_BCHECK
10222 " -b compile with built-in memory and bounds checker (implies -g)\n"
10224 " -bt N show N callers in stack traces\n"
10228 #define TCC_OPTION_HAS_ARG 0x0001
10229 #define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
10231 typedef struct TCCOption
{
10259 TCC_OPTION_nostdinc
,
10260 TCC_OPTION_nostdlib
,
10261 TCC_OPTION_print_search_dirs
,
10262 TCC_OPTION_rdynamic
,
10269 static const TCCOption tcc_options
[] = {
10270 { "h", TCC_OPTION_HELP
, 0 },
10271 { "?", TCC_OPTION_HELP
, 0 },
10272 { "I", TCC_OPTION_I
, TCC_OPTION_HAS_ARG
},
10273 { "D", TCC_OPTION_D
, TCC_OPTION_HAS_ARG
},
10274 { "U", TCC_OPTION_U
, TCC_OPTION_HAS_ARG
},
10275 { "L", TCC_OPTION_L
, TCC_OPTION_HAS_ARG
},
10276 { "B", TCC_OPTION_B
, TCC_OPTION_HAS_ARG
},
10277 { "l", TCC_OPTION_l
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10278 { "bench", TCC_OPTION_bench
, 0 },
10279 { "bt", TCC_OPTION_bt
, TCC_OPTION_HAS_ARG
},
10280 #ifdef CONFIG_TCC_BCHECK
10281 { "b", TCC_OPTION_b
, 0 },
10283 { "g", TCC_OPTION_g
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10284 { "c", TCC_OPTION_c
, 0 },
10285 { "static", TCC_OPTION_static
, 0 },
10286 { "shared", TCC_OPTION_shared
, 0 },
10287 { "o", TCC_OPTION_o
, TCC_OPTION_HAS_ARG
},
10288 { "run", TCC_OPTION_run
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10289 { "rdynamic", TCC_OPTION_rdynamic
, 0 },
10290 { "r", TCC_OPTION_r
, 0 },
10291 { "Wl,", TCC_OPTION_Wl
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10292 { "W", TCC_OPTION_W
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10293 { "O", TCC_OPTION_O
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10294 { "m", TCC_OPTION_m
, TCC_OPTION_HAS_ARG
},
10295 { "f", TCC_OPTION_f
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10296 { "nostdinc", TCC_OPTION_nostdinc
, 0 },
10297 { "nostdlib", TCC_OPTION_nostdlib
, 0 },
10298 { "print-search-dirs", TCC_OPTION_print_search_dirs
, 0 },
10299 { "v", TCC_OPTION_v
, 0 },
10300 { "w", TCC_OPTION_w
, 0 },
10301 { "pipe", TCC_OPTION_pipe
, 0},
10305 /* convert 'str' into an array of space separated strings */
10306 static int expand_args(char ***pargv
, const char *str
)
10315 while (is_space(*str
))
10320 while (*str
!= '\0' && !is_space(*str
))
10323 arg
= tcc_malloc(len
+ 1);
10324 memcpy(arg
, s1
, len
);
10326 dynarray_add((void ***)&argv
, &argc
, arg
);
10332 static char **files
;
10333 static int nb_files
, nb_libraries
;
10334 static int multiple_files
;
10335 static int print_search_dirs
;
10336 static int output_type
;
10337 static int reloc_output
;
10338 static const char *outfile
;
10340 int parse_args(TCCState
*s
, int argc
, char **argv
)
10343 const TCCOption
*popt
;
10344 const char *optarg
, *p1
, *r1
;
10349 if (optind
>= argc
) {
10350 if (nb_files
== 0 && !print_search_dirs
)
10355 r
= argv
[optind
++];
10357 /* add a new file */
10358 dynarray_add((void ***)&files
, &nb_files
, r
);
10359 if (!multiple_files
) {
10361 /* argv[0] will be this file */
10365 /* find option in table (match only the first chars */
10366 popt
= tcc_options
;
10370 error("invalid option -- '%s'", r
);
10383 if (popt
->flags
& TCC_OPTION_HAS_ARG
) {
10384 if (*r1
!= '\0' || (popt
->flags
& TCC_OPTION_NOSEP
)) {
10387 if (optind
>= argc
)
10388 error("argument to '%s' is missing", r
);
10389 optarg
= argv
[optind
++];
10397 switch(popt
->index
) {
10398 case TCC_OPTION_HELP
:
10403 if (tcc_add_include_path(s
, optarg
) < 0)
10404 error("too many include paths");
10409 sym
= (char *)optarg
;
10410 value
= strchr(sym
, '=');
10415 tcc_define_symbol(s
, sym
, value
);
10419 tcc_undefine_symbol(s
, optarg
);
10422 tcc_add_library_path(s
, optarg
);
10425 /* set tcc utilities path (mainly for tcc development) */
10426 tcc_lib_path
= optarg
;
10429 dynarray_add((void ***)&files
, &nb_files
, r
);
10432 case TCC_OPTION_bench
:
10435 case TCC_OPTION_bt
:
10436 num_callers
= atoi(optarg
);
10438 #ifdef CONFIG_TCC_BCHECK
10440 do_bounds_check
= 1;
10448 multiple_files
= 1;
10449 output_type
= TCC_OUTPUT_OBJ
;
10451 case TCC_OPTION_static
:
10452 s
->static_link
= 1;
10454 case TCC_OPTION_shared
:
10455 output_type
= TCC_OUTPUT_DLL
;
10458 multiple_files
= 1;
10462 /* generate a .o merging several output files */
10464 output_type
= TCC_OUTPUT_OBJ
;
10466 case TCC_OPTION_nostdinc
:
10469 case TCC_OPTION_nostdlib
:
10472 case TCC_OPTION_print_search_dirs
:
10473 print_search_dirs
= 1;
10475 case TCC_OPTION_run
:
10479 argc1
= expand_args(&argv1
, optarg
);
10481 parse_args(s
, argc1
, argv1
);
10483 multiple_files
= 0;
10484 output_type
= TCC_OUTPUT_MEMORY
;
10488 printf("tcc version %s\n", TCC_VERSION
);
10491 if (tcc_set_flag(s
, optarg
, 1) < 0 && s
->warn_unsupported
)
10492 goto unsupported_option
;
10495 if (tcc_set_warning(s
, optarg
, 1) < 0 &&
10496 s
->warn_unsupported
)
10497 goto unsupported_option
;
10502 case TCC_OPTION_rdynamic
:
10505 case TCC_OPTION_Wl
:
10508 if (strstart(optarg
, "-Ttext,", &p
)) {
10509 s
->text_addr
= strtoul(p
, NULL
, 16);
10510 s
->has_text_addr
= 1;
10511 } else if (strstart(optarg
, "--oformat,", &p
)) {
10512 if (strstart(p
, "elf32-", NULL
)) {
10513 s
->output_format
= TCC_OUTPUT_FORMAT_ELF
;
10514 } else if (!strcmp(p
, "binary")) {
10515 s
->output_format
= TCC_OUTPUT_FORMAT_BINARY
;
10517 #ifdef TCC_TARGET_COFF
10518 if (!strcmp(p
, "coff")) {
10519 s
->output_format
= TCC_OUTPUT_FORMAT_COFF
;
10523 error("target %s not found", p
);
10526 error("unsupported linker option '%s'", optarg
);
10531 if (s
->warn_unsupported
) {
10532 unsupported_option
:
10533 warning("unsupported option '%s'", r
);
10542 int main(int argc
, char **argv
)
10546 int nb_objfiles
, ret
, optind
;
10547 char objfilename
[1024];
10548 int64_t start_time
= 0;
10551 /* on win32, we suppose the lib and includes are at the location
10554 static char path
[1024];
10557 GetModuleFileNameA(NULL
, path
, sizeof path
);
10558 p
= d
= strlwr(path
);
10561 if (*d
== '\\') *d
= '/', p
= d
;
10565 tcc_lib_path
= path
;
10570 output_type
= TCC_OUTPUT_EXE
;
10572 multiple_files
= 1;
10577 print_search_dirs
= 0;
10579 optind
= parse_args(s
, argc
- 1, argv
+ 1) + 1;
10581 if (print_search_dirs
) {
10582 /* enough for Linux kernel */
10583 printf("install: %s/\n", tcc_lib_path
);
10587 nb_objfiles
= nb_files
- nb_libraries
;
10589 /* if outfile provided without other options, we output an
10591 if (outfile
&& output_type
== TCC_OUTPUT_MEMORY
)
10592 output_type
= TCC_OUTPUT_EXE
;
10594 /* check -c consistency : only single file handled. XXX: checks file type */
10595 if (output_type
== TCC_OUTPUT_OBJ
&& !reloc_output
) {
10596 /* accepts only a single input file */
10597 if (nb_objfiles
!= 1)
10598 error("cannot specify multiple files with -c");
10599 if (nb_libraries
!= 0)
10600 error("cannot specify libraries with -c");
10603 if (output_type
!= TCC_OUTPUT_MEMORY
) {
10605 /* compute default outfile name */
10606 pstrcpy(objfilename
, sizeof(objfilename
) - 1,
10608 tcc_basename(files
[0]));
10609 #ifdef TCC_TARGET_PE
10610 pe_guess_outfile(objfilename
, output_type
);
10612 if (output_type
== TCC_OUTPUT_OBJ
&& !reloc_output
) {
10613 char *ext
= strrchr(objfilename
, '.');
10615 goto default_outfile
;
10616 /* add .o extension */
10617 strcpy(ext
+ 1, "o");
10620 pstrcpy(objfilename
, sizeof(objfilename
), "a.out");
10623 outfile
= objfilename
;
10628 start_time
= getclock_us();
10631 tcc_set_output_type(s
, output_type
);
10633 /* compile or add each files or library */
10634 for(i
= 0;i
< nb_files
; i
++) {
10635 const char *filename
;
10637 filename
= files
[i
];
10638 if (filename
[0] == '-') {
10639 if (tcc_add_library(s
, filename
+ 2) < 0)
10640 error("cannot find %s", filename
);
10642 if (tcc_add_file(s
, filename
) < 0) {
10649 /* free all files */
10654 total_time
= (double)(getclock_us() - start_time
) / 1000000.0;
10655 if (total_time
< 0.001)
10656 total_time
= 0.001;
10657 if (total_bytes
< 1)
10659 printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
10660 tok_ident
- TOK_IDENT
, total_lines
, total_bytes
,
10661 total_time
, (int)(total_lines
/ total_time
),
10662 total_bytes
/ total_time
/ 1000000.0);
10665 if (s
->output_type
== TCC_OUTPUT_MEMORY
) {
10666 ret
= tcc_run(s
, argc
- optind
, argv
+ optind
);
10668 #ifdef TCC_TARGET_PE
10669 if (s
->output_type
!= TCC_OUTPUT_OBJ
) {
10670 ret
= tcc_output_pe(s
, outfile
);
10674 tcc_output_file(s
, outfile
);
10678 /* XXX: cannot do it with bound checking because of the malloc hooks */
10679 if (!do_bounds_check
)
10684 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size
, mem_max_size
);