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>
47 #include <sys/ucontext.h>
51 #endif /* !CONFIG_TCCBOOT */
68 /* preprocessor debug */
70 /* include file debug */
78 /* target selection */
79 //#define TCC_TARGET_I386 /* i386 code generator */
80 //#define TCC_TARGET_ARM /* ARMv4 code generator */
81 //#define TCC_TARGET_C67 /* TMS320C67xx code generator */
83 /* default target is I386 */
84 #if !defined(TCC_TARGET_I386) && !defined(TCC_TARGET_ARM) && \
85 !defined(TCC_TARGET_C67)
86 #define TCC_TARGET_I386
89 #if !defined(WIN32) && !defined(TCC_UCLIBC) && !defined(TCC_TARGET_ARM) && \
90 !defined(TCC_TARGET_C67)
91 #define CONFIG_TCC_BCHECK /* enable bound checking code */
94 #if defined(WIN32) && !defined(TCC_TARGET_PE)
95 #define CONFIG_TCC_STATIC
98 /* define it to include assembler support */
99 #if !defined(TCC_TARGET_ARM) && !defined(TCC_TARGET_C67)
100 #define CONFIG_TCC_ASM
103 /* object format selection */
104 #if defined(TCC_TARGET_C67)
105 #define TCC_TARGET_COFF
114 /* path to find crt1.o, crti.o and crtn.o. Only needed when generating
115 executables or dlls */
116 #define CONFIG_TCC_CRT_PREFIX "/usr/lib"
118 #define INCLUDE_STACK_SIZE 32
119 #define IFDEF_STACK_SIZE 64
120 #define VSTACK_SIZE 256
121 #define STRING_MAX_SIZE 1024
122 #define PACK_STACK_SIZE 8
124 #define TOK_HASH_SIZE 8192 /* must be a power of two */
125 #define TOK_ALLOC_INCR 512 /* must be a power of two */
126 #define TOK_MAX_SIZE 4 /* token max size in int unit when stored in string */
128 /* token symbol management */
129 typedef struct TokenSym
{
130 struct TokenSym
*hash_next
;
131 struct Sym
*sym_define
; /* direct pointer to define */
132 struct Sym
*sym_label
; /* direct pointer to label */
133 struct Sym
*sym_struct
; /* direct pointer to structure */
134 struct Sym
*sym_identifier
; /* direct pointer to identifier */
135 int tok
; /* token number */
140 typedef struct CString
{
141 int size
; /* size in bytes */
142 void *data
; /* either 'char *' or 'int *' */
144 void *data_allocated
; /* if non NULL, data has been malloced */
147 /* type definition */
148 typedef struct CType
{
154 typedef union CValue
{
160 unsigned int ul
; /* address (should be unsigned long on 64 bit cpu) */
162 unsigned long long ull
;
163 struct CString
*cstr
;
169 typedef struct SValue
{
170 CType type
; /* type */
171 unsigned short r
; /* register + flags */
172 unsigned short r2
; /* second register, used for 'long long'
173 type. If not used, set to VT_CONST */
174 CValue c
; /* constant, if VT_CONST */
175 struct Sym
*sym
; /* symbol, if (VT_SYM | VT_CONST) */
178 /* symbol management */
180 int v
; /* symbol token */
181 int r
; /* associated register */
182 int c
; /* associated number */
183 CType type
; /* associated type */
184 struct Sym
*next
; /* next related symbol */
185 struct Sym
*prev
; /* prev symbol in stack */
186 struct Sym
*prev_tok
; /* previous symbol for this token */
189 /* section definition */
190 /* XXX: use directly ELF structure for parameters ? */
191 /* special flag to indicate that the section should not be linked to
193 #define SHF_PRIVATE 0x80000000
195 typedef struct Section
{
196 unsigned long data_offset
; /* current data offset */
197 unsigned char *data
; /* section data */
198 unsigned long data_allocated
; /* used for realloc() handling */
199 int sh_name
; /* elf section name (only used during output) */
200 int sh_num
; /* elf section number */
201 int sh_type
; /* elf section type */
202 int sh_flags
; /* elf section flags */
203 int sh_info
; /* elf section info */
204 int sh_addralign
; /* elf section alignment */
205 int sh_entsize
; /* elf entry size */
206 unsigned long sh_size
; /* section size (only used during output) */
207 unsigned long sh_addr
; /* address at which the section is relocated */
208 unsigned long sh_offset
; /* file offset */
209 int nb_hashed_syms
; /* used to resize the hash table */
210 struct Section
*link
; /* link to another section */
211 struct Section
*reloc
; /* corresponding section for relocation, if any */
212 struct Section
*hash
; /* hash table for symbols */
213 struct Section
*next
;
214 char name
[1]; /* section name */
217 typedef struct DLLReference
{
222 /* GNUC attribute definition */
223 typedef struct AttributeDef
{
227 unsigned char func_call
; /* FUNC_CDECL, FUNC_STDCALL, FUNC_FASTCALLx */
228 unsigned char dllexport
;
231 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
232 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
233 #define SYM_FIRST_ANOM 0x10000000 /* first anonymous sym */
235 /* stored in 'Sym.c' field */
236 #define FUNC_NEW 1 /* ansi function prototype */
237 #define FUNC_OLD 2 /* old function prototype */
238 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
240 /* stored in 'Sym.r' field */
241 #define FUNC_CDECL 0 /* standard c call */
242 #define FUNC_STDCALL 1 /* pascal c call */
243 #define FUNC_FASTCALL1 2 /* first param in %eax */
244 #define FUNC_FASTCALL2 3 /* first parameters in %eax, %edx */
245 #define FUNC_FASTCALL3 4 /* first parameter in %eax, %edx, %ecx */
247 /* field 'Sym.t' for macros */
248 #define MACRO_OBJ 0 /* object like macro */
249 #define MACRO_FUNC 1 /* function like macro */
251 /* field 'Sym.r' for C labels */
252 #define LABEL_DEFINED 0 /* label is defined */
253 #define LABEL_FORWARD 1 /* label is forward defined */
254 #define LABEL_DECLARED 2 /* label is declared but never used */
256 /* type_decl() types */
257 #define TYPE_ABSTRACT 1 /* type without variable */
258 #define TYPE_DIRECT 2 /* type with variable */
260 #define IO_BUF_SIZE 8192
262 typedef struct BufferedFile
{
266 int line_num
; /* current line number - here to simplify code */
267 int ifndef_macro
; /* #ifndef macro / #endif search */
268 int ifndef_macro_saved
; /* saved ifndef_macro */
269 int *ifdef_stack_ptr
; /* ifdef_stack value at the start of the file */
270 char inc_type
; /* type of include */
271 char inc_filename
[512]; /* filename specified by the user */
272 char filename
[1024]; /* current filename - here to simplify code */
273 unsigned char buffer
[IO_BUF_SIZE
+ 1]; /* extra size for CH_EOB char */
276 #define CH_EOB '\\' /* end of buffer or '\0' char in file */
277 #define CH_EOF (-1) /* end of file */
279 /* parsing state (used to save parser state to reparse part of the
280 source several times) */
281 typedef struct ParseState
{
288 /* used to record tokens */
289 typedef struct TokenString
{
296 /* include file cache, used to find files faster and also to eliminate
297 inclusion if the include file is protected by #ifndef ... #endif */
298 typedef struct CachedInclude
{
300 int hash_next
; /* -1 if none */
301 char type
; /* '"' or '>' to give include type */
302 char filename
[1]; /* path specified in #include */
305 #define CACHED_INCLUDES_HASH_SIZE 512
308 static struct BufferedFile
*file
;
311 static CString tokcstr
; /* current parsed string, if any */
312 /* additional informations about token */
313 static int tok_flags
;
314 #define TOK_FLAG_BOL 0x0001 /* beginning of line before */
315 #define TOK_FLAG_BOF 0x0002 /* beginning of file before */
316 #define TOK_FLAG_ENDIF 0x0004 /* a endif was found matching starting #ifdef */
318 static int *macro_ptr
, *macro_ptr_allocated
;
319 static int *unget_saved_macro_ptr
;
320 static int unget_saved_buffer
[TOK_MAX_SIZE
+ 1];
321 static int unget_buffer_enabled
;
322 static int parse_flags
;
323 #define PARSE_FLAG_PREPROCESS 0x0001 /* activate preprocessing */
324 #define PARSE_FLAG_TOK_NUM 0x0002 /* return numbers instead of TOK_PPNUM */
325 #define PARSE_FLAG_LINEFEED 0x0004 /* line feed is returned as a
326 token. line feed is also
328 #define PARSE_FLAG_ASM_COMMENTS 0x0008 /* '#' can be used for line comment */
330 static Section
*text_section
, *data_section
, *bss_section
; /* predefined sections */
331 static Section
*cur_text_section
; /* current section where function code is
333 #ifdef CONFIG_TCC_ASM
334 static Section
*last_text_section
; /* to handle .previous asm directive */
336 /* bound check related sections */
337 static Section
*bounds_section
; /* contains global data bound description */
338 static Section
*lbounds_section
; /* contains local data bound description */
339 /* symbol sections */
340 static Section
*symtab_section
, *strtab_section
;
343 static Section
*stab_section
, *stabstr_section
;
345 /* loc : local variable index
346 ind : output code index
348 anon_sym: anonymous symbol index
350 static int rsym
, anon_sym
, ind
, loc
;
351 /* expression generation modifiers */
352 static int const_wanted
; /* true if constant wanted */
353 static int nocode_wanted
; /* true if no code generation wanted for an expression */
354 static int global_expr
; /* true if compound literals must be allocated
355 globally (used during initializers parsing */
356 static CType func_vt
; /* current function return type (used by return
359 static int last_line_num
, last_ind
, func_ind
; /* debug last line number and pc */
360 static int tok_ident
;
361 static TokenSym
**table_ident
;
362 static TokenSym
*hash_ident
[TOK_HASH_SIZE
];
363 static char token_buf
[STRING_MAX_SIZE
+ 1];
364 static char *funcname
;
365 static Sym
*global_stack
, *local_stack
;
366 static Sym
*define_stack
;
367 static Sym
*global_label_stack
, *local_label_stack
;
368 /* symbol allocator */
369 #define SYM_POOL_NB (8192 / sizeof(Sym))
370 static Sym
*sym_free_first
;
372 static SValue vstack
[VSTACK_SIZE
], *vtop
;
373 /* some predefined types */
374 static CType char_pointer_type
, func_old_type
, int_type
;
375 /* true if isid(c) || isnum(c) */
376 static unsigned char isidnum_table
[256];
378 /* compile with debug symbol (and use them if error during execution) */
379 static int do_debug
= 0;
381 /* compile with built-in memory and bounds checker */
382 static int do_bounds_check
= 0;
384 /* display benchmark infos */
386 static int do_bench
= 0;
388 static int total_lines
;
389 static int total_bytes
;
391 /* use GNU C extensions */
392 static int gnu_ext
= 1;
394 /* use Tiny C extensions */
395 static int tcc_ext
= 1;
397 /* max number of callers shown if error */
398 static int num_callers
= 6;
399 static const char **rt_bound_error_msg
;
401 /* XXX: get rid of this ASAP */
402 static struct TCCState
*tcc_state
;
404 /* give the path of the tcc libraries */
405 static const char *tcc_lib_path
= CONFIG_TCCDIR
;
410 BufferedFile
**include_stack_ptr
;
411 int *ifdef_stack_ptr
;
413 /* include file handling */
414 char **include_paths
;
415 int nb_include_paths
;
416 char **sysinclude_paths
;
417 int nb_sysinclude_paths
;
418 CachedInclude
**cached_includes
;
419 int nb_cached_includes
;
421 char **library_paths
;
422 int nb_library_paths
;
424 /* array of all loaded dlls (including those referenced by loaded
426 DLLReference
**loaded_dlls
;
431 int nb_sections
; /* number of sections, including first dummy section */
436 unsigned long *got_offsets
;
438 /* give the correspondance from symtab indexes to dynsym indexes */
439 int *symtab_to_dynsym
;
441 /* temporary dynamic symbol sections (for dll loading) */
442 Section
*dynsymtab_section
;
443 /* exported dynamic symbol section */
446 int nostdinc
; /* if true, no standard headers are added */
447 int nostdlib
; /* if true, no standard libraries are added */
449 int nocommon
; /* if true, do not use common symbols for .bss data */
451 /* if true, static linking is performed */
454 /* if true, all symbols are exported */
457 /* if true, only link in referenced objects from archive */
460 /* address of text section */
461 unsigned long text_addr
;
464 /* output format, see TCC_OUTPUT_FORMAT_xxx */
467 /* C language options */
468 int char_is_unsigned
;
469 int leading_underscore
;
471 /* warning switches */
472 int warn_write_strings
;
473 int warn_unsupported
;
476 int warn_implicit_function_declaration
;
480 void (*error_func
)(void *opaque
, const char *msg
);
481 int error_set_jmp_enabled
;
482 jmp_buf error_jmp_buf
;
485 /* tiny assembler state */
488 /* see include_stack_ptr */
489 BufferedFile
*include_stack
[INCLUDE_STACK_SIZE
];
491 /* see ifdef_stack_ptr */
492 int ifdef_stack
[IFDEF_STACK_SIZE
];
494 /* see cached_includes */
495 int cached_includes_hash
[CACHED_INCLUDES_HASH_SIZE
];
498 int pack_stack
[PACK_STACK_SIZE
];
502 /* The current value can be: */
503 #define VT_VALMASK 0x00ff
504 #define VT_CONST 0x00f0 /* constant in vc
505 (must be first non register value) */
506 #define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */
507 #define VT_LOCAL 0x00f2 /* offset on stack */
508 #define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */
509 #define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */
510 #define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */
511 #define VT_LVAL 0x0100 /* var is an lvalue */
512 #define VT_SYM 0x0200 /* a symbol value is added */
513 #define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for
514 char/short stored in integer registers) */
515 #define VT_MUSTBOUND 0x0800 /* bound checking must be done before
516 dereferencing value */
517 #define VT_BOUNDED 0x8000 /* value is bounded. The address of the
518 bounding function call point is in vc */
519 #define VT_LVAL_BYTE 0x1000 /* lvalue is a byte */
520 #define VT_LVAL_SHORT 0x2000 /* lvalue is a short */
521 #define VT_LVAL_UNSIGNED 0x4000 /* lvalue is unsigned */
522 #define VT_LVAL_TYPE (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)
525 #define VT_INT 0 /* integer type */
526 #define VT_BYTE 1 /* signed byte type */
527 #define VT_SHORT 2 /* short type */
528 #define VT_VOID 3 /* void type */
529 #define VT_PTR 4 /* pointer */
530 #define VT_ENUM 5 /* enum definition */
531 #define VT_FUNC 6 /* function type */
532 #define VT_STRUCT 7 /* struct/union definition */
533 #define VT_FLOAT 8 /* IEEE float */
534 #define VT_DOUBLE 9 /* IEEE double */
535 #define VT_LDOUBLE 10 /* IEEE long double */
536 #define VT_BOOL 11 /* ISOC99 boolean type */
537 #define VT_LLONG 12 /* 64 bit integer */
538 #define VT_LONG 13 /* long integer (NEVER USED as type, only
540 #define VT_BTYPE 0x000f /* mask for basic type */
541 #define VT_UNSIGNED 0x0010 /* unsigned type */
542 #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
543 #define VT_BITFIELD 0x0040 /* bitfield modifier */
544 #define VT_CONSTANT 0x0800 /* const modifier */
545 #define VT_VOLATILE 0x1000 /* volatile modifier */
546 #define VT_SIGNED 0x2000 /* signed type */
549 #define VT_EXTERN 0x00000080 /* extern definition */
550 #define VT_STATIC 0x00000100 /* static variable */
551 #define VT_TYPEDEF 0x00000200 /* typedef definition */
552 #define VT_INLINE 0x00000400 /* inline definition */
554 #define VT_STRUCT_SHIFT 16 /* shift for bitfield shift values */
556 /* type mask (except storage) */
557 #define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE)
558 #define VT_TYPE (~(VT_STORAGE))
562 /* warning: the following compare tokens depend on i386 asm code */
574 #define TOK_LAND 0xa0
578 #define TOK_MID 0xa3 /* inc/dec, to void constant */
580 #define TOK_UDIV 0xb0 /* unsigned division */
581 #define TOK_UMOD 0xb1 /* unsigned modulo */
582 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
583 #define TOK_CINT 0xb3 /* number in tokc */
584 #define TOK_CCHAR 0xb4 /* char constant in tokc */
585 #define TOK_STR 0xb5 /* pointer to string in tokc */
586 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
587 #define TOK_LCHAR 0xb7
588 #define TOK_LSTR 0xb8
589 #define TOK_CFLOAT 0xb9 /* float constant */
590 #define TOK_LINENUM 0xba /* line number info */
591 #define TOK_CDOUBLE 0xc0 /* double constant */
592 #define TOK_CLDOUBLE 0xc1 /* long double constant */
593 #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
594 #define TOK_ADDC1 0xc3 /* add with carry generation */
595 #define TOK_ADDC2 0xc4 /* add with carry use */
596 #define TOK_SUBC1 0xc5 /* add with carry generation */
597 #define TOK_SUBC2 0xc6 /* add with carry use */
598 #define TOK_CUINT 0xc8 /* unsigned int constant */
599 #define TOK_CLLONG 0xc9 /* long long constant */
600 #define TOK_CULLONG 0xca /* unsigned long long constant */
601 #define TOK_ARROW 0xcb
602 #define TOK_DOTS 0xcc /* three dots */
603 #define TOK_SHR 0xcd /* unsigned shift right */
604 #define TOK_PPNUM 0xce /* preprocessor number */
606 #define TOK_SHL 0x01 /* shift left */
607 #define TOK_SAR 0x02 /* signed shift right */
609 /* assignement operators : normal operator or 0x80 */
610 #define TOK_A_MOD 0xa5
611 #define TOK_A_AND 0xa6
612 #define TOK_A_MUL 0xaa
613 #define TOK_A_ADD 0xab
614 #define TOK_A_SUB 0xad
615 #define TOK_A_DIV 0xaf
616 #define TOK_A_XOR 0xde
617 #define TOK_A_OR 0xfc
618 #define TOK_A_SHL 0x81
619 #define TOK_A_SAR 0x82
622 #define offsetof(type, field) ((size_t) &((type *)0)->field)
626 #define countof(tab) (sizeof(tab) / sizeof((tab)[0]))
629 /* WARNING: the content of this string encodes token numbers */
630 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";
632 #define TOK_EOF (-1) /* end of file */
633 #define TOK_LINEFEED 10 /* line feed */
635 /* all identificators and strings have token above that */
636 #define TOK_IDENT 256
638 /* only used for i386 asm opcodes definitions */
639 #define DEF_ASM(x) DEF(TOK_ASM_ ## x, #x)
642 DEF(TOK_ASM_ ## x ## b, #x "b") \
643 DEF(TOK_ASM_ ## x ## w, #x "w") \
644 DEF(TOK_ASM_ ## x ## l, #x "l") \
645 DEF(TOK_ASM_ ## x, #x)
648 DEF(TOK_ASM_ ## x ## w, #x "w") \
649 DEF(TOK_ASM_ ## x ## l, #x "l") \
650 DEF(TOK_ASM_ ## x, #x)
653 DEF(TOK_ASM_ ## f ## x ## s, "f" #x "s") \
654 DEF(TOK_ASM_ ## fi ## x ## l, "fi" #x "l") \
655 DEF(TOK_ASM_ ## f ## x ## l, "f" #x "l") \
656 DEF(TOK_ASM_ ## fi ## x ## s, "fi" #x "s")
659 DEF(TOK_ASM_ ## f ## x, "f" #x ) \
660 DEF(TOK_ASM_ ## f ## x ## p, "f" #x "p") \
663 #define DEF_ASMTEST(x) \
695 #define TOK_ASM_int TOK_INT
698 TOK_LAST
= TOK_IDENT
- 1,
699 #define DEF(id, str) id,
704 static const char tcc_keywords
[] =
705 #define DEF(id, str) str "\0"
710 #define TOK_UIDENT TOK_DEFINE
713 int __stdcall
GetModuleFileNameA(void *, char *, int);
714 void *__stdcall
GetProcAddress(void *, const char *);
715 void *__stdcall
GetModuleHandleA(const char *);
716 void *__stdcall
LoadLibraryA(const char *);
717 int __stdcall
FreeConsole(void);
719 #define snprintf _snprintf
720 #define vsnprintf _vsnprintf
722 #define strtold (long double)strtod
723 #define strtof (float)strtod
724 #define strtoll (long long)strtol
726 #elif defined(TCC_UCLIBC) || defined(__FreeBSD__)
727 /* currently incorrect */
728 long double strtold(const char *nptr
, char **endptr
)
730 return (long double)strtod(nptr
, endptr
);
732 float strtof(const char *nptr
, char **endptr
)
734 return (float)strtod(nptr
, endptr
);
737 /* XXX: need to define this to use them in non ISOC99 context */
738 extern float strtof (const char *__nptr
, char **__endptr
);
739 extern long double strtold (const char *__nptr
, char **__endptr
);
742 static char *pstrcpy(char *buf
, int buf_size
, const char *s
);
743 static char *pstrcat(char *buf
, int buf_size
, const char *s
);
744 static const char *tcc_basename(const char *name
);
746 static void next(void);
747 static void next_nomacro(void);
748 static void parse_expr_type(CType
*type
);
749 static void expr_type(CType
*type
);
750 static void unary_type(CType
*type
);
751 static void block(int *bsym
, int *csym
, int *case_sym
, int *def_sym
,
752 int case_reg
, int is_expr
);
753 static int expr_const(void);
754 static void expr_eq(void);
755 static void gexpr(void);
756 static void gen_inline_functions(void);
757 static void decl(int l
);
758 static void decl_initializer(CType
*type
, Section
*sec
, unsigned long c
,
759 int first
, int size_only
);
760 static void decl_initializer_alloc(CType
*type
, AttributeDef
*ad
, int r
,
761 int has_init
, int v
, int scope
);
763 void gv2(int rc1
, int rc2
);
764 void move_reg(int r
, int s
);
765 void save_regs(int n
);
766 void save_reg(int r
);
771 int get_reg_ex(int rc
,int rc2
);
774 struct macro_level
*prev
;
778 static void macro_subst(TokenString
*tok_str
, Sym
**nested_list
,
779 const int *macro_str
, struct macro_level
**can_read_stream
);
781 void force_charshort_cast(int t
);
782 static void gen_cast(CType
*type
);
784 static Sym
*sym_find(int v
);
785 static Sym
*sym_push(int v
, CType
*type
, int r
, int c
);
788 static int type_size(CType
*type
, int *a
);
789 static inline CType
*pointed_type(CType
*type
);
790 static int pointed_size(CType
*type
);
791 static int lvalue_type(int t
);
792 static int parse_btype(CType
*type
, AttributeDef
*ad
);
793 static void type_decl(CType
*type
, AttributeDef
*ad
, int *v
, int td
);
794 static int is_compatible_types(CType
*type1
, CType
*type2
);
796 int ieee_finite(double d
);
797 void error(const char *fmt
, ...);
801 void lexpand_nr(void);
802 static void vpush_global_sym(CType
*type
, int v
);
803 void vset(CType
*type
, int r
, int v
);
804 void type_to_str(char *buf
, int buf_size
,
805 CType
*type
, const char *varstr
);
806 char *get_tok_str(int v
, CValue
*cv
);
807 static Sym
*get_sym_ref(CType
*type
, Section
*sec
,
808 unsigned long offset
, unsigned long size
);
809 static Sym
*external_global_sym(int v
, CType
*type
, int r
);
811 /* section generation */
812 static void section_realloc(Section
*sec
, unsigned long new_size
);
813 static void *section_ptr_add(Section
*sec
, unsigned long size
);
814 static void put_extern_sym(Sym
*sym
, Section
*section
,
815 unsigned long value
, unsigned long size
);
816 static void greloc(Section
*s
, Sym
*sym
, unsigned long addr
, int type
);
817 static int put_elf_str(Section
*s
, const char *sym
);
818 static int put_elf_sym(Section
*s
,
819 unsigned long value
, unsigned long size
,
820 int info
, int other
, int shndx
, const char *name
);
821 static int add_elf_sym(Section
*s
, unsigned long value
, unsigned long size
,
822 int info
, int other
, int sh_num
, const char *name
);
823 static void put_elf_reloc(Section
*symtab
, Section
*s
, unsigned long offset
,
824 int type
, int symbol
);
825 static void put_stabs(const char *str
, int type
, int other
, int desc
,
826 unsigned long value
);
827 static void put_stabs_r(const char *str
, int type
, int other
, int desc
,
828 unsigned long value
, Section
*sec
, int sym_index
);
829 static void put_stabn(int type
, int other
, int desc
, int value
);
830 static void put_stabd(int type
, int other
, int desc
);
831 static int tcc_add_dll(TCCState
*s
, const char *filename
, int flags
);
833 #define AFF_PRINT_ERROR 0x0001 /* print error if file not found */
834 #define AFF_REFERENCED_DLL 0x0002 /* load a referenced dll from another dll */
835 static int tcc_add_file_internal(TCCState
*s
, const char *filename
, int flags
);
838 int tcc_output_coff(TCCState
*s1
, FILE *f
);
841 void *resolve_sym(TCCState
*s1
, const char *sym
, int type
);
842 int pe_load_def_file(struct TCCState
*s1
, FILE *fp
);
843 void pe_setup_paths(struct TCCState
*s1
, int *p_output_type
, const char **p_outfile
, char *first_file
);
844 unsigned long pe_add_runtime(struct TCCState
*s1
);
845 int tcc_output_pe(struct TCCState
*s1
, const char *filename
);
849 #ifdef CONFIG_TCC_ASM
851 typedef struct ExprValue
{
856 #define MAX_ASM_OPERANDS 30
858 typedef struct ASMOperand
{
859 int id
; /* GCC 3 optionnal identifier (0 if number only supported */
861 char asm_str
[16]; /* computed asm string for operand */
862 SValue
*vt
; /* C value of the expression */
863 int ref_index
; /* if >= 0, gives reference to a output constraint */
864 int input_index
; /* if >= 0, gives reference to an input constraint */
865 int priority
; /* priority, used to assign registers */
866 int reg
; /* if >= 0, register number used for this operand */
867 int is_llong
; /* true if double register value */
868 int is_memory
; /* true if memory operand */
869 int is_rw
; /* for '+' modifier */
872 static void asm_expr(TCCState
*s1
, ExprValue
*pe
);
873 static int asm_int_expr(TCCState
*s1
);
874 static int find_constraint(ASMOperand
*operands
, int nb_operands
,
875 const char *name
, const char **pp
);
877 static int tcc_assemble(TCCState
*s1
, int do_preprocess
);
881 static void asm_instr(void);
882 static void asm_global_instr(void);
884 /* true if float/double/long double type */
885 static inline int is_float(int t
)
889 return bt
== VT_LDOUBLE
|| bt
== VT_DOUBLE
|| bt
== VT_FLOAT
;
892 #ifdef TCC_TARGET_I386
893 #include "i386-gen.c"
896 #ifdef TCC_TARGET_ARM
900 #ifdef TCC_TARGET_C67
904 #ifdef CONFIG_TCC_STATIC
906 #define RTLD_LAZY 0x001
907 #define RTLD_NOW 0x002
908 #define RTLD_GLOBAL 0x100
909 #define RTLD_DEFAULT NULL
911 /* dummy function for profiling */
912 void *dlopen(const char *filename
, int flag
)
917 const char *dlerror(void)
922 typedef struct TCCSyms
{
927 #define TCCSYM(a) { #a, &a, },
929 /* add the symbol you want here if no dynamic linking is done */
930 static TCCSyms tcc_syms
[] = {
931 #if !defined(CONFIG_TCCBOOT)
940 void *resolve_sym(TCCState
*s1
, const char *symbol
, int type
)
944 while (p
->str
!= NULL
) {
945 if (!strcmp(p
->str
, symbol
))
952 #elif !defined(WIN32)
956 void *resolve_sym(TCCState
*s1
, const char *sym
, int type
)
958 return dlsym(RTLD_DEFAULT
, sym
);
963 /********************************************************/
965 /* we use our own 'finite' function to avoid potential problems with
966 non standard math libs */
967 /* XXX: endianness dependent */
968 int ieee_finite(double d
)
971 return ((unsigned)((p
[1] | 0x800fffff) + 1)) >> 31;
974 /* copy a string and truncate it. */
975 static char *pstrcpy(char *buf
, int buf_size
, const char *s
)
982 q_end
= buf
+ buf_size
- 1;
994 /* strcat and truncate. */
995 static char *pstrcat(char *buf
, int buf_size
, const char *s
)
1000 pstrcpy(buf
+ len
, buf_size
- len
, s
);
1004 static int strstart(const char *str
, const char *val
, const char **ptr
)
1009 while (*q
!= '\0') {
1020 /* memory management */
1026 static inline void tcc_free(void *ptr
)
1029 mem_cur_size
-= malloc_usable_size(ptr
);
1034 static void *tcc_malloc(unsigned long size
)
1039 error("memory full");
1041 mem_cur_size
+= malloc_usable_size(ptr
);
1042 if (mem_cur_size
> mem_max_size
)
1043 mem_max_size
= mem_cur_size
;
1048 static void *tcc_mallocz(unsigned long size
)
1051 ptr
= tcc_malloc(size
);
1052 memset(ptr
, 0, size
);
1056 static inline void *tcc_realloc(void *ptr
, unsigned long size
)
1060 mem_cur_size
-= malloc_usable_size(ptr
);
1062 ptr1
= realloc(ptr
, size
);
1064 /* NOTE: count not correct if alloc error, but not critical */
1065 mem_cur_size
+= malloc_usable_size(ptr1
);
1066 if (mem_cur_size
> mem_max_size
)
1067 mem_max_size
= mem_cur_size
;
1072 static char *tcc_strdup(const char *str
)
1075 ptr
= tcc_malloc(strlen(str
) + 1);
1080 #define free(p) use_tcc_free(p)
1081 #define malloc(s) use_tcc_malloc(s)
1082 #define realloc(p, s) use_tcc_realloc(p, s)
1084 static void dynarray_add(void ***ptab
, int *nb_ptr
, void *data
)
1091 /* every power of two we double array size */
1092 if ((nb
& (nb
- 1)) == 0) {
1097 pp
= tcc_realloc(pp
, nb_alloc
* sizeof(void *));
1099 error("memory full");
1106 /* symbol allocator */
1107 static Sym
*__sym_malloc(void)
1109 Sym
*sym_pool
, *sym
, *last_sym
;
1112 sym_pool
= tcc_malloc(SYM_POOL_NB
* sizeof(Sym
));
1114 last_sym
= sym_free_first
;
1116 for(i
= 0; i
< SYM_POOL_NB
; i
++) {
1117 sym
->next
= last_sym
;
1121 sym_free_first
= last_sym
;
1125 static inline Sym
*sym_malloc(void)
1128 sym
= sym_free_first
;
1130 sym
= __sym_malloc();
1131 sym_free_first
= sym
->next
;
1135 static inline void sym_free(Sym
*sym
)
1137 sym
->next
= sym_free_first
;
1138 sym_free_first
= sym
;
1141 Section
*new_section(TCCState
*s1
, const char *name
, int sh_type
, int sh_flags
)
1145 sec
= tcc_mallocz(sizeof(Section
) + strlen(name
));
1146 strcpy(sec
->name
, name
);
1147 sec
->sh_type
= sh_type
;
1148 sec
->sh_flags
= sh_flags
;
1155 sec
->sh_addralign
= 4;
1158 sec
->sh_addralign
= 1;
1161 sec
->sh_addralign
= 32; /* default conservative alignment */
1165 /* only add section if not private */
1166 if (!(sh_flags
& SHF_PRIVATE
)) {
1167 sec
->sh_num
= s1
->nb_sections
;
1168 dynarray_add((void ***)&s1
->sections
, &s1
->nb_sections
, sec
);
1173 static void free_section(Section
*s
)
1179 /* realloc section and set its content to zero */
1180 static void section_realloc(Section
*sec
, unsigned long new_size
)
1183 unsigned char *data
;
1185 size
= sec
->data_allocated
;
1188 while (size
< new_size
)
1190 data
= tcc_realloc(sec
->data
, size
);
1192 error("memory full");
1193 memset(data
+ sec
->data_allocated
, 0, size
- sec
->data_allocated
);
1195 sec
->data_allocated
= size
;
1198 /* reserve at least 'size' bytes in section 'sec' from
1199 sec->data_offset. */
1200 static void *section_ptr_add(Section
*sec
, unsigned long size
)
1202 unsigned long offset
, offset1
;
1204 offset
= sec
->data_offset
;
1205 offset1
= offset
+ size
;
1206 if (offset1
> sec
->data_allocated
)
1207 section_realloc(sec
, offset1
);
1208 sec
->data_offset
= offset1
;
1209 return sec
->data
+ offset
;
1212 /* return a reference to a section, and create it if it does not
1214 Section
*find_section(TCCState
*s1
, const char *name
)
1218 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1219 sec
= s1
->sections
[i
];
1220 if (!strcmp(name
, sec
->name
))
1223 /* sections are created as PROGBITS */
1224 return new_section(s1
, name
, SHT_PROGBITS
, SHF_ALLOC
);
1227 #define SECTION_ABS ((void *)1)
1229 /* update sym->c so that it points to an external symbol in section
1230 'section' with value 'value' */
1231 static void put_extern_sym2(Sym
*sym
, Section
*section
,
1232 unsigned long value
, unsigned long size
,
1233 int can_add_underscore
)
1235 int sym_type
, sym_bind
, sh_num
, info
;
1240 if (section
== NULL
)
1242 else if (section
== SECTION_ABS
)
1245 sh_num
= section
->sh_num
;
1247 if ((sym
->type
.t
& VT_BTYPE
) == VT_FUNC
)
1248 sym_type
= STT_FUNC
;
1250 sym_type
= STT_OBJECT
;
1251 if (sym
->type
.t
& VT_STATIC
)
1252 sym_bind
= STB_LOCAL
;
1254 sym_bind
= STB_GLOBAL
;
1256 name
= get_tok_str(sym
->v
, NULL
);
1257 #ifdef CONFIG_TCC_BCHECK
1258 if (do_bounds_check
) {
1261 /* XXX: avoid doing that for statics ? */
1262 /* if bound checking is activated, we change some function
1263 names by adding the "__bound" prefix */
1266 /* XXX: we rely only on malloc hooks */
1278 strcpy(buf
, "__bound_");
1285 if (tcc_state
->leading_underscore
&& can_add_underscore
) {
1287 pstrcpy(buf1
+ 1, sizeof(buf1
) - 1, name
);
1290 info
= ELF32_ST_INFO(sym_bind
, sym_type
);
1291 sym
->c
= add_elf_sym(symtab_section
, value
, size
, info
, 0, sh_num
, name
);
1293 esym
= &((Elf32_Sym
*)symtab_section
->data
)[sym
->c
];
1294 esym
->st_value
= value
;
1295 esym
->st_size
= size
;
1296 esym
->st_shndx
= sh_num
;
1300 static void put_extern_sym(Sym
*sym
, Section
*section
,
1301 unsigned long value
, unsigned long size
)
1303 put_extern_sym2(sym
, section
, value
, size
, 1);
1306 /* add a new relocation entry to symbol 'sym' in section 's' */
1307 static void greloc(Section
*s
, Sym
*sym
, unsigned long offset
, int type
)
1310 put_extern_sym(sym
, NULL
, 0, 0);
1311 /* now we can add ELF relocation info */
1312 put_elf_reloc(symtab_section
, s
, offset
, type
, sym
->c
);
1315 static inline int isid(int c
)
1317 return (c
>= 'a' && c
<= 'z') ||
1318 (c
>= 'A' && c
<= 'Z') ||
1322 static inline int isnum(int c
)
1324 return c
>= '0' && c
<= '9';
1327 static inline int isoct(int c
)
1329 return c
>= '0' && c
<= '7';
1332 static inline int toup(int c
)
1334 if (c
>= 'a' && c
<= 'z')
1335 return c
- 'a' + 'A';
1340 static void strcat_vprintf(char *buf
, int buf_size
, const char *fmt
, va_list ap
)
1344 vsnprintf(buf
+ len
, buf_size
- len
, fmt
, ap
);
1347 static void strcat_printf(char *buf
, int buf_size
, const char *fmt
, ...)
1351 strcat_vprintf(buf
, buf_size
, fmt
, ap
);
1355 void error1(TCCState
*s1
, int is_warning
, const char *fmt
, va_list ap
)
1362 for(f
= s1
->include_stack
; f
< s1
->include_stack_ptr
; f
++)
1363 strcat_printf(buf
, sizeof(buf
), "In file included from %s:%d:\n",
1364 (*f
)->filename
, (*f
)->line_num
);
1365 if (file
->line_num
> 0) {
1366 strcat_printf(buf
, sizeof(buf
),
1367 "%s:%d: ", file
->filename
, file
->line_num
);
1369 strcat_printf(buf
, sizeof(buf
),
1370 "%s: ", file
->filename
);
1373 strcat_printf(buf
, sizeof(buf
),
1377 strcat_printf(buf
, sizeof(buf
), "warning: ");
1378 strcat_vprintf(buf
, sizeof(buf
), fmt
, ap
);
1380 if (!s1
->error_func
) {
1381 /* default case: stderr */
1382 fprintf(stderr
, "%s\n", buf
);
1384 s1
->error_func(s1
->error_opaque
, buf
);
1386 if (!is_warning
|| s1
->warn_error
)
1391 void tcc_set_error_func(TCCState
*s
, void *error_opaque
,
1392 void (*error_func
)(void *opaque
, const char *msg
))
1394 s
->error_opaque
= error_opaque
;
1395 s
->error_func
= error_func
;
1399 /* error without aborting current compilation */
1400 void error_noabort(const char *fmt
, ...)
1402 TCCState
*s1
= tcc_state
;
1406 error1(s1
, 0, fmt
, ap
);
1410 void error(const char *fmt
, ...)
1412 TCCState
*s1
= tcc_state
;
1416 error1(s1
, 0, fmt
, ap
);
1418 /* better than nothing: in some cases, we accept to handle errors */
1419 if (s1
->error_set_jmp_enabled
) {
1420 longjmp(s1
->error_jmp_buf
, 1);
1422 /* XXX: eliminate this someday */
1427 void expect(const char *msg
)
1429 error("%s expected", msg
);
1432 void warning(const char *fmt
, ...)
1434 TCCState
*s1
= tcc_state
;
1441 error1(s1
, 1, fmt
, ap
);
1448 error("'%c' expected", c
);
1452 static void test_lvalue(void)
1454 if (!(vtop
->r
& VT_LVAL
))
1458 /* allocate a new token */
1459 static TokenSym
*tok_alloc_new(TokenSym
**pts
, const char *str
, int len
)
1461 TokenSym
*ts
, **ptable
;
1464 if (tok_ident
>= SYM_FIRST_ANOM
)
1465 error("memory full");
1467 /* expand token table if needed */
1468 i
= tok_ident
- TOK_IDENT
;
1469 if ((i
% TOK_ALLOC_INCR
) == 0) {
1470 ptable
= tcc_realloc(table_ident
, (i
+ TOK_ALLOC_INCR
) * sizeof(TokenSym
*));
1472 error("memory full");
1473 table_ident
= ptable
;
1476 ts
= tcc_malloc(sizeof(TokenSym
) + len
);
1477 table_ident
[i
] = ts
;
1478 ts
->tok
= tok_ident
++;
1479 ts
->sym_define
= NULL
;
1480 ts
->sym_label
= NULL
;
1481 ts
->sym_struct
= NULL
;
1482 ts
->sym_identifier
= NULL
;
1484 ts
->hash_next
= NULL
;
1485 memcpy(ts
->str
, str
, len
);
1486 ts
->str
[len
] = '\0';
1491 #define TOK_HASH_INIT 1
1492 #define TOK_HASH_FUNC(h, c) ((h) * 263 + (c))
1494 /* find a token and add it if not found */
1495 static TokenSym
*tok_alloc(const char *str
, int len
)
1497 TokenSym
*ts
, **pts
;
1503 h
= TOK_HASH_FUNC(h
, ((unsigned char *)str
)[i
]);
1504 h
&= (TOK_HASH_SIZE
- 1);
1506 pts
= &hash_ident
[h
];
1511 if (ts
->len
== len
&& !memcmp(ts
->str
, str
, len
))
1513 pts
= &(ts
->hash_next
);
1515 return tok_alloc_new(pts
, str
, len
);
1518 /* CString handling */
1520 static void cstr_realloc(CString
*cstr
, int new_size
)
1525 size
= cstr
->size_allocated
;
1527 size
= 8; /* no need to allocate a too small first string */
1528 while (size
< new_size
)
1530 data
= tcc_realloc(cstr
->data_allocated
, size
);
1532 error("memory full");
1533 cstr
->data_allocated
= data
;
1534 cstr
->size_allocated
= size
;
1539 static inline void cstr_ccat(CString
*cstr
, int ch
)
1542 size
= cstr
->size
+ 1;
1543 if (size
> cstr
->size_allocated
)
1544 cstr_realloc(cstr
, size
);
1545 ((unsigned char *)cstr
->data
)[size
- 1] = ch
;
1549 static void cstr_cat(CString
*cstr
, const char *str
)
1561 /* add a wide char */
1562 static void cstr_wccat(CString
*cstr
, int ch
)
1565 size
= cstr
->size
+ sizeof(int);
1566 if (size
> cstr
->size_allocated
)
1567 cstr_realloc(cstr
, size
);
1568 *(int *)(((unsigned char *)cstr
->data
) + size
- sizeof(int)) = ch
;
1572 static void cstr_new(CString
*cstr
)
1574 memset(cstr
, 0, sizeof(CString
));
1577 /* free string and reset it to NULL */
1578 static void cstr_free(CString
*cstr
)
1580 tcc_free(cstr
->data_allocated
);
1584 #define cstr_reset(cstr) cstr_free(cstr)
1586 /* XXX: unicode ? */
1587 static void add_char(CString
*cstr
, int c
)
1589 if (c
== '\'' || c
== '\"' || c
== '\\') {
1590 /* XXX: could be more precise if char or string */
1591 cstr_ccat(cstr
, '\\');
1593 if (c
>= 32 && c
<= 126) {
1596 cstr_ccat(cstr
, '\\');
1598 cstr_ccat(cstr
, 'n');
1600 cstr_ccat(cstr
, '0' + ((c
>> 6) & 7));
1601 cstr_ccat(cstr
, '0' + ((c
>> 3) & 7));
1602 cstr_ccat(cstr
, '0' + (c
& 7));
1607 /* XXX: buffer overflow */
1608 /* XXX: float tokens */
1609 char *get_tok_str(int v
, CValue
*cv
)
1611 static char buf
[STRING_MAX_SIZE
+ 1];
1612 static CString cstr_buf
;
1618 /* NOTE: to go faster, we give a fixed buffer for small strings */
1619 cstr_reset(&cstr_buf
);
1620 cstr_buf
.data
= buf
;
1621 cstr_buf
.size_allocated
= sizeof(buf
);
1627 /* XXX: not quite exact, but only useful for testing */
1628 sprintf(p
, "%u", cv
->ui
);
1632 /* XXX: not quite exact, but only useful for testing */
1633 sprintf(p
, "%Lu", cv
->ull
);
1637 cstr_ccat(&cstr_buf
, '\'');
1638 add_char(&cstr_buf
, cv
->i
);
1639 cstr_ccat(&cstr_buf
, '\'');
1640 cstr_ccat(&cstr_buf
, '\0');
1644 len
= cstr
->size
- 1;
1646 add_char(&cstr_buf
, ((unsigned char *)cstr
->data
)[i
]);
1647 cstr_ccat(&cstr_buf
, '\0');
1652 cstr_ccat(&cstr_buf
, '\"');
1654 len
= cstr
->size
- 1;
1656 add_char(&cstr_buf
, ((unsigned char *)cstr
->data
)[i
]);
1658 len
= (cstr
->size
/ sizeof(int)) - 1;
1660 add_char(&cstr_buf
, ((int *)cstr
->data
)[i
]);
1662 cstr_ccat(&cstr_buf
, '\"');
1663 cstr_ccat(&cstr_buf
, '\0');
1672 return strcpy(p
, "<<=");
1674 return strcpy(p
, ">>=");
1676 if (v
< TOK_IDENT
) {
1677 /* search in two bytes table */
1691 } else if (v
< tok_ident
) {
1692 return table_ident
[v
- TOK_IDENT
]->str
;
1693 } else if (v
>= SYM_FIRST_ANOM
) {
1694 /* special name for anonymous symbol */
1695 sprintf(p
, "L.%u", v
- SYM_FIRST_ANOM
);
1697 /* should never happen */
1702 return cstr_buf
.data
;
1705 /* push, without hashing */
1706 static Sym
*sym_push2(Sym
**ps
, int v
, int t
, int c
)
1720 /* find a symbol and return its associated structure. 's' is the top
1721 of the symbol stack */
1722 static Sym
*sym_find2(Sym
*s
, int v
)
1732 /* structure lookup */
1733 static inline Sym
*struct_find(int v
)
1736 if ((unsigned)v
>= (unsigned)(tok_ident
- TOK_IDENT
))
1738 return table_ident
[v
]->sym_struct
;
1741 /* find an identifier */
1742 static inline Sym
*sym_find(int v
)
1745 if ((unsigned)v
>= (unsigned)(tok_ident
- TOK_IDENT
))
1747 return table_ident
[v
]->sym_identifier
;
1750 /* push a given symbol on the symbol stack */
1751 static Sym
*sym_push(int v
, CType
*type
, int r
, int c
)
1760 s
= sym_push2(ps
, v
, type
->t
, c
);
1761 s
->type
.ref
= type
->ref
;
1763 /* don't record fields or anonymous symbols */
1765 if (!(v
& SYM_FIELD
) && (v
& ~SYM_STRUCT
) < SYM_FIRST_ANOM
) {
1766 /* record symbol in token array */
1767 ts
= table_ident
[(v
& ~SYM_STRUCT
) - TOK_IDENT
];
1769 ps
= &ts
->sym_struct
;
1771 ps
= &ts
->sym_identifier
;
1778 /* push a global identifier */
1779 static Sym
*global_identifier_push(int v
, int t
, int c
)
1782 s
= sym_push2(&global_stack
, v
, t
, c
);
1783 /* don't record anonymous symbol */
1784 if (v
< SYM_FIRST_ANOM
) {
1785 ps
= &table_ident
[v
- TOK_IDENT
]->sym_identifier
;
1786 /* modify the top most local identifier, so that
1787 sym_identifier will point to 's' when popped */
1789 ps
= &(*ps
)->prev_tok
;
1796 /* pop symbols until top reaches 'b' */
1797 static void sym_pop(Sym
**ptop
, Sym
*b
)
1807 /* remove symbol in token array */
1809 if (!(v
& SYM_FIELD
) && (v
& ~SYM_STRUCT
) < SYM_FIRST_ANOM
) {
1810 ts
= table_ident
[(v
& ~SYM_STRUCT
) - TOK_IDENT
];
1812 ps
= &ts
->sym_struct
;
1814 ps
= &ts
->sym_identifier
;
1825 BufferedFile
*tcc_open(TCCState
*s1
, const char *filename
)
1830 fd
= open(filename
, O_RDONLY
| O_BINARY
);
1833 bf
= tcc_malloc(sizeof(BufferedFile
));
1839 bf
->buf_ptr
= bf
->buffer
;
1840 bf
->buf_end
= bf
->buffer
;
1841 bf
->buffer
[0] = CH_EOB
; /* put eob symbol */
1842 pstrcpy(bf
->filename
, sizeof(bf
->filename
), filename
);
1844 bf
->ifndef_macro
= 0;
1845 bf
->ifdef_stack_ptr
= s1
->ifdef_stack_ptr
;
1846 // printf("opening '%s'\n", filename);
1850 void tcc_close(BufferedFile
*bf
)
1852 total_lines
+= bf
->line_num
;
1857 /* fill input buffer and peek next char */
1858 static int tcc_peekc_slow(BufferedFile
*bf
)
1861 /* only tries to read if really end of buffer */
1862 if (bf
->buf_ptr
>= bf
->buf_end
) {
1864 #if defined(PARSE_DEBUG)
1869 len
= read(bf
->fd
, bf
->buffer
, len
);
1876 bf
->buf_ptr
= bf
->buffer
;
1877 bf
->buf_end
= bf
->buffer
+ len
;
1878 *bf
->buf_end
= CH_EOB
;
1880 if (bf
->buf_ptr
< bf
->buf_end
) {
1881 return bf
->buf_ptr
[0];
1883 bf
->buf_ptr
= bf
->buf_end
;
1888 /* return the current character, handling end of block if necessary
1890 static int handle_eob(void)
1892 return tcc_peekc_slow(file
);
1895 /* read next char from current input file and handle end of input buffer */
1896 static inline void inp(void)
1898 ch
= *(++(file
->buf_ptr
));
1899 /* end of buffer/file handling */
1904 /* handle '\[\r]\n' */
1905 static void handle_stray(void)
1907 while (ch
== '\\') {
1912 } else if (ch
== '\r') {
1920 error("stray '\\' in program");
1925 /* skip the stray and handle the \\n case. Output an error if
1926 incorrect char after the stray */
1927 static int handle_stray1(uint8_t *p
)
1931 if (p
>= file
->buf_end
) {
1948 /* handle just the EOB case, but not stray */
1949 #define PEEKC_EOB(c, p)\
1960 /* handle the complicated stray case */
1961 #define PEEKC(c, p)\
1966 c = handle_stray1(p);\
1971 /* input with '\[\r]\n' handling. Note that this function cannot
1972 handle other characters after '\', so you cannot call it inside
1973 strings or comments */
1974 static void minp(void)
1982 /* single line C++ comments */
1983 static uint8_t *parse_line_comment(uint8_t *p
)
1991 if (c
== '\n' || c
== CH_EOF
) {
1993 } else if (c
== '\\') {
2002 } else if (c
== '\r') {
2020 static uint8_t *parse_comment(uint8_t *p
)
2026 /* fast skip loop */
2029 if (c
== '\n' || c
== '*' || c
== '\\')
2033 if (c
== '\n' || c
== '*' || c
== '\\')
2037 /* now we can handle all the cases */
2041 } else if (c
== '*') {
2047 } else if (c
== '/') {
2048 goto end_of_comment
;
2049 } else if (c
== '\\') {
2054 /* skip '\[\r]\n', otherwise just skip the stray */
2060 } else if (c
== '\r') {
2077 /* stray, eob or eof */
2082 error("unexpected end of file in comment");
2083 } else if (c
== '\\') {
2095 /* space exlcuding newline */
2096 static inline int is_space(int ch
)
2098 return ch
== ' ' || ch
== '\t' || ch
== '\v' || ch
== '\f' || ch
== '\r';
2101 static inline void skip_spaces(void)
2103 while (is_space(ch
))
2107 /* parse a string without interpreting escapes */
2108 static uint8_t *parse_pp_string(uint8_t *p
,
2109 int sep
, CString
*str
)
2117 } else if (c
== '\\') {
2122 unterminated_string
:
2123 /* XXX: indicate line number of start of string */
2124 error("missing terminating %c character", sep
);
2125 } else if (c
== '\\') {
2126 /* escape : just skip \[\r]\n */
2131 } else if (c
== '\r') {
2134 expect("'\n' after '\r'");
2137 } else if (c
== CH_EOF
) {
2138 goto unterminated_string
;
2141 cstr_ccat(str
, '\\');
2147 } else if (c
== '\n') {
2150 } else if (c
== '\r') {
2154 cstr_ccat(str
, '\r');
2170 /* skip block of text until #else, #elif or #endif. skip also pairs of
2172 void preprocess_skip(void)
2174 int a
, start_of_line
, c
;
2201 } else if (c
== '\\') {
2202 /* XXX: incorrect: should not give an error */
2203 ch
= file
->buf_ptr
[0];
2211 p
= parse_pp_string(p
, c
, NULL
);
2220 p
= parse_comment(p
);
2221 } else if (ch
== '/') {
2222 p
= parse_line_comment(p
);
2228 if (start_of_line
) {
2233 (tok
== TOK_ELSE
|| tok
== TOK_ELIF
|| tok
== TOK_ENDIF
))
2235 if (tok
== TOK_IF
|| tok
== TOK_IFDEF
|| tok
== TOK_IFNDEF
)
2237 else if (tok
== TOK_ENDIF
)
2251 /* ParseState handling */
2253 /* XXX: currently, no include file info is stored. Thus, we cannot display
2254 accurate messages if the function or data definition spans multiple
2257 /* save current parse state in 's' */
2258 void save_parse_state(ParseState
*s
)
2260 s
->line_num
= file
->line_num
;
2261 s
->macro_ptr
= macro_ptr
;
2266 /* restore parse state from 's' */
2267 void restore_parse_state(ParseState
*s
)
2269 file
->line_num
= s
->line_num
;
2270 macro_ptr
= s
->macro_ptr
;
2275 /* return the number of additional 'ints' necessary to store the
2277 static inline int tok_ext_size(int t
)
2291 error("unsupported token");
2298 return LDOUBLE_SIZE
/ 4;
2304 /* token string handling */
2306 static inline void tok_str_new(TokenString
*s
)
2310 s
->allocated_len
= 0;
2311 s
->last_line_num
= -1;
2314 static void tok_str_free(int *str
)
2319 static int *tok_str_realloc(TokenString
*s
)
2323 if (s
->allocated_len
== 0) {
2326 len
= s
->allocated_len
* 2;
2328 str
= tcc_realloc(s
->str
, len
* sizeof(int));
2330 error("memory full");
2331 s
->allocated_len
= len
;
2336 static void tok_str_add(TokenString
*s
, int t
)
2342 if (len
>= s
->allocated_len
)
2343 str
= tok_str_realloc(s
);
2348 static void tok_str_add2(TokenString
*s
, int t
, CValue
*cv
)
2355 /* allocate space for worst case */
2356 if (len
+ TOK_MAX_SIZE
> s
->allocated_len
)
2357 str
= tok_str_realloc(s
);
2366 str
[len
++] = cv
->tab
[0];
2375 nb_words
= (sizeof(CString
) + cv
->cstr
->size
+ 3) >> 2;
2376 while ((len
+ nb_words
) > s
->allocated_len
)
2377 str
= tok_str_realloc(s
);
2378 cstr
= (CString
*)(str
+ len
);
2380 cstr
->size
= cv
->cstr
->size
;
2381 cstr
->data_allocated
= NULL
;
2382 cstr
->size_allocated
= cstr
->size
;
2383 memcpy((char *)cstr
+ sizeof(CString
),
2384 cv
->cstr
->data
, cstr
->size
);
2391 #if LDOUBLE_SIZE == 8
2394 str
[len
++] = cv
->tab
[0];
2395 str
[len
++] = cv
->tab
[1];
2397 #if LDOUBLE_SIZE == 12
2399 str
[len
++] = cv
->tab
[0];
2400 str
[len
++] = cv
->tab
[1];
2401 str
[len
++] = cv
->tab
[2];
2402 #elif LDOUBLE_SIZE != 8
2403 #error add long double size support
2412 /* add the current parse token in token string 's' */
2413 static void tok_str_add_tok(TokenString
*s
)
2417 /* save line number info */
2418 if (file
->line_num
!= s
->last_line_num
) {
2419 s
->last_line_num
= file
->line_num
;
2420 cval
.i
= s
->last_line_num
;
2421 tok_str_add2(s
, TOK_LINENUM
, &cval
);
2423 tok_str_add2(s
, tok
, &tokc
);
2426 #if LDOUBLE_SIZE == 12
2427 #define LDOUBLE_GET(p, cv) \
2431 #elif LDOUBLE_SIZE == 8
2432 #define LDOUBLE_GET(p, cv) \
2436 #error add long double size support
2440 /* get a token from an integer array and increment pointer
2441 accordingly. we code it as a macro to avoid pointer aliasing. */
2442 #define TOK_GET(t, p, cv) \
2457 cv.cstr = (CString *)p; \
2458 cv.cstr->data = (char *)p + sizeof(CString);\
2459 p += (sizeof(CString) + cv.cstr->size + 3) >> 2;\
2468 case TOK_CLDOUBLE: \
2469 LDOUBLE_GET(p, cv); \
2470 p += LDOUBLE_SIZE / 4; \
2477 /* defines handling */
2478 static inline void define_push(int v
, int macro_type
, int *str
, Sym
*first_arg
)
2482 s
= sym_push2(&define_stack
, v
, macro_type
, (int)str
);
2483 s
->next
= first_arg
;
2484 table_ident
[v
- TOK_IDENT
]->sym_define
= s
;
2487 /* undefined a define symbol. Its name is just set to zero */
2488 static void define_undef(Sym
*s
)
2492 if (v
>= TOK_IDENT
&& v
< tok_ident
)
2493 table_ident
[v
- TOK_IDENT
]->sym_define
= NULL
;
2497 static inline Sym
*define_find(int v
)
2500 if ((unsigned)v
>= (unsigned)(tok_ident
- TOK_IDENT
))
2502 return table_ident
[v
]->sym_define
;
2505 /* free define stack until top reaches 'b' */
2506 static void free_defines(Sym
*b
)
2514 /* do not free args or predefined defines */
2516 tok_str_free((int *)top
->c
);
2518 if (v
>= TOK_IDENT
&& v
< tok_ident
)
2519 table_ident
[v
- TOK_IDENT
]->sym_define
= NULL
;
2527 static Sym
*label_find(int v
)
2530 if ((unsigned)v
>= (unsigned)(tok_ident
- TOK_IDENT
))
2532 return table_ident
[v
]->sym_label
;
2535 static Sym
*label_push(Sym
**ptop
, int v
, int flags
)
2538 s
= sym_push2(ptop
, v
, 0, 0);
2540 ps
= &table_ident
[v
- TOK_IDENT
]->sym_label
;
2541 if (ptop
== &global_label_stack
) {
2542 /* modify the top most local identifier, so that
2543 sym_identifier will point to 's' when popped */
2545 ps
= &(*ps
)->prev_tok
;
2552 /* pop labels until element last is reached. Look if any labels are
2553 undefined. Define symbols if '&&label' was used. */
2554 static void label_pop(Sym
**ptop
, Sym
*slast
)
2557 for(s
= *ptop
; s
!= slast
; s
= s1
) {
2559 if (s
->r
== LABEL_DECLARED
) {
2560 warning("label '%s' declared but not used", get_tok_str(s
->v
, NULL
));
2561 } else if (s
->r
== LABEL_FORWARD
) {
2562 error("label '%s' used but not defined",
2563 get_tok_str(s
->v
, NULL
));
2566 /* define corresponding symbol. A size of
2568 put_extern_sym(s
, cur_text_section
, (long)s
->next
, 1);
2572 table_ident
[s
->v
- TOK_IDENT
]->sym_label
= s
->prev_tok
;
2578 /* eval an expression for #if/#elif */
2579 static int expr_preprocess(void)
2585 while (tok
!= TOK_LINEFEED
&& tok
!= TOK_EOF
) {
2586 next(); /* do macro subst */
2587 if (tok
== TOK_DEFINED
) {
2592 c
= define_find(tok
) != 0;
2597 } else if (tok
>= TOK_IDENT
) {
2598 /* if undefined macro */
2602 tok_str_add_tok(&str
);
2604 tok_str_add(&str
, -1); /* simulate end of file */
2605 tok_str_add(&str
, 0);
2606 /* now evaluate C constant expression */
2607 macro_ptr
= str
.str
;
2611 tok_str_free(str
.str
);
2615 #if defined(PARSE_DEBUG) || defined(PP_DEBUG)
2616 static void tok_print(int *str
)
2622 TOK_GET(t
, str
, cval
);
2625 printf(" %s", get_tok_str(t
, &cval
));
2631 /* parse after #define */
2632 static void parse_define(void)
2634 Sym
*s
, *first
, **ps
;
2635 int v
, t
, varg
, is_vaargs
, c
;
2640 error("invalid macro name '%s'", get_tok_str(tok
, &tokc
));
2641 /* XXX: should check if same macro (ANSI) */
2644 /* '(' must be just after macro definition for MACRO_FUNC */
2645 c
= file
->buf_ptr
[0];
2647 c
= handle_stray1(file
->buf_ptr
);
2652 while (tok
!= ')') {
2656 if (varg
== TOK_DOTS
) {
2657 varg
= TOK___VA_ARGS__
;
2659 } else if (tok
== TOK_DOTS
&& gnu_ext
) {
2663 if (varg
< TOK_IDENT
)
2664 error("badly punctuated parameter list");
2665 s
= sym_push2(&define_stack
, varg
| SYM_FIELD
, is_vaargs
, 0);
2676 /* EOF testing necessary for '-D' handling */
2677 while (tok
!= TOK_LINEFEED
&& tok
!= TOK_EOF
) {
2678 tok_str_add2(&str
, tok
, &tokc
);
2681 tok_str_add(&str
, 0);
2683 printf("define %s %d: ", get_tok_str(v
, NULL
), t
);
2686 define_push(v
, t
, str
.str
, first
);
2689 static inline int hash_cached_include(int type
, const char *filename
)
2691 const unsigned char *s
;
2695 h
= TOK_HASH_FUNC(h
, type
);
2698 h
= TOK_HASH_FUNC(h
, *s
);
2701 h
&= (CACHED_INCLUDES_HASH_SIZE
- 1);
2705 /* XXX: use a token or a hash table to accelerate matching ? */
2706 static CachedInclude
*search_cached_include(TCCState
*s1
,
2707 int type
, const char *filename
)
2711 h
= hash_cached_include(type
, filename
);
2712 i
= s1
->cached_includes_hash
[h
];
2716 e
= s1
->cached_includes
[i
- 1];
2717 if (e
->type
== type
&& !strcmp(e
->filename
, filename
))
2724 static inline void add_cached_include(TCCState
*s1
, int type
,
2725 const char *filename
, int ifndef_macro
)
2730 if (search_cached_include(s1
, type
, filename
))
2733 printf("adding cached '%s' %s\n", filename
, get_tok_str(ifndef_macro
, NULL
));
2735 e
= tcc_malloc(sizeof(CachedInclude
) + strlen(filename
));
2739 strcpy(e
->filename
, filename
);
2740 e
->ifndef_macro
= ifndef_macro
;
2741 dynarray_add((void ***)&s1
->cached_includes
, &s1
->nb_cached_includes
, e
);
2742 /* add in hash table */
2743 h
= hash_cached_include(type
, filename
);
2744 e
->hash_next
= s1
->cached_includes_hash
[h
];
2745 s1
->cached_includes_hash
[h
] = s1
->nb_cached_includes
;
2748 static void pragma_parse(TCCState
*s1
)
2753 if (tok
== TOK_pack
) {
2756 #pragma pack(1) // set
2757 #pragma pack() // reset to default
2758 #pragma pack(push,1) // push & set
2759 #pragma pack(pop) // restore previous
2763 if (tok
== TOK_ASM_pop
) {
2765 if (s1
->pack_stack_ptr
<= s1
->pack_stack
) {
2767 error("out of pack stack");
2769 s1
->pack_stack_ptr
--;
2773 if (tok
== TOK_ASM_push
) {
2775 if (s1
->pack_stack_ptr
>= s1
->pack_stack
+ PACK_STACK_SIZE
- 1)
2777 s1
->pack_stack_ptr
++;
2780 if (tok
!= TOK_CINT
) {
2782 error("invalid pack pragma");
2785 if (val
< 1 || val
> 16 || (val
& (val
- 1)) != 0)
2789 *s1
->pack_stack_ptr
= val
;
2795 /* is_bof is true if first non space token at beginning of file */
2796 static void preprocess(int is_bof
)
2798 TCCState
*s1
= tcc_state
;
2799 int size
, i
, c
, n
, saved_parse_flags
;
2800 char buf
[1024], *q
, *p
;
2806 saved_parse_flags
= parse_flags
;
2807 parse_flags
= PARSE_FLAG_PREPROCESS
| PARSE_FLAG_TOK_NUM
|
2808 PARSE_FLAG_LINEFEED
;
2818 s
= define_find(tok
);
2819 /* undefine symbol by putting an invalid name */
2824 case TOK_INCLUDE_NEXT
:
2825 ch
= file
->buf_ptr
[0];
2826 /* XXX: incorrect if comments : use next_nomacro with a special mode */
2831 } else if (ch
== '\"') {
2834 /* XXX: better stray handling */
2837 while (ch
!= c
&& ch
!= '\n' && ch
!= CH_EOF
) {
2838 if ((q
- buf
) < sizeof(buf
) - 1)
2845 /* eat all spaces and comments after include */
2846 /* XXX: slightly incorrect */
2847 while (ch1
!= '\n' && ch1
!= CH_EOF
)
2851 /* computed #include : either we have only strings or
2852 we have anything enclosed in '<>' */
2855 if (tok
== TOK_STR
) {
2856 while (tok
!= TOK_LINEFEED
) {
2857 if (tok
!= TOK_STR
) {
2859 error("'#include' expects \"FILENAME\" or <FILENAME>");
2861 pstrcat(buf
, sizeof(buf
), (char *)tokc
.cstr
->data
);
2867 while (tok
!= TOK_LINEFEED
) {
2868 pstrcat(buf
, sizeof(buf
), get_tok_str(tok
, &tokc
));
2872 /* check syntax and remove '<>' */
2873 if (len
< 2 || buf
[0] != '<' || buf
[len
- 1] != '>')
2874 goto include_syntax
;
2875 memmove(buf
, buf
+ 1, len
- 2);
2876 buf
[len
- 2] = '\0';
2881 e
= search_cached_include(s1
, c
, buf
);
2882 if (e
&& define_find(e
->ifndef_macro
)) {
2883 /* no need to parse the include because the 'ifndef macro'
2886 printf("%s: skipping %s\n", file
->filename
, buf
);
2890 /* first search in current dir if "header.h" */
2892 p
= strrchr(file
->filename
, '/');
2894 size
= p
+ 1 - file
->filename
;
2895 if (size
> sizeof(buf1
) - 1)
2896 size
= sizeof(buf1
) - 1;
2897 memcpy(buf1
, file
->filename
, size
);
2899 pstrcat(buf1
, sizeof(buf1
), buf
);
2900 f
= tcc_open(s1
, buf1
);
2902 if (tok
== TOK_INCLUDE_NEXT
)
2908 if (s1
->include_stack_ptr
>= s1
->include_stack
+ INCLUDE_STACK_SIZE
)
2909 error("#include recursion too deep");
2910 /* now search in all the include paths */
2911 n
= s1
->nb_include_paths
+ s1
->nb_sysinclude_paths
;
2912 for(i
= 0; i
< n
; i
++) {
2914 if (i
< s1
->nb_include_paths
)
2915 path
= s1
->include_paths
[i
];
2917 path
= s1
->sysinclude_paths
[i
- s1
->nb_include_paths
];
2918 pstrcpy(buf1
, sizeof(buf1
), path
);
2919 pstrcat(buf1
, sizeof(buf1
), "/");
2920 pstrcat(buf1
, sizeof(buf1
), buf
);
2921 f
= tcc_open(s1
, buf1
);
2923 if (tok
== TOK_INCLUDE_NEXT
)
2929 error("include file '%s' not found", buf
);
2933 printf("%s: including %s\n", file
->filename
, buf1
);
2936 pstrcpy(f
->inc_filename
, sizeof(f
->inc_filename
), buf
);
2937 /* push current file in stack */
2938 /* XXX: fix current line init */
2939 *s1
->include_stack_ptr
++ = file
;
2941 /* add include file debug info */
2943 put_stabs(file
->filename
, N_BINCL
, 0, 0, 0);
2945 tok_flags
|= TOK_FLAG_BOF
| TOK_FLAG_BOL
;
2946 ch
= file
->buf_ptr
[0];
2954 c
= expr_preprocess();
2960 if (tok
< TOK_IDENT
)
2961 error("invalid argument for '#if%sdef'", c
? "n" : "");
2965 printf("#ifndef %s\n", get_tok_str(tok
, NULL
));
2967 file
->ifndef_macro
= tok
;
2970 c
= (define_find(tok
) != 0) ^ c
;
2972 if (s1
->ifdef_stack_ptr
>= s1
->ifdef_stack
+ IFDEF_STACK_SIZE
)
2973 error("memory full");
2974 *s1
->ifdef_stack_ptr
++ = c
;
2977 if (s1
->ifdef_stack_ptr
== s1
->ifdef_stack
)
2978 error("#else without matching #if");
2979 if (s1
->ifdef_stack_ptr
[-1] & 2)
2980 error("#else after #else");
2981 c
= (s1
->ifdef_stack_ptr
[-1] ^= 3);
2984 if (s1
->ifdef_stack_ptr
== s1
->ifdef_stack
)
2985 error("#elif without matching #if");
2986 c
= s1
->ifdef_stack_ptr
[-1];
2988 error("#elif after #else");
2989 /* last #if/#elif expression was true: we skip */
2992 c
= expr_preprocess();
2993 s1
->ifdef_stack_ptr
[-1] = c
;
3003 if (s1
->ifdef_stack_ptr
<= file
->ifdef_stack_ptr
)
3004 error("#endif without matching #if");
3005 s1
->ifdef_stack_ptr
--;
3006 /* '#ifndef macro' was at the start of file. Now we check if
3007 an '#endif' is exactly at the end of file */
3008 if (file
->ifndef_macro
&&
3009 s1
->ifdef_stack_ptr
== file
->ifdef_stack_ptr
) {
3010 file
->ifndef_macro_saved
= file
->ifndef_macro
;
3011 /* need to set to zero to avoid false matches if another
3012 #ifndef at middle of file */
3013 file
->ifndef_macro
= 0;
3014 while (tok
!= TOK_LINEFEED
)
3016 tok_flags
|= TOK_FLAG_ENDIF
;
3022 if (tok
!= TOK_CINT
)
3024 file
->line_num
= tokc
.i
- 1; /* the line number will be incremented after */
3026 if (tok
!= TOK_LINEFEED
) {
3029 pstrcpy(file
->filename
, sizeof(file
->filename
),
3030 (char *)tokc
.cstr
->data
);
3036 ch
= file
->buf_ptr
[0];
3039 while (ch
!= '\n' && ch
!= CH_EOF
) {
3040 if ((q
- buf
) < sizeof(buf
) - 1)
3046 error("#error %s", buf
);
3048 warning("#warning %s", buf
);
3054 if (tok
== TOK_LINEFEED
|| tok
== '!' || tok
== TOK_CINT
) {
3055 /* '!' is ignored to allow C scripts. numbers are ignored
3056 to emulate cpp behaviour */
3058 if (!(saved_parse_flags
& PARSE_FLAG_ASM_COMMENTS
))
3059 error("invalid preprocessing directive #%s", get_tok_str(tok
, &tokc
));
3063 /* ignore other preprocess commands or #! for C scripts */
3064 while (tok
!= TOK_LINEFEED
)
3067 parse_flags
= saved_parse_flags
;
3070 /* evaluate escape codes in a string. */
3071 static void parse_escape_string(CString
*outstr
, const uint8_t *buf
, int is_long
)
3086 case '0': case '1': case '2': case '3':
3087 case '4': case '5': case '6': case '7':
3088 /* at most three octal digits */
3093 n
= n
* 8 + c
- '0';
3097 n
= n
* 8 + c
- '0';
3102 goto add_char_nonext
;
3108 if (c
>= 'a' && c
<= 'f')
3110 else if (c
>= 'A' && c
<= 'F')
3120 goto add_char_nonext
;
3144 goto invalid_escape
;
3154 if (c
>= '!' && c
<= '~')
3155 warning("unknown escape sequence: \'\\%c\'", c
);
3157 warning("unknown escape sequence: \'\\x%x\'", c
);
3164 cstr_ccat(outstr
, c
);
3166 cstr_wccat(outstr
, c
);
3168 /* add a trailing '\0' */
3170 cstr_ccat(outstr
, '\0');
3172 cstr_wccat(outstr
, '\0');
3175 /* we use 64 bit numbers */
3178 /* bn = (bn << shift) | or_val */
3179 void bn_lshift(unsigned int *bn
, int shift
, int or_val
)
3183 for(i
=0;i
<BN_SIZE
;i
++) {
3185 bn
[i
] = (v
<< shift
) | or_val
;
3186 or_val
= v
>> (32 - shift
);
3190 void bn_zero(unsigned int *bn
)
3193 for(i
=0;i
<BN_SIZE
;i
++) {
3198 /* parse number in null terminated string 'p' and return it in the
3200 void parse_number(const char *p
)
3202 int b
, t
, shift
, frac_bits
, s
, exp_val
, ch
;
3204 unsigned int bn
[BN_SIZE
];
3215 goto float_frac_parse
;
3216 } else if (t
== '0') {
3217 if (ch
== 'x' || ch
== 'X') {
3221 } else if (tcc_ext
&& (ch
== 'b' || ch
== 'B')) {
3227 /* parse all digits. cannot check octal numbers at this stage
3228 because of floating point constants */
3230 if (ch
>= 'a' && ch
<= 'f')
3232 else if (ch
>= 'A' && ch
<= 'F')
3240 if (q
>= token_buf
+ STRING_MAX_SIZE
) {
3242 error("number too long");
3248 ((ch
== 'e' || ch
== 'E') && b
== 10) ||
3249 ((ch
== 'p' || ch
== 'P') && (b
== 16 || b
== 2))) {
3251 /* NOTE: strtox should support that for hexa numbers, but
3252 non ISOC99 libcs do not support it, so we prefer to do
3254 /* hexadecimal or binary floats */
3255 /* XXX: handle overflows */
3267 } else if (t
>= 'a') {
3269 } else if (t
>= 'A') {
3274 bn_lshift(bn
, shift
, t
);
3281 if (t
>= 'a' && t
<= 'f') {
3283 } else if (t
>= 'A' && t
<= 'F') {
3285 } else if (t
>= '0' && t
<= '9') {
3291 error("invalid digit");
3292 bn_lshift(bn
, shift
, t
);
3297 if (ch
!= 'p' && ch
!= 'P')
3304 } else if (ch
== '-') {
3308 if (ch
< '0' || ch
> '9')
3309 expect("exponent digits");
3310 while (ch
>= '0' && ch
<= '9') {
3311 exp_val
= exp_val
* 10 + ch
- '0';
3314 exp_val
= exp_val
* s
;
3316 /* now we can generate the number */
3317 /* XXX: should patch directly float number */
3318 d
= (double)bn
[1] * 4294967296.0 + (double)bn
[0];
3319 d
= ldexp(d
, exp_val
- frac_bits
);
3324 /* float : should handle overflow */
3326 } else if (t
== 'L') {
3329 /* XXX: not large enough */
3330 tokc
.ld
= (long double)d
;
3336 /* decimal floats */
3338 if (q
>= token_buf
+ STRING_MAX_SIZE
)
3343 while (ch
>= '0' && ch
<= '9') {
3344 if (q
>= token_buf
+ STRING_MAX_SIZE
)
3350 if (ch
== 'e' || ch
== 'E') {
3351 if (q
>= token_buf
+ STRING_MAX_SIZE
)
3355 if (ch
== '-' || ch
== '+') {
3356 if (q
>= token_buf
+ STRING_MAX_SIZE
)
3361 if (ch
< '0' || ch
> '9')
3362 expect("exponent digits");
3363 while (ch
>= '0' && ch
<= '9') {
3364 if (q
>= token_buf
+ STRING_MAX_SIZE
)
3376 tokc
.f
= strtof(token_buf
, NULL
);
3377 } else if (t
== 'L') {
3380 tokc
.ld
= strtold(token_buf
, NULL
);
3383 tokc
.d
= strtod(token_buf
, NULL
);
3387 unsigned long long n
, n1
;
3390 /* integer number */
3393 if (b
== 10 && *q
== '0') {
3400 /* no need for checks except for base 10 / 8 errors */
3403 } else if (t
>= 'a') {
3405 } else if (t
>= 'A') {
3410 error("invalid digit");
3414 /* detect overflow */
3415 /* XXX: this test is not reliable */
3417 error("integer constant overflow");
3420 /* XXX: not exactly ANSI compliant */
3421 if ((n
& 0xffffffff00000000LL
) != 0) {
3426 } else if (n
> 0x7fffffff) {
3437 error("three 'l's in integer constant");
3440 if (tok
== TOK_CINT
)
3442 else if (tok
== TOK_CUINT
)
3446 } else if (t
== 'U') {
3448 error("two 'u's in integer constant");
3450 if (tok
== TOK_CINT
)
3452 else if (tok
== TOK_CLLONG
)
3459 if (tok
== TOK_CINT
|| tok
== TOK_CUINT
)
3467 #define PARSE2(c1, tok1, c2, tok2) \
3478 /* return next token without macro substitution */
3479 static inline void next_nomacro1(void)
3499 /* first look if it is in fact an end of buffer */
3500 if (p
>= file
->buf_end
) {
3504 if (p
>= file
->buf_end
)
3517 TCCState
*s1
= tcc_state
;
3518 if (parse_flags
& PARSE_FLAG_LINEFEED
) {
3520 } else if (s1
->include_stack_ptr
== s1
->include_stack
||
3521 !(parse_flags
& PARSE_FLAG_PREPROCESS
)) {
3522 /* no include left : end of file. */
3525 /* pop include file */
3527 /* test if previous '#endif' was after a #ifdef at
3529 if (tok_flags
& TOK_FLAG_ENDIF
) {
3531 printf("#endif %s\n", get_tok_str(file
->ifndef_macro_saved
, NULL
));
3533 add_cached_include(s1
, file
->inc_type
, file
->inc_filename
,
3534 file
->ifndef_macro_saved
);
3537 /* add end of include file debug info */
3539 put_stabd(N_EINCL
, 0, 0);
3541 /* pop include stack */
3543 s1
->include_stack_ptr
--;
3544 file
= *s1
->include_stack_ptr
;
3552 if (parse_flags
& PARSE_FLAG_LINEFEED
) {
3556 tok_flags
|= TOK_FLAG_BOL
;
3565 if ((tok_flags
& TOK_FLAG_BOL
) &&
3566 (parse_flags
& PARSE_FLAG_PREPROCESS
)) {
3568 preprocess(tok_flags
& TOK_FLAG_BOF
);
3574 tok
= TOK_TWOSHARPS
;
3576 if (parse_flags
& PARSE_FLAG_ASM_COMMENTS
) {
3577 p
= parse_line_comment(p
- 1);
3586 case 'a': case 'b': case 'c': case 'd':
3587 case 'e': case 'f': case 'g': case 'h':
3588 case 'i': case 'j': case 'k': case 'l':
3589 case 'm': case 'n': case 'o': case 'p':
3590 case 'q': case 'r': case 's': case 't':
3591 case 'u': case 'v': case 'w': case 'x':
3593 case 'A': case 'B': case 'C': case 'D':
3594 case 'E': case 'F': case 'G': case 'H':
3595 case 'I': case 'J': case 'K':
3596 case 'M': case 'N': case 'O': case 'P':
3597 case 'Q': case 'R': case 'S': case 'T':
3598 case 'U': case 'V': case 'W': case 'X':
3604 h
= TOK_HASH_FUNC(h
, c
);
3608 if (!isidnum_table
[c
])
3610 h
= TOK_HASH_FUNC(h
, c
);
3617 /* fast case : no stray found, so we have the full token
3618 and we have already hashed it */
3620 h
&= (TOK_HASH_SIZE
- 1);
3621 pts
= &hash_ident
[h
];
3626 if (ts
->len
== len
&& !memcmp(ts
->str
, p1
, len
))
3628 pts
= &(ts
->hash_next
);
3630 ts
= tok_alloc_new(pts
, p1
, len
);
3634 cstr_reset(&tokcstr
);
3637 cstr_ccat(&tokcstr
, *p1
);
3643 while (isidnum_table
[c
]) {
3644 cstr_ccat(&tokcstr
, c
);
3647 ts
= tok_alloc(tokcstr
.data
, tokcstr
.size
);
3653 if (t
!= '\\' && t
!= '\'' && t
!= '\"') {
3655 goto parse_ident_fast
;
3658 if (c
== '\'' || c
== '\"') {
3662 cstr_reset(&tokcstr
);
3663 cstr_ccat(&tokcstr
, 'L');
3664 goto parse_ident_slow
;
3668 case '0': case '1': case '2': case '3':
3669 case '4': case '5': case '6': case '7':
3672 cstr_reset(&tokcstr
);
3673 /* after the first digit, accept digits, alpha, '.' or sign if
3674 prefixed by 'eEpP' */
3678 cstr_ccat(&tokcstr
, c
);
3680 if (!(isnum(c
) || isid(c
) || c
== '.' ||
3681 ((c
== '+' || c
== '-') &&
3682 (t
== 'e' || t
== 'E' || t
== 'p' || t
== 'P'))))
3685 /* We add a trailing '\0' to ease parsing */
3686 cstr_ccat(&tokcstr
, '\0');
3687 tokc
.cstr
= &tokcstr
;
3691 /* special dot handling because it can also start a number */
3694 cstr_reset(&tokcstr
);
3695 cstr_ccat(&tokcstr
, '.');
3697 } else if (c
== '.') {
3717 /* parse the string */
3719 p
= parse_pp_string(p
, sep
, &str
);
3720 cstr_ccat(&str
, '\0');
3722 /* eval the escape (should be done as TOK_PPNUM) */
3723 cstr_reset(&tokcstr
);
3724 parse_escape_string(&tokcstr
, str
.data
, is_long
);
3729 /* XXX: make it portable */
3733 char_size
= sizeof(int);
3734 if (tokcstr
.size
<= char_size
)
3735 error("empty character constant");
3736 if (tokcstr
.size
> 2 * char_size
)
3737 warning("multi-character character constant");
3739 tokc
.i
= *(int8_t *)tokcstr
.data
;
3742 tokc
.i
= *(int *)tokcstr
.data
;
3746 tokc
.cstr
= &tokcstr
;
3760 } else if (c
== '<') {
3778 } else if (c
== '>') {
3796 } else if (c
== '=') {
3809 } else if (c
== '=') {
3822 } else if (c
== '=') {
3835 } else if (c
== '=') {
3838 } else if (c
== '>') {
3846 PARSE2('!', '!', '=', TOK_NE
)
3847 PARSE2('=', '=', '=', TOK_EQ
)
3848 PARSE2('*', '*', '=', TOK_A_MUL
)
3849 PARSE2('%', '%', '=', TOK_A_MOD
)
3850 PARSE2('^', '^', '=', TOK_A_XOR
)
3852 /* comments or operator */
3856 p
= parse_comment(p
);
3858 } else if (c
== '/') {
3859 p
= parse_line_comment(p
);
3861 } else if (c
== '=') {
3881 case '$': /* only used in assembler */
3882 case '@': /* dito */
3887 error("unrecognized character \\x%02x", c
);
3892 #if defined(PARSE_DEBUG)
3893 printf("token = %s\n", get_tok_str(tok
, &tokc
));
3897 /* return next token without macro substitution. Can read input from
3899 static void next_nomacro(void)
3905 TOK_GET(tok
, macro_ptr
, tokc
);
3906 if (tok
== TOK_LINENUM
) {
3907 file
->line_num
= tokc
.i
;
3916 /* substitute args in macro_str and return allocated string */
3917 static int *macro_arg_subst(Sym
**nested_list
, int *macro_str
, Sym
*args
)
3919 int *st
, last_tok
, t
, notfirst
;
3928 TOK_GET(t
, macro_str
, cval
);
3933 TOK_GET(t
, macro_str
, cval
);
3936 s
= sym_find2(args
, t
);
3943 cstr_ccat(&cstr
, ' ');
3944 TOK_GET(t
, st
, cval
);
3945 cstr_cat(&cstr
, get_tok_str(t
, &cval
));
3948 cstr_ccat(&cstr
, '\0');
3950 printf("stringize: %s\n", (char *)cstr
.data
);
3954 tok_str_add2(&str
, TOK_STR
, &cval
);
3957 tok_str_add2(&str
, t
, &cval
);
3959 } else if (t
>= TOK_IDENT
) {
3960 s
= sym_find2(args
, t
);
3963 /* if '##' is present before or after, no arg substitution */
3964 if (*macro_str
== TOK_TWOSHARPS
|| last_tok
== TOK_TWOSHARPS
) {
3965 /* special case for var arg macros : ## eats the
3966 ',' if empty VA_ARGS variable. */
3967 /* XXX: test of the ',' is not 100%
3968 reliable. should fix it to avoid security
3970 if (gnu_ext
&& s
->type
.t
&&
3971 last_tok
== TOK_TWOSHARPS
&&
3972 str
.len
>= 2 && str
.str
[str
.len
- 2] == ',') {
3974 /* suppress ',' '##' */
3977 /* suppress '##' and add variable */
3985 TOK_GET(t1
, st
, cval
);
3988 tok_str_add2(&str
, t1
, &cval
);
3992 /* NOTE: the stream cannot be read when macro
3993 substituing an argument */
3994 macro_subst(&str
, nested_list
, st
, NULL
);
3997 tok_str_add(&str
, t
);
4000 tok_str_add2(&str
, t
, &cval
);
4004 tok_str_add(&str
, 0);
4008 static char const ab_month_name
[12][4] =
4010 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
4011 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
4014 /* do macro substitution of current token with macro 's' and add
4015 result to (tok_str,tok_len). 'nested_list' is the list of all
4016 macros we got inside to avoid recursing. Return non zero if no
4017 substitution needs to be done */
4018 static int macro_subst_tok(TokenString
*tok_str
,
4019 Sym
**nested_list
, Sym
*s
, struct macro_level
**can_read_stream
)
4021 Sym
*args
, *sa
, *sa1
;
4022 int mstr_allocated
, parlevel
, *mstr
, t
, t1
;
4029 /* if symbol is a macro, prepare substitution */
4030 /* special macros */
4031 if (tok
== TOK___LINE__
) {
4032 snprintf(buf
, sizeof(buf
), "%d", file
->line_num
);
4036 } else if (tok
== TOK___FILE__
) {
4037 cstrval
= file
->filename
;
4039 } else if (tok
== TOK___DATE__
|| tok
== TOK___TIME__
) {
4044 tm
= localtime(&ti
);
4045 if (tok
== TOK___DATE__
) {
4046 snprintf(buf
, sizeof(buf
), "%s %2d %d",
4047 ab_month_name
[tm
->tm_mon
], tm
->tm_mday
, tm
->tm_year
+ 1900);
4049 snprintf(buf
, sizeof(buf
), "%02d:%02d:%02d",
4050 tm
->tm_hour
, tm
->tm_min
, tm
->tm_sec
);
4057 cstr_cat(&cstr
, cstrval
);
4058 cstr_ccat(&cstr
, '\0');
4060 tok_str_add2(tok_str
, t1
, &cval
);
4065 if (s
->type
.t
== MACRO_FUNC
) {
4066 /* NOTE: we do not use next_nomacro to avoid eating the
4067 next token. XXX: find better solution */
4071 if (t
== 0 && can_read_stream
) {
4072 /* end of macro stream: we must look at the token
4073 after in the file */
4074 struct macro_level
*ml
= *can_read_stream
;
4080 *can_read_stream
= ml
-> prev
;
4085 /* XXX: incorrect with comments */
4086 ch
= file
->buf_ptr
[0];
4087 while (is_space(ch
) || ch
== '\n')
4091 if (t
!= '(') /* no macro subst */
4094 /* argument macro */
4099 /* NOTE: empty args are allowed, except if no args */
4101 /* handle '()' case */
4102 if (!args
&& !sa
&& tok
== ')')
4105 error("macro '%s' used with too many args",
4106 get_tok_str(s
->v
, 0));
4109 /* NOTE: non zero sa->t indicates VA_ARGS */
4110 while ((parlevel
> 0 ||
4112 (tok
!= ',' || sa
->type
.t
))) &&
4116 else if (tok
== ')')
4118 tok_str_add2(&str
, tok
, &tokc
);
4121 tok_str_add(&str
, 0);
4122 sym_push2(&args
, sa
->v
& ~SYM_FIELD
, sa
->type
.t
, (int)str
.str
);
4125 /* special case for gcc var args: add an empty
4126 var arg argument if it is omitted */
4127 if (sa
&& sa
->type
.t
&& gnu_ext
)
4137 error("macro '%s' used with too few args",
4138 get_tok_str(s
->v
, 0));
4141 /* now subst each arg */
4142 mstr
= macro_arg_subst(nested_list
, mstr
, args
);
4147 tok_str_free((int *)sa
->c
);
4153 sym_push2(nested_list
, s
->v
, 0, 0);
4154 macro_subst(tok_str
, nested_list
, mstr
, can_read_stream
);
4155 /* pop nested defined symbol */
4157 *nested_list
= sa1
->prev
;
4165 /* handle the '##' operator. Return NULL if no '##' seen. Otherwise
4166 return the resulting string (which must be freed). */
4167 static inline int *macro_twosharps(const int *macro_str
)
4170 const int *macro_ptr1
, *start_macro_ptr
, *ptr
, *saved_macro_ptr
;
4172 const char *p1
, *p2
;
4174 TokenString macro_str1
;
4177 start_macro_ptr
= macro_str
;
4178 /* we search the first '##' */
4180 macro_ptr1
= macro_str
;
4181 TOK_GET(t
, macro_str
, cval
);
4182 /* nothing more to do if end of string */
4185 if (*macro_str
== TOK_TWOSHARPS
)
4189 /* we saw '##', so we need more processing to handle it */
4191 tok_str_new(¯o_str1
);
4195 /* add all tokens seen so far */
4196 for(ptr
= start_macro_ptr
; ptr
< macro_ptr1
;) {
4197 TOK_GET(t
, ptr
, cval
);
4198 tok_str_add2(¯o_str1
, t
, &cval
);
4200 saved_macro_ptr
= macro_ptr
;
4201 /* XXX: get rid of the use of macro_ptr here */
4202 macro_ptr
= (int *)macro_str
;
4204 while (*macro_ptr
== TOK_TWOSHARPS
) {
4206 macro_ptr1
= macro_ptr
;
4209 TOK_GET(t
, macro_ptr
, cval
);
4210 /* We concatenate the two tokens if we have an
4211 identifier or a preprocessing number */
4213 p1
= get_tok_str(tok
, &tokc
);
4214 cstr_cat(&cstr
, p1
);
4215 p2
= get_tok_str(t
, &cval
);
4216 cstr_cat(&cstr
, p2
);
4217 cstr_ccat(&cstr
, '\0');
4219 if ((tok
>= TOK_IDENT
|| tok
== TOK_PPNUM
) &&
4220 (t
>= TOK_IDENT
|| t
== TOK_PPNUM
)) {
4221 if (tok
== TOK_PPNUM
) {
4222 /* if number, then create a number token */
4223 /* NOTE: no need to allocate because
4224 tok_str_add2() does it */
4227 /* if identifier, we must do a test to
4228 validate we have a correct identifier */
4229 if (t
== TOK_PPNUM
) {
4239 if (!isnum(c
) && !isid(c
))
4243 ts
= tok_alloc(cstr
.data
, strlen(cstr
.data
));
4244 tok
= ts
->tok
; /* modify current token */
4247 const char *str
= cstr
.data
;
4248 const unsigned char *q
;
4250 /* we look for a valid token */
4251 /* XXX: do more extensive checks */
4252 if (!strcmp(str
, ">>=")) {
4254 } else if (!strcmp(str
, "<<=")) {
4256 } else if (strlen(str
) == 2) {
4257 /* search in two bytes table */
4262 if (q
[0] == str
[0] && q
[1] == str
[1])
4269 /* NOTE: because get_tok_str use a static buffer,
4272 p1
= get_tok_str(tok
, &tokc
);
4273 cstr_cat(&cstr
, p1
);
4274 cstr_ccat(&cstr
, '\0');
4275 p2
= get_tok_str(t
, &cval
);
4276 warning("pasting \"%s\" and \"%s\" does not give a valid preprocessing token", cstr
.data
, p2
);
4277 /* cannot merge tokens: just add them separately */
4278 tok_str_add2(¯o_str1
, tok
, &tokc
);
4279 /* XXX: free associated memory ? */
4286 tok_str_add2(¯o_str1
, tok
, &tokc
);
4291 macro_ptr
= (int *)saved_macro_ptr
;
4293 tok_str_add(¯o_str1
, 0);
4294 return macro_str1
.str
;
4298 /* do macro substitution of macro_str and add result to
4299 (tok_str,tok_len). 'nested_list' is the list of all macros we got
4300 inside to avoid recursing. */
4301 static void macro_subst(TokenString
*tok_str
, Sym
**nested_list
,
4302 const int *macro_str
, struct macro_level
** can_read_stream
)
4309 struct macro_level ml
;
4311 /* first scan for '##' operator handling */
4313 macro_str1
= macro_twosharps(ptr
);
4317 /* NOTE: ptr == NULL can only happen if tokens are read from
4318 file stream due to a macro function call */
4321 TOK_GET(t
, ptr
, cval
);
4326 /* if nested substitution, do nothing */
4327 if (sym_find2(*nested_list
, t
))
4330 if (can_read_stream
)
4331 ml
.prev
= *can_read_stream
, *can_read_stream
= &ml
;
4332 macro_ptr
= (int *)ptr
;
4334 ret
= macro_subst_tok(tok_str
, nested_list
, s
, can_read_stream
);
4335 ptr
= (int *)macro_ptr
;
4337 if (can_read_stream
&& *can_read_stream
== &ml
)
4338 *can_read_stream
= ml
.prev
;
4343 tok_str_add2(tok_str
, t
, &cval
);
4347 tok_str_free(macro_str1
);
4350 /* return next token with macro substitution */
4351 static void next(void)
4353 Sym
*nested_list
, *s
;
4355 struct macro_level
*ml
;
4360 /* if not reading from macro substituted string, then try
4361 to substitute macros */
4362 if (tok
>= TOK_IDENT
&&
4363 (parse_flags
& PARSE_FLAG_PREPROCESS
)) {
4364 s
= define_find(tok
);
4366 /* we have a macro: we try to substitute */
4370 if (macro_subst_tok(&str
, &nested_list
, s
, &ml
) == 0) {
4371 /* substitution done, NOTE: maybe empty */
4372 tok_str_add(&str
, 0);
4373 macro_ptr
= str
.str
;
4374 macro_ptr_allocated
= str
.str
;
4381 /* end of macro or end of unget buffer */
4382 if (unget_buffer_enabled
) {
4383 macro_ptr
= unget_saved_macro_ptr
;
4384 unget_buffer_enabled
= 0;
4386 /* end of macro string: free it */
4387 tok_str_free(macro_ptr_allocated
);
4394 /* convert preprocessor tokens into C tokens */
4395 if (tok
== TOK_PPNUM
&&
4396 (parse_flags
& PARSE_FLAG_TOK_NUM
)) {
4397 parse_number((char *)tokc
.cstr
->data
);
4401 /* push back current token and set current token to 'last_tok'. Only
4402 identifier case handled for labels. */
4403 static inline void unget_tok(int last_tok
)
4407 unget_saved_macro_ptr
= macro_ptr
;
4408 unget_buffer_enabled
= 1;
4409 q
= unget_saved_buffer
;
4412 n
= tok_ext_size(tok
) - 1;
4415 *q
= 0; /* end of token string */
4420 void swap(int *p
, int *q
)
4428 void vsetc(CType
*type
, int r
, CValue
*vc
)
4432 if (vtop
>= vstack
+ (VSTACK_SIZE
- 1))
4433 error("memory full");
4434 /* cannot let cpu flags if other instruction are generated. Also
4435 avoid leaving VT_JMP anywhere except on the top of the stack
4436 because it would complicate the code generator. */
4437 if (vtop
>= vstack
) {
4438 v
= vtop
->r
& VT_VALMASK
;
4439 if (v
== VT_CMP
|| (v
& ~1) == VT_JMP
)
4445 vtop
->r2
= VT_CONST
;
4449 /* push integer constant */
4454 vsetc(&int_type
, VT_CONST
, &cval
);
4457 /* Return a static symbol pointing to a section */
4458 static Sym
*get_sym_ref(CType
*type
, Section
*sec
,
4459 unsigned long offset
, unsigned long size
)
4465 sym
= global_identifier_push(v
, type
->t
| VT_STATIC
, 0);
4466 sym
->type
.ref
= type
->ref
;
4467 sym
->r
= VT_CONST
| VT_SYM
;
4468 put_extern_sym(sym
, sec
, offset
, size
);
4472 /* push a reference to a section offset by adding a dummy symbol */
4473 static void vpush_ref(CType
*type
, Section
*sec
, unsigned long offset
, unsigned long size
)
4478 vsetc(type
, VT_CONST
| VT_SYM
, &cval
);
4479 vtop
->sym
= get_sym_ref(type
, sec
, offset
, size
);
4482 /* define a new external reference to a symbol 'v' of type 'u' */
4483 static Sym
*external_global_sym(int v
, CType
*type
, int r
)
4489 /* push forward reference */
4490 s
= global_identifier_push(v
, type
->t
| VT_EXTERN
, 0);
4491 s
->type
.ref
= type
->ref
;
4492 s
->r
= r
| VT_CONST
| VT_SYM
;
4497 /* define a new external reference to a symbol 'v' of type 'u' */
4498 static Sym
*external_sym(int v
, CType
*type
, int r
)
4504 /* push forward reference */
4505 s
= sym_push(v
, type
, r
| VT_CONST
| VT_SYM
, 0);
4506 s
->type
.t
|= VT_EXTERN
;
4508 if (!is_compatible_types(&s
->type
, type
))
4509 error("incompatible types for redefinition of '%s'",
4510 get_tok_str(v
, NULL
));
4515 /* push a reference to global symbol v */
4516 static void vpush_global_sym(CType
*type
, int v
)
4521 sym
= external_global_sym(v
, type
, 0);
4523 vsetc(type
, VT_CONST
| VT_SYM
, &cval
);
4527 void vset(CType
*type
, int r
, int v
)
4532 vsetc(type
, r
, &cval
);
4535 void vseti(int r
, int v
)
4551 void vpushv(SValue
*v
)
4553 if (vtop
>= vstack
+ (VSTACK_SIZE
- 1))
4554 error("memory full");
4564 /* save r to the memory stack, and mark it as being free */
4565 void save_reg(int r
)
4567 int l
, saved
, size
, align
;
4571 /* modify all stack values */
4574 for(p
=vstack
;p
<=vtop
;p
++) {
4575 if ((p
->r
& VT_VALMASK
) == r
||
4576 (p
->r2
& VT_VALMASK
) == r
) {
4577 /* must save value on stack if not already done */
4579 /* NOTE: must reload 'r' because r might be equal to r2 */
4580 r
= p
->r
& VT_VALMASK
;
4581 /* store register in the stack */
4583 if ((p
->r
& VT_LVAL
) ||
4584 (!is_float(type
->t
) && (type
->t
& VT_BTYPE
) != VT_LLONG
))
4586 size
= type_size(type
, &align
);
4587 loc
= (loc
- size
) & -align
;
4588 sv
.type
.t
= type
->t
;
4589 sv
.r
= VT_LOCAL
| VT_LVAL
;
4592 #ifdef TCC_TARGET_I386
4593 /* x86 specific: need to pop fp register ST0 if saved */
4594 if (r
== TREG_ST0
) {
4595 o(0xd9dd); /* fstp %st(1) */
4598 /* special long long case */
4599 if ((type
->t
& VT_BTYPE
) == VT_LLONG
) {
4606 /* mark that stack entry as being saved on the stack */
4607 if (p
->r
& VT_LVAL
) {
4608 /* also clear the bounded flag because the
4609 relocation address of the function was stored in
4611 p
->r
= (p
->r
& ~(VT_VALMASK
| VT_BOUNDED
)) | VT_LLOCAL
;
4613 p
->r
= lvalue_type(p
->type
.t
) | VT_LOCAL
;
4621 /* find a register of class 'rc2' with at most one reference on stack.
4622 * If none, call get_reg(rc) */
4623 int get_reg_ex(int rc
, int rc2
)
4628 for(r
=0;r
<NB_REGS
;r
++) {
4629 if (reg_classes
[r
] & rc2
) {
4632 for(p
= vstack
; p
<= vtop
; p
++) {
4633 if ((p
->r
& VT_VALMASK
) == r
||
4634 (p
->r2
& VT_VALMASK
) == r
)
4644 /* find a free register of class 'rc'. If none, save one register */
4650 /* find a free register */
4651 for(r
=0;r
<NB_REGS
;r
++) {
4652 if (reg_classes
[r
] & rc
) {
4653 for(p
=vstack
;p
<=vtop
;p
++) {
4654 if ((p
->r
& VT_VALMASK
) == r
||
4655 (p
->r2
& VT_VALMASK
) == r
)
4663 /* no register left : free the first one on the stack (VERY
4664 IMPORTANT to start from the bottom to ensure that we don't
4665 spill registers used in gen_opi()) */
4666 for(p
=vstack
;p
<=vtop
;p
++) {
4667 r
= p
->r
& VT_VALMASK
;
4668 if (r
< VT_CONST
&& (reg_classes
[r
] & rc
))
4670 /* also look at second register (if long long) */
4671 r
= p
->r2
& VT_VALMASK
;
4672 if (r
< VT_CONST
&& (reg_classes
[r
] & rc
)) {
4678 /* Should never comes here */
4682 /* save registers up to (vtop - n) stack entry */
4683 void save_regs(int n
)
4688 for(p
= vstack
;p
<= p1
; p
++) {
4689 r
= p
->r
& VT_VALMASK
;
4696 /* move register 's' to 'r', and flush previous value of r to memory
4698 void move_reg(int r
, int s
)
4711 /* get address of vtop (vtop MUST BE an lvalue) */
4714 vtop
->r
&= ~VT_LVAL
;
4715 /* tricky: if saved lvalue, then we can go back to lvalue */
4716 if ((vtop
->r
& VT_VALMASK
) == VT_LLOCAL
)
4717 vtop
->r
= (vtop
->r
& ~(VT_VALMASK
| VT_LVAL_TYPE
)) | VT_LOCAL
| VT_LVAL
;
4720 #ifdef CONFIG_TCC_BCHECK
4721 /* generate lvalue bound code */
4727 vtop
->r
&= ~VT_MUSTBOUND
;
4728 /* if lvalue, then use checking code before dereferencing */
4729 if (vtop
->r
& VT_LVAL
) {
4730 /* if not VT_BOUNDED value, then make one */
4731 if (!(vtop
->r
& VT_BOUNDED
)) {
4732 lval_type
= vtop
->r
& (VT_LVAL_TYPE
| VT_LVAL
);
4733 /* must save type because we must set it to int to get pointer */
4735 vtop
->type
.t
= VT_INT
;
4738 gen_bounded_ptr_add();
4739 vtop
->r
|= lval_type
;
4742 /* then check for dereferencing */
4743 gen_bounded_ptr_deref();
4748 /* store vtop a register belonging to class 'rc'. lvalues are
4749 converted to values. Cannot be used if cannot be converted to
4750 register value (such as structures). */
4753 int r
, r2
, rc2
, bit_pos
, bit_size
, size
, align
, i
;
4754 unsigned long long ll
;
4756 /* NOTE: get_reg can modify vstack[] */
4757 if (vtop
->type
.t
& VT_BITFIELD
) {
4758 bit_pos
= (vtop
->type
.t
>> VT_STRUCT_SHIFT
) & 0x3f;
4759 bit_size
= (vtop
->type
.t
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f;
4760 /* remove bit field info to avoid loops */
4761 vtop
->type
.t
&= ~(VT_BITFIELD
| (-1 << VT_STRUCT_SHIFT
));
4762 /* generate shifts */
4763 vpushi(32 - (bit_pos
+ bit_size
));
4765 vpushi(32 - bit_size
);
4766 /* NOTE: transformed to SHR if unsigned */
4770 if (is_float(vtop
->type
.t
) &&
4771 (vtop
->r
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
) {
4774 unsigned long offset
;
4776 /* XXX: unify with initializers handling ? */
4777 /* CPUs usually cannot use float constants, so we store them
4778 generically in data segment */
4779 size
= type_size(&vtop
->type
, &align
);
4780 offset
= (data_section
->data_offset
+ align
- 1) & -align
;
4781 data_section
->data_offset
= offset
;
4782 /* XXX: not portable yet */
4783 ptr
= section_ptr_add(data_section
, size
);
4786 ptr
[i
] = vtop
->c
.tab
[i
];
4787 sym
= get_sym_ref(&vtop
->type
, data_section
, offset
, size
<< 2);
4788 vtop
->r
|= VT_LVAL
| VT_SYM
;
4792 #ifdef CONFIG_TCC_BCHECK
4793 if (vtop
->r
& VT_MUSTBOUND
)
4797 r
= vtop
->r
& VT_VALMASK
;
4798 /* need to reload if:
4800 - lvalue (need to dereference pointer)
4801 - already a register, but not in the right class */
4802 if (r
>= VT_CONST
||
4803 (vtop
->r
& VT_LVAL
) ||
4804 !(reg_classes
[r
] & rc
) ||
4805 ((vtop
->type
.t
& VT_BTYPE
) == VT_LLONG
&&
4806 !(reg_classes
[vtop
->r2
] & rc
))) {
4808 if ((vtop
->type
.t
& VT_BTYPE
) == VT_LLONG
) {
4809 /* two register type load : expand to two words
4811 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
) {
4814 vtop
->c
.ui
= ll
; /* first word */
4816 vtop
->r
= r
; /* save register value */
4817 vpushi(ll
>> 32); /* second word */
4818 } else if (r
>= VT_CONST
|| /* XXX: test to VT_CONST incorrect ? */
4819 (vtop
->r
& VT_LVAL
)) {
4820 /* We do not want to modifier the long long
4821 pointer here, so the safest (and less
4822 efficient) is to save all the other registers
4823 in the stack. XXX: totally inefficient. */
4825 /* load from memory */
4828 vtop
[-1].r
= r
; /* save register value */
4829 /* increment pointer to get second word */
4830 vtop
->type
.t
= VT_INT
;
4836 /* move registers */
4839 vtop
[-1].r
= r
; /* save register value */
4840 vtop
->r
= vtop
[-1].r2
;
4842 /* allocate second register */
4849 /* write second register */
4851 } else if ((vtop
->r
& VT_LVAL
) && !is_float(vtop
->type
.t
)) {
4853 /* lvalue of scalar type : need to use lvalue type
4854 because of possible cast */
4857 /* compute memory access type */
4858 if (vtop
->r
& VT_LVAL_BYTE
)
4860 else if (vtop
->r
& VT_LVAL_SHORT
)
4862 if (vtop
->r
& VT_LVAL_UNSIGNED
)
4866 /* restore wanted type */
4869 /* one register type load */
4874 #ifdef TCC_TARGET_C67
4875 /* uses register pairs for doubles */
4876 if ((vtop
->type
.t
& VT_BTYPE
) == VT_DOUBLE
)
4883 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
4884 void gv2(int rc1
, int rc2
)
4888 /* generate more generic register first. But VT_JMP or VT_CMP
4889 values must be generated first in all cases to avoid possible
4891 v
= vtop
[0].r
& VT_VALMASK
;
4892 if (v
!= VT_CMP
&& (v
& ~1) != VT_JMP
&& rc1
<= rc2
) {
4897 /* test if reload is needed for first register */
4898 if ((vtop
[-1].r
& VT_VALMASK
) >= VT_CONST
) {
4908 /* test if reload is needed for first register */
4909 if ((vtop
[0].r
& VT_VALMASK
) >= VT_CONST
) {
4915 /* expand long long on stack in two int registers */
4920 u
= vtop
->type
.t
& VT_UNSIGNED
;
4923 vtop
[0].r
= vtop
[-1].r2
;
4924 vtop
[0].r2
= VT_CONST
;
4925 vtop
[-1].r2
= VT_CONST
;
4926 vtop
[0].type
.t
= VT_INT
| u
;
4927 vtop
[-1].type
.t
= VT_INT
| u
;
4930 #ifdef TCC_TARGET_ARM
4931 /* expand long long on stack */
4932 void lexpand_nr(void)
4936 u
= vtop
->type
.t
& VT_UNSIGNED
;
4938 vtop
->r2
= VT_CONST
;
4939 vtop
->type
.t
= VT_INT
| u
;
4940 v
=vtop
[-1].r
& (VT_VALMASK
| VT_LVAL
);
4941 if (v
== VT_CONST
) {
4942 vtop
[-1].c
.ui
= vtop
->c
.ull
;
4943 vtop
->c
.ui
= vtop
->c
.ull
>> 32;
4945 } else if (v
== (VT_LVAL
|VT_CONST
) || v
== (VT_LVAL
|VT_LOCAL
)) {
4947 vtop
->r
= vtop
[-1].r
;
4948 } else if (v
> VT_CONST
) {
4952 vtop
->r
= vtop
[-1].r2
;
4953 vtop
[-1].r2
= VT_CONST
;
4954 vtop
[-1].type
.t
= VT_INT
| u
;
4958 /* build a long long from two ints */
4961 gv2(RC_INT
, RC_INT
);
4962 vtop
[-1].r2
= vtop
[0].r
;
4963 vtop
[-1].type
.t
= t
;
4967 /* rotate n first stack elements to the bottom
4968 I1 ... In -> I2 ... In I1 [top is right]
4976 for(i
=-n
+1;i
!=0;i
++)
4977 vtop
[i
] = vtop
[i
+1];
4981 /* rotate n first stack elements to the top
4982 I1 ... In -> In I1 ... I(n-1) [top is right]
4990 for(i
= 0;i
< n
- 1; i
++)
4991 vtop
[-i
] = vtop
[-i
- 1];
4995 #ifdef TCC_TARGET_ARM
4996 /* like vrott but in other direction
4997 In ... I1 -> I(n-1) ... I1 In [top is right]
5005 for(i
= n
- 1; i
> 0; i
--)
5006 vtop
[-i
] = vtop
[-i
+ 1];
5011 /* pop stack value */
5015 v
= vtop
->r
& VT_VALMASK
;
5016 #ifdef TCC_TARGET_I386
5017 /* for x86, we need to pop the FP stack */
5018 if (v
== TREG_ST0
&& !nocode_wanted
) {
5019 o(0xd9dd); /* fstp %st(1) */
5022 if (v
== VT_JMP
|| v
== VT_JMPI
) {
5023 /* need to put correct jump if && or || without test */
5029 /* convert stack entry to register and duplicate its value in another
5037 if ((t
& VT_BTYPE
) == VT_LLONG
) {
5044 /* stack: H L L1 H1 */
5052 /* duplicate value */
5063 load(r1
, &sv
); /* move r to r1 */
5065 /* duplicates value */
5070 /* generate CPU independent (unsigned) long long operations */
5071 void gen_opl(int op
)
5073 int t
, a
, b
, op1
, c
, i
;
5080 func
= TOK___divdi3
;
5083 func
= TOK___udivdi3
;
5086 func
= TOK___moddi3
;
5089 func
= TOK___umoddi3
;
5091 /* call generic long long function */
5092 vpush_global_sym(&func_old_type
, func
);
5097 vtop
->r2
= REG_LRET
;
5110 /* stack: L1 H1 L2 H2 */
5115 vtop
[-2] = vtop
[-3];
5118 /* stack: H1 H2 L1 L2 */
5124 /* stack: H1 H2 L1 L2 ML MH */
5127 /* stack: ML MH H1 H2 L1 L2 */
5131 /* stack: ML MH H1 L2 H2 L1 */
5136 /* stack: ML MH M1 M2 */
5139 } else if (op
== '+' || op
== '-') {
5140 /* XXX: add non carry method too (for MIPS or alpha) */
5146 /* stack: H1 H2 (L1 op L2) */
5149 gen_op(op1
+ 1); /* TOK_xxxC2 */
5152 /* stack: H1 H2 (L1 op L2) */
5155 /* stack: (L1 op L2) H1 H2 */
5157 /* stack: (L1 op L2) (H1 op H2) */
5165 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
) {
5166 t
= vtop
[-1].type
.t
;
5170 /* stack: L H shift */
5172 /* constant: simpler */
5173 /* NOTE: all comments are for SHL. the other cases are
5174 done by swaping words */
5185 if (op
!= TOK_SAR
) {
5218 /* XXX: should provide a faster fallback on x86 ? */
5221 func
= TOK___sardi3
;
5224 func
= TOK___shrdi3
;
5227 func
= TOK___shldi3
;
5233 /* compare operations */
5239 /* stack: L1 H1 L2 H2 */
5241 vtop
[-1] = vtop
[-2];
5243 /* stack: L1 L2 H1 H2 */
5246 /* when values are equal, we need to compare low words. since
5247 the jump is inverted, we invert the test too. */
5250 else if (op1
== TOK_GT
)
5252 else if (op1
== TOK_ULT
)
5254 else if (op1
== TOK_UGT
)
5259 if (op1
!= TOK_NE
) {
5263 /* generate non equal test */
5264 /* XXX: NOT PORTABLE yet */
5268 #if defined(TCC_TARGET_I386)
5269 b
= psym(0x850f, 0);
5270 #elif defined(TCC_TARGET_ARM)
5272 o(0x1A000000 | encbranch(ind
, 0, 1));
5273 #elif defined(TCC_TARGET_C67)
5274 error("not implemented");
5276 #error not supported
5280 /* compare low. Always unsigned */
5284 else if (op1
== TOK_LE
)
5286 else if (op1
== TOK_GT
)
5288 else if (op1
== TOK_GE
)
5298 /* handle integer constant optimizations and various machine
5300 void gen_opic(int op
)
5307 /* currently, we cannot do computations with forward symbols */
5308 c1
= (v1
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
5309 c2
= (v2
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
5313 case '+': v1
->c
.i
+= fc
; break;
5314 case '-': v1
->c
.i
-= fc
; break;
5315 case '&': v1
->c
.i
&= fc
; break;
5316 case '^': v1
->c
.i
^= fc
; break;
5317 case '|': v1
->c
.i
|= fc
; break;
5318 case '*': v1
->c
.i
*= fc
; break;
5325 /* if division by zero, generate explicit division */
5328 error("division by zero in constant");
5332 default: v1
->c
.i
/= fc
; break;
5333 case '%': v1
->c
.i
%= fc
; break;
5334 case TOK_UDIV
: v1
->c
.i
= (unsigned)v1
->c
.i
/ fc
; break;
5335 case TOK_UMOD
: v1
->c
.i
= (unsigned)v1
->c
.i
% fc
; break;
5338 case TOK_SHL
: v1
->c
.i
<<= fc
; break;
5339 case TOK_SHR
: v1
->c
.i
= (unsigned)v1
->c
.i
>> fc
; break;
5340 case TOK_SAR
: v1
->c
.i
>>= fc
; break;
5342 case TOK_ULT
: v1
->c
.i
= (unsigned)v1
->c
.i
< (unsigned)fc
; break;
5343 case TOK_UGE
: v1
->c
.i
= (unsigned)v1
->c
.i
>= (unsigned)fc
; break;
5344 case TOK_EQ
: v1
->c
.i
= v1
->c
.i
== fc
; break;
5345 case TOK_NE
: v1
->c
.i
= v1
->c
.i
!= fc
; break;
5346 case TOK_ULE
: v1
->c
.i
= (unsigned)v1
->c
.i
<= (unsigned)fc
; break;
5347 case TOK_UGT
: v1
->c
.i
= (unsigned)v1
->c
.i
> (unsigned)fc
; break;
5348 case TOK_LT
: v1
->c
.i
= v1
->c
.i
< fc
; break;
5349 case TOK_GE
: v1
->c
.i
= v1
->c
.i
>= fc
; break;
5350 case TOK_LE
: v1
->c
.i
= v1
->c
.i
<= fc
; break;
5351 case TOK_GT
: v1
->c
.i
= v1
->c
.i
> fc
; break;
5353 case TOK_LAND
: v1
->c
.i
= v1
->c
.i
&& fc
; break;
5354 case TOK_LOR
: v1
->c
.i
= v1
->c
.i
|| fc
; break;
5360 /* if commutative ops, put c2 as constant */
5361 if (c1
&& (op
== '+' || op
== '&' || op
== '^' ||
5362 op
== '|' || op
== '*')) {
5367 if (c2
&& (((op
== '*' || op
== '/' || op
== TOK_UDIV
||
5370 ((op
== '+' || op
== '-' || op
== '|' || op
== '^' ||
5371 op
== TOK_SHL
|| op
== TOK_SHR
|| op
== TOK_SAR
) &&
5377 } else if (c2
&& (op
== '*' || op
== TOK_PDIV
|| op
== TOK_UDIV
)) {
5378 /* try to use shifts instead of muls or divs */
5379 if (fc
> 0 && (fc
& (fc
- 1)) == 0) {
5388 else if (op
== TOK_PDIV
)
5394 } else if (c2
&& (op
== '+' || op
== '-') &&
5395 (vtop
[-1].r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) ==
5396 (VT_CONST
| VT_SYM
)) {
5397 /* symbol + constant case */
5404 if (!nocode_wanted
) {
5405 /* call low level op generator */
5414 /* generate a floating point operation with constant propagation */
5415 void gen_opif(int op
)
5423 /* currently, we cannot do computations with forward symbols */
5424 c1
= (v1
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
5425 c2
= (v2
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
5427 if (v1
->type
.t
== VT_FLOAT
) {
5430 } else if (v1
->type
.t
== VT_DOUBLE
) {
5438 /* NOTE: we only do constant propagation if finite number (not
5439 NaN or infinity) (ANSI spec) */
5440 if (!ieee_finite(f1
) || !ieee_finite(f2
))
5444 case '+': f1
+= f2
; break;
5445 case '-': f1
-= f2
; break;
5446 case '*': f1
*= f2
; break;
5450 error("division by zero in constant");
5455 /* XXX: also handles tests ? */
5459 /* XXX: overflow test ? */
5460 if (v1
->type
.t
== VT_FLOAT
) {
5462 } else if (v1
->type
.t
== VT_DOUBLE
) {
5470 if (!nocode_wanted
) {
5478 static int pointed_size(CType
*type
)
5481 return type_size(pointed_type(type
), &align
);
5484 static inline int is_null_pointer(SValue
*p
)
5486 if ((p
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) != VT_CONST
)
5488 return ((p
->type
.t
& VT_BTYPE
) == VT_INT
&& p
->c
.i
== 0) ||
5489 ((p
->type
.t
& VT_BTYPE
) == VT_LLONG
&& p
->c
.ll
== 0);
5492 static inline int is_integer_btype(int bt
)
5494 return (bt
== VT_BYTE
|| bt
== VT_SHORT
||
5495 bt
== VT_INT
|| bt
== VT_LLONG
);
5498 /* check types for comparison or substraction of pointers */
5499 static void check_comparison_pointer_types(SValue
*p1
, SValue
*p2
, int op
)
5501 CType
*type1
, *type2
, tmp_type1
, tmp_type2
;
5504 /* null pointers are accepted for all comparisons as gcc */
5505 if (is_null_pointer(p1
) || is_null_pointer(p2
))
5509 bt1
= type1
->t
& VT_BTYPE
;
5510 bt2
= type2
->t
& VT_BTYPE
;
5511 /* accept comparison between pointer and integer with a warning */
5512 if ((is_integer_btype(bt1
) || is_integer_btype(bt2
)) && op
!= '-') {
5513 warning("comparison between pointer and integer");
5517 /* both must be pointers or implicit function pointers */
5518 if (bt1
== VT_PTR
) {
5519 type1
= pointed_type(type1
);
5520 } else if (bt1
!= VT_FUNC
)
5521 goto invalid_operands
;
5523 if (bt2
== VT_PTR
) {
5524 type2
= pointed_type(type2
);
5525 } else if (bt2
!= VT_FUNC
) {
5527 error("invalid operands to binary %s", get_tok_str(op
, NULL
));
5529 if ((type1
->t
& VT_BTYPE
) == VT_VOID
||
5530 (type2
->t
& VT_BTYPE
) == VT_VOID
)
5534 tmp_type1
.t
&= ~(VT_UNSIGNED
| VT_CONSTANT
| VT_VOLATILE
);
5535 tmp_type2
.t
&= ~(VT_UNSIGNED
| VT_CONSTANT
| VT_VOLATILE
);
5536 if (!is_compatible_types(&tmp_type1
, &tmp_type2
)) {
5537 /* gcc-like error if '-' is used */
5539 goto invalid_operands
;
5541 warning("comparison of distinct pointer types lacks a cast");
5545 /* generic gen_op: handles types problems */
5548 int u
, t1
, t2
, bt1
, bt2
, t
;
5551 t1
= vtop
[-1].type
.t
;
5552 t2
= vtop
[0].type
.t
;
5553 bt1
= t1
& VT_BTYPE
;
5554 bt2
= t2
& VT_BTYPE
;
5556 if (bt1
== VT_PTR
|| bt2
== VT_PTR
) {
5557 /* at least one operand is a pointer */
5558 /* relationnal op: must be both pointers */
5559 if (op
>= TOK_ULT
&& op
<= TOK_GT
) {
5560 check_comparison_pointer_types(vtop
- 1, vtop
, op
);
5561 /* pointers are handled are unsigned */
5562 t
= VT_INT
| VT_UNSIGNED
;
5565 /* if both pointers, then it must be the '-' op */
5566 if (bt1
== VT_PTR
&& bt2
== VT_PTR
) {
5568 error("cannot use pointers here");
5569 check_comparison_pointer_types(vtop
- 1, vtop
, op
);
5570 /* XXX: check that types are compatible */
5571 u
= pointed_size(&vtop
[-1].type
);
5573 /* set to integer type */
5574 vtop
->type
.t
= VT_INT
;
5578 /* exactly one pointer : must be '+' or '-'. */
5579 if (op
!= '-' && op
!= '+')
5580 error("cannot use pointers here");
5581 /* Put pointer as first operand */
5582 if (bt2
== VT_PTR
) {
5586 type1
= vtop
[-1].type
;
5587 /* XXX: cast to int ? (long long case) */
5588 vpushi(pointed_size(&vtop
[-1].type
));
5590 #ifdef CONFIG_TCC_BCHECK
5591 /* if evaluating constant expression, no code should be
5592 generated, so no bound check */
5593 if (do_bounds_check
&& !const_wanted
) {
5594 /* if bounded pointers, we generate a special code to
5601 gen_bounded_ptr_add();
5607 /* put again type if gen_opic() swaped operands */
5610 } else if (is_float(bt1
) || is_float(bt2
)) {
5611 /* compute bigger type and do implicit casts */
5612 if (bt1
== VT_LDOUBLE
|| bt2
== VT_LDOUBLE
) {
5614 } else if (bt1
== VT_DOUBLE
|| bt2
== VT_DOUBLE
) {
5619 /* floats can only be used for a few operations */
5620 if (op
!= '+' && op
!= '-' && op
!= '*' && op
!= '/' &&
5621 (op
< TOK_ULT
|| op
> TOK_GT
))
5622 error("invalid operands for binary operation");
5624 } else if (bt1
== VT_LLONG
|| bt2
== VT_LLONG
) {
5625 /* cast to biggest op */
5627 /* convert to unsigned if it does not fit in a long long */
5628 if ((t1
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_LLONG
| VT_UNSIGNED
) ||
5629 (t2
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_LLONG
| VT_UNSIGNED
))
5633 /* integer operations */
5635 /* convert to unsigned if it does not fit in an integer */
5636 if ((t1
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
) ||
5637 (t2
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
))
5640 /* XXX: currently, some unsigned operations are explicit, so
5641 we modify them here */
5642 if (t
& VT_UNSIGNED
) {
5649 else if (op
== TOK_LT
)
5651 else if (op
== TOK_GT
)
5653 else if (op
== TOK_LE
)
5655 else if (op
== TOK_GE
)
5662 /* special case for shifts and long long: we keep the shift as
5664 if (op
== TOK_SHR
|| op
== TOK_SAR
|| op
== TOK_SHL
)
5669 else if ((t
& VT_BTYPE
) == VT_LLONG
)
5673 if (op
>= TOK_ULT
&& op
<= TOK_GT
) {
5674 /* relationnal op: the result is an int */
5675 vtop
->type
.t
= VT_INT
;
5682 /* generic itof for unsigned long long case */
5683 void gen_cvt_itof1(int t
)
5685 if ((vtop
->type
.t
& (VT_BTYPE
| VT_UNSIGNED
)) ==
5686 (VT_LLONG
| VT_UNSIGNED
)) {
5689 vpush_global_sym(&func_old_type
, TOK___ulltof
);
5690 else if (t
== VT_DOUBLE
)
5691 vpush_global_sym(&func_old_type
, TOK___ulltod
);
5693 vpush_global_sym(&func_old_type
, TOK___ulltold
);
5703 /* generic ftoi for unsigned long long case */
5704 void gen_cvt_ftoi1(int t
)
5708 if (t
== (VT_LLONG
| VT_UNSIGNED
)) {
5709 /* not handled natively */
5710 st
= vtop
->type
.t
& VT_BTYPE
;
5712 vpush_global_sym(&func_old_type
, TOK___fixunssfdi
);
5713 else if (st
== VT_DOUBLE
)
5714 vpush_global_sym(&func_old_type
, TOK___fixunsdfdi
);
5716 vpush_global_sym(&func_old_type
, TOK___fixunsxfdi
);
5721 vtop
->r2
= REG_LRET
;
5727 /* force char or short cast */
5728 void force_charshort_cast(int t
)
5732 /* XXX: add optimization if lvalue : just change type and offset */
5737 if (t
& VT_UNSIGNED
) {
5738 vpushi((1 << bits
) - 1);
5749 /* cast 'vtop' to 'type'. Casting to bitfields is forbidden. */
5750 static void gen_cast(CType
*type
)
5752 int sbt
, dbt
, sf
, df
, c
;
5754 /* special delayed cast for char/short */
5755 /* XXX: in some cases (multiple cascaded casts), it may still
5757 if (vtop
->r
& VT_MUSTCAST
) {
5758 vtop
->r
&= ~VT_MUSTCAST
;
5759 force_charshort_cast(vtop
->type
.t
);
5762 /* bitfields first get cast to ints */
5763 if (vtop
->type
.t
& VT_BITFIELD
) {
5767 dbt
= type
->t
& (VT_BTYPE
| VT_UNSIGNED
);
5768 sbt
= vtop
->type
.t
& (VT_BTYPE
| VT_UNSIGNED
);
5770 if (sbt
!= dbt
&& !nocode_wanted
) {
5773 c
= (vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
5775 /* convert from fp to fp */
5777 /* constant case: we can do it now */
5778 /* XXX: in ISOC, cannot do it if error in convert */
5779 if (dbt
== VT_FLOAT
&& sbt
== VT_DOUBLE
)
5780 vtop
->c
.f
= (float)vtop
->c
.d
;
5781 else if (dbt
== VT_FLOAT
&& sbt
== VT_LDOUBLE
)
5782 vtop
->c
.f
= (float)vtop
->c
.ld
;
5783 else if (dbt
== VT_DOUBLE
&& sbt
== VT_FLOAT
)
5784 vtop
->c
.d
= (double)vtop
->c
.f
;
5785 else if (dbt
== VT_DOUBLE
&& sbt
== VT_LDOUBLE
)
5786 vtop
->c
.d
= (double)vtop
->c
.ld
;
5787 else if (dbt
== VT_LDOUBLE
&& sbt
== VT_FLOAT
)
5788 vtop
->c
.ld
= (long double)vtop
->c
.f
;
5789 else if (dbt
== VT_LDOUBLE
&& sbt
== VT_DOUBLE
)
5790 vtop
->c
.ld
= (long double)vtop
->c
.d
;
5792 /* non constant case: generate code */
5796 /* convert int to fp */
5799 case VT_LLONG
| VT_UNSIGNED
:
5801 /* XXX: add const cases for long long */
5803 case VT_INT
| VT_UNSIGNED
:
5805 case VT_FLOAT
: vtop
->c
.f
= (float)vtop
->c
.ui
; break;
5806 case VT_DOUBLE
: vtop
->c
.d
= (double)vtop
->c
.ui
; break;
5807 case VT_LDOUBLE
: vtop
->c
.ld
= (long double)vtop
->c
.ui
; break;
5812 case VT_FLOAT
: vtop
->c
.f
= (float)vtop
->c
.i
; break;
5813 case VT_DOUBLE
: vtop
->c
.d
= (double)vtop
->c
.i
; break;
5814 case VT_LDOUBLE
: vtop
->c
.ld
= (long double)vtop
->c
.i
; break;
5820 #if !defined(TCC_TARGET_ARM)
5827 /* convert fp to int */
5828 /* we handle char/short/etc... with generic code */
5829 if (dbt
!= (VT_INT
| VT_UNSIGNED
) &&
5830 dbt
!= (VT_LLONG
| VT_UNSIGNED
) &&
5835 case VT_LLONG
| VT_UNSIGNED
:
5837 /* XXX: add const cases for long long */
5839 case VT_INT
| VT_UNSIGNED
:
5841 case VT_FLOAT
: vtop
->c
.ui
= (unsigned int)vtop
->c
.d
; break;
5842 case VT_DOUBLE
: vtop
->c
.ui
= (unsigned int)vtop
->c
.d
; break;
5843 case VT_LDOUBLE
: vtop
->c
.ui
= (unsigned int)vtop
->c
.d
; break;
5849 case VT_FLOAT
: vtop
->c
.i
= (int)vtop
->c
.d
; break;
5850 case VT_DOUBLE
: vtop
->c
.i
= (int)vtop
->c
.d
; break;
5851 case VT_LDOUBLE
: vtop
->c
.i
= (int)vtop
->c
.d
; break;
5859 if (dbt
== VT_INT
&& (type
->t
& (VT_BTYPE
| VT_UNSIGNED
)) != dbt
) {
5860 /* additional cast for char/short/bool... */
5864 } else if ((dbt
& VT_BTYPE
) == VT_LLONG
) {
5865 if ((sbt
& VT_BTYPE
) != VT_LLONG
) {
5866 /* scalar to long long */
5868 if (sbt
== (VT_INT
| VT_UNSIGNED
))
5869 vtop
->c
.ll
= vtop
->c
.ui
;
5871 vtop
->c
.ll
= vtop
->c
.i
;
5873 /* machine independent conversion */
5875 /* generate high word */
5876 if (sbt
== (VT_INT
| VT_UNSIGNED
)) {
5884 /* patch second register */
5885 vtop
[-1].r2
= vtop
->r
;
5889 } else if (dbt
== VT_BOOL
) {
5890 /* scalar to bool */
5893 } else if ((dbt
& VT_BTYPE
) == VT_BYTE
||
5894 (dbt
& VT_BTYPE
) == VT_SHORT
) {
5895 force_charshort_cast(dbt
);
5896 } else if ((dbt
& VT_BTYPE
) == VT_INT
) {
5898 if (sbt
== VT_LLONG
) {
5899 /* from long long: just take low order word */
5903 /* if lvalue and single word type, nothing to do because
5904 the lvalue already contains the real type size (see
5905 VT_LVAL_xxx constants) */
5911 /* return type size. Put alignment at 'a' */
5912 static int type_size(CType
*type
, int *a
)
5917 bt
= type
->t
& VT_BTYPE
;
5918 if (bt
== VT_STRUCT
) {
5923 } else if (bt
== VT_PTR
) {
5924 if (type
->t
& VT_ARRAY
) {
5926 return type_size(&s
->type
, a
) * s
->c
;
5931 } else if (bt
== VT_LDOUBLE
) {
5933 return LDOUBLE_SIZE
;
5934 } else if (bt
== VT_DOUBLE
|| bt
== VT_LLONG
) {
5935 #ifdef TCC_TARGET_I386
5941 } else if (bt
== VT_INT
|| bt
== VT_ENUM
|| bt
== VT_FLOAT
) {
5944 } else if (bt
== VT_SHORT
) {
5948 /* char, void, function, _Bool */
5954 /* return the pointed type of t */
5955 static inline CType
*pointed_type(CType
*type
)
5957 return &type
->ref
->type
;
5960 /* modify type so that its it is a pointer to type. */
5961 static void mk_pointer(CType
*type
)
5964 s
= sym_push(SYM_FIELD
, type
, 0, -1);
5965 type
->t
= VT_PTR
| (type
->t
& ~VT_TYPE
);
5969 /* compare function types. OLD functions match any new functions */
5970 static int is_compatible_func(CType
*type1
, CType
*type2
)
5976 if (!is_compatible_types(&s1
->type
, &s2
->type
))
5978 /* check func_call */
5981 /* XXX: not complete */
5982 if (s1
->c
== FUNC_OLD
|| s2
->c
== FUNC_OLD
)
5986 while (s1
!= NULL
) {
5989 if (!is_compatible_types(&s1
->type
, &s2
->type
))
5999 /* return true if type1 and type2 are exactly the same (including
6002 - enums are not checked as gcc __builtin_types_compatible_p ()
6004 static int is_compatible_types(CType
*type1
, CType
*type2
)
6008 t1
= type1
->t
& VT_TYPE
;
6009 t2
= type2
->t
& VT_TYPE
;
6010 /* XXX: bitfields ? */
6013 /* test more complicated cases */
6014 bt1
= t1
& VT_BTYPE
;
6015 if (bt1
== VT_PTR
) {
6016 type1
= pointed_type(type1
);
6017 type2
= pointed_type(type2
);
6018 return is_compatible_types(type1
, type2
);
6019 } else if (bt1
== VT_STRUCT
) {
6020 return (type1
->ref
== type2
->ref
);
6021 } else if (bt1
== VT_FUNC
) {
6022 return is_compatible_func(type1
, type2
);
6028 /* print a type. If 'varstr' is not NULL, then the variable is also
6029 printed in the type */
6031 /* XXX: add array and function pointers */
6032 void type_to_str(char *buf
, int buf_size
,
6033 CType
*type
, const char *varstr
)
6040 t
= type
->t
& VT_TYPE
;
6043 if (t
& VT_CONSTANT
)
6044 pstrcat(buf
, buf_size
, "const ");
6045 if (t
& VT_VOLATILE
)
6046 pstrcat(buf
, buf_size
, "volatile ");
6047 if (t
& VT_UNSIGNED
)
6048 pstrcat(buf
, buf_size
, "unsigned ");
6078 tstr
= "long double";
6080 pstrcat(buf
, buf_size
, tstr
);
6084 if (bt
== VT_STRUCT
)
6088 pstrcat(buf
, buf_size
, tstr
);
6089 v
= type
->ref
->v
& ~SYM_STRUCT
;
6090 if (v
>= SYM_FIRST_ANOM
)
6091 pstrcat(buf
, buf_size
, "<anonymous>");
6093 pstrcat(buf
, buf_size
, get_tok_str(v
, NULL
));
6097 type_to_str(buf
, buf_size
, &s
->type
, varstr
);
6098 pstrcat(buf
, buf_size
, "(");
6100 while (sa
!= NULL
) {
6101 type_to_str(buf1
, sizeof(buf1
), &sa
->type
, NULL
);
6102 pstrcat(buf
, buf_size
, buf1
);
6105 pstrcat(buf
, buf_size
, ", ");
6107 pstrcat(buf
, buf_size
, ")");
6111 pstrcpy(buf1
, sizeof(buf1
), "*");
6113 pstrcat(buf1
, sizeof(buf1
), varstr
);
6114 type_to_str(buf
, buf_size
, &s
->type
, buf1
);
6118 pstrcat(buf
, buf_size
, " ");
6119 pstrcat(buf
, buf_size
, varstr
);
6124 /* verify type compatibility to store vtop in 'dt' type, and generate
6126 static void gen_assign_cast(CType
*dt
)
6128 CType
*st
, *type1
, *type2
, tmp_type1
, tmp_type2
;
6129 char buf1
[256], buf2
[256];
6132 st
= &vtop
->type
; /* source type */
6133 dbt
= dt
->t
& VT_BTYPE
;
6134 sbt
= st
->t
& VT_BTYPE
;
6135 if (dt
->t
& VT_CONSTANT
)
6136 warning("assignment of read-only location");
6139 /* special cases for pointers */
6140 /* '0' can also be a pointer */
6141 if (is_null_pointer(vtop
))
6143 /* accept implicit pointer to integer cast with warning */
6144 if (is_integer_btype(sbt
)) {
6145 warning("assignment makes pointer from integer without a cast");
6148 type1
= pointed_type(dt
);
6149 /* a function is implicitely a function pointer */
6150 if (sbt
== VT_FUNC
) {
6151 if ((type1
->t
& VT_BTYPE
) != VT_VOID
&&
6152 !is_compatible_types(pointed_type(dt
), st
))
6159 type2
= pointed_type(st
);
6160 if ((type1
->t
& VT_BTYPE
) == VT_VOID
||
6161 (type2
->t
& VT_BTYPE
) == VT_VOID
) {
6162 /* void * can match anything */
6164 /* exact type match, except for unsigned */
6167 tmp_type1
.t
&= ~(VT_UNSIGNED
| VT_CONSTANT
| VT_VOLATILE
);
6168 tmp_type2
.t
&= ~(VT_UNSIGNED
| VT_CONSTANT
| VT_VOLATILE
);
6169 if (!is_compatible_types(&tmp_type1
, &tmp_type2
))
6172 /* check const and volatile */
6173 if ((!(type1
->t
& VT_CONSTANT
) && (type2
->t
& VT_CONSTANT
)) ||
6174 (!(type1
->t
& VT_VOLATILE
) && (type2
->t
& VT_VOLATILE
)))
6175 warning("assignment discards qualifiers from pointer target type");
6181 if (sbt
== VT_PTR
|| sbt
== VT_FUNC
) {
6182 warning("assignment makes integer from pointer without a cast");
6184 /* XXX: more tests */
6189 tmp_type1
.t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
6190 tmp_type2
.t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
6191 if (!is_compatible_types(&tmp_type1
, &tmp_type2
)) {
6193 type_to_str(buf1
, sizeof(buf1
), st
, NULL
);
6194 type_to_str(buf2
, sizeof(buf2
), dt
, NULL
);
6195 error("cannot cast '%s' to '%s'", buf1
, buf2
);
6203 /* store vtop in lvalue pushed on stack */
6206 int sbt
, dbt
, ft
, r
, t
, size
, align
, bit_size
, bit_pos
, rc
, delayed_cast
;
6208 ft
= vtop
[-1].type
.t
;
6209 sbt
= vtop
->type
.t
& VT_BTYPE
;
6210 dbt
= ft
& VT_BTYPE
;
6211 if (((sbt
== VT_INT
|| sbt
== VT_SHORT
) && dbt
== VT_BYTE
) ||
6212 (sbt
== VT_INT
&& dbt
== VT_SHORT
)) {
6213 /* optimize char/short casts */
6214 delayed_cast
= VT_MUSTCAST
;
6215 vtop
->type
.t
= ft
& VT_TYPE
;
6216 /* XXX: factorize */
6217 if (ft
& VT_CONSTANT
)
6218 warning("assignment of read-only location");
6221 if (!(ft
& VT_BITFIELD
))
6222 gen_assign_cast(&vtop
[-1].type
);
6225 if (sbt
== VT_STRUCT
) {
6226 /* if structure, only generate pointer */
6227 /* structure assignment : generate memcpy */
6228 /* XXX: optimize if small size */
6229 if (!nocode_wanted
) {
6230 size
= type_size(&vtop
->type
, &align
);
6232 vpush_global_sym(&func_old_type
, TOK_memcpy
);
6236 vtop
->type
.t
= VT_INT
;
6240 vtop
->type
.t
= VT_INT
;
6252 /* leave source on stack */
6253 } else if (ft
& VT_BITFIELD
) {
6254 /* bitfield store handling */
6255 bit_pos
= (ft
>> VT_STRUCT_SHIFT
) & 0x3f;
6256 bit_size
= (ft
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f;
6257 /* remove bit field info to avoid loops */
6258 vtop
[-1].type
.t
= ft
& ~(VT_BITFIELD
| (-1 << VT_STRUCT_SHIFT
));
6260 /* duplicate destination */
6262 vtop
[-1] = vtop
[-2];
6264 /* mask and shift source */
6265 vpushi((1 << bit_size
) - 1);
6269 /* load destination, mask and or with source */
6271 vpushi(~(((1 << bit_size
) - 1) << bit_pos
));
6277 #ifdef CONFIG_TCC_BCHECK
6278 /* bound check case */
6279 if (vtop
[-1].r
& VT_MUSTBOUND
) {
6285 if (!nocode_wanted
) {
6289 r
= gv(rc
); /* generate value */
6290 /* if lvalue was saved on stack, must read it */
6291 if ((vtop
[-1].r
& VT_VALMASK
) == VT_LLOCAL
) {
6293 t
= get_reg(RC_INT
);
6295 sv
.r
= VT_LOCAL
| VT_LVAL
;
6296 sv
.c
.ul
= vtop
[-1].c
.ul
;
6298 vtop
[-1].r
= t
| VT_LVAL
;
6301 /* two word case handling : store second register at word + 4 */
6302 if ((ft
& VT_BTYPE
) == VT_LLONG
) {
6304 /* convert to int to increment easily */
6305 vtop
->type
.t
= VT_INT
;
6311 /* XXX: it works because r2 is spilled last ! */
6312 store(vtop
->r2
, vtop
- 1);
6316 vtop
--; /* NOT vpop() because on x86 it would flush the fp stack */
6317 vtop
->r
|= delayed_cast
;
6321 /* post defines POST/PRE add. c is the token ++ or -- */
6322 void inc(int post
, int c
)
6325 vdup(); /* save lvalue */
6327 gv_dup(); /* duplicate value */
6332 vpushi(c
- TOK_MID
);
6334 vstore(); /* store value */
6336 vpop(); /* if post op, return saved value */
6339 /* Parse GNUC __attribute__ extension. Currently, the following
6340 extensions are recognized:
6341 - aligned(n) : set data/function alignment.
6342 - packed : force data alignment to 1
6343 - section(x) : generate data/code in this section.
6344 - unused : currently ignored, but may be used someday.
6345 - regparm(n) : pass function parameters in registers (i386 only)
6347 static void parse_attribute(AttributeDef
*ad
)
6351 while (tok
== TOK_ATTRIBUTE1
|| tok
== TOK_ATTRIBUTE2
) {
6355 while (tok
!= ')') {
6356 if (tok
< TOK_IDENT
)
6357 expect("attribute name");
6365 expect("section name");
6366 ad
->section
= find_section(tcc_state
, (char *)tokc
.cstr
->data
);
6375 if (n
<= 0 || (n
& (n
- 1)) != 0)
6376 error("alignment must be a positive power of two");
6389 /* currently, no need to handle it because tcc does not
6390 track unused objects */
6394 /* currently, no need to handle it because tcc does not
6395 track unused objects */
6400 ad
->func_call
= FUNC_CDECL
;
6405 ad
->func_call
= FUNC_STDCALL
;
6407 #ifdef TCC_TARGET_I386
6417 ad
->func_call
= FUNC_FASTCALL1
+ n
- 1;
6425 if (tcc_state
->warn_unsupported
)
6426 warning("'%s' attribute ignored", get_tok_str(t
, NULL
));
6427 /* skip parameters */
6428 /* XXX: skip parenthesis too */
6431 while (tok
!= ')' && tok
!= -1)
6446 /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
6447 static void struct_decl(CType
*type
, int u
)
6449 int a
, v
, size
, align
, maxalign
, c
, offset
;
6450 int bit_size
, bit_pos
, bsize
, bt
, lbit_pos
;
6455 a
= tok
; /* save decl type */
6460 /* struct already defined ? return it */
6462 expect("struct/union/enum name");
6466 error("invalid type");
6473 /* we put an undefined size for struct/union */
6474 s
= sym_push(v
| SYM_STRUCT
, &type1
, 0, -1);
6475 s
->r
= 0; /* default alignment is zero as gcc */
6476 /* put struct/union/enum name in type */
6484 error("struct/union/enum already defined");
6485 /* cannot be empty */
6487 /* non empty enums are not allowed */
6488 if (a
== TOK_ENUM
) {
6492 expect("identifier");
6498 /* enum symbols have static storage */
6499 ss
= sym_push(v
, &int_type
, VT_CONST
, c
);
6500 ss
->type
.t
|= VT_STATIC
;
6505 /* NOTE: we accept a trailing comma */
6515 while (tok
!= '}') {
6516 parse_btype(&btype
, &ad
);
6522 type_decl(&type1
, &ad
, &v
, TYPE_DIRECT
);
6523 if ((type1
.t
& VT_BTYPE
) == VT_FUNC
||
6524 (type1
.t
& (VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
| VT_INLINE
)))
6525 error("invalid type for '%s'",
6526 get_tok_str(v
, NULL
));
6530 bit_size
= expr_const();
6531 /* XXX: handle v = 0 case for messages */
6533 error("negative width in bit-field '%s'",
6534 get_tok_str(v
, NULL
));
6535 if (v
&& bit_size
== 0)
6536 error("zero width for bit-field '%s'",
6537 get_tok_str(v
, NULL
));
6539 size
= type_size(&type1
, &align
);
6541 if (align
< ad
.aligned
)
6543 } else if (ad
.packed
) {
6545 } else if (*tcc_state
->pack_stack_ptr
) {
6546 if (align
> *tcc_state
->pack_stack_ptr
)
6547 align
= *tcc_state
->pack_stack_ptr
;
6550 if (bit_size
>= 0) {
6551 bt
= type1
.t
& VT_BTYPE
;
6557 error("bitfields must have scalar type");
6559 if (bit_size
> bsize
) {
6560 error("width of '%s' exceeds its type",
6561 get_tok_str(v
, NULL
));
6562 } else if (bit_size
== bsize
) {
6563 /* no need for bit fields */
6565 } else if (bit_size
== 0) {
6566 /* XXX: what to do if only padding in a
6568 /* zero size: means to pad */
6572 /* we do not have enough room ? */
6573 if ((bit_pos
+ bit_size
) > bsize
)
6576 /* XXX: handle LSB first */
6577 type1
.t
|= VT_BITFIELD
|
6578 (bit_pos
<< VT_STRUCT_SHIFT
) |
6579 (bit_size
<< (VT_STRUCT_SHIFT
+ 6));
6580 bit_pos
+= bit_size
;
6586 /* add new memory data only if starting
6588 if (lbit_pos
== 0) {
6589 if (a
== TOK_STRUCT
) {
6590 c
= (c
+ align
- 1) & -align
;
6598 if (align
> maxalign
)
6602 printf("add field %s offset=%d",
6603 get_tok_str(v
, NULL
), offset
);
6604 if (type1
.t
& VT_BITFIELD
) {
6605 printf(" pos=%d size=%d",
6606 (type1
.t
>> VT_STRUCT_SHIFT
) & 0x3f,
6607 (type1
.t
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f);
6611 ss
= sym_push(v
| SYM_FIELD
, &type1
, 0, offset
);
6615 if (tok
== ';' || tok
== TOK_EOF
)
6622 /* store size and alignment */
6623 s
->c
= (c
+ maxalign
- 1) & -maxalign
;
6629 /* return 0 if no type declaration. otherwise, return the basic type
6632 static int parse_btype(CType
*type
, AttributeDef
*ad
)
6634 int t
, u
, type_found
, typespec_found
;
6638 memset(ad
, 0, sizeof(AttributeDef
));
6645 /* currently, we really ignore extension */
6655 if ((t
& VT_BTYPE
) != 0)
6656 error("too many basic types");
6672 if ((t
& VT_BTYPE
) == VT_DOUBLE
) {
6673 t
= (t
& ~VT_BTYPE
) | VT_LDOUBLE
;
6674 } else if ((t
& VT_BTYPE
) == VT_LONG
) {
6675 t
= (t
& ~VT_BTYPE
) | VT_LLONG
;
6689 if ((t
& VT_BTYPE
) == VT_LONG
) {
6690 t
= (t
& ~VT_BTYPE
) | VT_LDOUBLE
;
6697 struct_decl(&type1
, VT_ENUM
);
6700 type
->ref
= type1
.ref
;
6704 struct_decl(&type1
, VT_STRUCT
);
6707 /* type modifiers */
6760 /* GNUC attribute */
6761 case TOK_ATTRIBUTE1
:
6762 case TOK_ATTRIBUTE2
:
6763 parse_attribute(ad
);
6770 parse_expr_type(&type1
);
6776 if (!s
|| !(s
->type
.t
& VT_TYPEDEF
))
6778 t
|= (s
->type
.t
& ~VT_TYPEDEF
);
6779 type
->ref
= s
->type
.ref
;
6786 if ((t
& (VT_SIGNED
|VT_UNSIGNED
)) == (VT_SIGNED
|VT_UNSIGNED
))
6787 error("signed and unsigned modifier");
6788 if (tcc_state
->char_is_unsigned
) {
6789 if ((t
& (VT_SIGNED
|VT_UNSIGNED
|VT_BTYPE
)) == VT_BYTE
)
6794 /* long is never used as type */
6795 if ((t
& VT_BTYPE
) == VT_LONG
)
6796 t
= (t
& ~VT_BTYPE
) | VT_INT
;
6801 /* convert a function parameter type (array to pointer and function to
6802 function pointer) */
6803 static inline void convert_parameter_type(CType
*pt
)
6805 /* remove const and volatile qualifiers (XXX: const could be used
6806 to indicate a const function parameter */
6807 pt
->t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
6808 /* array must be transformed to pointer according to ANSI C */
6810 if ((pt
->t
& VT_BTYPE
) == VT_FUNC
) {
6815 static void post_type(CType
*type
, AttributeDef
*ad
)
6818 Sym
**plast
, *s
, *first
;
6823 /* function declaration */
6828 while (tok
!= ')') {
6829 /* read param name and compute offset */
6830 if (l
!= FUNC_OLD
) {
6831 if (!parse_btype(&pt
, &ad1
)) {
6833 error("invalid type");
6840 if ((pt
.t
& VT_BTYPE
) == VT_VOID
&& tok
== ')')
6842 type_decl(&pt
, &ad1
, &n
, TYPE_DIRECT
| TYPE_ABSTRACT
);
6843 if ((pt
.t
& VT_BTYPE
) == VT_VOID
)
6844 error("parameter declared as void");
6851 convert_parameter_type(&pt
);
6852 s
= sym_push(n
| SYM_FIELD
, &pt
, 0, 0);
6857 if (l
== FUNC_NEW
&& tok
== TOK_DOTS
) {
6864 /* if no parameters, then old type prototype */
6868 t1
= type
->t
& VT_STORAGE
;
6869 /* NOTE: const is ignored in returned type as it has a special
6870 meaning in gcc / C++ */
6871 type
->t
&= ~(VT_STORAGE
| VT_CONSTANT
);
6872 post_type(type
, ad
);
6873 /* we push a anonymous symbol which will contain the function prototype */
6874 s
= sym_push(SYM_FIELD
, type
, ad
->func_call
, l
);
6876 type
->t
= t1
| VT_FUNC
;
6878 } else if (tok
== '[') {
6879 /* array definition */
6885 error("invalid array size");
6888 /* parse next post type */
6889 t1
= type
->t
& VT_STORAGE
;
6890 type
->t
&= ~VT_STORAGE
;
6891 post_type(type
, ad
);
6893 /* we push a anonymous symbol which will contain the array
6895 s
= sym_push(SYM_FIELD
, type
, 0, n
);
6896 type
->t
= t1
| VT_ARRAY
| VT_PTR
;
6901 /* Parse a type declaration (except basic type), and return the type
6902 in 'type'. 'td' is a bitmask indicating which kind of type decl is
6903 expected. 'type' should contain the basic type. 'ad' is the
6904 attribute definition of the basic type. It can be modified by
6907 static void type_decl(CType
*type
, AttributeDef
*ad
, int *v
, int td
)
6910 CType type1
, *type2
;
6913 while (tok
== '*') {
6921 qualifiers
|= VT_CONSTANT
;
6926 qualifiers
|= VT_VOLATILE
;
6934 type
->t
|= qualifiers
;
6937 /* XXX: clarify attribute handling */
6938 if (tok
== TOK_ATTRIBUTE1
|| tok
== TOK_ATTRIBUTE2
)
6939 parse_attribute(ad
);
6941 /* recursive type */
6942 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
6943 type1
.t
= 0; /* XXX: same as int */
6946 /* XXX: this is not correct to modify 'ad' at this point, but
6947 the syntax is not clear */
6948 if (tok
== TOK_ATTRIBUTE1
|| tok
== TOK_ATTRIBUTE2
)
6949 parse_attribute(ad
);
6950 type_decl(&type1
, ad
, v
, td
);
6953 /* type identifier */
6954 if (tok
>= TOK_IDENT
&& (td
& TYPE_DIRECT
)) {
6958 if (!(td
& TYPE_ABSTRACT
))
6959 expect("identifier");
6963 post_type(type
, ad
);
6964 if (tok
== TOK_ATTRIBUTE1
|| tok
== TOK_ATTRIBUTE2
)
6965 parse_attribute(ad
);
6968 /* append type at the end of type1 */
6981 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
6982 static int lvalue_type(int t
)
6987 if (bt
== VT_BYTE
|| bt
== VT_BOOL
)
6989 else if (bt
== VT_SHORT
)
6993 if (t
& VT_UNSIGNED
)
6994 r
|= VT_LVAL_UNSIGNED
;
6998 /* indirection with full error checking and bound check */
6999 static void indir(void)
7001 if ((vtop
->type
.t
& VT_BTYPE
) != VT_PTR
)
7003 if ((vtop
->r
& VT_LVAL
) && !nocode_wanted
)
7005 vtop
->type
= *pointed_type(&vtop
->type
);
7006 /* an array is never an lvalue */
7007 if (!(vtop
->type
.t
& VT_ARRAY
)) {
7008 vtop
->r
|= lvalue_type(vtop
->type
.t
);
7009 /* if bound checking, the referenced pointer must be checked */
7010 if (do_bounds_check
)
7011 vtop
->r
|= VT_MUSTBOUND
;
7015 /* pass a parameter to a function and do type checking and casting */
7016 static void gfunc_param_typed(Sym
*func
, Sym
*arg
)
7021 func_type
= func
->c
;
7022 if (func_type
== FUNC_OLD
||
7023 (func_type
== FUNC_ELLIPSIS
&& arg
== NULL
)) {
7024 /* default casting : only need to convert float to double */
7025 if ((vtop
->type
.t
& VT_BTYPE
) == VT_FLOAT
) {
7029 } else if (arg
== NULL
) {
7030 error("too many arguments to function");
7033 type
.t
&= ~VT_CONSTANT
; /* need to do that to avoid false warning */
7034 gen_assign_cast(&type
);
7038 /* parse an expression of the form '(type)' or '(expr)' and return its
7040 static void parse_expr_type(CType
*type
)
7046 if (parse_btype(type
, &ad
)) {
7047 type_decl(type
, &ad
, &n
, TYPE_ABSTRACT
);
7054 static void parse_type(CType
*type
)
7059 if (!parse_btype(type
, &ad
)) {
7062 type_decl(type
, &ad
, &n
, TYPE_ABSTRACT
);
7065 static void vpush_tokc(int t
)
7069 vsetc(&type
, VT_CONST
, &tokc
);
7072 static void unary(void)
7074 int n
, t
, align
, size
, r
;
7079 /* XXX: GCC 2.95.3 does not generate a table although it should be
7093 vpush_tokc(VT_INT
| VT_UNSIGNED
);
7097 vpush_tokc(VT_LLONG
);
7101 vpush_tokc(VT_LLONG
| VT_UNSIGNED
);
7105 vpush_tokc(VT_FLOAT
);
7109 vpush_tokc(VT_DOUBLE
);
7113 vpush_tokc(VT_LDOUBLE
);
7116 case TOK___FUNCTION__
:
7118 goto tok_identifier
;
7124 /* special function name identifier */
7125 len
= strlen(funcname
) + 1;
7126 /* generate char[len] type */
7131 vpush_ref(&type
, data_section
, data_section
->data_offset
, len
);
7132 ptr
= section_ptr_add(data_section
, len
);
7133 memcpy(ptr
, funcname
, len
);
7141 /* string parsing */
7144 if (tcc_state
->warn_write_strings
)
7149 memset(&ad
, 0, sizeof(AttributeDef
));
7150 decl_initializer_alloc(&type
, &ad
, VT_CONST
, 2, 0, 0);
7155 if (parse_btype(&type
, &ad
)) {
7156 type_decl(&type
, &ad
, &n
, TYPE_ABSTRACT
);
7158 /* check ISOC99 compound literal */
7160 /* data is allocated locally by default */
7165 /* all except arrays are lvalues */
7166 if (!(type
.t
& VT_ARRAY
))
7167 r
|= lvalue_type(type
.t
);
7168 memset(&ad
, 0, sizeof(AttributeDef
));
7169 decl_initializer_alloc(&type
, &ad
, r
, 1, 0, 0);
7174 } else if (tok
== '{') {
7175 /* save all registers */
7177 /* statement expression : we do not accept break/continue
7178 inside as GCC does */
7179 block(NULL
, NULL
, NULL
, NULL
, 0, 1);
7194 /* functions names must be treated as function pointers,
7195 except for unary '&' and sizeof. Since we consider that
7196 functions are not lvalues, we only have to handle it
7197 there and in function calls. */
7198 /* arrays can also be used although they are not lvalues */
7199 if ((vtop
->type
.t
& VT_BTYPE
) != VT_FUNC
&&
7200 !(vtop
->type
.t
& VT_ARRAY
))
7202 mk_pointer(&vtop
->type
);
7208 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
)
7209 vtop
->c
.i
= !vtop
->c
.i
;
7210 else if ((vtop
->r
& VT_VALMASK
) == VT_CMP
)
7211 vtop
->c
.i
= vtop
->c
.i
^ 1;
7213 vseti(VT_JMP
, gtst(1, 0));
7223 /* in order to force cast, we add zero */
7225 if ((vtop
->type
.t
& VT_BTYPE
) == VT_PTR
)
7226 error("pointer not accepted for unary plus");
7236 parse_expr_type(&type
);
7240 size
= type_size(&type
, &align
);
7241 if (t
== TOK_SIZEOF
) {
7243 error("sizeof applied to an incomplete type");
7250 case TOK_builtin_types_compatible_p
:
7259 type1
.t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
7260 type2
.t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
7261 vpushi(is_compatible_types(&type1
, &type2
));
7264 case TOK_builtin_constant_p
:
7266 int saved_nocode_wanted
, res
;
7269 saved_nocode_wanted
= nocode_wanted
;
7272 res
= (vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
7274 nocode_wanted
= saved_nocode_wanted
;
7294 goto tok_identifier
;
7296 /* allow to take the address of a label */
7297 if (tok
< TOK_UIDENT
)
7298 expect("label identifier");
7299 s
= label_find(tok
);
7301 s
= label_push(&global_label_stack
, tok
, LABEL_FORWARD
);
7303 if (s
->r
== LABEL_DECLARED
)
7304 s
->r
= LABEL_FORWARD
;
7307 s
->type
.t
= VT_VOID
;
7308 mk_pointer(&s
->type
);
7309 s
->type
.t
|= VT_STATIC
;
7311 vset(&s
->type
, VT_CONST
| VT_SYM
, 0);
7320 expect("identifier");
7324 error("'%s' undeclared", get_tok_str(t
, NULL
));
7325 /* for simple function calls, we tolerate undeclared
7326 external reference to int() function */
7327 if (tcc_state
->warn_implicit_function_declaration
)
7328 warning("implicit declaration of function '%s'",
7329 get_tok_str(t
, NULL
));
7330 s
= external_global_sym(t
, &func_old_type
, 0);
7332 if ((s
->type
.t
& (VT_STATIC
| VT_INLINE
| VT_BTYPE
)) ==
7333 (VT_STATIC
| VT_INLINE
| VT_FUNC
)) {
7334 /* if referencing an inline function, then we generate a
7335 symbol to it if not already done. It will have the
7336 effect to generate code for it at the end of the
7337 compilation unit. Inline function as always
7338 generated in the text section. */
7340 put_extern_sym(s
, text_section
, 0, 0);
7341 r
= VT_SYM
| VT_CONST
;
7345 vset(&s
->type
, r
, s
->c
);
7346 /* if forward reference, we must point to s */
7347 if (vtop
->r
& VT_SYM
) {
7354 /* post operations */
7356 if (tok
== TOK_INC
|| tok
== TOK_DEC
) {
7359 } else if (tok
== '.' || tok
== TOK_ARROW
) {
7361 if (tok
== TOK_ARROW
)
7366 /* expect pointer on structure */
7367 if ((vtop
->type
.t
& VT_BTYPE
) != VT_STRUCT
)
7368 expect("struct or union");
7372 while ((s
= s
->next
) != NULL
) {
7377 error("field not found");
7378 /* add field offset to pointer */
7379 vtop
->type
= char_pointer_type
; /* change type to 'char *' */
7382 /* change type to field type, and set to lvalue */
7383 vtop
->type
= s
->type
;
7384 /* an array is never an lvalue */
7385 if (!(vtop
->type
.t
& VT_ARRAY
)) {
7386 vtop
->r
|= lvalue_type(vtop
->type
.t
);
7387 /* if bound checking, the referenced pointer must be checked */
7388 if (do_bounds_check
)
7389 vtop
->r
|= VT_MUSTBOUND
;
7392 } else if (tok
== '[') {
7398 } else if (tok
== '(') {
7404 if ((vtop
->type
.t
& VT_BTYPE
) != VT_FUNC
) {
7405 /* pointer test (no array accepted) */
7406 if ((vtop
->type
.t
& (VT_BTYPE
| VT_ARRAY
)) == VT_PTR
) {
7407 vtop
->type
= *pointed_type(&vtop
->type
);
7408 if ((vtop
->type
.t
& VT_BTYPE
) != VT_FUNC
)
7412 expect("function pointer");
7415 vtop
->r
&= ~VT_LVAL
; /* no lvalue */
7417 /* get return type */
7420 sa
= s
->next
; /* first parameter */
7422 /* compute first implicit argument if a structure is returned */
7423 if ((s
->type
.t
& VT_BTYPE
) == VT_STRUCT
) {
7424 /* get some space for the returned structure */
7425 size
= type_size(&s
->type
, &align
);
7426 loc
= (loc
- size
) & -align
;
7428 ret
.r
= VT_LOCAL
| VT_LVAL
;
7429 /* pass it as 'int' to avoid structure arg passing
7431 vseti(VT_LOCAL
, loc
);
7437 /* return in register */
7438 if (is_float(ret
.type
.t
)) {
7441 if ((ret
.type
.t
& VT_BTYPE
) == VT_LLONG
)
7450 gfunc_param_typed(s
, sa
);
7460 error("too few arguments to function");
7462 if (!nocode_wanted
) {
7463 gfunc_call(nb_args
);
7465 vtop
-= (nb_args
+ 1);
7468 vsetc(&ret
.type
, ret
.r
, &ret
.c
);
7476 static void uneq(void)
7482 (tok
>= TOK_A_MOD
&& tok
<= TOK_A_DIV
) ||
7483 tok
== TOK_A_XOR
|| tok
== TOK_A_OR
||
7484 tok
== TOK_A_SHL
|| tok
== TOK_A_SAR
) {
7499 static void expr_prod(void)
7504 while (tok
== '*' || tok
== '/' || tok
== '%') {
7512 static void expr_sum(void)
7517 while (tok
== '+' || tok
== '-') {
7525 static void expr_shift(void)
7530 while (tok
== TOK_SHL
|| tok
== TOK_SAR
) {
7538 static void expr_cmp(void)
7543 while ((tok
>= TOK_ULE
&& tok
<= TOK_GT
) ||
7544 tok
== TOK_ULT
|| tok
== TOK_UGE
) {
7552 static void expr_cmpeq(void)
7557 while (tok
== TOK_EQ
|| tok
== TOK_NE
) {
7565 static void expr_and(void)
7568 while (tok
== '&') {
7575 static void expr_xor(void)
7578 while (tok
== '^') {
7585 static void expr_or(void)
7588 while (tok
== '|') {
7595 /* XXX: fix this mess */
7596 static void expr_land_const(void)
7599 while (tok
== TOK_LAND
) {
7606 /* XXX: fix this mess */
7607 static void expr_lor_const(void)
7610 while (tok
== TOK_LOR
) {
7617 /* only used if non constant */
7618 static void expr_land(void)
7623 if (tok
== TOK_LAND
) {
7627 if (tok
!= TOK_LAND
) {
7637 static void expr_lor(void)
7642 if (tok
== TOK_LOR
) {
7646 if (tok
!= TOK_LOR
) {
7656 /* XXX: better constant handling */
7657 static void expr_eq(void)
7659 int tt
, u
, r1
, r2
, rc
, t1
, t2
, bt1
, bt2
;
7661 CType type
, type1
, type2
;
7670 if (tok
== ':' && gnu_ext
) {
7686 if (vtop
!= vstack
) {
7687 /* needed to avoid having different registers saved in
7689 if (is_float(vtop
->type
.t
))
7696 if (tok
== ':' && gnu_ext
) {
7704 sv
= *vtop
; /* save value to handle it later */
7705 vtop
--; /* no vpop so that FP stack is not flushed */
7713 bt1
= t1
& VT_BTYPE
;
7715 bt2
= t2
& VT_BTYPE
;
7716 /* cast operands to correct type according to ISOC rules */
7717 if (is_float(bt1
) || is_float(bt2
)) {
7718 if (bt1
== VT_LDOUBLE
|| bt2
== VT_LDOUBLE
) {
7719 type
.t
= VT_LDOUBLE
;
7720 } else if (bt1
== VT_DOUBLE
|| bt2
== VT_DOUBLE
) {
7725 } else if (bt1
== VT_LLONG
|| bt2
== VT_LLONG
) {
7726 /* cast to biggest op */
7728 /* convert to unsigned if it does not fit in a long long */
7729 if ((t1
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_LLONG
| VT_UNSIGNED
) ||
7730 (t2
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_LLONG
| VT_UNSIGNED
))
7731 type
.t
|= VT_UNSIGNED
;
7732 } else if (bt1
== VT_PTR
|| bt2
== VT_PTR
) {
7733 /* XXX: test pointer compatibility */
7735 } else if (bt1
== VT_STRUCT
|| bt2
== VT_STRUCT
) {
7736 /* XXX: test structure compatibility */
7738 } else if (bt1
== VT_VOID
|| bt2
== VT_VOID
) {
7739 /* NOTE: as an extension, we accept void on only one side */
7742 /* integer operations */
7744 /* convert to unsigned if it does not fit in an integer */
7745 if ((t1
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
) ||
7746 (t2
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
))
7747 type
.t
|= VT_UNSIGNED
;
7750 /* now we convert second operand */
7753 if (is_float(type
.t
)) {
7755 } else if ((type
.t
& VT_BTYPE
) == VT_LLONG
) {
7756 /* for long longs, we use fixed registers to avoid having
7757 to handle a complicated move */
7762 /* this is horrible, but we must also convert first
7766 /* put again first value and cast it */
7777 static void gexpr(void)
7788 /* parse an expression and return its type without any side effect. */
7789 static void expr_type(CType
*type
)
7791 int saved_nocode_wanted
;
7793 saved_nocode_wanted
= nocode_wanted
;
7798 nocode_wanted
= saved_nocode_wanted
;
7801 /* parse a unary expression and return its type without any side
7803 static void unary_type(CType
*type
)
7815 /* parse a constant expression and return value in vtop. */
7816 static void expr_const1(void)
7825 /* parse an integer constant and return its value. */
7826 static int expr_const(void)
7830 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) != VT_CONST
)
7831 expect("constant expression");
7837 /* return the label token if current token is a label, otherwise
7839 static int is_label(void)
7843 /* fast test first */
7844 if (tok
< TOK_UIDENT
)
7846 /* no need to save tokc because tok is an identifier */
7853 unget_tok(last_tok
);
7858 static void block(int *bsym
, int *csym
, int *case_sym
, int *def_sym
,
7859 int case_reg
, int is_expr
)
7864 /* generate line number info */
7866 (last_line_num
!= file
->line_num
|| last_ind
!= ind
)) {
7867 put_stabn(N_SLINE
, 0, file
->line_num
, ind
- func_ind
);
7869 last_line_num
= file
->line_num
;
7873 /* default return value is (void) */
7875 vtop
->type
.t
= VT_VOID
;
7878 if (tok
== TOK_IF
) {
7885 block(bsym
, csym
, case_sym
, def_sym
, case_reg
, 0);
7887 if (c
== TOK_ELSE
) {
7891 block(bsym
, csym
, case_sym
, def_sym
, case_reg
, 0);
7892 gsym(d
); /* patch else jmp */
7895 } else if (tok
== TOK_WHILE
) {
7903 block(&a
, &b
, case_sym
, def_sym
, case_reg
, 0);
7907 } else if (tok
== '{') {
7911 /* record local declaration stack position */
7913 llabel
= local_label_stack
;
7914 /* handle local labels declarations */
7915 if (tok
== TOK_LABEL
) {
7918 if (tok
< TOK_UIDENT
)
7919 expect("label identifier");
7920 label_push(&local_label_stack
, tok
, LABEL_DECLARED
);
7930 while (tok
!= '}') {
7935 block(bsym
, csym
, case_sym
, def_sym
, case_reg
, is_expr
);
7938 /* pop locally defined labels */
7939 label_pop(&local_label_stack
, llabel
);
7940 /* pop locally defined symbols */
7941 sym_pop(&local_stack
, s
);
7943 } else if (tok
== TOK_RETURN
) {
7947 gen_assign_cast(&func_vt
);
7948 if ((func_vt
.t
& VT_BTYPE
) == VT_STRUCT
) {
7950 /* if returning structure, must copy it to implicit
7951 first pointer arg location */
7954 vset(&type
, VT_LOCAL
| VT_LVAL
, func_vc
);
7957 /* copy structure value to pointer */
7959 } else if (is_float(func_vt
.t
)) {
7964 vtop
--; /* NOT vpop() because on x86 it would flush the fp stack */
7967 rsym
= gjmp(rsym
); /* jmp */
7968 } else if (tok
== TOK_BREAK
) {
7971 error("cannot break");
7972 *bsym
= gjmp(*bsym
);
7975 } else if (tok
== TOK_CONTINUE
) {
7978 error("cannot continue");
7979 *csym
= gjmp(*csym
);
7982 } else if (tok
== TOK_FOR
) {
8009 block(&a
, &b
, case_sym
, def_sym
, case_reg
, 0);
8014 if (tok
== TOK_DO
) {
8019 block(&a
, &b
, case_sym
, def_sym
, case_reg
, 0);
8030 if (tok
== TOK_SWITCH
) {
8034 /* XXX: other types than integer */
8035 case_reg
= gv(RC_INT
);
8039 b
= gjmp(0); /* jump to first case */
8041 block(&a
, csym
, &b
, &c
, case_reg
, 0);
8042 /* if no default, jmp after switch */
8050 if (tok
== TOK_CASE
) {
8057 if (gnu_ext
&& tok
== TOK_DOTS
) {
8061 warning("empty case range");
8063 /* since a case is like a label, we must skip it with a jmp */
8070 *case_sym
= gtst(1, 0);
8073 *case_sym
= gtst(1, 0);
8077 *case_sym
= gtst(1, *case_sym
);
8082 goto block_after_label
;
8084 if (tok
== TOK_DEFAULT
) {
8090 error("too many 'default'");
8093 goto block_after_label
;
8095 if (tok
== TOK_GOTO
) {
8097 if (tok
== '*' && gnu_ext
) {
8101 if ((vtop
->type
.t
& VT_BTYPE
) != VT_PTR
)
8104 } else if (tok
>= TOK_UIDENT
) {
8105 s
= label_find(tok
);
8106 /* put forward definition if needed */
8108 s
= label_push(&global_label_stack
, tok
, LABEL_FORWARD
);
8110 if (s
->r
== LABEL_DECLARED
)
8111 s
->r
= LABEL_FORWARD
;
8113 /* label already defined */
8114 if (s
->r
& LABEL_FORWARD
)
8115 s
->next
= (void *)gjmp((long)s
->next
);
8117 gjmp_addr((long)s
->next
);
8120 expect("label identifier");
8123 } else if (tok
== TOK_ASM1
|| tok
== TOK_ASM2
|| tok
== TOK_ASM3
) {
8131 if (s
->r
== LABEL_DEFINED
)
8132 error("duplicate label '%s'", get_tok_str(s
->v
, NULL
));
8133 gsym((long)s
->next
);
8134 s
->r
= LABEL_DEFINED
;
8136 s
= label_push(&global_label_stack
, b
, LABEL_DEFINED
);
8138 s
->next
= (void *)ind
;
8139 /* we accept this, but it is a mistake */
8142 warning("deprecated use of label at end of compound statement");
8146 block(bsym
, csym
, case_sym
, def_sym
, case_reg
, is_expr
);
8149 /* expression case */
8164 /* t is the array or struct type. c is the array or struct
8165 address. cur_index/cur_field is the pointer to the current
8166 value. 'size_only' is true if only size info is needed (only used
8168 static void decl_designator(CType
*type
, Section
*sec
, unsigned long c
,
8169 int *cur_index
, Sym
**cur_field
,
8173 int notfirst
, index
, index_last
, align
, l
, nb_elems
, elem_size
;
8179 if (gnu_ext
&& (l
= is_label()) != 0)
8181 while (tok
== '[' || tok
== '.') {
8183 if (!(type
->t
& VT_ARRAY
))
8184 expect("array type");
8187 index
= expr_const();
8188 if (index
< 0 || (s
->c
>= 0 && index
>= s
->c
))
8189 expect("invalid index");
8190 if (tok
== TOK_DOTS
&& gnu_ext
) {
8192 index_last
= expr_const();
8193 if (index_last
< 0 ||
8194 (s
->c
>= 0 && index_last
>= s
->c
) ||
8196 expect("invalid index");
8202 *cur_index
= index_last
;
8203 type
= pointed_type(type
);
8204 elem_size
= type_size(type
, &align
);
8205 c
+= index
* elem_size
;
8206 /* NOTE: we only support ranges for last designator */
8207 nb_elems
= index_last
- index
+ 1;
8208 if (nb_elems
!= 1) {
8217 if ((type
->t
& VT_BTYPE
) != VT_STRUCT
)
8218 expect("struct/union type");
8231 /* XXX: fix this mess by using explicit storage field */
8233 type1
.t
|= (type
->t
& ~VT_TYPE
);
8247 if (type
->t
& VT_ARRAY
) {
8249 type
= pointed_type(type
);
8250 c
+= index
* type_size(type
, &align
);
8254 error("too many field init");
8255 /* XXX: fix this mess by using explicit storage field */
8257 type1
.t
|= (type
->t
& ~VT_TYPE
);
8262 decl_initializer(type
, sec
, c
, 0, size_only
);
8264 /* XXX: make it more general */
8265 if (!size_only
&& nb_elems
> 1) {
8266 unsigned long c_end
;
8271 error("range init not supported yet for dynamic storage");
8272 c_end
= c
+ nb_elems
* elem_size
;
8273 if (c_end
> sec
->data_allocated
)
8274 section_realloc(sec
, c_end
);
8275 src
= sec
->data
+ c
;
8277 for(i
= 1; i
< nb_elems
; i
++) {
8279 memcpy(dst
, src
, elem_size
);
8285 #define EXPR_CONST 1
8288 /* store a value or an expression directly in global data or in local array */
8289 static void init_putv(CType
*type
, Section
*sec
, unsigned long c
,
8290 int v
, int expr_type
)
8292 int saved_global_expr
, bt
, bit_pos
, bit_size
;
8294 unsigned long long bit_mask
;
8302 /* compound literals must be allocated globally in this case */
8303 saved_global_expr
= global_expr
;
8306 global_expr
= saved_global_expr
;
8307 /* NOTE: symbols are accepted */
8308 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
)) != VT_CONST
)
8309 error("initializer element is not constant");
8317 dtype
.t
&= ~VT_CONSTANT
; /* need to do that to avoid false warning */
8320 /* XXX: not portable */
8321 /* XXX: generate error if incorrect relocation */
8322 gen_assign_cast(&dtype
);
8323 bt
= type
->t
& VT_BTYPE
;
8324 ptr
= sec
->data
+ c
;
8325 /* XXX: make code faster ? */
8326 if (!(type
->t
& VT_BITFIELD
)) {
8331 bit_pos
= (vtop
->type
.t
>> VT_STRUCT_SHIFT
) & 0x3f;
8332 bit_size
= (vtop
->type
.t
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f;
8333 bit_mask
= (1LL << bit_size
) - 1;
8335 if ((vtop
->r
& VT_SYM
) &&
8341 (bt
== VT_INT
&& bit_size
!= 32)))
8342 error("initializer element is not computable at load time");
8345 *(char *)ptr
|= (vtop
->c
.i
& bit_mask
) << bit_pos
;
8348 *(short *)ptr
|= (vtop
->c
.i
& bit_mask
) << bit_pos
;
8351 *(double *)ptr
= vtop
->c
.d
;
8354 *(long double *)ptr
= vtop
->c
.ld
;
8357 *(long long *)ptr
|= (vtop
->c
.ll
& bit_mask
) << bit_pos
;
8360 if (vtop
->r
& VT_SYM
) {
8361 greloc(sec
, vtop
->sym
, c
, R_DATA_32
);
8363 *(int *)ptr
|= (vtop
->c
.i
& bit_mask
) << bit_pos
;
8368 vset(&dtype
, VT_LOCAL
, c
);
8375 /* put zeros for variable based init */
8376 static void init_putz(CType
*t
, Section
*sec
, unsigned long c
, int size
)
8379 /* nothing to do because globals are already set to zero */
8381 vpush_global_sym(&func_old_type
, TOK_memset
);
8389 /* 't' contains the type and storage info. 'c' is the offset of the
8390 object in section 'sec'. If 'sec' is NULL, it means stack based
8391 allocation. 'first' is true if array '{' must be read (multi
8392 dimension implicit array init handling). 'size_only' is true if
8393 size only evaluation is wanted (only for arrays). */
8394 static void decl_initializer(CType
*type
, Section
*sec
, unsigned long c
,
8395 int first
, int size_only
)
8397 int index
, array_length
, n
, no_oblock
, nb
, parlevel
, i
;
8398 int size1
, align1
, expr_type
;
8402 if (type
->t
& VT_ARRAY
) {
8406 t1
= pointed_type(type
);
8407 size1
= type_size(t1
, &align1
);
8410 if ((first
&& tok
!= TOK_LSTR
&& tok
!= TOK_STR
) ||
8416 /* only parse strings here if correct type (otherwise: handle
8417 them as ((w)char *) expressions */
8418 if ((tok
== TOK_LSTR
&&
8419 (t1
->t
& VT_BTYPE
) == VT_INT
) ||
8421 (t1
->t
& VT_BTYPE
) == VT_BYTE
)) {
8422 while (tok
== TOK_STR
|| tok
== TOK_LSTR
) {
8427 /* compute maximum number of chars wanted */
8429 cstr_len
= cstr
->size
;
8431 cstr_len
= cstr
->size
/ sizeof(int);
8434 if (n
>= 0 && nb
> (n
- array_length
))
8435 nb
= n
- array_length
;
8438 warning("initializer-string for array is too long");
8439 /* in order to go faster for common case (char
8440 string in global variable, we handle it
8442 if (sec
&& tok
== TOK_STR
&& size1
== 1) {
8443 memcpy(sec
->data
+ c
+ array_length
, cstr
->data
, nb
);
8447 ch
= ((unsigned char *)cstr
->data
)[i
];
8449 ch
= ((int *)cstr
->data
)[i
];
8450 init_putv(t1
, sec
, c
+ (array_length
+ i
) * size1
,
8458 /* only add trailing zero if enough storage (no
8459 warning in this case since it is standard) */
8460 if (n
< 0 || array_length
< n
) {
8462 init_putv(t1
, sec
, c
+ (array_length
* size1
), 0, EXPR_VAL
);
8468 while (tok
!= '}') {
8469 decl_designator(type
, sec
, c
, &index
, NULL
, size_only
);
8470 if (n
>= 0 && index
>= n
)
8471 error("index too large");
8472 /* must put zero in holes (note that doing it that way
8473 ensures that it even works with designators) */
8474 if (!size_only
&& array_length
< index
) {
8475 init_putz(t1
, sec
, c
+ array_length
* size1
,
8476 (index
- array_length
) * size1
);
8479 if (index
> array_length
)
8480 array_length
= index
;
8481 /* special test for multi dimensional arrays (may not
8482 be strictly correct if designators are used at the
8484 if (index
>= n
&& no_oblock
)
8493 /* put zeros at the end */
8494 if (!size_only
&& n
>= 0 && array_length
< n
) {
8495 init_putz(t1
, sec
, c
+ array_length
* size1
,
8496 (n
- array_length
) * size1
);
8498 /* patch type size if needed */
8500 s
->c
= array_length
;
8501 } else if ((type
->t
& VT_BTYPE
) == VT_STRUCT
&&
8502 (sec
|| !first
|| tok
== '{')) {
8505 /* NOTE: the previous test is a specific case for automatic
8506 struct/union init */
8507 /* XXX: union needs only one init */
8509 /* XXX: this test is incorrect for local initializers
8510 beginning with ( without {. It would be much more difficult
8511 to do it correctly (ideally, the expression parser should
8512 be used in all cases) */
8518 while (tok
== '(') {
8522 if (!parse_btype(&type1
, &ad1
))
8524 type_decl(&type1
, &ad1
, &n
, TYPE_ABSTRACT
);
8526 if (!is_assignable_types(type
, &type1
))
8527 error("invalid type for cast");
8532 if (first
|| tok
== '{') {
8541 while (tok
!= '}') {
8542 decl_designator(type
, sec
, c
, NULL
, &f
, size_only
);
8544 if (!size_only
&& array_length
< index
) {
8545 init_putz(type
, sec
, c
+ array_length
,
8546 index
- array_length
);
8548 index
= index
+ type_size(&f
->type
, &align1
);
8549 if (index
> array_length
)
8550 array_length
= index
;
8552 if (no_oblock
&& f
== NULL
)
8558 /* put zeros at the end */
8559 if (!size_only
&& array_length
< n
) {
8560 init_putz(type
, sec
, c
+ array_length
,
8569 } else if (tok
== '{') {
8571 decl_initializer(type
, sec
, c
, first
, size_only
);
8573 } else if (size_only
) {
8574 /* just skip expression */
8576 while ((parlevel
> 0 || (tok
!= '}' && tok
!= ',')) &&
8580 else if (tok
== ')')
8585 /* currently, we always use constant expression for globals
8586 (may change for scripting case) */
8587 expr_type
= EXPR_CONST
;
8589 expr_type
= EXPR_ANY
;
8590 init_putv(type
, sec
, c
, 0, expr_type
);
8594 /* parse an initializer for type 't' if 'has_init' is non zero, and
8595 allocate space in local or global data space ('r' is either
8596 VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
8597 variable 'v' of scope 'scope' is declared before initializers are
8598 parsed. If 'v' is zero, then a reference to the new object is put
8599 in the value stack. If 'has_init' is 2, a special parsing is done
8600 to handle string constants. */
8601 static void decl_initializer_alloc(CType
*type
, AttributeDef
*ad
, int r
,
8602 int has_init
, int v
, int scope
)
8604 int size
, align
, addr
, data_offset
;
8606 ParseState saved_parse_state
;
8607 TokenString init_str
;
8610 size
= type_size(type
, &align
);
8611 /* If unknown size, we must evaluate it before
8612 evaluating initializers because
8613 initializers can generate global data too
8614 (e.g. string pointers or ISOC99 compound
8615 literals). It also simplifies local
8616 initializers handling */
8617 tok_str_new(&init_str
);
8620 error("unknown type size");
8621 /* get all init string */
8622 if (has_init
== 2) {
8623 /* only get strings */
8624 while (tok
== TOK_STR
|| tok
== TOK_LSTR
) {
8625 tok_str_add_tok(&init_str
);
8630 while (level
> 0 || (tok
!= ',' && tok
!= ';')) {
8632 error("unexpected end of file in initializer");
8633 tok_str_add_tok(&init_str
);
8636 else if (tok
== '}') {
8644 tok_str_add(&init_str
, -1);
8645 tok_str_add(&init_str
, 0);
8648 save_parse_state(&saved_parse_state
);
8650 macro_ptr
= init_str
.str
;
8652 decl_initializer(type
, NULL
, 0, 1, 1);
8653 /* prepare second initializer parsing */
8654 macro_ptr
= init_str
.str
;
8657 /* if still unknown size, error */
8658 size
= type_size(type
, &align
);
8660 error("unknown type size");
8662 /* take into account specified alignment if bigger */
8664 if (ad
->aligned
> align
)
8665 align
= ad
->aligned
;
8666 } else if (ad
->packed
) {
8669 if ((r
& VT_VALMASK
) == VT_LOCAL
) {
8671 if (do_bounds_check
&& (type
->t
& VT_ARRAY
))
8673 loc
= (loc
- size
) & -align
;
8675 /* handles bounds */
8676 /* XXX: currently, since we do only one pass, we cannot track
8677 '&' operators, so we add only arrays */
8678 if (do_bounds_check
&& (type
->t
& VT_ARRAY
)) {
8679 unsigned long *bounds_ptr
;
8680 /* add padding between regions */
8682 /* then add local bound info */
8683 bounds_ptr
= section_ptr_add(lbounds_section
, 2 * sizeof(unsigned long));
8684 bounds_ptr
[0] = addr
;
8685 bounds_ptr
[1] = size
;
8688 /* local variable */
8689 sym_push(v
, type
, r
, addr
);
8691 /* push local reference */
8692 vset(type
, r
, addr
);
8698 if (v
&& scope
== VT_CONST
) {
8699 /* see if the symbol was already defined */
8702 if (!is_compatible_types(&sym
->type
, type
))
8703 error("incompatible types for redefinition of '%s'",
8704 get_tok_str(v
, NULL
));
8705 if (sym
->type
.t
& VT_EXTERN
) {
8706 /* if the variable is extern, it was not allocated */
8707 sym
->type
.t
&= ~VT_EXTERN
;
8708 /* set array size if it was ommited in extern
8710 if ((sym
->type
.t
& VT_ARRAY
) &&
8711 sym
->type
.ref
->c
< 0 &&
8713 sym
->type
.ref
->c
= type
->ref
->c
;
8715 /* we accept several definitions of the same
8716 global variable. this is tricky, because we
8717 must play with the SHN_COMMON type of the symbol */
8718 /* XXX: should check if the variable was already
8719 initialized. It is incorrect to initialized it
8721 /* no init data, we won't add more to the symbol */
8728 /* allocate symbol in corresponding section */
8733 else if (tcc_state
->nocommon
)
8737 data_offset
= sec
->data_offset
;
8738 data_offset
= (data_offset
+ align
- 1) & -align
;
8740 /* very important to increment global pointer at this time
8741 because initializers themselves can create new initializers */
8742 data_offset
+= size
;
8743 /* add padding if bound check */
8744 if (do_bounds_check
)
8746 sec
->data_offset
= data_offset
;
8747 /* allocate section space to put the data */
8748 if (sec
->sh_type
!= SHT_NOBITS
&&
8749 data_offset
> sec
->data_allocated
)
8750 section_realloc(sec
, data_offset
);
8751 /* align section if needed */
8752 if (align
> sec
->sh_addralign
)
8753 sec
->sh_addralign
= align
;
8755 addr
= 0; /* avoid warning */
8759 if (scope
== VT_CONST
) {
8764 sym
= sym_push(v
, type
, r
| VT_SYM
, 0);
8766 /* update symbol definition */
8768 put_extern_sym(sym
, sec
, addr
, size
);
8771 /* put a common area */
8772 put_extern_sym(sym
, NULL
, align
, size
);
8773 /* XXX: find a nicer way */
8774 esym
= &((Elf32_Sym
*)symtab_section
->data
)[sym
->c
];
8775 esym
->st_shndx
= SHN_COMMON
;
8780 /* push global reference */
8781 sym
= get_sym_ref(type
, sec
, addr
, size
);
8783 vsetc(type
, VT_CONST
| VT_SYM
, &cval
);
8787 /* handles bounds now because the symbol must be defined
8788 before for the relocation */
8789 if (do_bounds_check
) {
8790 unsigned long *bounds_ptr
;
8792 greloc(bounds_section
, sym
, bounds_section
->data_offset
, R_DATA_32
);
8793 /* then add global bound info */
8794 bounds_ptr
= section_ptr_add(bounds_section
, 2 * sizeof(long));
8795 bounds_ptr
[0] = 0; /* relocated */
8796 bounds_ptr
[1] = size
;
8800 decl_initializer(type
, sec
, addr
, 1, 0);
8801 /* restore parse state if needed */
8803 tok_str_free(init_str
.str
);
8804 restore_parse_state(&saved_parse_state
);
8810 void put_func_debug(Sym
*sym
)
8815 /* XXX: we put here a dummy type */
8816 snprintf(buf
, sizeof(buf
), "%s:%c1",
8817 funcname
, sym
->type
.t
& VT_STATIC
? 'f' : 'F');
8818 put_stabs_r(buf
, N_FUN
, 0, file
->line_num
, 0,
8819 cur_text_section
, sym
->c
);
8824 /* parse an old style function declaration list */
8825 /* XXX: check multiple parameter */
8826 static void func_decl_list(Sym
*func_sym
)
8833 /* parse each declaration */
8834 while (tok
!= '{' && tok
!= ';' && tok
!= ',' && tok
!= TOK_EOF
) {
8835 if (!parse_btype(&btype
, &ad
))
8836 expect("declaration list");
8837 if (((btype
.t
& VT_BTYPE
) == VT_ENUM
||
8838 (btype
.t
& VT_BTYPE
) == VT_STRUCT
) &&
8840 /* we accept no variable after */
8844 type_decl(&type
, &ad
, &v
, TYPE_DIRECT
);
8845 /* find parameter in function parameter list */
8848 if ((s
->v
& ~SYM_FIELD
) == v
)
8852 error("declaration for parameter '%s' but no such parameter",
8853 get_tok_str(v
, NULL
));
8855 /* check that no storage specifier except 'register' was given */
8856 if (type
.t
& VT_STORAGE
)
8857 error("storage class specified for '%s'", get_tok_str(v
, NULL
));
8858 convert_parameter_type(&type
);
8859 /* we can add the type (NOTE: it could be local to the function) */
8861 /* accept other parameters */
8872 /* parse a function defined by symbol 'sym' and generate its code in
8873 'cur_text_section' */
8874 static void gen_function(Sym
*sym
)
8876 ind
= cur_text_section
->data_offset
;
8877 /* NOTE: we patch the symbol size later */
8878 put_extern_sym(sym
, cur_text_section
, ind
, 0);
8879 funcname
= get_tok_str(sym
->v
, NULL
);
8881 /* put debug symbol */
8883 put_func_debug(sym
);
8884 /* push a dummy symbol to enable local sym storage */
8885 sym_push2(&local_stack
, SYM_FIELD
, 0, 0);
8886 gfunc_prolog(&sym
->type
);
8888 block(NULL
, NULL
, NULL
, NULL
, 0, 0);
8891 cur_text_section
->data_offset
= ind
;
8892 label_pop(&global_label_stack
, NULL
);
8893 sym_pop(&local_stack
, NULL
); /* reset local stack */
8894 /* end of function */
8895 /* patch symbol size */
8896 ((Elf32_Sym
*)symtab_section
->data
)[sym
->c
].st_size
=
8899 put_stabn(N_FUN
, 0, 0, ind
- func_ind
);
8901 funcname
= ""; /* for safety */
8902 func_vt
.t
= VT_VOID
; /* for safety */
8903 ind
= 0; /* for safety */
8906 static void gen_inline_functions(void)
8910 int *str
, inline_generated
;
8912 /* iterate while inline function are referenced */
8914 inline_generated
= 0;
8915 for(sym
= global_stack
; sym
!= NULL
; sym
= sym
->prev
) {
8917 if (((type
->t
& VT_BTYPE
) == VT_FUNC
) &&
8918 (type
->t
& (VT_STATIC
| VT_INLINE
)) ==
8919 (VT_STATIC
| VT_INLINE
) &&
8921 /* the function was used: generate its code and
8922 convert it to a normal function */
8923 str
= (int *)sym
->r
;
8924 sym
->r
= VT_SYM
| VT_CONST
;
8925 type
->t
&= ~VT_INLINE
;
8929 cur_text_section
= text_section
;
8931 macro_ptr
= NULL
; /* fail safe */
8934 inline_generated
= 1;
8937 if (!inline_generated
)
8941 /* free all remaining inline function tokens */
8942 for(sym
= global_stack
; sym
!= NULL
; sym
= sym
->prev
) {
8944 if (((type
->t
& VT_BTYPE
) == VT_FUNC
) &&
8945 (type
->t
& (VT_STATIC
| VT_INLINE
)) ==
8946 (VT_STATIC
| VT_INLINE
)) {
8947 str
= (int *)sym
->r
;
8949 sym
->r
= 0; /* fail safe */
8954 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
8955 static void decl(int l
)
8963 if (!parse_btype(&btype
, &ad
)) {
8964 /* skip redundant ';' */
8965 /* XXX: find more elegant solution */
8970 if (l
== VT_CONST
&&
8971 (tok
== TOK_ASM1
|| tok
== TOK_ASM2
|| tok
== TOK_ASM3
)) {
8972 /* global asm block */
8976 /* special test for old K&R protos without explicit int
8977 type. Only accepted when defining global data */
8978 if (l
== VT_LOCAL
|| tok
< TOK_DEFINE
)
8982 if (((btype
.t
& VT_BTYPE
) == VT_ENUM
||
8983 (btype
.t
& VT_BTYPE
) == VT_STRUCT
) &&
8985 /* we accept no variable after */
8989 while (1) { /* iterate thru each declaration */
8991 type_decl(&type
, &ad
, &v
, TYPE_DIRECT
);
8995 type_to_str(buf
, sizeof(buf
), t
, get_tok_str(v
, NULL
));
8996 printf("type = '%s'\n", buf
);
8999 if ((type
.t
& VT_BTYPE
) == VT_FUNC
) {
9000 /* if old style function prototype, we accept a
9003 if (sym
->c
== FUNC_OLD
)
9004 func_decl_list(sym
);
9009 error("cannot use local functions");
9010 if (!(type
.t
& VT_FUNC
))
9011 expect("function definition");
9013 /* reject abstract declarators in function definition */
9015 while ((sym
= sym
->next
) != NULL
)
9016 if (!(sym
->v
& ~SYM_FIELD
))
9017 expect("identifier");
9019 /* XXX: cannot do better now: convert extern line to static inline */
9020 if ((type
.t
& (VT_EXTERN
| VT_INLINE
)) == (VT_EXTERN
| VT_INLINE
))
9021 type
.t
= (type
.t
& ~VT_EXTERN
) | VT_STATIC
;
9025 if ((sym
->type
.t
& VT_BTYPE
) != VT_FUNC
)
9027 /* specific case: if not func_call defined, we put
9028 the one of the prototype */
9029 /* XXX: should have default value */
9030 if (sym
->type
.ref
->r
!= FUNC_CDECL
&&
9031 type
.ref
->r
== FUNC_CDECL
)
9032 type
.ref
->r
= sym
->type
.ref
->r
;
9033 if (!is_compatible_types(&sym
->type
, &type
)) {
9035 error("incompatible types for redefinition of '%s'",
9036 get_tok_str(v
, NULL
));
9038 /* if symbol is already defined, then put complete type */
9041 /* put function symbol */
9042 sym
= global_identifier_push(v
, type
.t
, 0);
9043 sym
->type
.ref
= type
.ref
;
9046 /* static inline functions are just recorded as a kind
9047 of macro. Their code will be emitted at the end of
9048 the compilation unit only if they are used */
9049 if ((type
.t
& (VT_INLINE
| VT_STATIC
)) ==
9050 (VT_INLINE
| VT_STATIC
)) {
9051 TokenString func_str
;
9054 tok_str_new(&func_str
);
9060 error("unexpected end of file");
9061 tok_str_add_tok(&func_str
);
9066 } else if (t
== '}') {
9068 if (block_level
== 0)
9072 tok_str_add(&func_str
, -1);
9073 tok_str_add(&func_str
, 0);
9074 sym
->r
= (int)func_str
.str
;
9076 /* compute text section */
9077 cur_text_section
= ad
.section
;
9078 if (!cur_text_section
)
9079 cur_text_section
= text_section
;
9080 sym
->r
= VT_SYM
| VT_CONST
;
9082 #ifdef TCC_TARGET_PE
9084 ((Elf32_Sym
*)symtab_section
->data
)[sym
->c
].st_other
|= 1;
9090 if (btype
.t
& VT_TYPEDEF
) {
9091 /* save typedefed type */
9092 /* XXX: test storage specifiers ? */
9093 sym
= sym_push(v
, &type
, 0, 0);
9094 sym
->type
.t
|= VT_TYPEDEF
;
9095 } else if ((type
.t
& VT_BTYPE
) == VT_FUNC
) {
9096 /* external function definition */
9097 /* specific case for func_call attribute */
9099 type
.ref
->r
= ad
.func_call
;
9100 external_sym(v
, &type
, 0);
9102 /* not lvalue if array */
9104 if (!(type
.t
& VT_ARRAY
))
9105 r
|= lvalue_type(type
.t
);
9106 has_init
= (tok
== '=');
9107 if ((btype
.t
& VT_EXTERN
) ||
9108 ((type
.t
& VT_ARRAY
) && (type
.t
& VT_STATIC
) &&
9109 !has_init
&& l
== VT_CONST
&& type
.ref
->c
< 0)) {
9110 /* external variable */
9111 /* NOTE: as GCC, uninitialized global static
9112 arrays of null size are considered as
9114 external_sym(v
, &type
, r
);
9116 if (type
.t
& VT_STATIC
)
9122 decl_initializer_alloc(&type
, &ad
, r
,
9136 /* better than nothing, but needs extension to handle '-E' option
9138 static void preprocess_init(TCCState
*s1
)
9140 s1
->include_stack_ptr
= s1
->include_stack
;
9141 /* XXX: move that before to avoid having to initialize
9142 file->ifdef_stack_ptr ? */
9143 s1
->ifdef_stack_ptr
= s1
->ifdef_stack
;
9144 file
->ifdef_stack_ptr
= s1
->ifdef_stack_ptr
;
9146 /* XXX: not ANSI compliant: bound checking says error */
9148 s1
->pack_stack
[0] = 0;
9149 s1
->pack_stack_ptr
= s1
->pack_stack
;
9152 /* compile the C file opened in 'file'. Return non zero if errors. */
9153 static int tcc_compile(TCCState
*s1
)
9157 volatile int section_sym
;
9160 printf("%s: **** new file\n", file
->filename
);
9162 preprocess_init(s1
);
9165 anon_sym
= SYM_FIRST_ANOM
;
9167 /* file info: full path + filename */
9168 section_sym
= 0; /* avoid warning */
9170 section_sym
= put_elf_sym(symtab_section
, 0, 0,
9171 ELF32_ST_INFO(STB_LOCAL
, STT_SECTION
), 0,
9172 text_section
->sh_num
, NULL
);
9173 getcwd(buf
, sizeof(buf
));
9174 pstrcat(buf
, sizeof(buf
), "/");
9175 put_stabs_r(buf
, N_SO
, 0, 0,
9176 text_section
->data_offset
, text_section
, section_sym
);
9177 put_stabs_r(file
->filename
, N_SO
, 0, 0,
9178 text_section
->data_offset
, text_section
, section_sym
);
9180 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
9181 symbols can be safely used */
9182 put_elf_sym(symtab_section
, 0, 0,
9183 ELF32_ST_INFO(STB_LOCAL
, STT_FILE
), 0,
9184 SHN_ABS
, file
->filename
);
9186 /* define some often used types */
9187 int_type
.t
= VT_INT
;
9189 char_pointer_type
.t
= VT_BYTE
;
9190 mk_pointer(&char_pointer_type
);
9192 func_old_type
.t
= VT_FUNC
;
9193 func_old_type
.ref
= sym_push(SYM_FIELD
, &int_type
, FUNC_CDECL
, FUNC_OLD
);
9196 /* define 'void *alloca(unsigned int)' builtin function */
9201 sym
= sym_push(p
, mk_pointer(VT_VOID
), FUNC_CDECL
, FUNC_NEW
);
9202 s1
= sym_push(SYM_FIELD
, VT_UNSIGNED
| VT_INT
, 0, 0);
9205 sym_push(TOK_alloca
, VT_FUNC
| (p
<< VT_STRUCT_SHIFT
), VT_CONST
, 0);
9209 define_start
= define_stack
;
9211 if (setjmp(s1
->error_jmp_buf
) == 0) {
9213 s1
->error_set_jmp_enabled
= 1;
9215 ch
= file
->buf_ptr
[0];
9216 tok_flags
= TOK_FLAG_BOL
| TOK_FLAG_BOF
;
9217 parse_flags
= PARSE_FLAG_PREPROCESS
| PARSE_FLAG_TOK_NUM
;
9221 expect("declaration");
9223 /* end of translation unit info */
9225 put_stabs_r(NULL
, N_SO
, 0, 0,
9226 text_section
->data_offset
, text_section
, section_sym
);
9229 s1
->error_set_jmp_enabled
= 0;
9231 /* reset define stack, but leave -Dsymbols (may be incorrect if
9232 they are undefined) */
9233 free_defines(define_start
);
9235 gen_inline_functions();
9237 sym_pop(&global_stack
, NULL
);
9239 return s1
->nb_errors
!= 0 ? -1 : 0;
9243 int tcc_compile_string(TCCState
*s
, const char *str
)
9245 BufferedFile bf1
, *bf
= &bf1
;
9249 /* init file structure */
9251 /* XXX: avoid copying */
9253 buf
= tcc_malloc(len
+ 1);
9256 memcpy(buf
, str
, len
);
9259 bf
->buf_end
= buf
+ len
;
9260 pstrcpy(bf
->filename
, sizeof(bf
->filename
), "<string>");
9264 ret
= tcc_compile(s
);
9268 /* currently, no need to close */
9273 /* define a preprocessor symbol. A value can also be provided with the '=' operator */
9274 void tcc_define_symbol(TCCState
*s1
, const char *sym
, const char *value
)
9276 BufferedFile bf1
, *bf
= &bf1
;
9278 pstrcpy(bf
->buffer
, IO_BUF_SIZE
, sym
);
9279 pstrcat(bf
->buffer
, IO_BUF_SIZE
, " ");
9283 pstrcat(bf
->buffer
, IO_BUF_SIZE
, value
);
9285 /* init file structure */
9287 bf
->buf_ptr
= bf
->buffer
;
9288 bf
->buf_end
= bf
->buffer
+ strlen(bf
->buffer
);
9289 *bf
->buf_end
= CH_EOB
;
9290 bf
->filename
[0] = '\0';
9294 s1
->include_stack_ptr
= s1
->include_stack
;
9296 /* parse with define parser */
9297 ch
= file
->buf_ptr
[0];
9303 /* undefine a preprocessor symbol */
9304 void tcc_undefine_symbol(TCCState
*s1
, const char *sym
)
9308 ts
= tok_alloc(sym
, strlen(sym
));
9309 s
= define_find(ts
->tok
);
9310 /* undefine symbol by putting an invalid name */
9315 #ifdef CONFIG_TCC_ASM
9317 #ifdef TCC_TARGET_I386
9318 #include "i386-asm.c"
9323 static void asm_instr(void)
9325 error("inline asm() not supported");
9327 static void asm_global_instr(void)
9329 error("inline asm() not supported");
9335 #ifdef TCC_TARGET_COFF
9336 #include "tcccoff.c"
9339 #ifdef TCC_TARGET_PE
9343 /* print the position in the source file of PC value 'pc' by reading
9344 the stabs debug information */
9345 static void rt_printline(unsigned long wanted_pc
)
9347 Stab_Sym
*sym
, *sym_end
;
9348 char func_name
[128], last_func_name
[128];
9349 unsigned long func_addr
, last_pc
, pc
;
9350 const char *incl_files
[INCLUDE_STACK_SIZE
];
9351 int incl_index
, len
, last_line_num
, i
;
9352 const char *str
, *p
;
9354 fprintf(stderr
, "0x%08lx:", wanted_pc
);
9356 func_name
[0] = '\0';
9359 last_func_name
[0] = '\0';
9360 last_pc
= 0xffffffff;
9362 sym
= (Stab_Sym
*)stab_section
->data
+ 1;
9363 sym_end
= (Stab_Sym
*)(stab_section
->data
+ stab_section
->data_offset
);
9364 while (sym
< sym_end
) {
9365 switch(sym
->n_type
) {
9366 /* function start or end */
9368 if (sym
->n_strx
== 0) {
9369 /* we test if between last line and end of function */
9370 pc
= sym
->n_value
+ func_addr
;
9371 if (wanted_pc
>= last_pc
&& wanted_pc
< pc
)
9373 func_name
[0] = '\0';
9376 str
= stabstr_section
->data
+ sym
->n_strx
;
9377 p
= strchr(str
, ':');
9379 pstrcpy(func_name
, sizeof(func_name
), str
);
9382 if (len
> sizeof(func_name
) - 1)
9383 len
= sizeof(func_name
) - 1;
9384 memcpy(func_name
, str
, len
);
9385 func_name
[len
] = '\0';
9387 func_addr
= sym
->n_value
;
9390 /* line number info */
9392 pc
= sym
->n_value
+ func_addr
;
9393 if (wanted_pc
>= last_pc
&& wanted_pc
< pc
)
9396 last_line_num
= sym
->n_desc
;
9398 strcpy(last_func_name
, func_name
);
9402 str
= stabstr_section
->data
+ sym
->n_strx
;
9404 if (incl_index
< INCLUDE_STACK_SIZE
) {
9405 incl_files
[incl_index
++] = str
;
9413 if (sym
->n_strx
== 0) {
9414 incl_index
= 0; /* end of translation unit */
9416 str
= stabstr_section
->data
+ sym
->n_strx
;
9417 /* do not add path */
9419 if (len
> 0 && str
[len
- 1] != '/')
9427 /* second pass: we try symtab symbols (no line number info) */
9430 Elf32_Sym
*sym
, *sym_end
;
9433 sym_end
= (Elf32_Sym
*)(symtab_section
->data
+ symtab_section
->data_offset
);
9434 for(sym
= (Elf32_Sym
*)symtab_section
->data
+ 1;
9437 type
= ELF32_ST_TYPE(sym
->st_info
);
9438 if (type
== STT_FUNC
) {
9439 if (wanted_pc
>= sym
->st_value
&&
9440 wanted_pc
< sym
->st_value
+ sym
->st_size
) {
9441 pstrcpy(last_func_name
, sizeof(last_func_name
),
9442 strtab_section
->data
+ sym
->st_name
);
9448 /* did not find any info: */
9449 fprintf(stderr
, " ???\n");
9452 if (last_func_name
[0] != '\0') {
9453 fprintf(stderr
, " %s()", last_func_name
);
9455 if (incl_index
> 0) {
9456 fprintf(stderr
, " (%s:%d",
9457 incl_files
[incl_index
- 1], last_line_num
);
9458 for(i
= incl_index
- 2; i
>= 0; i
--)
9459 fprintf(stderr
, ", included from %s", incl_files
[i
]);
9460 fprintf(stderr
, ")");
9462 fprintf(stderr
, "\n");
9465 #if !defined(WIN32) && !defined(CONFIG_TCCBOOT)
9469 /* fix for glibc 2.1 */
9475 /* return the PC at frame level 'level'. Return non zero if not found */
9476 static int rt_get_caller_pc(unsigned long *paddr
,
9477 ucontext_t
*uc
, int level
)
9483 #if defined(__FreeBSD__)
9484 *paddr
= uc
->uc_mcontext
.mc_eip
;
9485 #elif defined(__dietlibc__)
9486 *paddr
= uc
->uc_mcontext
.eip
;
9488 *paddr
= uc
->uc_mcontext
.gregs
[REG_EIP
];
9492 #if defined(__FreeBSD__)
9493 fp
= uc
->uc_mcontext
.mc_ebp
;
9494 #elif defined(__dietlibc__)
9495 fp
= uc
->uc_mcontext
.ebp
;
9497 fp
= uc
->uc_mcontext
.gregs
[REG_EBP
];
9499 for(i
=1;i
<level
;i
++) {
9500 /* XXX: check address validity with program info */
9501 if (fp
<= 0x1000 || fp
>= 0xc0000000)
9503 fp
= ((unsigned long *)fp
)[0];
9505 *paddr
= ((unsigned long *)fp
)[1];
9511 #warning add arch specific rt_get_caller_pc()
9513 static int rt_get_caller_pc(unsigned long *paddr
,
9514 ucontext_t
*uc
, int level
)
9520 /* emit a run time error at position 'pc' */
9521 void rt_error(ucontext_t
*uc
, const char *fmt
, ...)
9528 fprintf(stderr
, "Runtime error: ");
9529 vfprintf(stderr
, fmt
, ap
);
9530 fprintf(stderr
, "\n");
9531 for(i
=0;i
<num_callers
;i
++) {
9532 if (rt_get_caller_pc(&pc
, uc
, i
) < 0)
9535 fprintf(stderr
, "at ");
9537 fprintf(stderr
, "by ");
9544 /* signal handler for fatal errors */
9545 static void sig_error(int signum
, siginfo_t
*siginf
, void *puc
)
9547 ucontext_t
*uc
= puc
;
9551 switch(siginf
->si_code
) {
9554 rt_error(uc
, "division by zero");
9557 rt_error(uc
, "floating point exception");
9563 if (rt_bound_error_msg
&& *rt_bound_error_msg
)
9564 rt_error(uc
, *rt_bound_error_msg
);
9566 rt_error(uc
, "dereferencing invalid pointer");
9569 rt_error(uc
, "illegal instruction");
9572 rt_error(uc
, "abort() called");
9575 rt_error(uc
, "caught signal %d", signum
);
9582 /* do all relocations (needed before using tcc_get_symbol()) */
9583 int tcc_relocate(TCCState
*s1
)
9590 #ifdef TCC_TARGET_PE
9593 tcc_add_runtime(s1
);
9596 relocate_common_syms();
9598 tcc_add_linker_symbols(s1
);
9600 build_got_entries(s1
);
9602 /* compute relocation address : section are relocated in place. We
9603 also alloc the bss space */
9604 for(i
= 1; i
< s1
->nb_sections
; i
++) {
9605 s
= s1
->sections
[i
];
9606 if (s
->sh_flags
& SHF_ALLOC
) {
9607 if (s
->sh_type
== SHT_NOBITS
)
9608 s
->data
= tcc_mallocz(s
->data_offset
);
9609 s
->sh_addr
= (unsigned long)s
->data
;
9613 relocate_syms(s1
, 1);
9615 if (s1
->nb_errors
!= 0)
9618 /* relocate each section */
9619 for(i
= 1; i
< s1
->nb_sections
; i
++) {
9620 s
= s1
->sections
[i
];
9622 relocate_section(s1
, s
);
9625 /* mark executable sections as executable in memory */
9626 for(i
= 1; i
< s1
->nb_sections
; i
++) {
9627 s
= s1
->sections
[i
];
9628 if ((s
->sh_flags
& (SHF_ALLOC
| SHF_EXECINSTR
)) ==
9629 (SHF_ALLOC
| SHF_EXECINSTR
)) {
9633 VirtualProtect(s
->data
, s
->data_offset
,
9634 PAGE_EXECUTE_READWRITE
, &old_protect
);
9638 unsigned long start
, end
;
9639 start
= (unsigned long)(s
->data
) & ~(PAGESIZE
- 1);
9640 end
= (unsigned long)(s
->data
+ s
->data_offset
);
9641 end
= (end
+ PAGESIZE
- 1) & ~(PAGESIZE
- 1);
9642 mprotect((void *)start
, end
- start
,
9643 PROT_READ
| PROT_WRITE
| PROT_EXEC
);
9651 /* launch the compiled program with the given arguments */
9652 int tcc_run(TCCState
*s1
, int argc
, char **argv
)
9654 int (*prog_main
)(int, char **);
9656 if (tcc_relocate(s1
) < 0)
9659 prog_main
= tcc_get_symbol_err(s1
, "main");
9662 #if defined(WIN32) || defined(CONFIG_TCCBOOT)
9663 error("debug mode currently not available for Windows");
9665 struct sigaction sigact
;
9666 /* install TCC signal handlers to print debug info on fatal
9668 sigact
.sa_flags
= SA_SIGINFO
| SA_RESETHAND
;
9669 sigact
.sa_sigaction
= sig_error
;
9670 sigemptyset(&sigact
.sa_mask
);
9671 sigaction(SIGFPE
, &sigact
, NULL
);
9672 sigaction(SIGILL
, &sigact
, NULL
);
9673 sigaction(SIGSEGV
, &sigact
, NULL
);
9674 sigaction(SIGBUS
, &sigact
, NULL
);
9675 sigaction(SIGABRT
, &sigact
, NULL
);
9679 #ifdef CONFIG_TCC_BCHECK
9680 if (do_bounds_check
) {
9681 void (*bound_init
)(void);
9683 /* set error function */
9684 rt_bound_error_msg
= (void *)tcc_get_symbol_err(s1
,
9685 "__bound_error_msg");
9687 /* XXX: use .init section so that it also work in binary ? */
9688 bound_init
= (void *)tcc_get_symbol_err(s1
, "__bound_init");
9692 return (*prog_main
)(argc
, argv
);
9695 TCCState
*tcc_new(void)
9702 s
= tcc_mallocz(sizeof(TCCState
));
9706 s
->output_type
= TCC_OUTPUT_MEMORY
;
9708 /* init isid table */
9710 isidnum_table
[i
] = isid(i
) || isnum(i
);
9712 /* add all tokens */
9714 memset(hash_ident
, 0, TOK_HASH_SIZE
* sizeof(TokenSym
*));
9716 tok_ident
= TOK_IDENT
;
9725 ts
= tok_alloc(p
, r
- p
- 1);
9729 /* we add dummy defines for some special macros to speed up tests
9730 and to have working defined() */
9731 define_push(TOK___LINE__
, MACRO_OBJ
, NULL
, NULL
);
9732 define_push(TOK___FILE__
, MACRO_OBJ
, NULL
, NULL
);
9733 define_push(TOK___DATE__
, MACRO_OBJ
, NULL
, NULL
);
9734 define_push(TOK___TIME__
, MACRO_OBJ
, NULL
, NULL
);
9736 /* standard defines */
9737 tcc_define_symbol(s
, "__STDC__", NULL
);
9738 #if defined(TCC_TARGET_I386)
9739 tcc_define_symbol(s
, "__i386__", NULL
);
9741 #if defined(TCC_TARGET_ARM)
9742 tcc_define_symbol(s
, "__ARM_ARCH_4__", NULL
);
9743 tcc_define_symbol(s
, "__arm_elf__", NULL
);
9744 tcc_define_symbol(s
, "__arm_elf", NULL
);
9745 tcc_define_symbol(s
, "arm_elf", NULL
);
9746 tcc_define_symbol(s
, "__arm__", NULL
);
9747 tcc_define_symbol(s
, "__arm", NULL
);
9748 tcc_define_symbol(s
, "arm", NULL
);
9749 tcc_define_symbol(s
, "__APCS_32__", NULL
);
9752 tcc_define_symbol(s
, "__linux__", NULL
);
9753 tcc_define_symbol(s
, "linux", NULL
);
9755 /* tiny C specific defines */
9756 tcc_define_symbol(s
, "__TINYC__", NULL
);
9758 /* tiny C & gcc defines */
9759 tcc_define_symbol(s
, "__SIZE_TYPE__", "unsigned int");
9760 tcc_define_symbol(s
, "__PTRDIFF_TYPE__", "int");
9761 tcc_define_symbol(s
, "__WCHAR_TYPE__", "int");
9763 /* default library paths */
9764 #ifdef TCC_TARGET_PE
9767 snprintf(buf
, sizeof(buf
), "%s/lib", tcc_lib_path
);
9768 tcc_add_library_path(s
, buf
);
9771 tcc_add_library_path(s
, "/usr/local/lib");
9772 tcc_add_library_path(s
, "/usr/lib");
9773 tcc_add_library_path(s
, "/lib");
9776 /* no section zero */
9777 dynarray_add((void ***)&s
->sections
, &s
->nb_sections
, NULL
);
9779 /* create standard sections */
9780 text_section
= new_section(s
, ".text", SHT_PROGBITS
, SHF_ALLOC
| SHF_EXECINSTR
);
9781 data_section
= new_section(s
, ".data", SHT_PROGBITS
, SHF_ALLOC
| SHF_WRITE
);
9782 bss_section
= new_section(s
, ".bss", SHT_NOBITS
, SHF_ALLOC
| SHF_WRITE
);
9784 /* symbols are always generated for linking stage */
9785 symtab_section
= new_symtab(s
, ".symtab", SHT_SYMTAB
, 0,
9787 ".hashtab", SHF_PRIVATE
);
9788 strtab_section
= symtab_section
->link
;
9790 /* private symbol table for dynamic symbols */
9791 s
->dynsymtab_section
= new_symtab(s
, ".dynsymtab", SHT_SYMTAB
, SHF_PRIVATE
,
9793 ".dynhashtab", SHF_PRIVATE
);
9794 s
->alacarte_link
= 1;
9796 #ifdef CHAR_IS_UNSIGNED
9797 s
->char_is_unsigned
= 1;
9799 #if defined(TCC_TARGET_PE) && 0
9800 /* XXX: currently the PE linker is not ready to support that */
9801 s
->leading_underscore
= 1;
9806 void tcc_delete(TCCState
*s1
)
9810 /* free -D defines */
9814 n
= tok_ident
- TOK_IDENT
;
9815 for(i
= 0; i
< n
; i
++)
9816 tcc_free(table_ident
[i
]);
9817 tcc_free(table_ident
);
9819 /* free all sections */
9821 free_section(symtab_section
->hash
);
9823 free_section(s1
->dynsymtab_section
->hash
);
9824 free_section(s1
->dynsymtab_section
->link
);
9825 free_section(s1
->dynsymtab_section
);
9827 for(i
= 1; i
< s1
->nb_sections
; i
++)
9828 free_section(s1
->sections
[i
]);
9829 tcc_free(s1
->sections
);
9831 /* free loaded dlls array */
9832 for(i
= 0; i
< s1
->nb_loaded_dlls
; i
++)
9833 tcc_free(s1
->loaded_dlls
[i
]);
9834 tcc_free(s1
->loaded_dlls
);
9837 for(i
= 0; i
< s1
->nb_library_paths
; i
++)
9838 tcc_free(s1
->library_paths
[i
]);
9839 tcc_free(s1
->library_paths
);
9841 /* cached includes */
9842 for(i
= 0; i
< s1
->nb_cached_includes
; i
++)
9843 tcc_free(s1
->cached_includes
[i
]);
9844 tcc_free(s1
->cached_includes
);
9846 for(i
= 0; i
< s1
->nb_include_paths
; i
++)
9847 tcc_free(s1
->include_paths
[i
]);
9848 tcc_free(s1
->include_paths
);
9850 for(i
= 0; i
< s1
->nb_sysinclude_paths
; i
++)
9851 tcc_free(s1
->sysinclude_paths
[i
]);
9852 tcc_free(s1
->sysinclude_paths
);
9857 int tcc_add_include_path(TCCState
*s1
, const char *pathname
)
9861 pathname1
= tcc_strdup(pathname
);
9862 dynarray_add((void ***)&s1
->include_paths
, &s1
->nb_include_paths
, pathname1
);
9866 int tcc_add_sysinclude_path(TCCState
*s1
, const char *pathname
)
9870 pathname1
= tcc_strdup(pathname
);
9871 dynarray_add((void ***)&s1
->sysinclude_paths
, &s1
->nb_sysinclude_paths
, pathname1
);
9875 static int tcc_add_file_internal(TCCState
*s1
, const char *filename
, int flags
)
9877 const char *ext
, *filename1
;
9880 BufferedFile
*saved_file
;
9882 /* find source file type with extension */
9883 filename1
= strrchr(filename
, '/');
9887 filename1
= filename
;
9888 ext
= strrchr(filename1
, '.');
9894 file
= tcc_open(s1
, filename
);
9896 if (flags
& AFF_PRINT_ERROR
) {
9897 error_noabort("file '%s' not found", filename
);
9903 if (!ext
|| !strcmp(ext
, "c")) {
9904 /* C file assumed */
9905 ret
= tcc_compile(s1
);
9907 #ifdef CONFIG_TCC_ASM
9908 if (!strcmp(ext
, "S")) {
9909 /* preprocessed assembler */
9910 ret
= tcc_assemble(s1
, 1);
9911 } else if (!strcmp(ext
, "s")) {
9912 /* non preprocessed assembler */
9913 ret
= tcc_assemble(s1
, 0);
9916 #ifdef TCC_TARGET_PE
9917 if (!strcmp(ext
, "def")) {
9918 ret
= pe_load_def_file(s1
, fdopen(file
->fd
, "rb"));
9923 /* assume executable format: auto guess file type */
9924 ret
= read(fd
, &ehdr
, sizeof(ehdr
));
9925 lseek(fd
, 0, SEEK_SET
);
9927 error_noabort("could not read header");
9929 } else if (ret
!= sizeof(ehdr
)) {
9930 goto try_load_script
;
9933 if (ehdr
.e_ident
[0] == ELFMAG0
&&
9934 ehdr
.e_ident
[1] == ELFMAG1
&&
9935 ehdr
.e_ident
[2] == ELFMAG2
&&
9936 ehdr
.e_ident
[3] == ELFMAG3
) {
9937 file
->line_num
= 0; /* do not display line number if error */
9938 if (ehdr
.e_type
== ET_REL
) {
9939 ret
= tcc_load_object_file(s1
, fd
, 0);
9940 } else if (ehdr
.e_type
== ET_DYN
) {
9941 if (s1
->output_type
== TCC_OUTPUT_MEMORY
) {
9942 #ifdef TCC_TARGET_PE
9946 h
= dlopen(filename
, RTLD_GLOBAL
| RTLD_LAZY
);
9953 ret
= tcc_load_dll(s1
, fd
, filename
,
9954 (flags
& AFF_REFERENCED_DLL
) != 0);
9957 error_noabort("unrecognized ELF file");
9960 } else if (memcmp((char *)&ehdr
, ARMAG
, 8) == 0) {
9961 file
->line_num
= 0; /* do not display line number if error */
9962 ret
= tcc_load_archive(s1
, fd
);
9964 #ifdef TCC_TARGET_COFF
9965 if (*(uint16_t *)(&ehdr
) == COFF_C67_MAGIC
) {
9966 ret
= tcc_load_coff(s1
, fd
);
9970 /* as GNU ld, consider it is an ld script if not recognized */
9972 ret
= tcc_load_ldscript(s1
);
9974 error_noabort("unrecognized file type");
9989 int tcc_add_file(TCCState
*s
, const char *filename
)
9991 return tcc_add_file_internal(s
, filename
, AFF_PRINT_ERROR
);
9994 int tcc_add_library_path(TCCState
*s
, const char *pathname
)
9998 pathname1
= tcc_strdup(pathname
);
9999 dynarray_add((void ***)&s
->library_paths
, &s
->nb_library_paths
, pathname1
);
10003 /* find and load a dll. Return non zero if not found */
10004 /* XXX: add '-rpath' option support ? */
10005 static int tcc_add_dll(TCCState
*s
, const char *filename
, int flags
)
10010 for(i
= 0; i
< s
->nb_library_paths
; i
++) {
10011 snprintf(buf
, sizeof(buf
), "%s/%s",
10012 s
->library_paths
[i
], filename
);
10013 if (tcc_add_file_internal(s
, buf
, flags
) == 0)
10019 /* the library name is the same as the argument of the '-l' option */
10020 int tcc_add_library(TCCState
*s
, const char *libraryname
)
10025 /* first we look for the dynamic library if not static linking */
10026 if (!s
->static_link
) {
10027 #ifdef TCC_TARGET_PE
10028 snprintf(buf
, sizeof(buf
), "%s.def", libraryname
);
10030 snprintf(buf
, sizeof(buf
), "lib%s.so", libraryname
);
10032 if (tcc_add_dll(s
, buf
, 0) == 0)
10036 /* then we look for the static library */
10037 for(i
= 0; i
< s
->nb_library_paths
; i
++) {
10038 snprintf(buf
, sizeof(buf
), "%s/lib%s.a",
10039 s
->library_paths
[i
], libraryname
);
10040 if (tcc_add_file_internal(s
, buf
, 0) == 0)
10046 int tcc_add_symbol(TCCState
*s
, const char *name
, unsigned long val
)
10048 add_elf_sym(symtab_section
, val
, 0,
10049 ELF32_ST_INFO(STB_GLOBAL
, STT_NOTYPE
), 0,
10054 int tcc_set_output_type(TCCState
*s
, int output_type
)
10056 s
->output_type
= output_type
;
10058 if (!s
->nostdinc
) {
10061 /* default include paths */
10062 /* XXX: reverse order needed if -isystem support */
10063 #ifndef TCC_TARGET_PE
10064 tcc_add_sysinclude_path(s
, "/usr/local/include");
10065 tcc_add_sysinclude_path(s
, "/usr/include");
10067 snprintf(buf
, sizeof(buf
), "%s/include", tcc_lib_path
);
10068 tcc_add_sysinclude_path(s
, buf
);
10069 #ifdef TCC_TARGET_PE
10070 snprintf(buf
, sizeof(buf
), "%s/include/winapi", tcc_lib_path
);
10071 tcc_add_sysinclude_path(s
, buf
);
10075 /* if bound checking, then add corresponding sections */
10076 #ifdef CONFIG_TCC_BCHECK
10077 if (do_bounds_check
) {
10078 /* define symbol */
10079 tcc_define_symbol(s
, "__BOUNDS_CHECKING_ON", NULL
);
10080 /* create bounds sections */
10081 bounds_section
= new_section(s
, ".bounds",
10082 SHT_PROGBITS
, SHF_ALLOC
);
10083 lbounds_section
= new_section(s
, ".lbounds",
10084 SHT_PROGBITS
, SHF_ALLOC
);
10088 if (s
->char_is_unsigned
) {
10089 tcc_define_symbol(s
, "__CHAR_UNSIGNED__", NULL
);
10092 /* add debug sections */
10095 stab_section
= new_section(s
, ".stab", SHT_PROGBITS
, 0);
10096 stab_section
->sh_entsize
= sizeof(Stab_Sym
);
10097 stabstr_section
= new_section(s
, ".stabstr", SHT_STRTAB
, 0);
10098 put_elf_str(stabstr_section
, "");
10099 stab_section
->link
= stabstr_section
;
10100 /* put first entry */
10101 put_stabs("", 0, 0, 0, 0);
10104 /* add libc crt1/crti objects */
10105 #ifndef TCC_TARGET_PE
10106 if ((output_type
== TCC_OUTPUT_EXE
|| output_type
== TCC_OUTPUT_DLL
) &&
10108 if (output_type
!= TCC_OUTPUT_DLL
)
10109 tcc_add_file(s
, CONFIG_TCC_CRT_PREFIX
"/crt1.o");
10110 tcc_add_file(s
, CONFIG_TCC_CRT_PREFIX
"/crti.o");
10116 #define WD_ALL 0x0001 /* warning is activated when using -Wall */
10117 #define FD_INVERT 0x0002 /* invert value before storing */
10119 typedef struct FlagDef
{
10125 static const FlagDef warning_defs
[] = {
10126 { offsetof(TCCState
, warn_unsupported
), 0, "unsupported" },
10127 { offsetof(TCCState
, warn_write_strings
), 0, "write-strings" },
10128 { offsetof(TCCState
, warn_error
), 0, "error" },
10129 { offsetof(TCCState
, warn_implicit_function_declaration
), WD_ALL
,
10130 "implicit-function-declaration" },
10133 static int set_flag(TCCState
*s
, const FlagDef
*flags
, int nb_flags
,
10134 const char *name
, int value
)
10141 if (r
[0] == 'n' && r
[1] == 'o' && r
[2] == '-') {
10145 for(i
= 0, p
= flags
; i
< nb_flags
; i
++, p
++) {
10146 if (!strcmp(r
, p
->name
))
10151 if (p
->flags
& FD_INVERT
)
10153 *(int *)((uint8_t *)s
+ p
->offset
) = value
;
10158 /* set/reset a warning */
10159 int tcc_set_warning(TCCState
*s
, const char *warning_name
, int value
)
10164 if (!strcmp(warning_name
, "all")) {
10165 for(i
= 0, p
= warning_defs
; i
< countof(warning_defs
); i
++, p
++) {
10166 if (p
->flags
& WD_ALL
)
10167 *(int *)((uint8_t *)s
+ p
->offset
) = 1;
10171 return set_flag(s
, warning_defs
, countof(warning_defs
),
10172 warning_name
, value
);
10176 static const FlagDef flag_defs
[] = {
10177 { offsetof(TCCState
, char_is_unsigned
), 0, "unsigned-char" },
10178 { offsetof(TCCState
, char_is_unsigned
), FD_INVERT
, "signed-char" },
10179 { offsetof(TCCState
, nocommon
), FD_INVERT
, "common" },
10180 { offsetof(TCCState
, leading_underscore
), 0, "leading-underscore" },
10183 /* set/reset a flag */
10184 int tcc_set_flag(TCCState
*s
, const char *flag_name
, int value
)
10186 return set_flag(s
, flag_defs
, countof(flag_defs
),
10190 #if !defined(LIBTCC)
10192 /* extract the basename of a file */
10193 static const char *tcc_basename(const char *name
)
10196 p
= strrchr(name
, '/');
10199 p
= strrchr(name
, '\\');
10208 static int64_t getclock_us(void)
10213 return (tb
.time
* 1000LL + tb
.millitm
) * 1000LL;
10216 gettimeofday(&tv
, NULL
);
10217 return tv
.tv_sec
* 1000000LL + tv
.tv_usec
;
10223 printf("tcc version " TCC_VERSION
" - Tiny C Compiler - Copyright (C) 2001-2005 Fabrice Bellard\n"
10224 "usage: tcc [-v] [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
10225 " [-Wwarn] [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-static]\n"
10226 " [infile1 infile2...] [-run infile args...]\n"
10228 "General options:\n"
10229 " -v display current version\n"
10230 " -c compile only - generate an object file\n"
10231 " -o outfile set output filename\n"
10232 " -Bdir set tcc internal library path\n"
10233 " -bench output compilation statistics\n"
10234 " -run run compiled source\n"
10235 " -fflag set or reset (with 'no-' prefix) 'flag' (see man page)\n"
10236 " -Wwarning set or reset (with 'no-' prefix) 'warning' (see man page)\n"
10237 " -w disable all warnings\n"
10238 "Preprocessor options:\n"
10239 " -Idir add include path 'dir'\n"
10240 " -Dsym[=val] define 'sym' with value 'val'\n"
10241 " -Usym undefine 'sym'\n"
10242 "Linker options:\n"
10243 " -Ldir add library path 'dir'\n"
10244 " -llib link with dynamic or static library 'lib'\n"
10245 " -shared generate a shared library\n"
10246 " -static static linking\n"
10247 " -rdynamic export all global symbols to dynamic linker\n"
10248 " -r relocatable output\n"
10249 "Debugger options:\n"
10250 " -g generate runtime debug info\n"
10251 #ifdef CONFIG_TCC_BCHECK
10252 " -b compile with built-in memory and bounds checker (implies -g)\n"
10254 " -bt N show N callers in stack traces\n"
10258 #define TCC_OPTION_HAS_ARG 0x0001
10259 #define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
10261 typedef struct TCCOption
{
10289 TCC_OPTION_nostdinc
,
10290 TCC_OPTION_nostdlib
,
10291 TCC_OPTION_print_search_dirs
,
10292 TCC_OPTION_rdynamic
,
10299 static const TCCOption tcc_options
[] = {
10300 { "h", TCC_OPTION_HELP
, 0 },
10301 { "?", TCC_OPTION_HELP
, 0 },
10302 { "I", TCC_OPTION_I
, TCC_OPTION_HAS_ARG
},
10303 { "D", TCC_OPTION_D
, TCC_OPTION_HAS_ARG
},
10304 { "U", TCC_OPTION_U
, TCC_OPTION_HAS_ARG
},
10305 { "L", TCC_OPTION_L
, TCC_OPTION_HAS_ARG
},
10306 { "B", TCC_OPTION_B
, TCC_OPTION_HAS_ARG
},
10307 { "l", TCC_OPTION_l
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10308 { "bench", TCC_OPTION_bench
, 0 },
10309 { "bt", TCC_OPTION_bt
, TCC_OPTION_HAS_ARG
},
10310 #ifdef CONFIG_TCC_BCHECK
10311 { "b", TCC_OPTION_b
, 0 },
10313 { "g", TCC_OPTION_g
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10314 { "c", TCC_OPTION_c
, 0 },
10315 { "static", TCC_OPTION_static
, 0 },
10316 { "shared", TCC_OPTION_shared
, 0 },
10317 { "o", TCC_OPTION_o
, TCC_OPTION_HAS_ARG
},
10318 { "run", TCC_OPTION_run
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10319 { "rdynamic", TCC_OPTION_rdynamic
, 0 },
10320 { "r", TCC_OPTION_r
, 0 },
10321 { "Wl,", TCC_OPTION_Wl
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10322 { "W", TCC_OPTION_W
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10323 { "O", TCC_OPTION_O
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10324 { "m", TCC_OPTION_m
, TCC_OPTION_HAS_ARG
},
10325 { "f", TCC_OPTION_f
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10326 { "nostdinc", TCC_OPTION_nostdinc
, 0 },
10327 { "nostdlib", TCC_OPTION_nostdlib
, 0 },
10328 { "print-search-dirs", TCC_OPTION_print_search_dirs
, 0 },
10329 { "v", TCC_OPTION_v
, 0 },
10330 { "w", TCC_OPTION_w
, 0 },
10331 { "pipe", TCC_OPTION_pipe
, 0},
10335 /* convert 'str' into an array of space separated strings */
10336 static int expand_args(char ***pargv
, const char *str
)
10345 while (is_space(*str
))
10350 while (*str
!= '\0' && !is_space(*str
))
10353 arg
= tcc_malloc(len
+ 1);
10354 memcpy(arg
, s1
, len
);
10356 dynarray_add((void ***)&argv
, &argc
, arg
);
10362 static char **files
;
10363 static int nb_files
, nb_libraries
;
10364 static int multiple_files
;
10365 static int print_search_dirs
;
10366 static int output_type
;
10367 static int reloc_output
;
10368 static const char *outfile
;
10370 int parse_args(TCCState
*s
, int argc
, char **argv
)
10373 const TCCOption
*popt
;
10374 const char *optarg
, *p1
, *r1
;
10379 if (optind
>= argc
) {
10380 if (nb_files
== 0 && !print_search_dirs
)
10385 r
= argv
[optind
++];
10387 /* add a new file */
10388 dynarray_add((void ***)&files
, &nb_files
, r
);
10389 if (!multiple_files
) {
10391 /* argv[0] will be this file */
10395 /* find option in table (match only the first chars */
10396 popt
= tcc_options
;
10400 error("invalid option -- '%s'", r
);
10413 if (popt
->flags
& TCC_OPTION_HAS_ARG
) {
10414 if (*r1
!= '\0' || (popt
->flags
& TCC_OPTION_NOSEP
)) {
10417 if (optind
>= argc
)
10418 error("argument to '%s' is missing", r
);
10419 optarg
= argv
[optind
++];
10427 switch(popt
->index
) {
10428 case TCC_OPTION_HELP
:
10433 if (tcc_add_include_path(s
, optarg
) < 0)
10434 error("too many include paths");
10439 sym
= (char *)optarg
;
10440 value
= strchr(sym
, '=');
10445 tcc_define_symbol(s
, sym
, value
);
10449 tcc_undefine_symbol(s
, optarg
);
10452 tcc_add_library_path(s
, optarg
);
10455 /* set tcc utilities path (mainly for tcc development) */
10456 tcc_lib_path
= optarg
;
10459 dynarray_add((void ***)&files
, &nb_files
, r
);
10462 case TCC_OPTION_bench
:
10465 case TCC_OPTION_bt
:
10466 num_callers
= atoi(optarg
);
10468 #ifdef CONFIG_TCC_BCHECK
10470 do_bounds_check
= 1;
10478 multiple_files
= 1;
10479 output_type
= TCC_OUTPUT_OBJ
;
10481 case TCC_OPTION_static
:
10482 s
->static_link
= 1;
10484 case TCC_OPTION_shared
:
10485 output_type
= TCC_OUTPUT_DLL
;
10488 multiple_files
= 1;
10492 /* generate a .o merging several output files */
10494 output_type
= TCC_OUTPUT_OBJ
;
10496 case TCC_OPTION_nostdinc
:
10499 case TCC_OPTION_nostdlib
:
10502 case TCC_OPTION_print_search_dirs
:
10503 print_search_dirs
= 1;
10505 case TCC_OPTION_run
:
10509 argc1
= expand_args(&argv1
, optarg
);
10511 parse_args(s
, argc1
, argv1
);
10513 multiple_files
= 0;
10514 output_type
= TCC_OUTPUT_MEMORY
;
10518 printf("tcc version %s\n", TCC_VERSION
);
10521 if (tcc_set_flag(s
, optarg
, 1) < 0 && s
->warn_unsupported
)
10522 goto unsupported_option
;
10525 if (tcc_set_warning(s
, optarg
, 1) < 0 &&
10526 s
->warn_unsupported
)
10527 goto unsupported_option
;
10532 case TCC_OPTION_rdynamic
:
10535 case TCC_OPTION_Wl
:
10538 if (strstart(optarg
, "-Ttext,", &p
)) {
10539 s
->text_addr
= strtoul(p
, NULL
, 16);
10540 s
->has_text_addr
= 1;
10541 } else if (strstart(optarg
, "--oformat,", &p
)) {
10542 if (strstart(p
, "elf32-", NULL
)) {
10543 s
->output_format
= TCC_OUTPUT_FORMAT_ELF
;
10544 } else if (!strcmp(p
, "binary")) {
10545 s
->output_format
= TCC_OUTPUT_FORMAT_BINARY
;
10547 #ifdef TCC_TARGET_COFF
10548 if (!strcmp(p
, "coff")) {
10549 s
->output_format
= TCC_OUTPUT_FORMAT_COFF
;
10553 error("target %s not found", p
);
10556 error("unsupported linker option '%s'", optarg
);
10561 if (s
->warn_unsupported
) {
10562 unsupported_option
:
10563 warning("unsupported option '%s'", r
);
10572 int main(int argc
, char **argv
)
10576 int nb_objfiles
, ret
, optind
;
10577 char objfilename
[1024];
10578 int64_t start_time
= 0;
10581 /* on win32, we suppose the lib and includes are at the location
10584 static char path
[1024];
10587 GetModuleFileNameA(NULL
, path
, sizeof path
);
10588 p
= d
= strlwr(path
);
10591 if (*d
== '\\') *d
= '/', p
= d
;
10595 tcc_lib_path
= path
;
10600 output_type
= TCC_OUTPUT_EXE
;
10602 multiple_files
= 1;
10607 print_search_dirs
= 0;
10609 optind
= parse_args(s
, argc
- 1, argv
+ 1) + 1;
10611 if (print_search_dirs
) {
10612 /* enough for Linux kernel */
10613 printf("install: %s/\n", tcc_lib_path
);
10617 nb_objfiles
= nb_files
- nb_libraries
;
10619 /* if outfile provided without other options, we output an
10621 if (outfile
&& output_type
== TCC_OUTPUT_MEMORY
)
10622 output_type
= TCC_OUTPUT_EXE
;
10624 /* check -c consistency : only single file handled. XXX: checks file type */
10625 if (output_type
== TCC_OUTPUT_OBJ
&& !reloc_output
) {
10626 /* accepts only a single input file */
10627 if (nb_objfiles
!= 1)
10628 error("cannot specify multiple files with -c");
10629 if (nb_libraries
!= 0)
10630 error("cannot specify libraries with -c");
10633 if (output_type
!= TCC_OUTPUT_MEMORY
) {
10635 /* compute default outfile name */
10636 pstrcpy(objfilename
, sizeof(objfilename
) - 1,
10638 tcc_basename(files
[0]));
10639 #ifdef TCC_TARGET_PE
10640 pe_guess_outfile(objfilename
, output_type
);
10642 if (output_type
== TCC_OUTPUT_OBJ
&& !reloc_output
) {
10643 char *ext
= strrchr(objfilename
, '.');
10645 goto default_outfile
;
10646 /* add .o extension */
10647 strcpy(ext
+ 1, "o");
10650 pstrcpy(objfilename
, sizeof(objfilename
), "a.out");
10653 outfile
= objfilename
;
10658 start_time
= getclock_us();
10661 tcc_set_output_type(s
, output_type
);
10663 /* compile or add each files or library */
10664 for(i
= 0;i
< nb_files
; i
++) {
10665 const char *filename
;
10667 filename
= files
[i
];
10668 if (filename
[0] == '-') {
10669 if (tcc_add_library(s
, filename
+ 2) < 0)
10670 error("cannot find %s", filename
);
10672 if (tcc_add_file(s
, filename
) < 0) {
10679 /* free all files */
10684 total_time
= (double)(getclock_us() - start_time
) / 1000000.0;
10685 if (total_time
< 0.001)
10686 total_time
= 0.001;
10687 if (total_bytes
< 1)
10689 printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
10690 tok_ident
- TOK_IDENT
, total_lines
, total_bytes
,
10691 total_time
, (int)(total_lines
/ total_time
),
10692 total_bytes
/ total_time
/ 1000000.0);
10695 if (s
->output_type
== TCC_OUTPUT_MEMORY
) {
10696 ret
= tcc_run(s
, argc
- optind
, argv
+ optind
);
10698 #ifdef TCC_TARGET_PE
10699 if (s
->output_type
!= TCC_OUTPUT_OBJ
) {
10700 ret
= tcc_output_pe(s
, outfile
);
10704 tcc_output_file(s
, outfile
);
10708 /* XXX: cannot do it with bound checking because of the malloc hooks */
10709 if (!do_bounds_check
)
10714 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size
, mem_max_size
);