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
43 #include <sys/timeb.h>
45 #define inline __inline
52 #include <sys/ucontext.h>
56 #endif /* !CONFIG_TCCBOOT */
73 /* preprocessor debug */
75 /* include file debug */
83 /* target selection */
84 //#define TCC_TARGET_I386 /* i386 code generator */
85 //#define TCC_TARGET_ARM /* ARMv4 code generator */
86 //#define TCC_TARGET_C67 /* TMS320C67xx code generator */
87 //#define TCC_TARGET_X86_64 /* x86-64 code generator */
89 /* default target is I386 */
90 #if !defined(TCC_TARGET_I386) && !defined(TCC_TARGET_ARM) && \
91 !defined(TCC_TARGET_C67) && !defined(TCC_TARGET_X86_64)
92 #define TCC_TARGET_I386
95 #if !defined(_WIN32) && !defined(TCC_UCLIBC) && !defined(TCC_TARGET_ARM) && \
96 !defined(TCC_TARGET_C67) && !defined(TCC_TARGET_X86_64)
97 #define CONFIG_TCC_BCHECK /* enable bound checking code */
100 #if defined(_WIN32) && !defined(TCC_TARGET_PE)
101 #define CONFIG_TCC_STATIC
104 /* define it to include assembler support */
105 #if !defined(TCC_TARGET_ARM) && !defined(TCC_TARGET_C67) && \
106 !defined(TCC_TARGET_X86_64)
107 #define CONFIG_TCC_ASM
110 /* object format selection */
111 #if defined(TCC_TARGET_C67)
112 #define TCC_TARGET_COFF
121 /* path to find crt1.o, crti.o and crtn.o. Only needed when generating
122 executables or dlls */
123 #define CONFIG_TCC_CRT_PREFIX CONFIG_SYSROOT "/usr/lib"
125 #define INCLUDE_STACK_SIZE 32
126 #define IFDEF_STACK_SIZE 64
127 #define VSTACK_SIZE 256
128 #define STRING_MAX_SIZE 1024
129 #define PACK_STACK_SIZE 8
131 #define TOK_HASH_SIZE 8192 /* must be a power of two */
132 #define TOK_ALLOC_INCR 512 /* must be a power of two */
133 #define TOK_MAX_SIZE 4 /* token max size in int unit when stored in string */
135 /* token symbol management */
136 typedef struct TokenSym
{
137 struct TokenSym
*hash_next
;
138 struct Sym
*sym_define
; /* direct pointer to define */
139 struct Sym
*sym_label
; /* direct pointer to label */
140 struct Sym
*sym_struct
; /* direct pointer to structure */
141 struct Sym
*sym_identifier
; /* direct pointer to identifier */
142 int tok
; /* token number */
148 typedef unsigned short nwchar_t
;
150 typedef int nwchar_t
;
153 typedef struct CString
{
154 int size
; /* size in bytes */
155 void *data
; /* either 'char *' or 'nwchar_t *' */
157 void *data_allocated
; /* if non NULL, data has been malloced */
160 /* type definition */
161 typedef struct CType
{
167 typedef union CValue
{
173 unsigned int ul
; /* address (should be unsigned long on 64 bit cpu) */
175 unsigned long long ull
;
176 struct CString
*cstr
;
182 typedef struct SValue
{
183 CType type
; /* type */
184 unsigned short r
; /* register + flags */
185 unsigned short r2
; /* second register, used for 'long long'
186 type. If not used, set to VT_CONST */
187 CValue c
; /* constant, if VT_CONST */
188 struct Sym
*sym
; /* symbol, if (VT_SYM | VT_CONST) */
191 /* symbol management */
193 int v
; /* symbol token */
194 long r
; /* associated register */
195 long c
; /* associated number */
196 CType type
; /* associated type */
197 struct Sym
*next
; /* next related symbol */
198 struct Sym
*prev
; /* prev symbol in stack */
199 struct Sym
*prev_tok
; /* previous symbol for this token */
202 /* section definition */
203 /* XXX: use directly ELF structure for parameters ? */
204 /* special flag to indicate that the section should not be linked to
206 #define SHF_PRIVATE 0x80000000
208 typedef struct Section
{
209 unsigned long data_offset
; /* current data offset */
210 unsigned char *data
; /* section data */
211 unsigned long data_allocated
; /* used for realloc() handling */
212 int sh_name
; /* elf section name (only used during output) */
213 int sh_num
; /* elf section number */
214 int sh_type
; /* elf section type */
215 int sh_flags
; /* elf section flags */
216 int sh_info
; /* elf section info */
217 int sh_addralign
; /* elf section alignment */
218 int sh_entsize
; /* elf entry size */
219 unsigned long sh_size
; /* section size (only used during output) */
220 unsigned long sh_addr
; /* address at which the section is relocated */
221 unsigned long sh_offset
; /* file offset */
222 int nb_hashed_syms
; /* used to resize the hash table */
223 struct Section
*link
; /* link to another section */
224 struct Section
*reloc
; /* corresponding section for relocation, if any */
225 struct Section
*hash
; /* hash table for symbols */
226 struct Section
*next
;
227 char name
[1]; /* section name */
230 typedef struct DLLReference
{
236 /* GNUC attribute definition */
237 typedef struct AttributeDef
{
241 int func_attr
; /* calling convention, exports, ... */
244 /* -------------------------------------------------- */
245 /* gr: wrappers for casting sym->r for other purposes */
253 #define FUNC_CALL(r) (((func_attr_t*)&(r))->func_call)
254 #define FUNC_EXPORT(r) (((func_attr_t*)&(r))->func_export)
255 #define FUNC_ARGS(r) (((func_attr_t*)&(r))->func_args)
256 #define INLINE_DEF(r) (*(int **)&(r))
257 /* -------------------------------------------------- */
259 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
260 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
261 #define SYM_FIRST_ANOM 0x10000000 /* first anonymous sym */
263 /* stored in 'Sym.c' field */
264 #define FUNC_NEW 1 /* ansi function prototype */
265 #define FUNC_OLD 2 /* old function prototype */
266 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
268 /* stored in 'Sym.r' field */
269 #define FUNC_CDECL 0 /* standard c call */
270 #define FUNC_STDCALL 1 /* pascal c call */
271 #define FUNC_FASTCALL1 2 /* first param in %eax */
272 #define FUNC_FASTCALL2 3 /* first parameters in %eax, %edx */
273 #define FUNC_FASTCALL3 4 /* first parameter in %eax, %edx, %ecx */
274 #define FUNC_FASTCALLW 5 /* first parameter in %ecx, %edx */
276 /* field 'Sym.t' for macros */
277 #define MACRO_OBJ 0 /* object like macro */
278 #define MACRO_FUNC 1 /* function like macro */
280 /* field 'Sym.r' for C labels */
281 #define LABEL_DEFINED 0 /* label is defined */
282 #define LABEL_FORWARD 1 /* label is forward defined */
283 #define LABEL_DECLARED 2 /* label is declared but never used */
285 /* type_decl() types */
286 #define TYPE_ABSTRACT 1 /* type without variable */
287 #define TYPE_DIRECT 2 /* type with variable */
289 #define IO_BUF_SIZE 8192
291 typedef struct BufferedFile
{
295 int line_num
; /* current line number - here to simplify code */
296 int ifndef_macro
; /* #ifndef macro / #endif search */
297 int ifndef_macro_saved
; /* saved ifndef_macro */
298 int *ifdef_stack_ptr
; /* ifdef_stack value at the start of the file */
299 char inc_type
; /* type of include */
300 char inc_filename
[512]; /* filename specified by the user */
301 char filename
[1024]; /* current filename - here to simplify code */
302 unsigned char buffer
[IO_BUF_SIZE
+ 1]; /* extra size for CH_EOB char */
305 #define CH_EOB '\\' /* end of buffer or '\0' char in file */
306 #define CH_EOF (-1) /* end of file */
308 /* parsing state (used to save parser state to reparse part of the
309 source several times) */
310 typedef struct ParseState
{
317 /* used to record tokens */
318 typedef struct TokenString
{
325 /* include file cache, used to find files faster and also to eliminate
326 inclusion if the include file is protected by #ifndef ... #endif */
327 typedef struct CachedInclude
{
329 int hash_next
; /* -1 if none */
330 char type
; /* '"' or '>' to give include type */
331 char filename
[1]; /* path specified in #include */
334 #define CACHED_INCLUDES_HASH_SIZE 512
337 static struct BufferedFile
*file
;
340 static CString tokcstr
; /* current parsed string, if any */
341 /* additional informations about token */
342 static int tok_flags
;
343 #define TOK_FLAG_BOL 0x0001 /* beginning of line before */
344 #define TOK_FLAG_BOF 0x0002 /* beginning of file before */
345 #define TOK_FLAG_ENDIF 0x0004 /* a endif was found matching starting #ifdef */
346 #define TOK_FLAG_EOF 0x0008 /* end of file */
348 static int *macro_ptr
, *macro_ptr_allocated
;
349 static int *unget_saved_macro_ptr
;
350 static int unget_saved_buffer
[TOK_MAX_SIZE
+ 1];
351 static int unget_buffer_enabled
;
352 static int parse_flags
;
353 #define PARSE_FLAG_PREPROCESS 0x0001 /* activate preprocessing */
354 #define PARSE_FLAG_TOK_NUM 0x0002 /* return numbers instead of TOK_PPNUM */
355 #define PARSE_FLAG_LINEFEED 0x0004 /* line feed is returned as a
356 token. line feed is also
358 #define PARSE_FLAG_ASM_COMMENTS 0x0008 /* '#' can be used for line comment */
359 #define PARSE_FLAG_SPACES 0x0010 /* next() returns space tokens (for -E) */
361 static Section
*text_section
, *data_section
, *bss_section
; /* predefined sections */
362 static Section
*cur_text_section
; /* current section where function code is
364 #ifdef CONFIG_TCC_ASM
365 static Section
*last_text_section
; /* to handle .previous asm directive */
367 /* bound check related sections */
368 static Section
*bounds_section
; /* contains global data bound description */
369 static Section
*lbounds_section
; /* contains local data bound description */
370 /* symbol sections */
371 static Section
*symtab_section
, *strtab_section
;
374 static Section
*stab_section
, *stabstr_section
;
376 /* loc : local variable index
377 ind : output code index
379 anon_sym: anonymous symbol index
381 static int rsym
, anon_sym
, ind
, loc
;
382 /* expression generation modifiers */
383 static int const_wanted
; /* true if constant wanted */
384 static int nocode_wanted
; /* true if no code generation wanted for an expression */
385 static int global_expr
; /* true if compound literals must be allocated
386 globally (used during initializers parsing */
387 static CType func_vt
; /* current function return type (used by return
390 static int last_line_num
, last_ind
, func_ind
; /* debug last line number and pc */
391 static int tok_ident
;
392 static TokenSym
**table_ident
;
393 static TokenSym
*hash_ident
[TOK_HASH_SIZE
];
394 static char token_buf
[STRING_MAX_SIZE
+ 1];
395 static char *funcname
;
396 static Sym
*global_stack
, *local_stack
;
397 static Sym
*define_stack
;
398 static Sym
*global_label_stack
, *local_label_stack
;
399 /* symbol allocator */
400 #define SYM_POOL_NB (8192 / sizeof(Sym))
401 static Sym
*sym_free_first
;
402 static void **sym_pools
;
403 static int nb_sym_pools
;
405 static SValue vstack
[VSTACK_SIZE
], *vtop
;
406 /* some predefined types */
407 static CType char_pointer_type
, func_old_type
, int_type
;
408 /* true if isid(c) || isnum(c) */
409 static unsigned char isidnum_table
[256-CH_EOF
];
411 /* display some information during compilation */
412 static int verbose
= 0;
414 /* compile with debug symbol (and use them if error during execution) */
415 static int do_debug
= 0;
417 /* compile with built-in memory and bounds checker */
418 static int do_bounds_check
= 0;
420 /* display benchmark infos */
422 static int do_bench
= 0;
424 static int total_lines
;
425 static int total_bytes
;
427 /* use GNU C extensions */
428 static int gnu_ext
= 1;
430 /* use Tiny C extensions */
431 static int tcc_ext
= 1;
433 /* max number of callers shown if error */
434 static int num_callers
= 6;
435 static const char **rt_bound_error_msg
;
437 /* XXX: get rid of this ASAP */
438 static struct TCCState
*tcc_state
;
440 /* give the path of the tcc libraries */
441 static const char *tcc_lib_path
= CONFIG_TCCDIR
;
446 BufferedFile
**include_stack_ptr
;
447 int *ifdef_stack_ptr
;
449 /* include file handling */
450 char **include_paths
;
451 int nb_include_paths
;
452 char **sysinclude_paths
;
453 int nb_sysinclude_paths
;
454 CachedInclude
**cached_includes
;
455 int nb_cached_includes
;
457 char **library_paths
;
458 int nb_library_paths
;
460 /* array of all loaded dlls (including those referenced by loaded
462 DLLReference
**loaded_dlls
;
467 int nb_sections
; /* number of sections, including first dummy section */
469 Section
**priv_sections
;
470 int nb_priv_sections
; /* number of private sections */
475 unsigned long *got_offsets
;
477 /* give the correspondance from symtab indexes to dynsym indexes */
478 int *symtab_to_dynsym
;
480 /* temporary dynamic symbol sections (for dll loading) */
481 Section
*dynsymtab_section
;
482 /* exported dynamic symbol section */
485 int nostdinc
; /* if true, no standard headers are added */
486 int nostdlib
; /* if true, no standard libraries are added */
488 int nocommon
; /* if true, do not use common symbols for .bss data */
490 /* if true, static linking is performed */
493 /* soname as specified on the command line (-soname) */
496 /* if true, all symbols are exported */
499 /* if true, only link in referenced objects from archive */
502 /* address of text section */
503 unsigned long text_addr
;
506 /* output format, see TCC_OUTPUT_FORMAT_xxx */
509 /* C language options */
510 int char_is_unsigned
;
511 int leading_underscore
;
513 /* warning switches */
514 int warn_write_strings
;
515 int warn_unsupported
;
518 int warn_implicit_function_declaration
;
522 void (*error_func
)(void *opaque
, const char *msg
);
523 int error_set_jmp_enabled
;
524 jmp_buf error_jmp_buf
;
527 /* tiny assembler state */
530 /* see include_stack_ptr */
531 BufferedFile
*include_stack
[INCLUDE_STACK_SIZE
];
533 /* see ifdef_stack_ptr */
534 int ifdef_stack
[IFDEF_STACK_SIZE
];
536 /* see cached_includes */
537 int cached_includes_hash
[CACHED_INCLUDES_HASH_SIZE
];
540 int pack_stack
[PACK_STACK_SIZE
];
543 /* output file for preprocessing */
546 /* for tcc_relocate */
549 #ifdef TCC_TARGET_X86_64
550 /* write PLT and GOT here */
551 char *runtime_plt_and_got
;
552 unsigned int runtime_plt_and_got_offset
;
556 /* The current value can be: */
557 #define VT_VALMASK 0x00ff
558 #define VT_CONST 0x00f0 /* constant in vc
559 (must be first non register value) */
560 #define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */
561 #define VT_LOCAL 0x00f2 /* offset on stack */
562 #define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */
563 #define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */
564 #define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */
565 #define VT_LVAL 0x0100 /* var is an lvalue */
566 #define VT_SYM 0x0200 /* a symbol value is added */
567 #define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for
568 char/short stored in integer registers) */
569 #define VT_MUSTBOUND 0x0800 /* bound checking must be done before
570 dereferencing value */
571 #define VT_BOUNDED 0x8000 /* value is bounded. The address of the
572 bounding function call point is in vc */
573 #define VT_LVAL_BYTE 0x1000 /* lvalue is a byte */
574 #define VT_LVAL_SHORT 0x2000 /* lvalue is a short */
575 #define VT_LVAL_UNSIGNED 0x4000 /* lvalue is unsigned */
576 #define VT_LVAL_TYPE (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)
579 #define VT_INT 0 /* integer type */
580 #define VT_BYTE 1 /* signed byte type */
581 #define VT_SHORT 2 /* short type */
582 #define VT_VOID 3 /* void type */
583 #define VT_PTR 4 /* pointer */
584 #define VT_ENUM 5 /* enum definition */
585 #define VT_FUNC 6 /* function type */
586 #define VT_STRUCT 7 /* struct/union definition */
587 #define VT_FLOAT 8 /* IEEE float */
588 #define VT_DOUBLE 9 /* IEEE double */
589 #define VT_LDOUBLE 10 /* IEEE long double */
590 #define VT_BOOL 11 /* ISOC99 boolean type */
591 #define VT_LLONG 12 /* 64 bit integer */
592 #define VT_LONG 13 /* long integer (NEVER USED as type, only
594 #define VT_BTYPE 0x000f /* mask for basic type */
595 #define VT_UNSIGNED 0x0010 /* unsigned type */
596 #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
597 #define VT_BITFIELD 0x0040 /* bitfield modifier */
598 #define VT_CONSTANT 0x0800 /* const modifier */
599 #define VT_VOLATILE 0x1000 /* volatile modifier */
600 #define VT_SIGNED 0x2000 /* signed type */
603 #define VT_EXTERN 0x00000080 /* extern definition */
604 #define VT_STATIC 0x00000100 /* static variable */
605 #define VT_TYPEDEF 0x00000200 /* typedef definition */
606 #define VT_INLINE 0x00000400 /* inline definition */
608 #define VT_STRUCT_SHIFT 16 /* shift for bitfield shift values */
610 /* type mask (except storage) */
611 #define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE)
612 #define VT_TYPE (~(VT_STORAGE))
616 /* warning: the following compare tokens depend on i386 asm code */
623 #define TOK_Nset 0x98
624 #define TOK_Nclear 0x99
630 #define TOK_LAND 0xa0
634 #define TOK_MID 0xa3 /* inc/dec, to void constant */
636 #define TOK_UDIV 0xb0 /* unsigned division */
637 #define TOK_UMOD 0xb1 /* unsigned modulo */
638 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
639 #define TOK_CINT 0xb3 /* number in tokc */
640 #define TOK_CCHAR 0xb4 /* char constant in tokc */
641 #define TOK_STR 0xb5 /* pointer to string in tokc */
642 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
643 #define TOK_LCHAR 0xb7
644 #define TOK_LSTR 0xb8
645 #define TOK_CFLOAT 0xb9 /* float constant */
646 #define TOK_LINENUM 0xba /* line number info */
647 #define TOK_CDOUBLE 0xc0 /* double constant */
648 #define TOK_CLDOUBLE 0xc1 /* long double constant */
649 #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
650 #define TOK_ADDC1 0xc3 /* add with carry generation */
651 #define TOK_ADDC2 0xc4 /* add with carry use */
652 #define TOK_SUBC1 0xc5 /* add with carry generation */
653 #define TOK_SUBC2 0xc6 /* add with carry use */
654 #define TOK_CUINT 0xc8 /* unsigned int constant */
655 #define TOK_CLLONG 0xc9 /* long long constant */
656 #define TOK_CULLONG 0xca /* unsigned long long constant */
657 #define TOK_ARROW 0xcb
658 #define TOK_DOTS 0xcc /* three dots */
659 #define TOK_SHR 0xcd /* unsigned shift right */
660 #define TOK_PPNUM 0xce /* preprocessor number */
662 #define TOK_SHL 0x01 /* shift left */
663 #define TOK_SAR 0x02 /* signed shift right */
665 /* assignement operators : normal operator or 0x80 */
666 #define TOK_A_MOD 0xa5
667 #define TOK_A_AND 0xa6
668 #define TOK_A_MUL 0xaa
669 #define TOK_A_ADD 0xab
670 #define TOK_A_SUB 0xad
671 #define TOK_A_DIV 0xaf
672 #define TOK_A_XOR 0xde
673 #define TOK_A_OR 0xfc
674 #define TOK_A_SHL 0x81
675 #define TOK_A_SAR 0x82
678 #define offsetof(type, field) ((size_t) &((type *)0)->field)
682 #define countof(tab) (sizeof(tab) / sizeof((tab)[0]))
685 /* WARNING: the content of this string encodes token numbers */
686 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";
688 #define TOK_EOF (-1) /* end of file */
689 #define TOK_LINEFEED 10 /* line feed */
691 /* all identificators and strings have token above that */
692 #define TOK_IDENT 256
694 /* only used for i386 asm opcodes definitions */
695 #define DEF_ASM(x) DEF(TOK_ASM_ ## x, #x)
698 DEF(TOK_ASM_ ## x ## b, #x "b") \
699 DEF(TOK_ASM_ ## x ## w, #x "w") \
700 DEF(TOK_ASM_ ## x ## l, #x "l") \
701 DEF(TOK_ASM_ ## x, #x)
704 DEF(TOK_ASM_ ## x ## w, #x "w") \
705 DEF(TOK_ASM_ ## x ## l, #x "l") \
706 DEF(TOK_ASM_ ## x, #x)
709 DEF(TOK_ASM_ ## f ## x ## s, "f" #x "s") \
710 DEF(TOK_ASM_ ## fi ## x ## l, "fi" #x "l") \
711 DEF(TOK_ASM_ ## f ## x ## l, "f" #x "l") \
712 DEF(TOK_ASM_ ## fi ## x ## s, "fi" #x "s")
715 DEF(TOK_ASM_ ## f ## x, "f" #x ) \
716 DEF(TOK_ASM_ ## f ## x ## p, "f" #x "p") \
719 #define DEF_ASMTEST(x) \
751 #define TOK_ASM_int TOK_INT
754 TOK_LAST
= TOK_IDENT
- 1,
755 #define DEF(id, str) id,
760 static const char tcc_keywords
[] =
761 #define DEF(id, str) str "\0"
766 #define TOK_UIDENT TOK_DEFINE
769 #define snprintf _snprintf
770 #define vsnprintf _vsnprintf
772 #define strtold (long double)strtod
773 #define strtof (float)strtod
774 #define strtoll (long long)strtol
776 #elif defined(TCC_UCLIBC) || defined(__FreeBSD__) || defined(__DragonFly__) \
777 || defined(__OpenBSD__)
778 /* currently incorrect */
779 long double strtold(const char *nptr
, char **endptr
)
781 return (long double)strtod(nptr
, endptr
);
783 float strtof(const char *nptr
, char **endptr
)
785 return (float)strtod(nptr
, endptr
);
788 /* XXX: need to define this to use them in non ISOC99 context */
789 extern float strtof (const char *__nptr
, char **__endptr
);
790 extern long double strtold (const char *__nptr
, char **__endptr
);
793 static char *pstrcpy(char *buf
, int buf_size
, const char *s
);
794 static char *pstrcat(char *buf
, int buf_size
, const char *s
);
795 static char *tcc_basename(const char *name
);
796 static char *tcc_fileextension (const char *p
);
798 static void next(void);
799 static void next_nomacro(void);
800 static void next_nomacro_spc(void);
801 static void parse_expr_type(CType
*type
);
802 static void expr_type(CType
*type
);
803 static void unary_type(CType
*type
);
804 static void block(int *bsym
, int *csym
, int *case_sym
, int *def_sym
,
805 int case_reg
, int is_expr
);
806 static int expr_const(void);
807 static void expr_eq(void);
808 static void gexpr(void);
809 static void gen_inline_functions(void);
810 static void decl(int l
);
811 static void decl_initializer(CType
*type
, Section
*sec
, unsigned long c
,
812 int first
, int size_only
);
813 static void decl_initializer_alloc(CType
*type
, AttributeDef
*ad
, int r
,
814 int has_init
, int v
, int scope
);
816 void gv2(int rc1
, int rc2
);
817 void move_reg(int r
, int s
);
818 void save_regs(int n
);
819 void save_reg(int r
);
824 int get_reg_ex(int rc
,int rc2
);
827 struct macro_level
*prev
;
831 static void macro_subst(TokenString
*tok_str
, Sym
**nested_list
,
832 const int *macro_str
, struct macro_level
**can_read_stream
);
834 void force_charshort_cast(int t
);
835 static void gen_cast(CType
*type
);
837 static Sym
*sym_find(int v
);
838 static Sym
*sym_push(int v
, CType
*type
, int r
, int c
);
841 static int type_size(CType
*type
, int *a
);
842 static inline CType
*pointed_type(CType
*type
);
843 static int pointed_size(CType
*type
);
844 static int lvalue_type(int t
);
845 static int parse_btype(CType
*type
, AttributeDef
*ad
);
846 static void type_decl(CType
*type
, AttributeDef
*ad
, int *v
, int td
);
847 static int compare_types(CType
*type1
, CType
*type2
, int unqualified
);
848 static int is_compatible_types(CType
*type1
, CType
*type2
);
849 static int is_compatible_parameter_types(CType
*type1
, CType
*type2
);
851 int ieee_finite(double d
);
852 void error(const char *fmt
, ...);
854 void vpushll(long long v
);
857 void lexpand_nr(void);
858 static void vpush_global_sym(CType
*type
, int v
);
859 void vset(CType
*type
, int r
, int v
);
860 void type_to_str(char *buf
, int buf_size
,
861 CType
*type
, const char *varstr
);
862 char *get_tok_str(int v
, CValue
*cv
);
863 static Sym
*get_sym_ref(CType
*type
, Section
*sec
,
864 unsigned long offset
, unsigned long size
);
865 static Sym
*external_global_sym(int v
, CType
*type
, int r
);
867 /* section generation */
868 static void section_realloc(Section
*sec
, unsigned long new_size
);
869 static void *section_ptr_add(Section
*sec
, unsigned long size
);
870 static void put_extern_sym(Sym
*sym
, Section
*section
,
871 unsigned long value
, unsigned long size
);
872 static void greloc(Section
*s
, Sym
*sym
, unsigned long addr
, int type
);
873 static int put_elf_str(Section
*s
, const char *sym
);
874 static int put_elf_sym(Section
*s
,
875 unsigned long value
, unsigned long size
,
876 int info
, int other
, int shndx
, const char *name
);
877 static int add_elf_sym(Section
*s
, unsigned long value
, unsigned long size
,
878 int info
, int other
, int sh_num
, const char *name
);
879 static void put_elf_reloc(Section
*symtab
, Section
*s
, unsigned long offset
,
880 int type
, int symbol
);
881 static void put_stabs(const char *str
, int type
, int other
, int desc
,
882 unsigned long value
);
883 static void put_stabs_r(const char *str
, int type
, int other
, int desc
,
884 unsigned long value
, Section
*sec
, int sym_index
);
885 static void put_stabn(int type
, int other
, int desc
, int value
);
886 static void put_stabd(int type
, int other
, int desc
);
887 static int tcc_add_dll(TCCState
*s
, const char *filename
, int flags
);
889 #define AFF_PRINT_ERROR 0x0001 /* print error if file not found */
890 #define AFF_REFERENCED_DLL 0x0002 /* load a referenced dll from another dll */
891 #define AFF_PREPROCESS 0x0004 /* preprocess file */
892 static int tcc_add_file_internal(TCCState
*s
, const char *filename
, int flags
);
895 int tcc_output_coff(TCCState
*s1
, FILE *f
);
898 void *resolve_sym(TCCState
*s1
, const char *sym
, int type
);
899 int pe_load_def_file(struct TCCState
*s1
, int fd
);
900 int pe_test_res_file(void *v
, int size
);
901 int pe_load_res_file(struct TCCState
*s1
, int fd
);
902 void pe_add_runtime(struct TCCState
*s1
);
903 void pe_guess_outfile(char *objfilename
, int output_type
);
904 int pe_output_file(struct TCCState
*s1
, const char *filename
);
908 #ifdef CONFIG_TCC_ASM
910 typedef struct ExprValue
{
915 #define MAX_ASM_OPERANDS 30
917 typedef struct ASMOperand
{
918 int id
; /* GCC 3 optionnal identifier (0 if number only supported */
920 char asm_str
[16]; /* computed asm string for operand */
921 SValue
*vt
; /* C value of the expression */
922 int ref_index
; /* if >= 0, gives reference to a output constraint */
923 int input_index
; /* if >= 0, gives reference to an input constraint */
924 int priority
; /* priority, used to assign registers */
925 int reg
; /* if >= 0, register number used for this operand */
926 int is_llong
; /* true if double register value */
927 int is_memory
; /* true if memory operand */
928 int is_rw
; /* for '+' modifier */
931 static void asm_expr(TCCState
*s1
, ExprValue
*pe
);
932 static int asm_int_expr(TCCState
*s1
);
933 static int find_constraint(ASMOperand
*operands
, int nb_operands
,
934 const char *name
, const char **pp
);
936 static int tcc_assemble(TCCState
*s1
, int do_preprocess
);
940 static void asm_instr(void);
941 static void asm_global_instr(void);
943 /* true if float/double/long double type */
944 static inline int is_float(int t
)
948 return bt
== VT_LDOUBLE
|| bt
== VT_DOUBLE
|| bt
== VT_FLOAT
;
951 #ifdef TCC_TARGET_I386
952 #include "i386-gen.c"
955 #ifdef TCC_TARGET_ARM
959 #ifdef TCC_TARGET_C67
963 #ifdef TCC_TARGET_X86_64
964 #include "x86_64-gen.c"
967 #ifdef CONFIG_TCC_STATIC
969 #define RTLD_LAZY 0x001
970 #define RTLD_NOW 0x002
971 #define RTLD_GLOBAL 0x100
972 #define RTLD_DEFAULT NULL
974 /* dummy function for profiling */
975 void *dlopen(const char *filename
, int flag
)
980 void dlclose(void *p
)
984 const char *dlerror(void)
989 typedef struct TCCSyms
{
994 #define TCCSYM(a) { #a, &a, },
996 /* add the symbol you want here if no dynamic linking is done */
997 static TCCSyms tcc_syms
[] = {
998 #if !defined(CONFIG_TCCBOOT)
1007 void *resolve_sym(TCCState
*s1
, const char *symbol
, int type
)
1011 while (p
->str
!= NULL
) {
1012 if (!strcmp(p
->str
, symbol
))
1019 #elif !defined(_WIN32)
1023 void *resolve_sym(TCCState
*s1
, const char *sym
, int type
)
1025 return dlsym(RTLD_DEFAULT
, sym
);
1030 /********************************************************/
1032 /* we use our own 'finite' function to avoid potential problems with
1033 non standard math libs */
1034 /* XXX: endianness dependent */
1035 int ieee_finite(double d
)
1038 return ((unsigned)((p
[1] | 0x800fffff) + 1)) >> 31;
1041 /* copy a string and truncate it. */
1042 static char *pstrcpy(char *buf
, int buf_size
, const char *s
)
1049 q_end
= buf
+ buf_size
- 1;
1061 /* strcat and truncate. */
1062 static char *pstrcat(char *buf
, int buf_size
, const char *s
)
1067 pstrcpy(buf
+ len
, buf_size
- len
, s
);
1072 static int strstart(const char *str
, const char *val
, const char **ptr
)
1077 while (*q
!= '\0') {
1090 #define IS_PATHSEP(c) (c == '/' || c == '\\')
1091 #define IS_ABSPATH(p) (IS_PATHSEP(p[0]) || (p[0] && p[1] == ':' && IS_PATHSEP(p[2])))
1092 #define PATHCMP stricmp
1094 #define IS_PATHSEP(c) (c == '/')
1095 #define IS_ABSPATH(p) IS_PATHSEP(p[0])
1096 #define PATHCMP strcmp
1099 /* extract the basename of a file */
1100 static char *tcc_basename(const char *name
)
1102 char *p
= strchr(name
, 0);
1103 while (p
> name
&& !IS_PATHSEP(p
[-1]))
1108 static char *tcc_fileextension (const char *name
)
1110 char *b
= tcc_basename(name
);
1111 char *e
= strrchr(b
, '.');
1112 return e
? e
: strchr(b
, 0);
1116 char *normalize_slashes(char *path
)
1119 for (p
= path
; *p
; ++p
)
1125 void tcc_set_lib_path_w32(TCCState
*s
)
1127 /* on win32, we suppose the lib and includes are at the location
1129 char path
[1024], *p
;
1130 GetModuleFileNameA(NULL
, path
, sizeof path
);
1131 p
= tcc_basename(normalize_slashes(strlwr(path
)));
1132 if (p
- 5 > path
&& 0 == strncmp(p
- 5, "/bin/", 5))
1137 tcc_set_lib_path(s
, path
);
1141 void set_pages_executable(void *ptr
, unsigned long length
)
1144 unsigned long old_protect
;
1145 VirtualProtect(ptr
, length
, PAGE_EXECUTE_READWRITE
, &old_protect
);
1147 unsigned long start
, end
;
1148 start
= (unsigned long)ptr
& ~(PAGESIZE
- 1);
1149 end
= (unsigned long)ptr
+ length
;
1150 end
= (end
+ PAGESIZE
- 1) & ~(PAGESIZE
- 1);
1151 mprotect((void *)start
, end
- start
, PROT_READ
| PROT_WRITE
| PROT_EXEC
);
1155 /* memory management */
1159 unsigned malloc_usable_size(void*);
1162 static inline void tcc_free(void *ptr
)
1165 mem_cur_size
-= malloc_usable_size(ptr
);
1170 static void *tcc_malloc(unsigned long size
)
1175 error("memory full");
1177 mem_cur_size
+= malloc_usable_size(ptr
);
1178 if (mem_cur_size
> mem_max_size
)
1179 mem_max_size
= mem_cur_size
;
1184 static void *tcc_mallocz(unsigned long size
)
1187 ptr
= tcc_malloc(size
);
1188 memset(ptr
, 0, size
);
1192 static inline void *tcc_realloc(void *ptr
, unsigned long size
)
1196 mem_cur_size
-= malloc_usable_size(ptr
);
1198 ptr1
= realloc(ptr
, size
);
1200 /* NOTE: count not correct if alloc error, but not critical */
1201 mem_cur_size
+= malloc_usable_size(ptr1
);
1202 if (mem_cur_size
> mem_max_size
)
1203 mem_max_size
= mem_cur_size
;
1208 static char *tcc_strdup(const char *str
)
1211 ptr
= tcc_malloc(strlen(str
) + 1);
1216 #define free(p) use_tcc_free(p)
1217 #define malloc(s) use_tcc_malloc(s)
1218 #define realloc(p, s) use_tcc_realloc(p, s)
1220 static void dynarray_add(void ***ptab
, int *nb_ptr
, void *data
)
1227 /* every power of two we double array size */
1228 if ((nb
& (nb
- 1)) == 0) {
1233 pp
= tcc_realloc(pp
, nb_alloc
* sizeof(void *));
1235 error("memory full");
1242 static void dynarray_reset(void *pp
, int *n
)
1245 for (p
= *(void***)pp
; *n
; ++p
, --*n
)
1248 tcc_free(*(void**)pp
);
1252 /* symbol allocator */
1253 static Sym
*__sym_malloc(void)
1255 Sym
*sym_pool
, *sym
, *last_sym
;
1258 sym_pool
= tcc_malloc(SYM_POOL_NB
* sizeof(Sym
));
1259 dynarray_add(&sym_pools
, &nb_sym_pools
, sym_pool
);
1261 last_sym
= sym_free_first
;
1263 for(i
= 0; i
< SYM_POOL_NB
; i
++) {
1264 sym
->next
= last_sym
;
1268 sym_free_first
= last_sym
;
1272 static inline Sym
*sym_malloc(void)
1275 sym
= sym_free_first
;
1277 sym
= __sym_malloc();
1278 sym_free_first
= sym
->next
;
1282 static inline void sym_free(Sym
*sym
)
1284 sym
->next
= sym_free_first
;
1285 sym_free_first
= sym
;
1288 Section
*new_section(TCCState
*s1
, const char *name
, int sh_type
, int sh_flags
)
1292 sec
= tcc_mallocz(sizeof(Section
) + strlen(name
));
1293 strcpy(sec
->name
, name
);
1294 sec
->sh_type
= sh_type
;
1295 sec
->sh_flags
= sh_flags
;
1303 sec
->sh_addralign
= 4;
1306 sec
->sh_addralign
= 1;
1309 sec
->sh_addralign
= 32; /* default conservative alignment */
1313 if (sh_flags
& SHF_PRIVATE
) {
1314 dynarray_add((void ***)&s1
->priv_sections
, &s1
->nb_priv_sections
, sec
);
1316 sec
->sh_num
= s1
->nb_sections
;
1317 dynarray_add((void ***)&s1
->sections
, &s1
->nb_sections
, sec
);
1323 static void free_section(Section
*s
)
1328 /* realloc section and set its content to zero */
1329 static void section_realloc(Section
*sec
, unsigned long new_size
)
1332 unsigned char *data
;
1334 size
= sec
->data_allocated
;
1337 while (size
< new_size
)
1339 data
= tcc_realloc(sec
->data
, size
);
1341 error("memory full");
1342 memset(data
+ sec
->data_allocated
, 0, size
- sec
->data_allocated
);
1344 sec
->data_allocated
= size
;
1347 /* reserve at least 'size' bytes in section 'sec' from
1348 sec->data_offset. */
1349 static void *section_ptr_add(Section
*sec
, unsigned long size
)
1351 unsigned long offset
, offset1
;
1353 offset
= sec
->data_offset
;
1354 offset1
= offset
+ size
;
1355 if (offset1
> sec
->data_allocated
)
1356 section_realloc(sec
, offset1
);
1357 sec
->data_offset
= offset1
;
1358 return sec
->data
+ offset
;
1361 /* return a reference to a section, and create it if it does not
1363 Section
*find_section(TCCState
*s1
, const char *name
)
1367 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1368 sec
= s1
->sections
[i
];
1369 if (!strcmp(name
, sec
->name
))
1372 /* sections are created as PROGBITS */
1373 return new_section(s1
, name
, SHT_PROGBITS
, SHF_ALLOC
);
1376 #define SECTION_ABS ((void *)1)
1378 /* update sym->c so that it points to an external symbol in section
1379 'section' with value 'value' */
1380 static void put_extern_sym2(Sym
*sym
, Section
*section
,
1381 unsigned long value
, unsigned long size
,
1382 int can_add_underscore
)
1384 int sym_type
, sym_bind
, sh_num
, info
, other
, attr
;
1389 if (section
== NULL
)
1391 else if (section
== SECTION_ABS
)
1394 sh_num
= section
->sh_num
;
1398 if ((sym
->type
.t
& VT_BTYPE
) == VT_FUNC
) {
1399 sym_type
= STT_FUNC
;
1400 #ifdef TCC_TARGET_PE
1402 attr
= sym
->type
.ref
->r
;
1403 if (FUNC_EXPORT(attr
))
1405 if (FUNC_CALL(attr
) == FUNC_STDCALL
)
1409 sym_type
= STT_OBJECT
;
1412 if (sym
->type
.t
& VT_STATIC
)
1413 sym_bind
= STB_LOCAL
;
1415 sym_bind
= STB_GLOBAL
;
1418 name
= get_tok_str(sym
->v
, NULL
);
1419 #ifdef CONFIG_TCC_BCHECK
1420 if (do_bounds_check
) {
1423 /* XXX: avoid doing that for statics ? */
1424 /* if bound checking is activated, we change some function
1425 names by adding the "__bound" prefix */
1428 /* XXX: we rely only on malloc hooks */
1441 strcpy(buf
, "__bound_");
1449 #ifdef TCC_TARGET_PE
1450 if ((other
& 2) && can_add_underscore
) {
1451 sprintf(buf1
, "_%s@%d", name
, FUNC_ARGS(attr
));
1455 if (tcc_state
->leading_underscore
&& can_add_underscore
) {
1457 pstrcpy(buf1
+ 1, sizeof(buf1
) - 1, name
);
1460 info
= ELFW(ST_INFO
)(sym_bind
, sym_type
);
1461 sym
->c
= add_elf_sym(symtab_section
, value
, size
, info
, other
, sh_num
, name
);
1463 esym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym
->c
];
1464 esym
->st_value
= value
;
1465 esym
->st_size
= size
;
1466 esym
->st_shndx
= sh_num
;
1467 esym
->st_other
|= other
;
1471 static void put_extern_sym(Sym
*sym
, Section
*section
,
1472 unsigned long value
, unsigned long size
)
1474 put_extern_sym2(sym
, section
, value
, size
, 1);
1477 /* add a new relocation entry to symbol 'sym' in section 's' */
1478 static void greloc(Section
*s
, Sym
*sym
, unsigned long offset
, int type
)
1481 put_extern_sym(sym
, NULL
, 0, 0);
1482 /* now we can add ELF relocation info */
1483 put_elf_reloc(symtab_section
, s
, offset
, type
, sym
->c
);
1486 static inline int isid(int c
)
1488 return (c
>= 'a' && c
<= 'z') ||
1489 (c
>= 'A' && c
<= 'Z') ||
1493 static inline int isnum(int c
)
1495 return c
>= '0' && c
<= '9';
1498 static inline int isoct(int c
)
1500 return c
>= '0' && c
<= '7';
1503 static inline int toup(int c
)
1505 if (c
>= 'a' && c
<= 'z')
1506 return c
- 'a' + 'A';
1511 static void strcat_vprintf(char *buf
, int buf_size
, const char *fmt
, va_list ap
)
1515 vsnprintf(buf
+ len
, buf_size
- len
, fmt
, ap
);
1518 static void strcat_printf(char *buf
, int buf_size
, const char *fmt
, ...)
1522 strcat_vprintf(buf
, buf_size
, fmt
, ap
);
1526 void error1(TCCState
*s1
, int is_warning
, const char *fmt
, va_list ap
)
1533 for(f
= s1
->include_stack
; f
< s1
->include_stack_ptr
; f
++)
1534 strcat_printf(buf
, sizeof(buf
), "In file included from %s:%d:\n",
1535 (*f
)->filename
, (*f
)->line_num
);
1536 if (file
->line_num
> 0) {
1537 strcat_printf(buf
, sizeof(buf
),
1538 "%s:%d: ", file
->filename
, file
->line_num
);
1540 strcat_printf(buf
, sizeof(buf
),
1541 "%s: ", file
->filename
);
1544 strcat_printf(buf
, sizeof(buf
),
1548 strcat_printf(buf
, sizeof(buf
), "warning: ");
1549 strcat_vprintf(buf
, sizeof(buf
), fmt
, ap
);
1551 if (!s1
->error_func
) {
1552 /* default case: stderr */
1553 fprintf(stderr
, "%s\n", buf
);
1555 s1
->error_func(s1
->error_opaque
, buf
);
1557 if (!is_warning
|| s1
->warn_error
)
1562 void tcc_set_error_func(TCCState
*s
, void *error_opaque
,
1563 void (*error_func
)(void *opaque
, const char *msg
))
1565 s
->error_opaque
= error_opaque
;
1566 s
->error_func
= error_func
;
1570 /* error without aborting current compilation */
1571 void error_noabort(const char *fmt
, ...)
1573 TCCState
*s1
= tcc_state
;
1577 error1(s1
, 0, fmt
, ap
);
1581 void error(const char *fmt
, ...)
1583 TCCState
*s1
= tcc_state
;
1587 error1(s1
, 0, fmt
, ap
);
1589 /* better than nothing: in some cases, we accept to handle errors */
1590 if (s1
->error_set_jmp_enabled
) {
1591 longjmp(s1
->error_jmp_buf
, 1);
1593 /* XXX: eliminate this someday */
1598 void expect(const char *msg
)
1600 error("%s expected", msg
);
1603 void warning(const char *fmt
, ...)
1605 TCCState
*s1
= tcc_state
;
1612 error1(s1
, 1, fmt
, ap
);
1619 error("'%c' expected", c
);
1623 static void test_lvalue(void)
1625 if (!(vtop
->r
& VT_LVAL
))
1629 /* allocate a new token */
1630 static TokenSym
*tok_alloc_new(TokenSym
**pts
, const char *str
, int len
)
1632 TokenSym
*ts
, **ptable
;
1635 if (tok_ident
>= SYM_FIRST_ANOM
)
1636 error("memory full");
1638 /* expand token table if needed */
1639 i
= tok_ident
- TOK_IDENT
;
1640 if ((i
% TOK_ALLOC_INCR
) == 0) {
1641 ptable
= tcc_realloc(table_ident
, (i
+ TOK_ALLOC_INCR
) * sizeof(TokenSym
*));
1643 error("memory full");
1644 table_ident
= ptable
;
1647 ts
= tcc_malloc(sizeof(TokenSym
) + len
);
1648 table_ident
[i
] = ts
;
1649 ts
->tok
= tok_ident
++;
1650 ts
->sym_define
= NULL
;
1651 ts
->sym_label
= NULL
;
1652 ts
->sym_struct
= NULL
;
1653 ts
->sym_identifier
= NULL
;
1655 ts
->hash_next
= NULL
;
1656 memcpy(ts
->str
, str
, len
);
1657 ts
->str
[len
] = '\0';
1662 #define TOK_HASH_INIT 1
1663 #define TOK_HASH_FUNC(h, c) ((h) * 263 + (c))
1665 /* find a token and add it if not found */
1666 static TokenSym
*tok_alloc(const char *str
, int len
)
1668 TokenSym
*ts
, **pts
;
1674 h
= TOK_HASH_FUNC(h
, ((unsigned char *)str
)[i
]);
1675 h
&= (TOK_HASH_SIZE
- 1);
1677 pts
= &hash_ident
[h
];
1682 if (ts
->len
== len
&& !memcmp(ts
->str
, str
, len
))
1684 pts
= &(ts
->hash_next
);
1686 return tok_alloc_new(pts
, str
, len
);
1689 /* CString handling */
1691 static void cstr_realloc(CString
*cstr
, int new_size
)
1696 size
= cstr
->size_allocated
;
1698 size
= 8; /* no need to allocate a too small first string */
1699 while (size
< new_size
)
1701 data
= tcc_realloc(cstr
->data_allocated
, size
);
1703 error("memory full");
1704 cstr
->data_allocated
= data
;
1705 cstr
->size_allocated
= size
;
1710 static inline void cstr_ccat(CString
*cstr
, int ch
)
1713 size
= cstr
->size
+ 1;
1714 if (size
> cstr
->size_allocated
)
1715 cstr_realloc(cstr
, size
);
1716 ((unsigned char *)cstr
->data
)[size
- 1] = ch
;
1720 static void cstr_cat(CString
*cstr
, const char *str
)
1732 /* add a wide char */
1733 static void cstr_wccat(CString
*cstr
, int ch
)
1736 size
= cstr
->size
+ sizeof(nwchar_t
);
1737 if (size
> cstr
->size_allocated
)
1738 cstr_realloc(cstr
, size
);
1739 *(nwchar_t
*)(((unsigned char *)cstr
->data
) + size
- sizeof(nwchar_t
)) = ch
;
1743 static void cstr_new(CString
*cstr
)
1745 memset(cstr
, 0, sizeof(CString
));
1748 /* free string and reset it to NULL */
1749 static void cstr_free(CString
*cstr
)
1751 tcc_free(cstr
->data_allocated
);
1755 #define cstr_reset(cstr) cstr_free(cstr)
1757 /* XXX: unicode ? */
1758 static void add_char(CString
*cstr
, int c
)
1760 if (c
== '\'' || c
== '\"' || c
== '\\') {
1761 /* XXX: could be more precise if char or string */
1762 cstr_ccat(cstr
, '\\');
1764 if (c
>= 32 && c
<= 126) {
1767 cstr_ccat(cstr
, '\\');
1769 cstr_ccat(cstr
, 'n');
1771 cstr_ccat(cstr
, '0' + ((c
>> 6) & 7));
1772 cstr_ccat(cstr
, '0' + ((c
>> 3) & 7));
1773 cstr_ccat(cstr
, '0' + (c
& 7));
1778 /* XXX: buffer overflow */
1779 /* XXX: float tokens */
1780 char *get_tok_str(int v
, CValue
*cv
)
1782 static char buf
[STRING_MAX_SIZE
+ 1];
1783 static CString cstr_buf
;
1789 /* NOTE: to go faster, we give a fixed buffer for small strings */
1790 cstr_reset(&cstr_buf
);
1791 cstr_buf
.data
= buf
;
1792 cstr_buf
.size_allocated
= sizeof(buf
);
1798 /* XXX: not quite exact, but only useful for testing */
1799 sprintf(p
, "%u", cv
->ui
);
1803 /* XXX: not quite exact, but only useful for testing */
1804 sprintf(p
, "%Lu", cv
->ull
);
1807 cstr_ccat(&cstr_buf
, 'L');
1809 cstr_ccat(&cstr_buf
, '\'');
1810 add_char(&cstr_buf
, cv
->i
);
1811 cstr_ccat(&cstr_buf
, '\'');
1812 cstr_ccat(&cstr_buf
, '\0');
1816 len
= cstr
->size
- 1;
1818 add_char(&cstr_buf
, ((unsigned char *)cstr
->data
)[i
]);
1819 cstr_ccat(&cstr_buf
, '\0');
1822 cstr_ccat(&cstr_buf
, 'L');
1825 cstr_ccat(&cstr_buf
, '\"');
1827 len
= cstr
->size
- 1;
1829 add_char(&cstr_buf
, ((unsigned char *)cstr
->data
)[i
]);
1831 len
= (cstr
->size
/ sizeof(nwchar_t
)) - 1;
1833 add_char(&cstr_buf
, ((nwchar_t
*)cstr
->data
)[i
]);
1835 cstr_ccat(&cstr_buf
, '\"');
1836 cstr_ccat(&cstr_buf
, '\0');
1845 return strcpy(p
, "...");
1847 return strcpy(p
, "<<=");
1849 return strcpy(p
, ">>=");
1851 if (v
< TOK_IDENT
) {
1852 /* search in two bytes table */
1866 } else if (v
< tok_ident
) {
1867 return table_ident
[v
- TOK_IDENT
]->str
;
1868 } else if (v
>= SYM_FIRST_ANOM
) {
1869 /* special name for anonymous symbol */
1870 sprintf(p
, "L.%u", v
- SYM_FIRST_ANOM
);
1872 /* should never happen */
1877 return cstr_buf
.data
;
1880 /* push, without hashing */
1881 static Sym
*sym_push2(Sym
**ps
, int v
, int t
, long c
)
1895 /* find a symbol and return its associated structure. 's' is the top
1896 of the symbol stack */
1897 static Sym
*sym_find2(Sym
*s
, int v
)
1907 /* structure lookup */
1908 static inline Sym
*struct_find(int v
)
1911 if ((unsigned)v
>= (unsigned)(tok_ident
- TOK_IDENT
))
1913 return table_ident
[v
]->sym_struct
;
1916 /* find an identifier */
1917 static inline Sym
*sym_find(int v
)
1920 if ((unsigned)v
>= (unsigned)(tok_ident
- TOK_IDENT
))
1922 return table_ident
[v
]->sym_identifier
;
1925 /* push a given symbol on the symbol stack */
1926 static Sym
*sym_push(int v
, CType
*type
, int r
, int c
)
1935 s
= sym_push2(ps
, v
, type
->t
, c
);
1936 s
->type
.ref
= type
->ref
;
1938 /* don't record fields or anonymous symbols */
1940 if (!(v
& SYM_FIELD
) && (v
& ~SYM_STRUCT
) < SYM_FIRST_ANOM
) {
1941 /* record symbol in token array */
1942 ts
= table_ident
[(v
& ~SYM_STRUCT
) - TOK_IDENT
];
1944 ps
= &ts
->sym_struct
;
1946 ps
= &ts
->sym_identifier
;
1953 /* push a global identifier */
1954 static Sym
*global_identifier_push(int v
, int t
, int c
)
1957 s
= sym_push2(&global_stack
, v
, t
, c
);
1958 /* don't record anonymous symbol */
1959 if (v
< SYM_FIRST_ANOM
) {
1960 ps
= &table_ident
[v
- TOK_IDENT
]->sym_identifier
;
1961 /* modify the top most local identifier, so that
1962 sym_identifier will point to 's' when popped */
1964 ps
= &(*ps
)->prev_tok
;
1971 /* pop symbols until top reaches 'b' */
1972 static void sym_pop(Sym
**ptop
, Sym
*b
)
1982 /* remove symbol in token array */
1984 if (!(v
& SYM_FIELD
) && (v
& ~SYM_STRUCT
) < SYM_FIRST_ANOM
) {
1985 ts
= table_ident
[(v
& ~SYM_STRUCT
) - TOK_IDENT
];
1987 ps
= &ts
->sym_struct
;
1989 ps
= &ts
->sym_identifier
;
2000 BufferedFile
*tcc_open(TCCState
*s1
, const char *filename
)
2005 if (strcmp(filename
, "-") == 0)
2006 fd
= 0, filename
= "stdin";
2008 fd
= open(filename
, O_RDONLY
| O_BINARY
);
2009 if ((verbose
== 2 && fd
>= 0) || verbose
== 3)
2010 printf("%s %*s%s\n", fd
< 0 ? "nf":"->",
2011 (s1
->include_stack_ptr
- s1
->include_stack
), "", filename
);
2014 bf
= tcc_malloc(sizeof(BufferedFile
));
2016 bf
->buf_ptr
= bf
->buffer
;
2017 bf
->buf_end
= bf
->buffer
;
2018 bf
->buffer
[0] = CH_EOB
; /* put eob symbol */
2019 pstrcpy(bf
->filename
, sizeof(bf
->filename
), filename
);
2021 normalize_slashes(bf
->filename
);
2024 bf
->ifndef_macro
= 0;
2025 bf
->ifdef_stack_ptr
= s1
->ifdef_stack_ptr
;
2026 // printf("opening '%s'\n", filename);
2030 void tcc_close(BufferedFile
*bf
)
2032 total_lines
+= bf
->line_num
;
2037 /* fill input buffer and peek next char */
2038 static int tcc_peekc_slow(BufferedFile
*bf
)
2041 /* only tries to read if really end of buffer */
2042 if (bf
->buf_ptr
>= bf
->buf_end
) {
2044 #if defined(PARSE_DEBUG)
2049 len
= read(bf
->fd
, bf
->buffer
, len
);
2056 bf
->buf_ptr
= bf
->buffer
;
2057 bf
->buf_end
= bf
->buffer
+ len
;
2058 *bf
->buf_end
= CH_EOB
;
2060 if (bf
->buf_ptr
< bf
->buf_end
) {
2061 return bf
->buf_ptr
[0];
2063 bf
->buf_ptr
= bf
->buf_end
;
2068 /* return the current character, handling end of block if necessary
2070 static int handle_eob(void)
2072 return tcc_peekc_slow(file
);
2075 /* read next char from current input file and handle end of input buffer */
2076 static inline void inp(void)
2078 ch
= *(++(file
->buf_ptr
));
2079 /* end of buffer/file handling */
2084 /* handle '\[\r]\n' */
2085 static int handle_stray_noerror(void)
2087 while (ch
== '\\') {
2092 } else if (ch
== '\r') {
2106 static void handle_stray(void)
2108 if (handle_stray_noerror())
2109 error("stray '\\' in program");
2112 /* skip the stray and handle the \\n case. Output an error if
2113 incorrect char after the stray */
2114 static int handle_stray1(uint8_t *p
)
2118 if (p
>= file
->buf_end
) {
2135 /* handle just the EOB case, but not stray */
2136 #define PEEKC_EOB(c, p)\
2147 /* handle the complicated stray case */
2148 #define PEEKC(c, p)\
2153 c = handle_stray1(p);\
2158 /* input with '\[\r]\n' handling. Note that this function cannot
2159 handle other characters after '\', so you cannot call it inside
2160 strings or comments */
2161 static void minp(void)
2169 /* single line C++ comments */
2170 static uint8_t *parse_line_comment(uint8_t *p
)
2178 if (c
== '\n' || c
== CH_EOF
) {
2180 } else if (c
== '\\') {
2189 } else if (c
== '\r') {
2207 static uint8_t *parse_comment(uint8_t *p
)
2213 /* fast skip loop */
2216 if (c
== '\n' || c
== '*' || c
== '\\')
2220 if (c
== '\n' || c
== '*' || c
== '\\')
2224 /* now we can handle all the cases */
2228 } else if (c
== '*') {
2234 } else if (c
== '/') {
2235 goto end_of_comment
;
2236 } else if (c
== '\\') {
2241 /* skip '\[\r]\n', otherwise just skip the stray */
2247 } else if (c
== '\r') {
2264 /* stray, eob or eof */
2269 error("unexpected end of file in comment");
2270 } else if (c
== '\\') {
2282 /* space exlcuding newline */
2283 static inline int is_space(int ch
)
2285 return ch
== ' ' || ch
== '\t' || ch
== '\v' || ch
== '\f' || ch
== '\r';
2288 static inline void skip_spaces(void)
2290 while (is_space(ch
))
2294 static inline int check_space(int t
, int *spc
)
2305 /* parse a string without interpreting escapes */
2306 static uint8_t *parse_pp_string(uint8_t *p
,
2307 int sep
, CString
*str
)
2315 } else if (c
== '\\') {
2320 unterminated_string
:
2321 /* XXX: indicate line number of start of string */
2322 error("missing terminating %c character", sep
);
2323 } else if (c
== '\\') {
2324 /* escape : just skip \[\r]\n */
2329 } else if (c
== '\r') {
2332 expect("'\n' after '\r'");
2335 } else if (c
== CH_EOF
) {
2336 goto unterminated_string
;
2339 cstr_ccat(str
, '\\');
2345 } else if (c
== '\n') {
2348 } else if (c
== '\r') {
2352 cstr_ccat(str
, '\r');
2368 /* skip block of text until #else, #elif or #endif. skip also pairs of
2370 void preprocess_skip(void)
2372 int a
, start_of_line
, c
, in_warn_or_error
;
2379 in_warn_or_error
= 0;
2400 } else if (c
== '\\') {
2401 ch
= file
->buf_ptr
[0];
2402 handle_stray_noerror();
2409 if (in_warn_or_error
)
2411 p
= parse_pp_string(p
, c
, NULL
);
2415 if (in_warn_or_error
)
2422 p
= parse_comment(p
);
2423 } else if (ch
== '/') {
2424 p
= parse_line_comment(p
);
2429 if (start_of_line
) {
2434 (tok
== TOK_ELSE
|| tok
== TOK_ELIF
|| tok
== TOK_ENDIF
))
2436 if (tok
== TOK_IF
|| tok
== TOK_IFDEF
|| tok
== TOK_IFNDEF
)
2438 else if (tok
== TOK_ENDIF
)
2440 else if( tok
== TOK_ERROR
|| tok
== TOK_WARNING
)
2441 in_warn_or_error
= 1;
2455 /* ParseState handling */
2457 /* XXX: currently, no include file info is stored. Thus, we cannot display
2458 accurate messages if the function or data definition spans multiple
2461 /* save current parse state in 's' */
2462 void save_parse_state(ParseState
*s
)
2464 s
->line_num
= file
->line_num
;
2465 s
->macro_ptr
= macro_ptr
;
2470 /* restore parse state from 's' */
2471 void restore_parse_state(ParseState
*s
)
2473 file
->line_num
= s
->line_num
;
2474 macro_ptr
= s
->macro_ptr
;
2479 /* return the number of additional 'ints' necessary to store the
2481 static inline int tok_ext_size(int t
)
2495 error("unsupported token");
2502 return LDOUBLE_SIZE
/ 4;
2508 /* token string handling */
2510 static inline void tok_str_new(TokenString
*s
)
2514 s
->allocated_len
= 0;
2515 s
->last_line_num
= -1;
2518 static void tok_str_free(int *str
)
2523 static int *tok_str_realloc(TokenString
*s
)
2527 if (s
->allocated_len
== 0) {
2530 len
= s
->allocated_len
* 2;
2532 str
= tcc_realloc(s
->str
, len
* sizeof(int));
2534 error("memory full");
2535 s
->allocated_len
= len
;
2540 static void tok_str_add(TokenString
*s
, int t
)
2546 if (len
>= s
->allocated_len
)
2547 str
= tok_str_realloc(s
);
2552 static void tok_str_add2(TokenString
*s
, int t
, CValue
*cv
)
2559 /* allocate space for worst case */
2560 if (len
+ TOK_MAX_SIZE
> s
->allocated_len
)
2561 str
= tok_str_realloc(s
);
2570 str
[len
++] = cv
->tab
[0];
2579 nb_words
= (sizeof(CString
) + cv
->cstr
->size
+ 3) >> 2;
2580 while ((len
+ nb_words
) > s
->allocated_len
)
2581 str
= tok_str_realloc(s
);
2582 cstr
= (CString
*)(str
+ len
);
2584 cstr
->size
= cv
->cstr
->size
;
2585 cstr
->data_allocated
= NULL
;
2586 cstr
->size_allocated
= cstr
->size
;
2587 memcpy((char *)cstr
+ sizeof(CString
),
2588 cv
->cstr
->data
, cstr
->size
);
2595 #if LDOUBLE_SIZE == 8
2598 str
[len
++] = cv
->tab
[0];
2599 str
[len
++] = cv
->tab
[1];
2601 #if LDOUBLE_SIZE == 12
2603 str
[len
++] = cv
->tab
[0];
2604 str
[len
++] = cv
->tab
[1];
2605 str
[len
++] = cv
->tab
[2];
2606 #elif LDOUBLE_SIZE == 16
2608 str
[len
++] = cv
->tab
[0];
2609 str
[len
++] = cv
->tab
[1];
2610 str
[len
++] = cv
->tab
[2];
2611 str
[len
++] = cv
->tab
[3];
2612 #elif LDOUBLE_SIZE != 8
2613 #error add long double size support
2622 /* add the current parse token in token string 's' */
2623 static void tok_str_add_tok(TokenString
*s
)
2627 /* save line number info */
2628 if (file
->line_num
!= s
->last_line_num
) {
2629 s
->last_line_num
= file
->line_num
;
2630 cval
.i
= s
->last_line_num
;
2631 tok_str_add2(s
, TOK_LINENUM
, &cval
);
2633 tok_str_add2(s
, tok
, &tokc
);
2636 #if LDOUBLE_SIZE == 16
2637 #define LDOUBLE_GET(p, cv) \
2642 #elif LDOUBLE_SIZE == 12
2643 #define LDOUBLE_GET(p, cv) \
2647 #elif LDOUBLE_SIZE == 8
2648 #define LDOUBLE_GET(p, cv) \
2652 #error add long double size support
2656 /* get a token from an integer array and increment pointer
2657 accordingly. we code it as a macro to avoid pointer aliasing. */
2658 #define TOK_GET(t, p, cv) \
2673 cv.cstr = (CString *)p; \
2674 cv.cstr->data = (char *)p + sizeof(CString);\
2675 p += (sizeof(CString) + cv.cstr->size + 3) >> 2;\
2684 case TOK_CLDOUBLE: \
2685 LDOUBLE_GET(p, cv); \
2686 p += LDOUBLE_SIZE / 4; \
2693 /* defines handling */
2694 static inline void define_push(int v
, int macro_type
, int *str
, Sym
*first_arg
)
2698 s
= sym_push2(&define_stack
, v
, macro_type
, (long)str
);
2699 s
->next
= first_arg
;
2700 table_ident
[v
- TOK_IDENT
]->sym_define
= s
;
2703 /* undefined a define symbol. Its name is just set to zero */
2704 static void define_undef(Sym
*s
)
2708 if (v
>= TOK_IDENT
&& v
< tok_ident
)
2709 table_ident
[v
- TOK_IDENT
]->sym_define
= NULL
;
2713 static inline Sym
*define_find(int v
)
2716 if ((unsigned)v
>= (unsigned)(tok_ident
- TOK_IDENT
))
2718 return table_ident
[v
]->sym_define
;
2721 /* free define stack until top reaches 'b' */
2722 static void free_defines(Sym
*b
)
2730 /* do not free args or predefined defines */
2732 tok_str_free((int *)top
->c
);
2734 if (v
>= TOK_IDENT
&& v
< tok_ident
)
2735 table_ident
[v
- TOK_IDENT
]->sym_define
= NULL
;
2743 static Sym
*label_find(int v
)
2746 if ((unsigned)v
>= (unsigned)(tok_ident
- TOK_IDENT
))
2748 return table_ident
[v
]->sym_label
;
2751 static Sym
*label_push(Sym
**ptop
, int v
, int flags
)
2754 s
= sym_push2(ptop
, v
, 0, 0);
2756 ps
= &table_ident
[v
- TOK_IDENT
]->sym_label
;
2757 if (ptop
== &global_label_stack
) {
2758 /* modify the top most local identifier, so that
2759 sym_identifier will point to 's' when popped */
2761 ps
= &(*ps
)->prev_tok
;
2768 /* pop labels until element last is reached. Look if any labels are
2769 undefined. Define symbols if '&&label' was used. */
2770 static void label_pop(Sym
**ptop
, Sym
*slast
)
2773 for(s
= *ptop
; s
!= slast
; s
= s1
) {
2775 if (s
->r
== LABEL_DECLARED
) {
2776 warning("label '%s' declared but not used", get_tok_str(s
->v
, NULL
));
2777 } else if (s
->r
== LABEL_FORWARD
) {
2778 error("label '%s' used but not defined",
2779 get_tok_str(s
->v
, NULL
));
2782 /* define corresponding symbol. A size of
2784 put_extern_sym(s
, cur_text_section
, (long)s
->next
, 1);
2788 table_ident
[s
->v
- TOK_IDENT
]->sym_label
= s
->prev_tok
;
2794 /* eval an expression for #if/#elif */
2795 static int expr_preprocess(void)
2801 while (tok
!= TOK_LINEFEED
&& tok
!= TOK_EOF
) {
2802 next(); /* do macro subst */
2803 if (tok
== TOK_DEFINED
) {
2808 c
= define_find(tok
) != 0;
2813 } else if (tok
>= TOK_IDENT
) {
2814 /* if undefined macro */
2818 tok_str_add_tok(&str
);
2820 tok_str_add(&str
, -1); /* simulate end of file */
2821 tok_str_add(&str
, 0);
2822 /* now evaluate C constant expression */
2823 macro_ptr
= str
.str
;
2827 tok_str_free(str
.str
);
2831 #if defined(PARSE_DEBUG) || defined(PP_DEBUG)
2832 static void tok_print(int *str
)
2839 TOK_GET(t
, str
, cval
);
2842 printf("%s", get_tok_str(t
, &cval
));
2848 /* parse after #define */
2849 static void parse_define(void)
2851 Sym
*s
, *first
, **ps
;
2852 int v
, t
, varg
, is_vaargs
, spc
;
2857 error("invalid macro name '%s'", get_tok_str(tok
, &tokc
));
2858 /* XXX: should check if same macro (ANSI) */
2861 /* '(' must be just after macro definition for MACRO_FUNC */
2866 while (tok
!= ')') {
2870 if (varg
== TOK_DOTS
) {
2871 varg
= TOK___VA_ARGS__
;
2873 } else if (tok
== TOK_DOTS
&& gnu_ext
) {
2877 if (varg
< TOK_IDENT
)
2878 error("badly punctuated parameter list");
2879 s
= sym_push2(&define_stack
, varg
| SYM_FIELD
, is_vaargs
, 0);
2892 /* EOF testing necessary for '-D' handling */
2893 while (tok
!= TOK_LINEFEED
&& tok
!= TOK_EOF
) {
2894 /* remove spaces around ## and after '#' */
2895 if (TOK_TWOSHARPS
== tok
) {
2899 } else if ('#' == tok
) {
2901 } else if (check_space(tok
, &spc
)) {
2904 tok_str_add2(&str
, tok
, &tokc
);
2909 --str
.len
; /* remove trailing space */
2910 tok_str_add(&str
, 0);
2912 printf("define %s %d: ", get_tok_str(v
, NULL
), t
);
2915 define_push(v
, t
, str
.str
, first
);
2918 static inline int hash_cached_include(int type
, const char *filename
)
2920 const unsigned char *s
;
2924 h
= TOK_HASH_FUNC(h
, type
);
2927 h
= TOK_HASH_FUNC(h
, *s
);
2930 h
&= (CACHED_INCLUDES_HASH_SIZE
- 1);
2934 /* XXX: use a token or a hash table to accelerate matching ? */
2935 static CachedInclude
*search_cached_include(TCCState
*s1
,
2936 int type
, const char *filename
)
2940 h
= hash_cached_include(type
, filename
);
2941 i
= s1
->cached_includes_hash
[h
];
2945 e
= s1
->cached_includes
[i
- 1];
2946 if (e
->type
== type
&& !PATHCMP(e
->filename
, filename
))
2953 static inline void add_cached_include(TCCState
*s1
, int type
,
2954 const char *filename
, int ifndef_macro
)
2959 if (search_cached_include(s1
, type
, filename
))
2962 printf("adding cached '%s' %s\n", filename
, get_tok_str(ifndef_macro
, NULL
));
2964 e
= tcc_malloc(sizeof(CachedInclude
) + strlen(filename
));
2968 strcpy(e
->filename
, filename
);
2969 e
->ifndef_macro
= ifndef_macro
;
2970 dynarray_add((void ***)&s1
->cached_includes
, &s1
->nb_cached_includes
, e
);
2971 /* add in hash table */
2972 h
= hash_cached_include(type
, filename
);
2973 e
->hash_next
= s1
->cached_includes_hash
[h
];
2974 s1
->cached_includes_hash
[h
] = s1
->nb_cached_includes
;
2977 static void pragma_parse(TCCState
*s1
)
2982 if (tok
== TOK_pack
) {
2985 #pragma pack(1) // set
2986 #pragma pack() // reset to default
2987 #pragma pack(push,1) // push & set
2988 #pragma pack(pop) // restore previous
2992 if (tok
== TOK_ASM_pop
) {
2994 if (s1
->pack_stack_ptr
<= s1
->pack_stack
) {
2996 error("out of pack stack");
2998 s1
->pack_stack_ptr
--;
3002 if (tok
== TOK_ASM_push
) {
3004 if (s1
->pack_stack_ptr
>= s1
->pack_stack
+ PACK_STACK_SIZE
- 1)
3006 s1
->pack_stack_ptr
++;
3009 if (tok
!= TOK_CINT
) {
3011 error("invalid pack pragma");
3014 if (val
< 1 || val
> 16 || (val
& (val
- 1)) != 0)
3018 *s1
->pack_stack_ptr
= val
;
3024 /* is_bof is true if first non space token at beginning of file */
3025 static void preprocess(int is_bof
)
3027 TCCState
*s1
= tcc_state
;
3028 int size
, i
, c
, n
, saved_parse_flags
;
3035 saved_parse_flags
= parse_flags
;
3036 parse_flags
= PARSE_FLAG_PREPROCESS
| PARSE_FLAG_TOK_NUM
|
3037 PARSE_FLAG_LINEFEED
;
3047 s
= define_find(tok
);
3048 /* undefine symbol by putting an invalid name */
3053 case TOK_INCLUDE_NEXT
:
3054 ch
= file
->buf_ptr
[0];
3055 /* XXX: incorrect if comments : use next_nomacro with a special mode */
3060 } else if (ch
== '\"') {
3065 while (ch
!= c
&& ch
!= '\n' && ch
!= CH_EOF
) {
3066 if ((q
- buf
) < sizeof(buf
) - 1)
3069 if (handle_stray_noerror() == 0)
3077 /* eat all spaces and comments after include */
3078 /* XXX: slightly incorrect */
3079 while (ch1
!= '\n' && ch1
!= CH_EOF
)
3083 /* computed #include : either we have only strings or
3084 we have anything enclosed in '<>' */
3087 if (tok
== TOK_STR
) {
3088 while (tok
!= TOK_LINEFEED
) {
3089 if (tok
!= TOK_STR
) {
3091 error("'#include' expects \"FILENAME\" or <FILENAME>");
3093 pstrcat(buf
, sizeof(buf
), (char *)tokc
.cstr
->data
);
3099 while (tok
!= TOK_LINEFEED
) {
3100 pstrcat(buf
, sizeof(buf
), get_tok_str(tok
, &tokc
));
3104 /* check syntax and remove '<>' */
3105 if (len
< 2 || buf
[0] != '<' || buf
[len
- 1] != '>')
3106 goto include_syntax
;
3107 memmove(buf
, buf
+ 1, len
- 2);
3108 buf
[len
- 2] = '\0';
3113 e
= search_cached_include(s1
, c
, buf
);
3114 if (e
&& define_find(e
->ifndef_macro
)) {
3115 /* no need to parse the include because the 'ifndef macro'
3118 printf("%s: skipping %s\n", file
->filename
, buf
);
3121 if (s1
->include_stack_ptr
>= s1
->include_stack
+ INCLUDE_STACK_SIZE
)
3122 error("#include recursion too deep");
3123 /* push current file in stack */
3124 /* XXX: fix current line init */
3125 *s1
->include_stack_ptr
++ = file
;
3127 /* check absolute include path */
3128 if (IS_ABSPATH(buf
)) {
3129 f
= tcc_open(s1
, buf
);
3134 /* first search in current dir if "header.h" */
3135 size
= tcc_basename(file
->filename
) - file
->filename
;
3136 if (size
> sizeof(buf1
) - 1)
3137 size
= sizeof(buf1
) - 1;
3138 memcpy(buf1
, file
->filename
, size
);
3140 pstrcat(buf1
, sizeof(buf1
), buf
);
3141 f
= tcc_open(s1
, buf1
);
3143 if (tok
== TOK_INCLUDE_NEXT
)
3149 /* now search in all the include paths */
3150 n
= s1
->nb_include_paths
+ s1
->nb_sysinclude_paths
;
3151 for(i
= 0; i
< n
; i
++) {
3153 if (i
< s1
->nb_include_paths
)
3154 path
= s1
->include_paths
[i
];
3156 path
= s1
->sysinclude_paths
[i
- s1
->nb_include_paths
];
3157 pstrcpy(buf1
, sizeof(buf1
), path
);
3158 pstrcat(buf1
, sizeof(buf1
), "/");
3159 pstrcat(buf1
, sizeof(buf1
), buf
);
3160 f
= tcc_open(s1
, buf1
);
3162 if (tok
== TOK_INCLUDE_NEXT
)
3168 --s1
->include_stack_ptr
;
3169 error("include file '%s' not found", buf
);
3173 printf("%s: including %s\n", file
->filename
, buf1
);
3176 pstrcpy(f
->inc_filename
, sizeof(f
->inc_filename
), buf
);
3178 /* add include file debug info */
3180 put_stabs(file
->filename
, N_BINCL
, 0, 0, 0);
3182 tok_flags
|= TOK_FLAG_BOF
| TOK_FLAG_BOL
;
3183 ch
= file
->buf_ptr
[0];
3191 c
= expr_preprocess();
3197 if (tok
< TOK_IDENT
)
3198 error("invalid argument for '#if%sdef'", c
? "n" : "");
3202 printf("#ifndef %s\n", get_tok_str(tok
, NULL
));
3204 file
->ifndef_macro
= tok
;
3207 c
= (define_find(tok
) != 0) ^ c
;
3209 if (s1
->ifdef_stack_ptr
>= s1
->ifdef_stack
+ IFDEF_STACK_SIZE
)
3210 error("memory full");
3211 *s1
->ifdef_stack_ptr
++ = c
;
3214 if (s1
->ifdef_stack_ptr
== s1
->ifdef_stack
)
3215 error("#else without matching #if");
3216 if (s1
->ifdef_stack_ptr
[-1] & 2)
3217 error("#else after #else");
3218 c
= (s1
->ifdef_stack_ptr
[-1] ^= 3);
3221 if (s1
->ifdef_stack_ptr
== s1
->ifdef_stack
)
3222 error("#elif without matching #if");
3223 c
= s1
->ifdef_stack_ptr
[-1];
3225 error("#elif after #else");
3226 /* last #if/#elif expression was true: we skip */
3229 c
= expr_preprocess();
3230 s1
->ifdef_stack_ptr
[-1] = c
;
3240 if (s1
->ifdef_stack_ptr
<= file
->ifdef_stack_ptr
)
3241 error("#endif without matching #if");
3242 s1
->ifdef_stack_ptr
--;
3243 /* '#ifndef macro' was at the start of file. Now we check if
3244 an '#endif' is exactly at the end of file */
3245 if (file
->ifndef_macro
&&
3246 s1
->ifdef_stack_ptr
== file
->ifdef_stack_ptr
) {
3247 file
->ifndef_macro_saved
= file
->ifndef_macro
;
3248 /* need to set to zero to avoid false matches if another
3249 #ifndef at middle of file */
3250 file
->ifndef_macro
= 0;
3251 while (tok
!= TOK_LINEFEED
)
3253 tok_flags
|= TOK_FLAG_ENDIF
;
3259 if (tok
!= TOK_CINT
)
3261 file
->line_num
= tokc
.i
- 1; /* the line number will be incremented after */
3263 if (tok
!= TOK_LINEFEED
) {
3266 pstrcpy(file
->filename
, sizeof(file
->filename
),
3267 (char *)tokc
.cstr
->data
);
3273 ch
= file
->buf_ptr
[0];
3276 while (ch
!= '\n' && ch
!= CH_EOF
) {
3277 if ((q
- buf
) < sizeof(buf
) - 1)
3280 if (handle_stray_noerror() == 0)
3287 error("#error %s", buf
);
3289 warning("#warning %s", buf
);
3295 if (tok
== TOK_LINEFEED
|| tok
== '!' || tok
== TOK_CINT
) {
3296 /* '!' is ignored to allow C scripts. numbers are ignored
3297 to emulate cpp behaviour */
3299 if (!(saved_parse_flags
& PARSE_FLAG_ASM_COMMENTS
))
3300 warning("Ignoring unknown preprocessing directive #%s", get_tok_str(tok
, &tokc
));
3304 /* ignore other preprocess commands or #! for C scripts */
3305 while (tok
!= TOK_LINEFEED
)
3308 parse_flags
= saved_parse_flags
;
3311 /* evaluate escape codes in a string. */
3312 static void parse_escape_string(CString
*outstr
, const uint8_t *buf
, int is_long
)
3327 case '0': case '1': case '2': case '3':
3328 case '4': case '5': case '6': case '7':
3329 /* at most three octal digits */
3334 n
= n
* 8 + c
- '0';
3338 n
= n
* 8 + c
- '0';
3343 goto add_char_nonext
;
3351 if (c
>= 'a' && c
<= 'f')
3353 else if (c
>= 'A' && c
<= 'F')
3363 goto add_char_nonext
;
3387 goto invalid_escape
;
3397 if (c
>= '!' && c
<= '~')
3398 warning("unknown escape sequence: \'\\%c\'", c
);
3400 warning("unknown escape sequence: \'\\x%x\'", c
);
3407 cstr_ccat(outstr
, c
);
3409 cstr_wccat(outstr
, c
);
3411 /* add a trailing '\0' */
3413 cstr_ccat(outstr
, '\0');
3415 cstr_wccat(outstr
, '\0');
3418 /* we use 64 bit numbers */
3421 /* bn = (bn << shift) | or_val */
3422 void bn_lshift(unsigned int *bn
, int shift
, int or_val
)
3426 for(i
=0;i
<BN_SIZE
;i
++) {
3428 bn
[i
] = (v
<< shift
) | or_val
;
3429 or_val
= v
>> (32 - shift
);
3433 void bn_zero(unsigned int *bn
)
3436 for(i
=0;i
<BN_SIZE
;i
++) {
3441 /* parse number in null terminated string 'p' and return it in the
3443 void parse_number(const char *p
)
3445 int b
, t
, shift
, frac_bits
, s
, exp_val
, ch
;
3447 unsigned int bn
[BN_SIZE
];
3458 goto float_frac_parse
;
3459 } else if (t
== '0') {
3460 if (ch
== 'x' || ch
== 'X') {
3464 } else if (tcc_ext
&& (ch
== 'b' || ch
== 'B')) {
3470 /* parse all digits. cannot check octal numbers at this stage
3471 because of floating point constants */
3473 if (ch
>= 'a' && ch
<= 'f')
3475 else if (ch
>= 'A' && ch
<= 'F')
3483 if (q
>= token_buf
+ STRING_MAX_SIZE
) {
3485 error("number too long");
3491 ((ch
== 'e' || ch
== 'E') && b
== 10) ||
3492 ((ch
== 'p' || ch
== 'P') && (b
== 16 || b
== 2))) {
3494 /* NOTE: strtox should support that for hexa numbers, but
3495 non ISOC99 libcs do not support it, so we prefer to do
3497 /* hexadecimal or binary floats */
3498 /* XXX: handle overflows */
3510 } else if (t
>= 'a') {
3512 } else if (t
>= 'A') {
3517 bn_lshift(bn
, shift
, t
);
3524 if (t
>= 'a' && t
<= 'f') {
3526 } else if (t
>= 'A' && t
<= 'F') {
3528 } else if (t
>= '0' && t
<= '9') {
3534 error("invalid digit");
3535 bn_lshift(bn
, shift
, t
);
3540 if (ch
!= 'p' && ch
!= 'P')
3547 } else if (ch
== '-') {
3551 if (ch
< '0' || ch
> '9')
3552 expect("exponent digits");
3553 while (ch
>= '0' && ch
<= '9') {
3554 exp_val
= exp_val
* 10 + ch
- '0';
3557 exp_val
= exp_val
* s
;
3559 /* now we can generate the number */
3560 /* XXX: should patch directly float number */
3561 d
= (double)bn
[1] * 4294967296.0 + (double)bn
[0];
3562 d
= ldexp(d
, exp_val
- frac_bits
);
3567 /* float : should handle overflow */
3569 } else if (t
== 'L') {
3572 /* XXX: not large enough */
3573 tokc
.ld
= (long double)d
;
3579 /* decimal floats */
3581 if (q
>= token_buf
+ STRING_MAX_SIZE
)
3586 while (ch
>= '0' && ch
<= '9') {
3587 if (q
>= token_buf
+ STRING_MAX_SIZE
)
3593 if (ch
== 'e' || ch
== 'E') {
3594 if (q
>= token_buf
+ STRING_MAX_SIZE
)
3598 if (ch
== '-' || ch
== '+') {
3599 if (q
>= token_buf
+ STRING_MAX_SIZE
)
3604 if (ch
< '0' || ch
> '9')
3605 expect("exponent digits");
3606 while (ch
>= '0' && ch
<= '9') {
3607 if (q
>= token_buf
+ STRING_MAX_SIZE
)
3619 tokc
.f
= strtof(token_buf
, NULL
);
3620 } else if (t
== 'L') {
3623 tokc
.ld
= strtold(token_buf
, NULL
);
3626 tokc
.d
= strtod(token_buf
, NULL
);
3630 unsigned long long n
, n1
;
3633 /* integer number */
3636 if (b
== 10 && *q
== '0') {
3643 /* no need for checks except for base 10 / 8 errors */
3646 } else if (t
>= 'a') {
3648 } else if (t
>= 'A') {
3653 error("invalid digit");
3657 /* detect overflow */
3658 /* XXX: this test is not reliable */
3660 error("integer constant overflow");
3663 /* XXX: not exactly ANSI compliant */
3664 if ((n
& 0xffffffff00000000LL
) != 0) {
3669 } else if (n
> 0x7fffffff) {
3680 error("three 'l's in integer constant");
3683 if (tok
== TOK_CINT
)
3685 else if (tok
== TOK_CUINT
)
3689 } else if (t
== 'U') {
3691 error("two 'u's in integer constant");
3693 if (tok
== TOK_CINT
)
3695 else if (tok
== TOK_CLLONG
)
3702 if (tok
== TOK_CINT
|| tok
== TOK_CUINT
)
3708 error("invalid number\n");
3712 #define PARSE2(c1, tok1, c2, tok2) \
3723 /* return next token without macro substitution */
3724 static inline void next_nomacro1(void)
3739 goto keep_tok_flags
;
3746 /* first look if it is in fact an end of buffer */
3747 if (p
>= file
->buf_end
) {
3751 if (p
>= file
->buf_end
)
3764 TCCState
*s1
= tcc_state
;
3765 if ((parse_flags
& PARSE_FLAG_LINEFEED
)
3766 && !(tok_flags
& TOK_FLAG_EOF
)) {
3767 tok_flags
|= TOK_FLAG_EOF
;
3769 goto keep_tok_flags
;
3770 } else if (s1
->include_stack_ptr
== s1
->include_stack
||
3771 !(parse_flags
& PARSE_FLAG_PREPROCESS
)) {
3772 /* no include left : end of file. */
3775 tok_flags
&= ~TOK_FLAG_EOF
;
3776 /* pop include file */
3778 /* test if previous '#endif' was after a #ifdef at
3780 if (tok_flags
& TOK_FLAG_ENDIF
) {
3782 printf("#endif %s\n", get_tok_str(file
->ifndef_macro_saved
, NULL
));
3784 add_cached_include(s1
, file
->inc_type
, file
->inc_filename
,
3785 file
->ifndef_macro_saved
);
3788 /* add end of include file debug info */
3790 put_stabd(N_EINCL
, 0, 0);
3792 /* pop include stack */
3794 s1
->include_stack_ptr
--;
3795 file
= *s1
->include_stack_ptr
;
3804 tok_flags
|= TOK_FLAG_BOL
;
3806 if (0 == (parse_flags
& PARSE_FLAG_LINEFEED
))
3809 goto keep_tok_flags
;
3814 if ((tok_flags
& TOK_FLAG_BOL
) &&
3815 (parse_flags
& PARSE_FLAG_PREPROCESS
)) {
3817 preprocess(tok_flags
& TOK_FLAG_BOF
);
3823 tok
= TOK_TWOSHARPS
;
3825 if (parse_flags
& PARSE_FLAG_ASM_COMMENTS
) {
3826 p
= parse_line_comment(p
- 1);
3835 case 'a': case 'b': case 'c': case 'd':
3836 case 'e': case 'f': case 'g': case 'h':
3837 case 'i': case 'j': case 'k': case 'l':
3838 case 'm': case 'n': case 'o': case 'p':
3839 case 'q': case 'r': case 's': case 't':
3840 case 'u': case 'v': case 'w': case 'x':
3842 case 'A': case 'B': case 'C': case 'D':
3843 case 'E': case 'F': case 'G': case 'H':
3844 case 'I': case 'J': case 'K':
3845 case 'M': case 'N': case 'O': case 'P':
3846 case 'Q': case 'R': case 'S': case 'T':
3847 case 'U': case 'V': case 'W': case 'X':
3853 h
= TOK_HASH_FUNC(h
, c
);
3857 if (!isidnum_table
[c
-CH_EOF
])
3859 h
= TOK_HASH_FUNC(h
, c
);
3866 /* fast case : no stray found, so we have the full token
3867 and we have already hashed it */
3869 h
&= (TOK_HASH_SIZE
- 1);
3870 pts
= &hash_ident
[h
];
3875 if (ts
->len
== len
&& !memcmp(ts
->str
, p1
, len
))
3877 pts
= &(ts
->hash_next
);
3879 ts
= tok_alloc_new(pts
, p1
, len
);
3883 cstr_reset(&tokcstr
);
3886 cstr_ccat(&tokcstr
, *p1
);
3892 while (isidnum_table
[c
-CH_EOF
]) {
3893 cstr_ccat(&tokcstr
, c
);
3896 ts
= tok_alloc(tokcstr
.data
, tokcstr
.size
);
3902 if (t
!= '\\' && t
!= '\'' && t
!= '\"') {
3904 goto parse_ident_fast
;
3907 if (c
== '\'' || c
== '\"') {
3911 cstr_reset(&tokcstr
);
3912 cstr_ccat(&tokcstr
, 'L');
3913 goto parse_ident_slow
;
3917 case '0': case '1': case '2': case '3':
3918 case '4': case '5': case '6': case '7':
3921 cstr_reset(&tokcstr
);
3922 /* after the first digit, accept digits, alpha, '.' or sign if
3923 prefixed by 'eEpP' */
3927 cstr_ccat(&tokcstr
, c
);
3929 if (!(isnum(c
) || isid(c
) || c
== '.' ||
3930 ((c
== '+' || c
== '-') &&
3931 (t
== 'e' || t
== 'E' || t
== 'p' || t
== 'P'))))
3934 /* We add a trailing '\0' to ease parsing */
3935 cstr_ccat(&tokcstr
, '\0');
3936 tokc
.cstr
= &tokcstr
;
3940 /* special dot handling because it can also start a number */
3943 cstr_reset(&tokcstr
);
3944 cstr_ccat(&tokcstr
, '.');
3946 } else if (c
== '.') {
3966 /* parse the string */
3968 p
= parse_pp_string(p
, sep
, &str
);
3969 cstr_ccat(&str
, '\0');
3971 /* eval the escape (should be done as TOK_PPNUM) */
3972 cstr_reset(&tokcstr
);
3973 parse_escape_string(&tokcstr
, str
.data
, is_long
);
3978 /* XXX: make it portable */
3982 char_size
= sizeof(nwchar_t
);
3983 if (tokcstr
.size
<= char_size
)
3984 error("empty character constant");
3985 if (tokcstr
.size
> 2 * char_size
)
3986 warning("multi-character character constant");
3988 tokc
.i
= *(int8_t *)tokcstr
.data
;
3991 tokc
.i
= *(nwchar_t
*)tokcstr
.data
;
3995 tokc
.cstr
= &tokcstr
;
4009 } else if (c
== '<') {
4027 } else if (c
== '>') {
4045 } else if (c
== '=') {
4058 } else if (c
== '=') {
4071 } else if (c
== '=') {
4084 } else if (c
== '=') {
4087 } else if (c
== '>') {
4095 PARSE2('!', '!', '=', TOK_NE
)
4096 PARSE2('=', '=', '=', TOK_EQ
)
4097 PARSE2('*', '*', '=', TOK_A_MUL
)
4098 PARSE2('%', '%', '=', TOK_A_MOD
)
4099 PARSE2('^', '^', '=', TOK_A_XOR
)
4101 /* comments or operator */
4105 p
= parse_comment(p
);
4107 } else if (c
== '/') {
4108 p
= parse_line_comment(p
);
4110 } else if (c
== '=') {
4130 case '$': /* only used in assembler */
4131 case '@': /* dito */
4136 error("unrecognized character \\x%02x", c
);
4142 #if defined(PARSE_DEBUG)
4143 printf("token = %s\n", get_tok_str(tok
, &tokc
));
4147 /* return next token without macro substitution. Can read input from
4149 static void next_nomacro_spc(void)
4155 TOK_GET(tok
, macro_ptr
, tokc
);
4156 if (tok
== TOK_LINENUM
) {
4157 file
->line_num
= tokc
.i
;
4166 static void next_nomacro(void)
4170 } while (is_space(tok
));
4173 /* substitute args in macro_str and return allocated string */
4174 static int *macro_arg_subst(Sym
**nested_list
, int *macro_str
, Sym
*args
)
4176 int *st
, last_tok
, t
, spc
;
4185 TOK_GET(t
, macro_str
, cval
);
4190 TOK_GET(t
, macro_str
, cval
);
4193 s
= sym_find2(args
, t
);
4199 TOK_GET(t
, st
, cval
);
4200 if (!check_space(t
, &spc
))
4201 cstr_cat(&cstr
, get_tok_str(t
, &cval
));
4204 cstr_ccat(&cstr
, '\0');
4206 printf("stringize: %s\n", (char *)cstr
.data
);
4210 tok_str_add2(&str
, TOK_STR
, &cval
);
4213 tok_str_add2(&str
, t
, &cval
);
4215 } else if (t
>= TOK_IDENT
) {
4216 s
= sym_find2(args
, t
);
4219 /* if '##' is present before or after, no arg substitution */
4220 if (*macro_str
== TOK_TWOSHARPS
|| last_tok
== TOK_TWOSHARPS
) {
4221 /* special case for var arg macros : ## eats the
4222 ',' if empty VA_ARGS variable. */
4223 /* XXX: test of the ',' is not 100%
4224 reliable. should fix it to avoid security
4226 if (gnu_ext
&& s
->type
.t
&&
4227 last_tok
== TOK_TWOSHARPS
&&
4228 str
.len
>= 2 && str
.str
[str
.len
- 2] == ',') {
4230 /* suppress ',' '##' */
4233 /* suppress '##' and add variable */
4241 TOK_GET(t1
, st
, cval
);
4244 tok_str_add2(&str
, t1
, &cval
);
4248 /* NOTE: the stream cannot be read when macro
4249 substituing an argument */
4250 macro_subst(&str
, nested_list
, st
, NULL
);
4253 tok_str_add(&str
, t
);
4256 tok_str_add2(&str
, t
, &cval
);
4260 tok_str_add(&str
, 0);
4264 static char const ab_month_name
[12][4] =
4266 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
4267 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
4270 /* do macro substitution of current token with macro 's' and add
4271 result to (tok_str,tok_len). 'nested_list' is the list of all
4272 macros we got inside to avoid recursing. Return non zero if no
4273 substitution needs to be done */
4274 static int macro_subst_tok(TokenString
*tok_str
,
4275 Sym
**nested_list
, Sym
*s
, struct macro_level
**can_read_stream
)
4277 Sym
*args
, *sa
, *sa1
;
4278 int mstr_allocated
, parlevel
, *mstr
, t
, t1
, *p
, spc
;
4285 /* if symbol is a macro, prepare substitution */
4286 /* special macros */
4287 if (tok
== TOK___LINE__
) {
4288 snprintf(buf
, sizeof(buf
), "%d", file
->line_num
);
4292 } else if (tok
== TOK___FILE__
) {
4293 cstrval
= file
->filename
;
4295 } else if (tok
== TOK___DATE__
|| tok
== TOK___TIME__
) {
4300 tm
= localtime(&ti
);
4301 if (tok
== TOK___DATE__
) {
4302 snprintf(buf
, sizeof(buf
), "%s %2d %d",
4303 ab_month_name
[tm
->tm_mon
], tm
->tm_mday
, tm
->tm_year
+ 1900);
4305 snprintf(buf
, sizeof(buf
), "%02d:%02d:%02d",
4306 tm
->tm_hour
, tm
->tm_min
, tm
->tm_sec
);
4313 cstr_cat(&cstr
, cstrval
);
4314 cstr_ccat(&cstr
, '\0');
4316 tok_str_add2(tok_str
, t1
, &cval
);
4321 if (s
->type
.t
== MACRO_FUNC
) {
4322 /* NOTE: we do not use next_nomacro to avoid eating the
4323 next token. XXX: find better solution */
4327 while (is_space(t
= *p
) || TOK_LINEFEED
== t
)
4329 if (t
== 0 && can_read_stream
) {
4330 /* end of macro stream: we must look at the token
4331 after in the file */
4332 struct macro_level
*ml
= *can_read_stream
;
4338 *can_read_stream
= ml
-> prev
;
4343 /* XXX: incorrect with comments */
4344 ch
= file
->buf_ptr
[0];
4345 while (is_space(ch
) || ch
== '\n')
4349 if (t
!= '(') /* no macro subst */
4352 /* argument macro */
4357 /* NOTE: empty args are allowed, except if no args */
4359 /* handle '()' case */
4360 if (!args
&& !sa
&& tok
== ')')
4363 error("macro '%s' used with too many args",
4364 get_tok_str(s
->v
, 0));
4367 /* NOTE: non zero sa->t indicates VA_ARGS */
4368 while ((parlevel
> 0 ||
4370 (tok
!= ',' || sa
->type
.t
))) &&
4374 else if (tok
== ')')
4376 if (tok
== TOK_LINEFEED
)
4378 if (!check_space(tok
, &spc
))
4379 tok_str_add2(&str
, tok
, &tokc
);
4383 tok_str_add(&str
, 0);
4384 sym_push2(&args
, sa
->v
& ~SYM_FIELD
, sa
->type
.t
, (long)str
.str
);
4387 /* special case for gcc var args: add an empty
4388 var arg argument if it is omitted */
4389 if (sa
&& sa
->type
.t
&& gnu_ext
)
4399 error("macro '%s' used with too few args",
4400 get_tok_str(s
->v
, 0));
4403 /* now subst each arg */
4404 mstr
= macro_arg_subst(nested_list
, mstr
, args
);
4409 tok_str_free((int *)sa
->c
);
4415 sym_push2(nested_list
, s
->v
, 0, 0);
4416 macro_subst(tok_str
, nested_list
, mstr
, can_read_stream
);
4417 /* pop nested defined symbol */
4419 *nested_list
= sa1
->prev
;
4427 /* handle the '##' operator. Return NULL if no '##' seen. Otherwise
4428 return the resulting string (which must be freed). */
4429 static inline int *macro_twosharps(const int *macro_str
)
4432 const int *ptr
, *saved_macro_ptr
;
4434 const char *p1
, *p2
;
4436 TokenString macro_str1
;
4439 /* we search the first '##' */
4440 for(ptr
= macro_str
;;) {
4441 TOK_GET(t
, ptr
, cval
);
4442 if (t
== TOK_TWOSHARPS
)
4444 /* nothing more to do if end of string */
4449 /* we saw '##', so we need more processing to handle it */
4451 tok_str_new(¯o_str1
);
4452 saved_macro_ptr
= macro_ptr
;
4453 /* XXX: get rid of the use of macro_ptr here */
4454 macro_ptr
= (int *)macro_str
;
4459 if (tok
== TOK_TWOSHARPS
)
4461 while (*macro_ptr
== TOK_TWOSHARPS
) {
4463 if (t
&& t
!= TOK_TWOSHARPS
) {
4464 TOK_GET(t
, macro_ptr
, cval
);
4465 /* We concatenate the two tokens if we have an
4466 identifier or a preprocessing number */
4468 p1
= get_tok_str(tok
, &tokc
);
4469 cstr_cat(&cstr
, p1
);
4470 p2
= get_tok_str(t
, &cval
);
4471 cstr_cat(&cstr
, p2
);
4472 cstr_ccat(&cstr
, '\0');
4474 if ((tok
>= TOK_IDENT
|| tok
== TOK_PPNUM
) &&
4475 (t
>= TOK_IDENT
|| t
== TOK_PPNUM
)) {
4476 if (tok
== TOK_PPNUM
) {
4477 /* if number, then create a number token */
4478 /* NOTE: no need to allocate because
4479 tok_str_add2() does it */
4480 cstr_reset(&tokcstr
);
4483 tokc
.cstr
= &tokcstr
;
4485 /* if identifier, we must do a test to
4486 validate we have a correct identifier */
4487 if (t
== TOK_PPNUM
) {
4497 if (!isnum(c
) && !isid(c
))
4501 ts
= tok_alloc(cstr
.data
, strlen(cstr
.data
));
4502 tok
= ts
->tok
; /* modify current token */
4505 const char *str
= cstr
.data
;
4506 const unsigned char *q
;
4508 /* we look for a valid token */
4509 /* XXX: do more extensive checks */
4510 if (!strcmp(str
, ">>=")) {
4512 } else if (!strcmp(str
, "<<=")) {
4514 } else if (strlen(str
) == 2) {
4515 /* search in two bytes table */
4520 if (q
[0] == str
[0] && q
[1] == str
[1])
4527 /* NOTE: because get_tok_str use a static buffer,
4530 p1
= get_tok_str(tok
, &tokc
);
4531 cstr_cat(&cstr
, p1
);
4532 cstr_ccat(&cstr
, '\0');
4533 p2
= get_tok_str(t
, &cval
);
4534 warning("pasting \"%s\" and \"%s\" does not give a valid preprocessing token", cstr
.data
, p2
);
4535 /* cannot merge tokens: just add them separately */
4536 tok_str_add2(¯o_str1
, tok
, &tokc
);
4537 /* XXX: free associated memory ? */
4544 tok_str_add2(¯o_str1
, tok
, &tokc
);
4546 macro_ptr
= (int *)saved_macro_ptr
;
4548 tok_str_add(¯o_str1
, 0);
4549 return macro_str1
.str
;
4553 /* do macro substitution of macro_str and add result to
4554 (tok_str,tok_len). 'nested_list' is the list of all macros we got
4555 inside to avoid recursing. */
4556 static void macro_subst(TokenString
*tok_str
, Sym
**nested_list
,
4557 const int *macro_str
, struct macro_level
** can_read_stream
)
4564 struct macro_level ml
;
4566 /* first scan for '##' operator handling */
4568 macro_str1
= macro_twosharps(ptr
);
4573 /* NOTE: ptr == NULL can only happen if tokens are read from
4574 file stream due to a macro function call */
4577 TOK_GET(t
, ptr
, cval
);
4582 /* if nested substitution, do nothing */
4583 if (sym_find2(*nested_list
, t
))
4586 if (can_read_stream
)
4587 ml
.prev
= *can_read_stream
, *can_read_stream
= &ml
;
4588 macro_ptr
= (int *)ptr
;
4590 ret
= macro_subst_tok(tok_str
, nested_list
, s
, can_read_stream
);
4591 ptr
= (int *)macro_ptr
;
4593 if (can_read_stream
&& *can_read_stream
== &ml
)
4594 *can_read_stream
= ml
.prev
;
4599 if (!check_space(t
, &spc
))
4600 tok_str_add2(tok_str
, t
, &cval
);
4604 tok_str_free(macro_str1
);
4607 /* return next token with macro substitution */
4608 static void next(void)
4610 Sym
*nested_list
, *s
;
4612 struct macro_level
*ml
;
4615 if (parse_flags
& PARSE_FLAG_SPACES
)
4620 /* if not reading from macro substituted string, then try
4621 to substitute macros */
4622 if (tok
>= TOK_IDENT
&&
4623 (parse_flags
& PARSE_FLAG_PREPROCESS
)) {
4624 s
= define_find(tok
);
4626 /* we have a macro: we try to substitute */
4630 if (macro_subst_tok(&str
, &nested_list
, s
, &ml
) == 0) {
4631 /* substitution done, NOTE: maybe empty */
4632 tok_str_add(&str
, 0);
4633 macro_ptr
= str
.str
;
4634 macro_ptr_allocated
= str
.str
;
4641 /* end of macro or end of unget buffer */
4642 if (unget_buffer_enabled
) {
4643 macro_ptr
= unget_saved_macro_ptr
;
4644 unget_buffer_enabled
= 0;
4646 /* end of macro string: free it */
4647 tok_str_free(macro_ptr_allocated
);
4654 /* convert preprocessor tokens into C tokens */
4655 if (tok
== TOK_PPNUM
&&
4656 (parse_flags
& PARSE_FLAG_TOK_NUM
)) {
4657 parse_number((char *)tokc
.cstr
->data
);
4661 /* push back current token and set current token to 'last_tok'. Only
4662 identifier case handled for labels. */
4663 static inline void unget_tok(int last_tok
)
4667 unget_saved_macro_ptr
= macro_ptr
;
4668 unget_buffer_enabled
= 1;
4669 q
= unget_saved_buffer
;
4672 n
= tok_ext_size(tok
) - 1;
4675 *q
= 0; /* end of token string */
4680 void swap(int *p
, int *q
)
4688 void vsetc(CType
*type
, int r
, CValue
*vc
)
4692 if (vtop
>= vstack
+ (VSTACK_SIZE
- 1))
4693 error("memory full");
4694 /* cannot let cpu flags if other instruction are generated. Also
4695 avoid leaving VT_JMP anywhere except on the top of the stack
4696 because it would complicate the code generator. */
4697 if (vtop
>= vstack
) {
4698 v
= vtop
->r
& VT_VALMASK
;
4699 if (v
== VT_CMP
|| (v
& ~1) == VT_JMP
)
4705 vtop
->r2
= VT_CONST
;
4709 /* push integer constant */
4714 vsetc(&int_type
, VT_CONST
, &cval
);
4717 /* push long long constant */
4718 void vpushll(long long v
)
4724 vsetc(&ctype
, VT_CONST
, &cval
);
4727 /* Return a static symbol pointing to a section */
4728 static Sym
*get_sym_ref(CType
*type
, Section
*sec
,
4729 unsigned long offset
, unsigned long size
)
4735 sym
= global_identifier_push(v
, type
->t
| VT_STATIC
, 0);
4736 sym
->type
.ref
= type
->ref
;
4737 sym
->r
= VT_CONST
| VT_SYM
;
4738 put_extern_sym(sym
, sec
, offset
, size
);
4742 /* push a reference to a section offset by adding a dummy symbol */
4743 static void vpush_ref(CType
*type
, Section
*sec
, unsigned long offset
, unsigned long size
)
4748 vsetc(type
, VT_CONST
| VT_SYM
, &cval
);
4749 vtop
->sym
= get_sym_ref(type
, sec
, offset
, size
);
4752 /* define a new external reference to a symbol 'v' of type 'u' */
4753 static Sym
*external_global_sym(int v
, CType
*type
, int r
)
4759 /* push forward reference */
4760 s
= global_identifier_push(v
, type
->t
| VT_EXTERN
, 0);
4761 s
->type
.ref
= type
->ref
;
4762 s
->r
= r
| VT_CONST
| VT_SYM
;
4767 /* define a new external reference to a symbol 'v' of type 'u' */
4768 static Sym
*external_sym(int v
, CType
*type
, int r
)
4774 /* push forward reference */
4775 s
= sym_push(v
, type
, r
| VT_CONST
| VT_SYM
, 0);
4776 s
->type
.t
|= VT_EXTERN
;
4778 if (!is_compatible_types(&s
->type
, type
))
4779 error("incompatible types for redefinition of '%s'",
4780 get_tok_str(v
, NULL
));
4785 /* push a reference to global symbol v */
4786 static void vpush_global_sym(CType
*type
, int v
)
4791 sym
= external_global_sym(v
, type
, 0);
4793 vsetc(type
, VT_CONST
| VT_SYM
, &cval
);
4797 void vset(CType
*type
, int r
, int v
)
4802 vsetc(type
, r
, &cval
);
4805 void vseti(int r
, int v
)
4821 void vpushv(SValue
*v
)
4823 if (vtop
>= vstack
+ (VSTACK_SIZE
- 1))
4824 error("memory full");
4834 /* save r to the memory stack, and mark it as being free */
4835 void save_reg(int r
)
4837 int l
, saved
, size
, align
;
4841 /* modify all stack values */
4844 for(p
=vstack
;p
<=vtop
;p
++) {
4845 if ((p
->r
& VT_VALMASK
) == r
||
4846 ((p
->type
.t
& VT_BTYPE
) == VT_LLONG
&& (p
->r2
& VT_VALMASK
) == r
)) {
4847 /* must save value on stack if not already done */
4849 /* NOTE: must reload 'r' because r might be equal to r2 */
4850 r
= p
->r
& VT_VALMASK
;
4851 /* store register in the stack */
4853 if ((p
->r
& VT_LVAL
) ||
4854 (!is_float(type
->t
) && (type
->t
& VT_BTYPE
) != VT_LLONG
))
4855 #ifdef TCC_TARGET_X86_64
4856 type
= &char_pointer_type
;
4860 size
= type_size(type
, &align
);
4861 loc
= (loc
- size
) & -align
;
4862 sv
.type
.t
= type
->t
;
4863 sv
.r
= VT_LOCAL
| VT_LVAL
;
4866 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
4867 /* x86 specific: need to pop fp register ST0 if saved */
4868 if (r
== TREG_ST0
) {
4869 o(0xd9dd); /* fstp %st(1) */
4872 #ifndef TCC_TARGET_X86_64
4873 /* special long long case */
4874 if ((type
->t
& VT_BTYPE
) == VT_LLONG
) {
4882 /* mark that stack entry as being saved on the stack */
4883 if (p
->r
& VT_LVAL
) {
4884 /* also clear the bounded flag because the
4885 relocation address of the function was stored in
4887 p
->r
= (p
->r
& ~(VT_VALMASK
| VT_BOUNDED
)) | VT_LLOCAL
;
4889 p
->r
= lvalue_type(p
->type
.t
) | VT_LOCAL
;
4897 /* find a register of class 'rc2' with at most one reference on stack.
4898 * If none, call get_reg(rc) */
4899 int get_reg_ex(int rc
, int rc2
)
4904 for(r
=0;r
<NB_REGS
;r
++) {
4905 if (reg_classes
[r
] & rc2
) {
4908 for(p
= vstack
; p
<= vtop
; p
++) {
4909 if ((p
->r
& VT_VALMASK
) == r
||
4910 (p
->r2
& VT_VALMASK
) == r
)
4920 /* find a free register of class 'rc'. If none, save one register */
4926 /* find a free register */
4927 for(r
=0;r
<NB_REGS
;r
++) {
4928 if (reg_classes
[r
] & rc
) {
4929 for(p
=vstack
;p
<=vtop
;p
++) {
4930 if ((p
->r
& VT_VALMASK
) == r
||
4931 (p
->r2
& VT_VALMASK
) == r
)
4939 /* no register left : free the first one on the stack (VERY
4940 IMPORTANT to start from the bottom to ensure that we don't
4941 spill registers used in gen_opi()) */
4942 for(p
=vstack
;p
<=vtop
;p
++) {
4943 r
= p
->r
& VT_VALMASK
;
4944 if (r
< VT_CONST
&& (reg_classes
[r
] & rc
))
4946 /* also look at second register (if long long) */
4947 r
= p
->r2
& VT_VALMASK
;
4948 if (r
< VT_CONST
&& (reg_classes
[r
] & rc
)) {
4954 /* Should never comes here */
4958 /* save registers up to (vtop - n) stack entry */
4959 void save_regs(int n
)
4964 for(p
= vstack
;p
<= p1
; p
++) {
4965 r
= p
->r
& VT_VALMASK
;
4972 /* move register 's' to 'r', and flush previous value of r to memory
4974 void move_reg(int r
, int s
)
4987 /* get address of vtop (vtop MUST BE an lvalue) */
4990 vtop
->r
&= ~VT_LVAL
;
4991 /* tricky: if saved lvalue, then we can go back to lvalue */
4992 if ((vtop
->r
& VT_VALMASK
) == VT_LLOCAL
)
4993 vtop
->r
= (vtop
->r
& ~(VT_VALMASK
| VT_LVAL_TYPE
)) | VT_LOCAL
| VT_LVAL
;
4996 #ifdef CONFIG_TCC_BCHECK
4997 /* generate lvalue bound code */
5003 vtop
->r
&= ~VT_MUSTBOUND
;
5004 /* if lvalue, then use checking code before dereferencing */
5005 if (vtop
->r
& VT_LVAL
) {
5006 /* if not VT_BOUNDED value, then make one */
5007 if (!(vtop
->r
& VT_BOUNDED
)) {
5008 lval_type
= vtop
->r
& (VT_LVAL_TYPE
| VT_LVAL
);
5009 /* must save type because we must set it to int to get pointer */
5011 vtop
->type
.t
= VT_INT
;
5014 gen_bounded_ptr_add();
5015 vtop
->r
|= lval_type
;
5018 /* then check for dereferencing */
5019 gen_bounded_ptr_deref();
5024 /* store vtop a register belonging to class 'rc'. lvalues are
5025 converted to values. Cannot be used if cannot be converted to
5026 register value (such as structures). */
5029 int r
, rc2
, bit_pos
, bit_size
, size
, align
, i
;
5031 /* NOTE: get_reg can modify vstack[] */
5032 if (vtop
->type
.t
& VT_BITFIELD
) {
5035 bit_pos
= (vtop
->type
.t
>> VT_STRUCT_SHIFT
) & 0x3f;
5036 bit_size
= (vtop
->type
.t
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f;
5037 /* remove bit field info to avoid loops */
5038 vtop
->type
.t
&= ~(VT_BITFIELD
| (-1 << VT_STRUCT_SHIFT
));
5039 /* cast to int to propagate signedness in following ops */
5040 if ((vtop
->type
.t
& VT_BTYPE
) == VT_LLONG
) {
5045 if((vtop
->type
.t
& VT_UNSIGNED
) ||
5046 (vtop
->type
.t
& VT_BTYPE
) == VT_BOOL
)
5047 type
.t
|= VT_UNSIGNED
;
5049 /* generate shifts */
5050 vpushi(bits
- (bit_pos
+ bit_size
));
5052 vpushi(bits
- bit_size
);
5053 /* NOTE: transformed to SHR if unsigned */
5057 if (is_float(vtop
->type
.t
) &&
5058 (vtop
->r
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
) {
5061 unsigned long offset
;
5062 #if defined(TCC_TARGET_ARM) && !defined(TCC_ARM_VFP)
5066 /* XXX: unify with initializers handling ? */
5067 /* CPUs usually cannot use float constants, so we store them
5068 generically in data segment */
5069 size
= type_size(&vtop
->type
, &align
);
5070 offset
= (data_section
->data_offset
+ align
- 1) & -align
;
5071 data_section
->data_offset
= offset
;
5072 /* XXX: not portable yet */
5073 #if defined(__i386__) || defined(__x86_64__)
5074 /* Zero pad x87 tenbyte long doubles */
5075 if (size
== LDOUBLE_SIZE
)
5076 vtop
->c
.tab
[2] &= 0xffff;
5078 ptr
= section_ptr_add(data_section
, size
);
5080 #if defined(TCC_TARGET_ARM) && !defined(TCC_ARM_VFP)
5084 ptr
[i
] = vtop
->c
.tab
[size
-1-i
];
5088 ptr
[i
] = vtop
->c
.tab
[i
];
5089 sym
= get_sym_ref(&vtop
->type
, data_section
, offset
, size
<< 2);
5090 vtop
->r
|= VT_LVAL
| VT_SYM
;
5094 #ifdef CONFIG_TCC_BCHECK
5095 if (vtop
->r
& VT_MUSTBOUND
)
5099 r
= vtop
->r
& VT_VALMASK
;
5103 /* need to reload if:
5105 - lvalue (need to dereference pointer)
5106 - already a register, but not in the right class */
5107 if (r
>= VT_CONST
||
5108 (vtop
->r
& VT_LVAL
) ||
5109 !(reg_classes
[r
] & rc
) ||
5110 ((vtop
->type
.t
& VT_BTYPE
) == VT_LLONG
&&
5111 !(reg_classes
[vtop
->r2
] & rc2
))) {
5113 #ifndef TCC_TARGET_X86_64
5114 if ((vtop
->type
.t
& VT_BTYPE
) == VT_LLONG
) {
5116 unsigned long long ll
;
5117 /* two register type load : expand to two words
5119 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
) {
5122 vtop
->c
.ui
= ll
; /* first word */
5124 vtop
->r
= r
; /* save register value */
5125 vpushi(ll
>> 32); /* second word */
5126 } else if (r
>= VT_CONST
|| /* XXX: test to VT_CONST incorrect ? */
5127 (vtop
->r
& VT_LVAL
)) {
5128 /* We do not want to modifier the long long
5129 pointer here, so the safest (and less
5130 efficient) is to save all the other registers
5131 in the stack. XXX: totally inefficient. */
5133 /* load from memory */
5136 vtop
[-1].r
= r
; /* save register value */
5137 /* increment pointer to get second word */
5138 vtop
->type
.t
= VT_INT
;
5144 /* move registers */
5147 vtop
[-1].r
= r
; /* save register value */
5148 vtop
->r
= vtop
[-1].r2
;
5150 /* allocate second register */
5154 /* write second register */
5158 if ((vtop
->r
& VT_LVAL
) && !is_float(vtop
->type
.t
)) {
5160 /* lvalue of scalar type : need to use lvalue type
5161 because of possible cast */
5164 /* compute memory access type */
5165 if (vtop
->r
& VT_LVAL_BYTE
)
5167 else if (vtop
->r
& VT_LVAL_SHORT
)
5169 if (vtop
->r
& VT_LVAL_UNSIGNED
)
5173 /* restore wanted type */
5176 /* one register type load */
5181 #ifdef TCC_TARGET_C67
5182 /* uses register pairs for doubles */
5183 if ((vtop
->type
.t
& VT_BTYPE
) == VT_DOUBLE
)
5190 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
5191 void gv2(int rc1
, int rc2
)
5195 /* generate more generic register first. But VT_JMP or VT_CMP
5196 values must be generated first in all cases to avoid possible
5198 v
= vtop
[0].r
& VT_VALMASK
;
5199 if (v
!= VT_CMP
&& (v
& ~1) != VT_JMP
&& rc1
<= rc2
) {
5204 /* test if reload is needed for first register */
5205 if ((vtop
[-1].r
& VT_VALMASK
) >= VT_CONST
) {
5215 /* test if reload is needed for first register */
5216 if ((vtop
[0].r
& VT_VALMASK
) >= VT_CONST
) {
5222 /* wrapper around RC_FRET to return a register by type */
5225 #ifdef TCC_TARGET_X86_64
5226 if (t
== VT_LDOUBLE
) {
5233 /* wrapper around REG_FRET to return a register by type */
5236 #ifdef TCC_TARGET_X86_64
5237 if (t
== VT_LDOUBLE
) {
5244 /* expand long long on stack in two int registers */
5249 u
= vtop
->type
.t
& VT_UNSIGNED
;
5252 vtop
[0].r
= vtop
[-1].r2
;
5253 vtop
[0].r2
= VT_CONST
;
5254 vtop
[-1].r2
= VT_CONST
;
5255 vtop
[0].type
.t
= VT_INT
| u
;
5256 vtop
[-1].type
.t
= VT_INT
| u
;
5259 #ifdef TCC_TARGET_ARM
5260 /* expand long long on stack */
5261 void lexpand_nr(void)
5265 u
= vtop
->type
.t
& VT_UNSIGNED
;
5267 vtop
->r2
= VT_CONST
;
5268 vtop
->type
.t
= VT_INT
| u
;
5269 v
=vtop
[-1].r
& (VT_VALMASK
| VT_LVAL
);
5270 if (v
== VT_CONST
) {
5271 vtop
[-1].c
.ui
= vtop
->c
.ull
;
5272 vtop
->c
.ui
= vtop
->c
.ull
>> 32;
5274 } else if (v
== (VT_LVAL
|VT_CONST
) || v
== (VT_LVAL
|VT_LOCAL
)) {
5276 vtop
->r
= vtop
[-1].r
;
5277 } else if (v
> VT_CONST
) {
5281 vtop
->r
= vtop
[-1].r2
;
5282 vtop
[-1].r2
= VT_CONST
;
5283 vtop
[-1].type
.t
= VT_INT
| u
;
5287 /* build a long long from two ints */
5290 gv2(RC_INT
, RC_INT
);
5291 vtop
[-1].r2
= vtop
[0].r
;
5292 vtop
[-1].type
.t
= t
;
5296 /* rotate n first stack elements to the bottom
5297 I1 ... In -> I2 ... In I1 [top is right]
5305 for(i
=-n
+1;i
!=0;i
++)
5306 vtop
[i
] = vtop
[i
+1];
5310 /* rotate n first stack elements to the top
5311 I1 ... In -> In I1 ... I(n-1) [top is right]
5319 for(i
= 0;i
< n
- 1; i
++)
5320 vtop
[-i
] = vtop
[-i
- 1];
5324 #ifdef TCC_TARGET_ARM
5325 /* like vrott but in other direction
5326 In ... I1 -> I(n-1) ... I1 In [top is right]
5334 for(i
= n
- 1; i
> 0; i
--)
5335 vtop
[-i
] = vtop
[-i
+ 1];
5340 /* pop stack value */
5344 v
= vtop
->r
& VT_VALMASK
;
5345 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
5346 /* for x86, we need to pop the FP stack */
5347 if (v
== TREG_ST0
&& !nocode_wanted
) {
5348 o(0xd9dd); /* fstp %st(1) */
5351 if (v
== VT_JMP
|| v
== VT_JMPI
) {
5352 /* need to put correct jump if && or || without test */
5358 /* convert stack entry to register and duplicate its value in another
5366 if ((t
& VT_BTYPE
) == VT_LLONG
) {
5373 /* stack: H L L1 H1 */
5381 /* duplicate value */
5386 #ifdef TCC_TARGET_X86_64
5387 if ((t
& VT_BTYPE
) == VT_LDOUBLE
) {
5397 load(r1
, &sv
); /* move r to r1 */
5399 /* duplicates value */
5404 #ifndef TCC_TARGET_X86_64
5405 /* generate CPU independent (unsigned) long long operations */
5406 void gen_opl(int op
)
5408 int t
, a
, b
, op1
, c
, i
;
5410 unsigned short reg_iret
= REG_IRET
;
5411 unsigned short reg_lret
= REG_LRET
;
5417 func
= TOK___divdi3
;
5420 func
= TOK___udivdi3
;
5423 func
= TOK___moddi3
;
5426 func
= TOK___umoddi3
;
5433 /* call generic long long function */
5434 vpush_global_sym(&func_old_type
, func
);
5439 vtop
->r2
= reg_lret
;
5452 /* stack: L1 H1 L2 H2 */
5457 vtop
[-2] = vtop
[-3];
5460 /* stack: H1 H2 L1 L2 */
5466 /* stack: H1 H2 L1 L2 ML MH */
5469 /* stack: ML MH H1 H2 L1 L2 */
5473 /* stack: ML MH H1 L2 H2 L1 */
5478 /* stack: ML MH M1 M2 */
5481 } else if (op
== '+' || op
== '-') {
5482 /* XXX: add non carry method too (for MIPS or alpha) */
5488 /* stack: H1 H2 (L1 op L2) */
5491 gen_op(op1
+ 1); /* TOK_xxxC2 */
5494 /* stack: H1 H2 (L1 op L2) */
5497 /* stack: (L1 op L2) H1 H2 */
5499 /* stack: (L1 op L2) (H1 op H2) */
5507 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
) {
5508 t
= vtop
[-1].type
.t
;
5512 /* stack: L H shift */
5514 /* constant: simpler */
5515 /* NOTE: all comments are for SHL. the other cases are
5516 done by swaping words */
5527 if (op
!= TOK_SAR
) {
5560 /* XXX: should provide a faster fallback on x86 ? */
5563 func
= TOK___ashrdi3
;
5566 func
= TOK___lshrdi3
;
5569 func
= TOK___ashldi3
;
5575 /* compare operations */
5581 /* stack: L1 H1 L2 H2 */
5583 vtop
[-1] = vtop
[-2];
5585 /* stack: L1 L2 H1 H2 */
5588 /* when values are equal, we need to compare low words. since
5589 the jump is inverted, we invert the test too. */
5592 else if (op1
== TOK_GT
)
5594 else if (op1
== TOK_ULT
)
5596 else if (op1
== TOK_UGT
)
5601 if (op1
!= TOK_NE
) {
5605 /* generate non equal test */
5606 /* XXX: NOT PORTABLE yet */
5610 #if defined(TCC_TARGET_I386)
5611 b
= psym(0x850f, 0);
5612 #elif defined(TCC_TARGET_ARM)
5614 o(0x1A000000 | encbranch(ind
, 0, 1));
5615 #elif defined(TCC_TARGET_C67)
5616 error("not implemented");
5618 #error not supported
5622 /* compare low. Always unsigned */
5626 else if (op1
== TOK_LE
)
5628 else if (op1
== TOK_GT
)
5630 else if (op1
== TOK_GE
)
5641 /* handle integer constant optimizations and various machine
5643 void gen_opic(int op
)
5645 int c1
, c2
, t1
, t2
, n
;
5648 typedef unsigned long long U
;
5652 t1
= v1
->type
.t
& VT_BTYPE
;
5653 t2
= v2
->type
.t
& VT_BTYPE
;
5657 else if (v1
->type
.t
& VT_UNSIGNED
)
5664 else if (v2
->type
.t
& VT_UNSIGNED
)
5669 /* currently, we cannot do computations with forward symbols */
5670 c1
= (v1
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
5671 c2
= (v2
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
5674 case '+': l1
+= l2
; break;
5675 case '-': l1
-= l2
; break;
5676 case '&': l1
&= l2
; break;
5677 case '^': l1
^= l2
; break;
5678 case '|': l1
|= l2
; break;
5679 case '*': l1
*= l2
; break;
5686 /* if division by zero, generate explicit division */
5689 error("division by zero in constant");
5693 default: l1
/= l2
; break;
5694 case '%': l1
%= l2
; break;
5695 case TOK_UDIV
: l1
= (U
)l1
/ l2
; break;
5696 case TOK_UMOD
: l1
= (U
)l1
% l2
; break;
5699 case TOK_SHL
: l1
<<= l2
; break;
5700 case TOK_SHR
: l1
= (U
)l1
>> l2
; break;
5701 case TOK_SAR
: l1
>>= l2
; break;
5703 case TOK_ULT
: l1
= (U
)l1
< (U
)l2
; break;
5704 case TOK_UGE
: l1
= (U
)l1
>= (U
)l2
; break;
5705 case TOK_EQ
: l1
= l1
== l2
; break;
5706 case TOK_NE
: l1
= l1
!= l2
; break;
5707 case TOK_ULE
: l1
= (U
)l1
<= (U
)l2
; break;
5708 case TOK_UGT
: l1
= (U
)l1
> (U
)l2
; break;
5709 case TOK_LT
: l1
= l1
< l2
; break;
5710 case TOK_GE
: l1
= l1
>= l2
; break;
5711 case TOK_LE
: l1
= l1
<= l2
; break;
5712 case TOK_GT
: l1
= l1
> l2
; break;
5714 case TOK_LAND
: l1
= l1
&& l2
; break;
5715 case TOK_LOR
: l1
= l1
|| l2
; break;
5722 /* if commutative ops, put c2 as constant */
5723 if (c1
&& (op
== '+' || op
== '&' || op
== '^' ||
5724 op
== '|' || op
== '*')) {
5726 c2
= c1
; //c = c1, c1 = c2, c2 = c;
5727 l2
= l1
; //l = l1, l1 = l2, l2 = l;
5729 /* Filter out NOP operations like x*1, x-0, x&-1... */
5730 if (c2
&& (((op
== '*' || op
== '/' || op
== TOK_UDIV
||
5733 ((op
== '+' || op
== '-' || op
== '|' || op
== '^' ||
5734 op
== TOK_SHL
|| op
== TOK_SHR
|| op
== TOK_SAR
) &&
5740 } else if (c2
&& (op
== '*' || op
== TOK_PDIV
|| op
== TOK_UDIV
)) {
5741 /* try to use shifts instead of muls or divs */
5742 if (l2
> 0 && (l2
& (l2
- 1)) == 0) {
5751 else if (op
== TOK_PDIV
)
5757 } else if (c2
&& (op
== '+' || op
== '-') &&
5758 ((vtop
[-1].r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) ==
5759 (VT_CONST
| VT_SYM
) ||
5760 (vtop
[-1].r
& (VT_VALMASK
| VT_LVAL
)) == VT_LOCAL
)) {
5761 /* symbol + constant case */
5768 if (!nocode_wanted
) {
5769 /* call low level op generator */
5770 if (t1
== VT_LLONG
|| t2
== VT_LLONG
)
5781 /* generate a floating point operation with constant propagation */
5782 void gen_opif(int op
)
5790 /* currently, we cannot do computations with forward symbols */
5791 c1
= (v1
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
5792 c2
= (v2
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
5794 if (v1
->type
.t
== VT_FLOAT
) {
5797 } else if (v1
->type
.t
== VT_DOUBLE
) {
5805 /* NOTE: we only do constant propagation if finite number (not
5806 NaN or infinity) (ANSI spec) */
5807 if (!ieee_finite(f1
) || !ieee_finite(f2
))
5811 case '+': f1
+= f2
; break;
5812 case '-': f1
-= f2
; break;
5813 case '*': f1
*= f2
; break;
5817 error("division by zero in constant");
5822 /* XXX: also handles tests ? */
5826 /* XXX: overflow test ? */
5827 if (v1
->type
.t
== VT_FLOAT
) {
5829 } else if (v1
->type
.t
== VT_DOUBLE
) {
5837 if (!nocode_wanted
) {
5845 static int pointed_size(CType
*type
)
5848 return type_size(pointed_type(type
), &align
);
5851 static inline int is_null_pointer(SValue
*p
)
5853 if ((p
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) != VT_CONST
)
5855 return ((p
->type
.t
& VT_BTYPE
) == VT_INT
&& p
->c
.i
== 0) ||
5856 ((p
->type
.t
& VT_BTYPE
) == VT_LLONG
&& p
->c
.ll
== 0);
5859 static inline int is_integer_btype(int bt
)
5861 return (bt
== VT_BYTE
|| bt
== VT_SHORT
||
5862 bt
== VT_INT
|| bt
== VT_LLONG
);
5865 /* check types for comparison or substraction of pointers */
5866 static void check_comparison_pointer_types(SValue
*p1
, SValue
*p2
, int op
)
5868 CType
*type1
, *type2
, tmp_type1
, tmp_type2
;
5871 /* null pointers are accepted for all comparisons as gcc */
5872 if (is_null_pointer(p1
) || is_null_pointer(p2
))
5876 bt1
= type1
->t
& VT_BTYPE
;
5877 bt2
= type2
->t
& VT_BTYPE
;
5878 /* accept comparison between pointer and integer with a warning */
5879 if ((is_integer_btype(bt1
) || is_integer_btype(bt2
)) && op
!= '-') {
5880 if (op
!= TOK_LOR
&& op
!= TOK_LAND
)
5881 warning("comparison between pointer and integer");
5885 /* both must be pointers or implicit function pointers */
5886 if (bt1
== VT_PTR
) {
5887 type1
= pointed_type(type1
);
5888 } else if (bt1
!= VT_FUNC
)
5889 goto invalid_operands
;
5891 if (bt2
== VT_PTR
) {
5892 type2
= pointed_type(type2
);
5893 } else if (bt2
!= VT_FUNC
) {
5895 error("invalid operands to binary %s", get_tok_str(op
, NULL
));
5897 if ((type1
->t
& VT_BTYPE
) == VT_VOID
||
5898 (type2
->t
& VT_BTYPE
) == VT_VOID
)
5902 tmp_type1
.t
&= ~(VT_UNSIGNED
| VT_CONSTANT
| VT_VOLATILE
);
5903 tmp_type2
.t
&= ~(VT_UNSIGNED
| VT_CONSTANT
| VT_VOLATILE
);
5904 if (!is_compatible_types(&tmp_type1
, &tmp_type2
)) {
5905 /* gcc-like error if '-' is used */
5907 goto invalid_operands
;
5909 warning("comparison of distinct pointer types lacks a cast");
5913 /* generic gen_op: handles types problems */
5916 int u
, t1
, t2
, bt1
, bt2
, t
;
5919 t1
= vtop
[-1].type
.t
;
5920 t2
= vtop
[0].type
.t
;
5921 bt1
= t1
& VT_BTYPE
;
5922 bt2
= t2
& VT_BTYPE
;
5924 if (bt1
== VT_PTR
|| bt2
== VT_PTR
) {
5925 /* at least one operand is a pointer */
5926 /* relationnal op: must be both pointers */
5927 if (op
>= TOK_ULT
&& op
<= TOK_LOR
) {
5928 check_comparison_pointer_types(vtop
- 1, vtop
, op
);
5929 /* pointers are handled are unsigned */
5930 #ifdef TCC_TARGET_X86_64
5931 t
= VT_LLONG
| VT_UNSIGNED
;
5933 t
= VT_INT
| VT_UNSIGNED
;
5937 /* if both pointers, then it must be the '-' op */
5938 if (bt1
== VT_PTR
&& bt2
== VT_PTR
) {
5940 error("cannot use pointers here");
5941 check_comparison_pointer_types(vtop
- 1, vtop
, op
);
5942 /* XXX: check that types are compatible */
5943 u
= pointed_size(&vtop
[-1].type
);
5945 /* set to integer type */
5946 #ifdef TCC_TARGET_X86_64
5947 vtop
->type
.t
= VT_LLONG
;
5949 vtop
->type
.t
= VT_INT
;
5954 /* exactly one pointer : must be '+' or '-'. */
5955 if (op
!= '-' && op
!= '+')
5956 error("cannot use pointers here");
5957 /* Put pointer as first operand */
5958 if (bt2
== VT_PTR
) {
5962 type1
= vtop
[-1].type
;
5963 #ifdef TCC_TARGET_X86_64
5964 vpushll(pointed_size(&vtop
[-1].type
));
5966 /* XXX: cast to int ? (long long case) */
5967 vpushi(pointed_size(&vtop
[-1].type
));
5970 #ifdef CONFIG_TCC_BCHECK
5971 /* if evaluating constant expression, no code should be
5972 generated, so no bound check */
5973 if (do_bounds_check
&& !const_wanted
) {
5974 /* if bounded pointers, we generate a special code to
5981 gen_bounded_ptr_add();
5987 /* put again type if gen_opic() swaped operands */
5990 } else if (is_float(bt1
) || is_float(bt2
)) {
5991 /* compute bigger type and do implicit casts */
5992 if (bt1
== VT_LDOUBLE
|| bt2
== VT_LDOUBLE
) {
5994 } else if (bt1
== VT_DOUBLE
|| bt2
== VT_DOUBLE
) {
5999 /* floats can only be used for a few operations */
6000 if (op
!= '+' && op
!= '-' && op
!= '*' && op
!= '/' &&
6001 (op
< TOK_ULT
|| op
> TOK_GT
))
6002 error("invalid operands for binary operation");
6004 } else if (bt1
== VT_LLONG
|| bt2
== VT_LLONG
) {
6005 /* cast to biggest op */
6007 /* convert to unsigned if it does not fit in a long long */
6008 if ((t1
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_LLONG
| VT_UNSIGNED
) ||
6009 (t2
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_LLONG
| VT_UNSIGNED
))
6013 /* integer operations */
6015 /* convert to unsigned if it does not fit in an integer */
6016 if ((t1
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
) ||
6017 (t2
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
))
6020 /* XXX: currently, some unsigned operations are explicit, so
6021 we modify them here */
6022 if (t
& VT_UNSIGNED
) {
6029 else if (op
== TOK_LT
)
6031 else if (op
== TOK_GT
)
6033 else if (op
== TOK_LE
)
6035 else if (op
== TOK_GE
)
6042 /* special case for shifts and long long: we keep the shift as
6044 if (op
== TOK_SHR
|| op
== TOK_SAR
|| op
== TOK_SHL
)
6051 if (op
>= TOK_ULT
&& op
<= TOK_GT
) {
6052 /* relationnal op: the result is an int */
6053 vtop
->type
.t
= VT_INT
;
6060 #ifndef TCC_TARGET_ARM
6061 /* generic itof for unsigned long long case */
6062 void gen_cvt_itof1(int t
)
6064 if ((vtop
->type
.t
& (VT_BTYPE
| VT_UNSIGNED
)) ==
6065 (VT_LLONG
| VT_UNSIGNED
)) {
6068 vpush_global_sym(&func_old_type
, TOK___floatundisf
);
6069 #if LDOUBLE_SIZE != 8
6070 else if (t
== VT_LDOUBLE
)
6071 vpush_global_sym(&func_old_type
, TOK___floatundixf
);
6074 vpush_global_sym(&func_old_type
, TOK___floatundidf
);
6078 vtop
->r
= reg_fret(t
);
6085 /* generic ftoi for unsigned long long case */
6086 void gen_cvt_ftoi1(int t
)
6090 if (t
== (VT_LLONG
| VT_UNSIGNED
)) {
6091 /* not handled natively */
6092 st
= vtop
->type
.t
& VT_BTYPE
;
6094 vpush_global_sym(&func_old_type
, TOK___fixunssfdi
);
6095 #if LDOUBLE_SIZE != 8
6096 else if (st
== VT_LDOUBLE
)
6097 vpush_global_sym(&func_old_type
, TOK___fixunsxfdi
);
6100 vpush_global_sym(&func_old_type
, TOK___fixunsdfdi
);
6105 vtop
->r2
= REG_LRET
;
6111 /* force char or short cast */
6112 void force_charshort_cast(int t
)
6116 /* XXX: add optimization if lvalue : just change type and offset */
6121 if (t
& VT_UNSIGNED
) {
6122 vpushi((1 << bits
) - 1);
6128 /* result must be signed or the SAR is converted to an SHL
6129 This was not the case when "t" was a signed short
6130 and the last value on the stack was an unsigned int */
6131 vtop
->type
.t
&= ~VT_UNSIGNED
;
6137 /* cast 'vtop' to 'type'. Casting to bitfields is forbidden. */
6138 static void gen_cast(CType
*type
)
6140 int sbt
, dbt
, sf
, df
, c
, p
;
6142 /* special delayed cast for char/short */
6143 /* XXX: in some cases (multiple cascaded casts), it may still
6145 if (vtop
->r
& VT_MUSTCAST
) {
6146 vtop
->r
&= ~VT_MUSTCAST
;
6147 force_charshort_cast(vtop
->type
.t
);
6150 /* bitfields first get cast to ints */
6151 if (vtop
->type
.t
& VT_BITFIELD
) {
6155 dbt
= type
->t
& (VT_BTYPE
| VT_UNSIGNED
);
6156 sbt
= vtop
->type
.t
& (VT_BTYPE
| VT_UNSIGNED
);
6161 c
= (vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
6162 p
= (vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == (VT_CONST
| VT_SYM
);
6164 /* constant case: we can do it now */
6165 /* XXX: in ISOC, cannot do it if error in convert */
6166 if (sbt
== VT_FLOAT
)
6167 vtop
->c
.ld
= vtop
->c
.f
;
6168 else if (sbt
== VT_DOUBLE
)
6169 vtop
->c
.ld
= vtop
->c
.d
;
6172 if ((sbt
& VT_BTYPE
) == VT_LLONG
) {
6173 if (sbt
& VT_UNSIGNED
)
6174 vtop
->c
.ld
= vtop
->c
.ull
;
6176 vtop
->c
.ld
= vtop
->c
.ll
;
6178 if (sbt
& VT_UNSIGNED
)
6179 vtop
->c
.ld
= vtop
->c
.ui
;
6181 vtop
->c
.ld
= vtop
->c
.i
;
6184 if (dbt
== VT_FLOAT
)
6185 vtop
->c
.f
= (float)vtop
->c
.ld
;
6186 else if (dbt
== VT_DOUBLE
)
6187 vtop
->c
.d
= (double)vtop
->c
.ld
;
6188 } else if (sf
&& dbt
== (VT_LLONG
|VT_UNSIGNED
)) {
6189 vtop
->c
.ull
= (unsigned long long)vtop
->c
.ld
;
6190 } else if (sf
&& dbt
== VT_BOOL
) {
6191 vtop
->c
.i
= (vtop
->c
.ld
!= 0);
6194 vtop
->c
.ll
= (long long)vtop
->c
.ld
;
6195 else if (sbt
== (VT_LLONG
|VT_UNSIGNED
))
6196 vtop
->c
.ll
= vtop
->c
.ull
;
6197 else if (sbt
& VT_UNSIGNED
)
6198 vtop
->c
.ll
= vtop
->c
.ui
;
6199 else if (sbt
!= VT_LLONG
)
6200 vtop
->c
.ll
= vtop
->c
.i
;
6202 if (dbt
== (VT_LLONG
|VT_UNSIGNED
))
6203 vtop
->c
.ull
= vtop
->c
.ll
;
6204 else if (dbt
== VT_BOOL
)
6205 vtop
->c
.i
= (vtop
->c
.ll
!= 0);
6206 else if (dbt
!= VT_LLONG
) {
6208 if ((dbt
& VT_BTYPE
) == VT_BYTE
)
6210 else if ((dbt
& VT_BTYPE
) == VT_SHORT
)
6213 if(dbt
& VT_UNSIGNED
)
6214 vtop
->c
.ui
= ((unsigned int)vtop
->c
.ll
<< s
) >> s
;
6216 vtop
->c
.i
= ((int)vtop
->c
.ll
<< s
) >> s
;
6219 } else if (p
&& dbt
== VT_BOOL
) {
6222 } else if (!nocode_wanted
) {
6223 /* non constant case: generate code */
6225 /* convert from fp to fp */
6228 /* convert int to fp */
6231 /* convert fp to int */
6232 if (dbt
== VT_BOOL
) {
6236 /* we handle char/short/etc... with generic code */
6237 if (dbt
!= (VT_INT
| VT_UNSIGNED
) &&
6238 dbt
!= (VT_LLONG
| VT_UNSIGNED
) &&
6242 if (dbt
== VT_INT
&& (type
->t
& (VT_BTYPE
| VT_UNSIGNED
)) != dbt
) {
6243 /* additional cast for char/short... */
6248 #ifndef TCC_TARGET_X86_64
6249 } else if ((dbt
& VT_BTYPE
) == VT_LLONG
) {
6250 if ((sbt
& VT_BTYPE
) != VT_LLONG
) {
6251 /* scalar to long long */
6252 /* machine independent conversion */
6254 /* generate high word */
6255 if (sbt
== (VT_INT
| VT_UNSIGNED
)) {
6259 if (sbt
== VT_PTR
) {
6260 /* cast from pointer to int before we apply
6261 shift operation, which pointers don't support*/
6262 gen_cast(&int_type
);
6268 /* patch second register */
6269 vtop
[-1].r2
= vtop
->r
;
6273 } else if ((dbt
& VT_BTYPE
) == VT_LLONG
||
6274 (dbt
& VT_BTYPE
) == VT_PTR
) {
6275 /* XXX: not sure if this is perfect... need more tests */
6276 if ((sbt
& VT_BTYPE
) != VT_LLONG
) {
6278 if (sbt
!= (VT_INT
| VT_UNSIGNED
) &&
6279 sbt
!= VT_PTR
&& sbt
!= VT_FUNC
) {
6280 /* x86_64 specific: movslq */
6282 o(0xc0 + (REG_VALUE(r
) << 3) + REG_VALUE(r
));
6286 } else if (dbt
== VT_BOOL
) {
6287 /* scalar to bool */
6290 } else if ((dbt
& VT_BTYPE
) == VT_BYTE
||
6291 (dbt
& VT_BTYPE
) == VT_SHORT
) {
6292 if (sbt
== VT_PTR
) {
6293 vtop
->type
.t
= VT_INT
;
6294 warning("nonportable conversion from pointer to char/short");
6296 force_charshort_cast(dbt
);
6297 } else if ((dbt
& VT_BTYPE
) == VT_INT
) {
6299 if (sbt
== VT_LLONG
) {
6300 /* from long long: just take low order word */
6304 /* if lvalue and single word type, nothing to do because
6305 the lvalue already contains the real type size (see
6306 VT_LVAL_xxx constants) */
6309 } else if ((dbt
& VT_BTYPE
) == VT_PTR
&& !(vtop
->r
& VT_LVAL
)) {
6310 /* if we are casting between pointer types,
6311 we must update the VT_LVAL_xxx size */
6312 vtop
->r
= (vtop
->r
& ~VT_LVAL_TYPE
)
6313 | (lvalue_type(type
->ref
->type
.t
) & VT_LVAL_TYPE
);
6318 /* return type size. Put alignment at 'a' */
6319 static int type_size(CType
*type
, int *a
)
6324 bt
= type
->t
& VT_BTYPE
;
6325 if (bt
== VT_STRUCT
) {
6330 } else if (bt
== VT_PTR
) {
6331 if (type
->t
& VT_ARRAY
) {
6335 ts
= type_size(&s
->type
, a
);
6337 if (ts
< 0 && s
->c
< 0)
6345 } else if (bt
== VT_LDOUBLE
) {
6347 return LDOUBLE_SIZE
;
6348 } else if (bt
== VT_DOUBLE
|| bt
== VT_LLONG
) {
6349 #ifdef TCC_TARGET_I386
6350 #ifdef TCC_TARGET_PE
6355 #elif defined(TCC_TARGET_ARM)
6365 } else if (bt
== VT_INT
|| bt
== VT_ENUM
|| bt
== VT_FLOAT
) {
6368 } else if (bt
== VT_SHORT
) {
6372 /* char, void, function, _Bool */
6378 /* return the pointed type of t */
6379 static inline CType
*pointed_type(CType
*type
)
6381 return &type
->ref
->type
;
6384 /* modify type so that its it is a pointer to type. */
6385 static void mk_pointer(CType
*type
)
6388 s
= sym_push(SYM_FIELD
, type
, 0, -1);
6389 type
->t
= VT_PTR
| (type
->t
& ~VT_TYPE
);
6393 /* compare function types. OLD functions match any new functions */
6394 static int is_compatible_func(CType
*type1
, CType
*type2
)
6400 if (!is_compatible_types(&s1
->type
, &s2
->type
))
6402 /* check func_call */
6403 if (FUNC_CALL(s1
->r
) != FUNC_CALL(s2
->r
))
6405 /* XXX: not complete */
6406 if (s1
->c
== FUNC_OLD
|| s2
->c
== FUNC_OLD
)
6410 while (s1
!= NULL
) {
6413 if (!is_compatible_parameter_types(&s1
->type
, &s2
->type
))
6423 /* return true if type1 and type2 are the same. If unqualified is
6424 true, qualifiers on the types are ignored.
6426 - enums are not checked as gcc __builtin_types_compatible_p ()
6428 static int compare_types(CType
*type1
, CType
*type2
, int unqualified
)
6432 t1
= type1
->t
& VT_TYPE
;
6433 t2
= type2
->t
& VT_TYPE
;
6435 /* strip qualifiers before comparing */
6436 t1
&= ~(VT_CONSTANT
| VT_VOLATILE
);
6437 t2
&= ~(VT_CONSTANT
| VT_VOLATILE
);
6439 /* XXX: bitfields ? */
6442 /* test more complicated cases */
6443 bt1
= t1
& VT_BTYPE
;
6444 if (bt1
== VT_PTR
) {
6445 type1
= pointed_type(type1
);
6446 type2
= pointed_type(type2
);
6447 return is_compatible_types(type1
, type2
);
6448 } else if (bt1
== VT_STRUCT
) {
6449 return (type1
->ref
== type2
->ref
);
6450 } else if (bt1
== VT_FUNC
) {
6451 return is_compatible_func(type1
, type2
);
6457 /* return true if type1 and type2 are exactly the same (including
6460 static int is_compatible_types(CType
*type1
, CType
*type2
)
6462 return compare_types(type1
,type2
,0);
6465 /* return true if type1 and type2 are the same (ignoring qualifiers).
6467 static int is_compatible_parameter_types(CType
*type1
, CType
*type2
)
6469 return compare_types(type1
,type2
,1);
6472 /* print a type. If 'varstr' is not NULL, then the variable is also
6473 printed in the type */
6475 /* XXX: add array and function pointers */
6476 void type_to_str(char *buf
, int buf_size
,
6477 CType
*type
, const char *varstr
)
6484 t
= type
->t
& VT_TYPE
;
6487 if (t
& VT_CONSTANT
)
6488 pstrcat(buf
, buf_size
, "const ");
6489 if (t
& VT_VOLATILE
)
6490 pstrcat(buf
, buf_size
, "volatile ");
6491 if (t
& VT_UNSIGNED
)
6492 pstrcat(buf
, buf_size
, "unsigned ");
6522 tstr
= "long double";
6524 pstrcat(buf
, buf_size
, tstr
);
6528 if (bt
== VT_STRUCT
)
6532 pstrcat(buf
, buf_size
, tstr
);
6533 v
= type
->ref
->v
& ~SYM_STRUCT
;
6534 if (v
>= SYM_FIRST_ANOM
)
6535 pstrcat(buf
, buf_size
, "<anonymous>");
6537 pstrcat(buf
, buf_size
, get_tok_str(v
, NULL
));
6541 type_to_str(buf
, buf_size
, &s
->type
, varstr
);
6542 pstrcat(buf
, buf_size
, "(");
6544 while (sa
!= NULL
) {
6545 type_to_str(buf1
, sizeof(buf1
), &sa
->type
, NULL
);
6546 pstrcat(buf
, buf_size
, buf1
);
6549 pstrcat(buf
, buf_size
, ", ");
6551 pstrcat(buf
, buf_size
, ")");
6555 pstrcpy(buf1
, sizeof(buf1
), "*");
6557 pstrcat(buf1
, sizeof(buf1
), varstr
);
6558 type_to_str(buf
, buf_size
, &s
->type
, buf1
);
6562 pstrcat(buf
, buf_size
, " ");
6563 pstrcat(buf
, buf_size
, varstr
);
6568 /* verify type compatibility to store vtop in 'dt' type, and generate
6570 static void gen_assign_cast(CType
*dt
)
6572 CType
*st
, *type1
, *type2
, tmp_type1
, tmp_type2
;
6573 char buf1
[256], buf2
[256];
6576 st
= &vtop
->type
; /* source type */
6577 dbt
= dt
->t
& VT_BTYPE
;
6578 sbt
= st
->t
& VT_BTYPE
;
6579 if (dt
->t
& VT_CONSTANT
)
6580 warning("assignment of read-only location");
6583 /* special cases for pointers */
6584 /* '0' can also be a pointer */
6585 if (is_null_pointer(vtop
))
6587 /* accept implicit pointer to integer cast with warning */
6588 if (is_integer_btype(sbt
)) {
6589 warning("assignment makes pointer from integer without a cast");
6592 type1
= pointed_type(dt
);
6593 /* a function is implicitely a function pointer */
6594 if (sbt
== VT_FUNC
) {
6595 if ((type1
->t
& VT_BTYPE
) != VT_VOID
&&
6596 !is_compatible_types(pointed_type(dt
), st
))
6603 type2
= pointed_type(st
);
6604 if ((type1
->t
& VT_BTYPE
) == VT_VOID
||
6605 (type2
->t
& VT_BTYPE
) == VT_VOID
) {
6606 /* void * can match anything */
6608 /* exact type match, except for unsigned */
6611 tmp_type1
.t
&= ~(VT_UNSIGNED
| VT_CONSTANT
| VT_VOLATILE
);
6612 tmp_type2
.t
&= ~(VT_UNSIGNED
| VT_CONSTANT
| VT_VOLATILE
);
6613 if (!is_compatible_types(&tmp_type1
, &tmp_type2
))
6614 warning("assignment from incompatible pointer type");
6616 /* check const and volatile */
6617 if ((!(type1
->t
& VT_CONSTANT
) && (type2
->t
& VT_CONSTANT
)) ||
6618 (!(type1
->t
& VT_VOLATILE
) && (type2
->t
& VT_VOLATILE
)))
6619 warning("assignment discards qualifiers from pointer target type");
6625 if (sbt
== VT_PTR
|| sbt
== VT_FUNC
) {
6626 warning("assignment makes integer from pointer without a cast");
6628 /* XXX: more tests */
6633 tmp_type1
.t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
6634 tmp_type2
.t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
6635 if (!is_compatible_types(&tmp_type1
, &tmp_type2
)) {
6637 type_to_str(buf1
, sizeof(buf1
), st
, NULL
);
6638 type_to_str(buf2
, sizeof(buf2
), dt
, NULL
);
6639 error("cannot cast '%s' to '%s'", buf1
, buf2
);
6647 /* store vtop in lvalue pushed on stack */
6650 int sbt
, dbt
, ft
, r
, t
, size
, align
, bit_size
, bit_pos
, rc
, delayed_cast
;
6652 ft
= vtop
[-1].type
.t
;
6653 sbt
= vtop
->type
.t
& VT_BTYPE
;
6654 dbt
= ft
& VT_BTYPE
;
6655 if (((sbt
== VT_INT
|| sbt
== VT_SHORT
) && dbt
== VT_BYTE
) ||
6656 (sbt
== VT_INT
&& dbt
== VT_SHORT
)) {
6657 /* optimize char/short casts */
6658 delayed_cast
= VT_MUSTCAST
;
6659 vtop
->type
.t
= ft
& (VT_TYPE
& ~(VT_BITFIELD
| (-1 << VT_STRUCT_SHIFT
)));
6660 /* XXX: factorize */
6661 if (ft
& VT_CONSTANT
)
6662 warning("assignment of read-only location");
6665 if (!(ft
& VT_BITFIELD
))
6666 gen_assign_cast(&vtop
[-1].type
);
6669 if (sbt
== VT_STRUCT
) {
6670 /* if structure, only generate pointer */
6671 /* structure assignment : generate memcpy */
6672 /* XXX: optimize if small size */
6673 if (!nocode_wanted
) {
6674 size
= type_size(&vtop
->type
, &align
);
6678 vpush_global_sym(&func_old_type
, TOK_memcpy8
);
6679 else if(!(align
& 3))
6680 vpush_global_sym(&func_old_type
, TOK_memcpy4
);
6683 vpush_global_sym(&func_old_type
, TOK_memcpy
);
6687 vtop
->type
.t
= VT_PTR
;
6691 vtop
->type
.t
= VT_PTR
;
6703 /* leave source on stack */
6704 } else if (ft
& VT_BITFIELD
) {
6705 /* bitfield store handling */
6706 bit_pos
= (ft
>> VT_STRUCT_SHIFT
) & 0x3f;
6707 bit_size
= (ft
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f;
6708 /* remove bit field info to avoid loops */
6709 vtop
[-1].type
.t
= ft
& ~(VT_BITFIELD
| (-1 << VT_STRUCT_SHIFT
));
6711 /* duplicate source into other register */
6716 if((ft
& VT_BTYPE
) == VT_BOOL
) {
6717 gen_cast(&vtop
[-1].type
);
6718 vtop
[-1].type
.t
= (vtop
[-1].type
.t
& ~VT_BTYPE
) | (VT_BYTE
| VT_UNSIGNED
);
6721 /* duplicate destination */
6723 vtop
[-1] = vtop
[-2];
6725 /* mask and shift source */
6726 if((ft
& VT_BTYPE
) != VT_BOOL
) {
6727 if((ft
& VT_BTYPE
) == VT_LLONG
) {
6728 vpushll((1ULL << bit_size
) - 1ULL);
6730 vpushi((1 << bit_size
) - 1);
6736 /* load destination, mask and or with source */
6738 if((ft
& VT_BTYPE
) == VT_LLONG
) {
6739 vpushll(~(((1ULL << bit_size
) - 1ULL) << bit_pos
));
6741 vpushi(~(((1 << bit_size
) - 1) << bit_pos
));
6748 /* pop off shifted source from "duplicate source..." above */
6752 #ifdef CONFIG_TCC_BCHECK
6753 /* bound check case */
6754 if (vtop
[-1].r
& VT_MUSTBOUND
) {
6760 if (!nocode_wanted
) {
6764 #ifdef TCC_TARGET_X86_64
6765 if ((ft
& VT_BTYPE
) == VT_LDOUBLE
) {
6770 r
= gv(rc
); /* generate value */
6771 /* if lvalue was saved on stack, must read it */
6772 if ((vtop
[-1].r
& VT_VALMASK
) == VT_LLOCAL
) {
6774 t
= get_reg(RC_INT
);
6775 #ifdef TCC_TARGET_X86_64
6780 sv
.r
= VT_LOCAL
| VT_LVAL
;
6781 sv
.c
.ul
= vtop
[-1].c
.ul
;
6783 vtop
[-1].r
= t
| VT_LVAL
;
6786 #ifndef TCC_TARGET_X86_64
6787 /* two word case handling : store second register at word + 4 */
6788 if ((ft
& VT_BTYPE
) == VT_LLONG
) {
6790 /* convert to int to increment easily */
6791 vtop
->type
.t
= VT_INT
;
6797 /* XXX: it works because r2 is spilled last ! */
6798 store(vtop
->r2
, vtop
- 1);
6803 vtop
--; /* NOT vpop() because on x86 it would flush the fp stack */
6804 vtop
->r
|= delayed_cast
;
6808 /* post defines POST/PRE add. c is the token ++ or -- */
6809 void inc(int post
, int c
)
6812 vdup(); /* save lvalue */
6814 gv_dup(); /* duplicate value */
6819 vpushi(c
- TOK_MID
);
6821 vstore(); /* store value */
6823 vpop(); /* if post op, return saved value */
6826 /* Parse GNUC __attribute__ extension. Currently, the following
6827 extensions are recognized:
6828 - aligned(n) : set data/function alignment.
6829 - packed : force data alignment to 1
6830 - section(x) : generate data/code in this section.
6831 - unused : currently ignored, but may be used someday.
6832 - regparm(n) : pass function parameters in registers (i386 only)
6834 static void parse_attribute(AttributeDef
*ad
)
6838 while (tok
== TOK_ATTRIBUTE1
|| tok
== TOK_ATTRIBUTE2
) {
6842 while (tok
!= ')') {
6843 if (tok
< TOK_IDENT
)
6844 expect("attribute name");
6852 expect("section name");
6853 ad
->section
= find_section(tcc_state
, (char *)tokc
.cstr
->data
);
6862 if (n
<= 0 || (n
& (n
- 1)) != 0)
6863 error("alignment must be a positive power of two");
6876 /* currently, no need to handle it because tcc does not
6877 track unused objects */
6881 /* currently, no need to handle it because tcc does not
6882 track unused objects */
6887 FUNC_CALL(ad
->func_attr
) = FUNC_CDECL
;
6892 FUNC_CALL(ad
->func_attr
) = FUNC_STDCALL
;
6894 #ifdef TCC_TARGET_I386
6904 FUNC_CALL(ad
->func_attr
) = FUNC_FASTCALL1
+ n
- 1;
6910 FUNC_CALL(ad
->func_attr
) = FUNC_FASTCALLW
;
6914 FUNC_EXPORT(ad
->func_attr
) = 1;
6917 if (tcc_state
->warn_unsupported
)
6918 warning("'%s' attribute ignored", get_tok_str(t
, NULL
));
6919 /* skip parameters */
6921 int parenthesis
= 0;
6925 else if (tok
== ')')
6928 } while (parenthesis
&& tok
!= -1);
6941 /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
6942 static void struct_decl(CType
*type
, int u
)
6944 int a
, v
, size
, align
, maxalign
, c
, offset
;
6945 int bit_size
, bit_pos
, bsize
, bt
, lbit_pos
, prevbt
;
6946 Sym
*s
, *ss
, *ass
, **ps
;
6950 a
= tok
; /* save decl type */
6955 /* struct already defined ? return it */
6957 expect("struct/union/enum name");
6961 error("invalid type");
6968 /* we put an undefined size for struct/union */
6969 s
= sym_push(v
| SYM_STRUCT
, &type1
, 0, -1);
6970 s
->r
= 0; /* default alignment is zero as gcc */
6971 /* put struct/union/enum name in type */
6979 error("struct/union/enum already defined");
6980 /* cannot be empty */
6982 /* non empty enums are not allowed */
6983 if (a
== TOK_ENUM
) {
6987 expect("identifier");
6993 /* enum symbols have static storage */
6994 ss
= sym_push(v
, &int_type
, VT_CONST
, c
);
6995 ss
->type
.t
|= VT_STATIC
;
7000 /* NOTE: we accept a trailing comma */
7011 while (tok
!= '}') {
7012 parse_btype(&btype
, &ad
);
7018 type_decl(&type1
, &ad
, &v
, TYPE_DIRECT
| TYPE_ABSTRACT
);
7019 if (v
== 0 && (type1
.t
& VT_BTYPE
) != VT_STRUCT
)
7020 expect("identifier");
7021 if ((type1
.t
& VT_BTYPE
) == VT_FUNC
||
7022 (type1
.t
& (VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
| VT_INLINE
)))
7023 error("invalid type for '%s'",
7024 get_tok_str(v
, NULL
));
7028 bit_size
= expr_const();
7029 /* XXX: handle v = 0 case for messages */
7031 error("negative width in bit-field '%s'",
7032 get_tok_str(v
, NULL
));
7033 if (v
&& bit_size
== 0)
7034 error("zero width for bit-field '%s'",
7035 get_tok_str(v
, NULL
));
7037 size
= type_size(&type1
, &align
);
7039 if (align
< ad
.aligned
)
7041 } else if (ad
.packed
) {
7043 } else if (*tcc_state
->pack_stack_ptr
) {
7044 if (align
> *tcc_state
->pack_stack_ptr
)
7045 align
= *tcc_state
->pack_stack_ptr
;
7048 if (bit_size
>= 0) {
7049 bt
= type1
.t
& VT_BTYPE
;
7056 error("bitfields must have scalar type");
7058 if (bit_size
> bsize
) {
7059 error("width of '%s' exceeds its type",
7060 get_tok_str(v
, NULL
));
7061 } else if (bit_size
== bsize
) {
7062 /* no need for bit fields */
7064 } else if (bit_size
== 0) {
7065 /* XXX: what to do if only padding in a
7067 /* zero size: means to pad */
7070 /* we do not have enough room ?
7071 did the type change?
7073 if ((bit_pos
+ bit_size
) > bsize
||
7074 bt
!= prevbt
|| a
== TOK_UNION
)
7077 /* XXX: handle LSB first */
7078 type1
.t
|= VT_BITFIELD
|
7079 (bit_pos
<< VT_STRUCT_SHIFT
) |
7080 (bit_size
<< (VT_STRUCT_SHIFT
+ 6));
7081 bit_pos
+= bit_size
;
7087 if (v
!= 0 || (type1
.t
& VT_BTYPE
) == VT_STRUCT
) {
7088 /* add new memory data only if starting
7090 if (lbit_pos
== 0) {
7091 if (a
== TOK_STRUCT
) {
7092 c
= (c
+ align
- 1) & -align
;
7101 if (align
> maxalign
)
7105 printf("add field %s offset=%d",
7106 get_tok_str(v
, NULL
), offset
);
7107 if (type1
.t
& VT_BITFIELD
) {
7108 printf(" pos=%d size=%d",
7109 (type1
.t
>> VT_STRUCT_SHIFT
) & 0x3f,
7110 (type1
.t
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f);
7115 if (v
== 0 && (type1
.t
& VT_BTYPE
) == VT_STRUCT
) {
7117 while ((ass
= ass
->next
) != NULL
) {
7118 ss
= sym_push(ass
->v
, &ass
->type
, 0, offset
+ ass
->c
);
7123 ss
= sym_push(v
| SYM_FIELD
, &type1
, 0, offset
);
7127 if (tok
== ';' || tok
== TOK_EOF
)
7134 /* store size and alignment */
7135 s
->c
= (c
+ maxalign
- 1) & -maxalign
;
7141 /* return 0 if no type declaration. otherwise, return the basic type
7144 static int parse_btype(CType
*type
, AttributeDef
*ad
)
7146 int t
, u
, type_found
, typespec_found
, typedef_found
;
7150 memset(ad
, 0, sizeof(AttributeDef
));
7158 /* currently, we really ignore extension */
7168 if ((t
& VT_BTYPE
) != 0)
7169 error("too many basic types");
7185 if ((t
& VT_BTYPE
) == VT_DOUBLE
) {
7186 t
= (t
& ~VT_BTYPE
) | VT_LDOUBLE
;
7187 } else if ((t
& VT_BTYPE
) == VT_LONG
) {
7188 t
= (t
& ~VT_BTYPE
) | VT_LLONG
;
7202 if ((t
& VT_BTYPE
) == VT_LONG
) {
7203 t
= (t
& ~VT_BTYPE
) | VT_LDOUBLE
;
7210 struct_decl(&type1
, VT_ENUM
);
7213 type
->ref
= type1
.ref
;
7217 struct_decl(&type1
, VT_STRUCT
);
7220 /* type modifiers */
7273 /* GNUC attribute */
7274 case TOK_ATTRIBUTE1
:
7275 case TOK_ATTRIBUTE2
:
7276 parse_attribute(ad
);
7283 parse_expr_type(&type1
);
7286 if (typespec_found
|| typedef_found
)
7289 if (!s
|| !(s
->type
.t
& VT_TYPEDEF
))
7292 t
|= (s
->type
.t
& ~VT_TYPEDEF
);
7293 type
->ref
= s
->type
.ref
;
7301 if ((t
& (VT_SIGNED
|VT_UNSIGNED
)) == (VT_SIGNED
|VT_UNSIGNED
))
7302 error("signed and unsigned modifier");
7303 if (tcc_state
->char_is_unsigned
) {
7304 if ((t
& (VT_SIGNED
|VT_UNSIGNED
|VT_BTYPE
)) == VT_BYTE
)
7309 /* long is never used as type */
7310 if ((t
& VT_BTYPE
) == VT_LONG
)
7311 #ifndef TCC_TARGET_X86_64
7312 t
= (t
& ~VT_BTYPE
) | VT_INT
;
7314 t
= (t
& ~VT_BTYPE
) | VT_LLONG
;
7320 /* convert a function parameter type (array to pointer and function to
7321 function pointer) */
7322 static inline void convert_parameter_type(CType
*pt
)
7324 /* remove const and volatile qualifiers (XXX: const could be used
7325 to indicate a const function parameter */
7326 pt
->t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
7327 /* array must be transformed to pointer according to ANSI C */
7329 if ((pt
->t
& VT_BTYPE
) == VT_FUNC
) {
7334 static void post_type(CType
*type
, AttributeDef
*ad
)
7336 int n
, l
, t1
, arg_size
, align
;
7337 Sym
**plast
, *s
, *first
;
7342 /* function declaration */
7350 /* read param name and compute offset */
7351 if (l
!= FUNC_OLD
) {
7352 if (!parse_btype(&pt
, &ad1
)) {
7354 error("invalid type");
7361 if ((pt
.t
& VT_BTYPE
) == VT_VOID
&& tok
== ')')
7363 type_decl(&pt
, &ad1
, &n
, TYPE_DIRECT
| TYPE_ABSTRACT
);
7364 if ((pt
.t
& VT_BTYPE
) == VT_VOID
)
7365 error("parameter declared as void");
7366 arg_size
+= (type_size(&pt
, &align
) + 3) & ~3;
7371 expect("identifier");
7375 convert_parameter_type(&pt
);
7376 s
= sym_push(n
| SYM_FIELD
, &pt
, 0, 0);
7382 if (l
== FUNC_NEW
&& tok
== TOK_DOTS
) {
7389 /* if no parameters, then old type prototype */
7393 t1
= type
->t
& VT_STORAGE
;
7394 /* NOTE: const is ignored in returned type as it has a special
7395 meaning in gcc / C++ */
7396 type
->t
&= ~(VT_STORAGE
| VT_CONSTANT
);
7397 post_type(type
, ad
);
7398 /* we push a anonymous symbol which will contain the function prototype */
7399 FUNC_ARGS(ad
->func_attr
) = arg_size
;
7400 s
= sym_push(SYM_FIELD
, type
, ad
->func_attr
, l
);
7402 type
->t
= t1
| VT_FUNC
;
7404 } else if (tok
== '[') {
7405 /* array definition */
7407 if (tok
== TOK_RESTRICT1
)
7413 error("invalid array size");
7416 /* parse next post type */
7417 t1
= type
->t
& VT_STORAGE
;
7418 type
->t
&= ~VT_STORAGE
;
7419 post_type(type
, ad
);
7421 /* we push a anonymous symbol which will contain the array
7423 s
= sym_push(SYM_FIELD
, type
, 0, n
);
7424 type
->t
= t1
| VT_ARRAY
| VT_PTR
;
7429 /* Parse a type declaration (except basic type), and return the type
7430 in 'type'. 'td' is a bitmask indicating which kind of type decl is
7431 expected. 'type' should contain the basic type. 'ad' is the
7432 attribute definition of the basic type. It can be modified by
7435 static void type_decl(CType
*type
, AttributeDef
*ad
, int *v
, int td
)
7438 CType type1
, *type2
;
7441 while (tok
== '*') {
7449 qualifiers
|= VT_CONSTANT
;
7454 qualifiers
|= VT_VOLATILE
;
7462 type
->t
|= qualifiers
;
7465 /* XXX: clarify attribute handling */
7466 if (tok
== TOK_ATTRIBUTE1
|| tok
== TOK_ATTRIBUTE2
)
7467 parse_attribute(ad
);
7469 /* recursive type */
7470 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
7471 type1
.t
= 0; /* XXX: same as int */
7474 /* XXX: this is not correct to modify 'ad' at this point, but
7475 the syntax is not clear */
7476 if (tok
== TOK_ATTRIBUTE1
|| tok
== TOK_ATTRIBUTE2
)
7477 parse_attribute(ad
);
7478 type_decl(&type1
, ad
, v
, td
);
7481 /* type identifier */
7482 if (tok
>= TOK_IDENT
&& (td
& TYPE_DIRECT
)) {
7486 if (!(td
& TYPE_ABSTRACT
))
7487 expect("identifier");
7491 post_type(type
, ad
);
7492 if (tok
== TOK_ATTRIBUTE1
|| tok
== TOK_ATTRIBUTE2
)
7493 parse_attribute(ad
);
7496 /* append type at the end of type1 */
7509 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
7510 static int lvalue_type(int t
)
7515 if (bt
== VT_BYTE
|| bt
== VT_BOOL
)
7517 else if (bt
== VT_SHORT
)
7521 if (t
& VT_UNSIGNED
)
7522 r
|= VT_LVAL_UNSIGNED
;
7526 /* indirection with full error checking and bound check */
7527 static void indir(void)
7529 if ((vtop
->type
.t
& VT_BTYPE
) != VT_PTR
) {
7530 if ((vtop
->type
.t
& VT_BTYPE
) == VT_FUNC
)
7534 if ((vtop
->r
& VT_LVAL
) && !nocode_wanted
)
7536 vtop
->type
= *pointed_type(&vtop
->type
);
7537 /* Arrays and functions are never lvalues */
7538 if (!(vtop
->type
.t
& VT_ARRAY
)
7539 && (vtop
->type
.t
& VT_BTYPE
) != VT_FUNC
) {
7540 vtop
->r
|= lvalue_type(vtop
->type
.t
);
7541 /* if bound checking, the referenced pointer must be checked */
7542 if (do_bounds_check
)
7543 vtop
->r
|= VT_MUSTBOUND
;
7547 /* pass a parameter to a function and do type checking and casting */
7548 static void gfunc_param_typed(Sym
*func
, Sym
*arg
)
7553 func_type
= func
->c
;
7554 if (func_type
== FUNC_OLD
||
7555 (func_type
== FUNC_ELLIPSIS
&& arg
== NULL
)) {
7556 /* default casting : only need to convert float to double */
7557 if ((vtop
->type
.t
& VT_BTYPE
) == VT_FLOAT
) {
7561 } else if (arg
== NULL
) {
7562 error("too many arguments to function");
7565 type
.t
&= ~VT_CONSTANT
; /* need to do that to avoid false warning */
7566 gen_assign_cast(&type
);
7570 /* parse an expression of the form '(type)' or '(expr)' and return its
7572 static void parse_expr_type(CType
*type
)
7578 if (parse_btype(type
, &ad
)) {
7579 type_decl(type
, &ad
, &n
, TYPE_ABSTRACT
);
7586 static void parse_type(CType
*type
)
7591 if (!parse_btype(type
, &ad
)) {
7594 type_decl(type
, &ad
, &n
, TYPE_ABSTRACT
);
7597 static void vpush_tokc(int t
)
7601 vsetc(&type
, VT_CONST
, &tokc
);
7604 static void unary(void)
7606 int n
, t
, align
, size
, r
;
7611 /* XXX: GCC 2.95.3 does not generate a table although it should be
7625 vpush_tokc(VT_INT
| VT_UNSIGNED
);
7629 vpush_tokc(VT_LLONG
);
7633 vpush_tokc(VT_LLONG
| VT_UNSIGNED
);
7637 vpush_tokc(VT_FLOAT
);
7641 vpush_tokc(VT_DOUBLE
);
7645 vpush_tokc(VT_LDOUBLE
);
7648 case TOK___FUNCTION__
:
7650 goto tok_identifier
;
7656 /* special function name identifier */
7657 len
= strlen(funcname
) + 1;
7658 /* generate char[len] type */
7663 vpush_ref(&type
, data_section
, data_section
->data_offset
, len
);
7664 ptr
= section_ptr_add(data_section
, len
);
7665 memcpy(ptr
, funcname
, len
);
7670 #ifdef TCC_TARGET_PE
7671 t
= VT_SHORT
| VT_UNSIGNED
;
7677 /* string parsing */
7680 if (tcc_state
->warn_write_strings
)
7685 memset(&ad
, 0, sizeof(AttributeDef
));
7686 decl_initializer_alloc(&type
, &ad
, VT_CONST
, 2, 0, 0);
7691 if (parse_btype(&type
, &ad
)) {
7692 type_decl(&type
, &ad
, &n
, TYPE_ABSTRACT
);
7694 /* check ISOC99 compound literal */
7696 /* data is allocated locally by default */
7701 /* all except arrays are lvalues */
7702 if (!(type
.t
& VT_ARRAY
))
7703 r
|= lvalue_type(type
.t
);
7704 memset(&ad
, 0, sizeof(AttributeDef
));
7705 decl_initializer_alloc(&type
, &ad
, r
, 1, 0, 0);
7710 } else if (tok
== '{') {
7711 /* save all registers */
7713 /* statement expression : we do not accept break/continue
7714 inside as GCC does */
7715 block(NULL
, NULL
, NULL
, NULL
, 0, 1);
7730 /* functions names must be treated as function pointers,
7731 except for unary '&' and sizeof. Since we consider that
7732 functions are not lvalues, we only have to handle it
7733 there and in function calls. */
7734 /* arrays can also be used although they are not lvalues */
7735 if ((vtop
->type
.t
& VT_BTYPE
) != VT_FUNC
&&
7736 !(vtop
->type
.t
& VT_ARRAY
) && !(vtop
->type
.t
& VT_LLOCAL
))
7738 mk_pointer(&vtop
->type
);
7744 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
) {
7746 boolean
.t
= VT_BOOL
;
7748 vtop
->c
.i
= !vtop
->c
.i
;
7749 } else if ((vtop
->r
& VT_VALMASK
) == VT_CMP
)
7750 vtop
->c
.i
= vtop
->c
.i
^ 1;
7753 vseti(VT_JMP
, gtst(1, 0));
7764 /* in order to force cast, we add zero */
7766 if ((vtop
->type
.t
& VT_BTYPE
) == VT_PTR
)
7767 error("pointer not accepted for unary plus");
7777 parse_expr_type(&type
);
7781 size
= type_size(&type
, &align
);
7782 if (t
== TOK_SIZEOF
) {
7784 error("sizeof applied to an incomplete type");
7789 vtop
->type
.t
|= VT_UNSIGNED
;
7792 case TOK_builtin_types_compatible_p
:
7801 type1
.t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
7802 type2
.t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
7803 vpushi(is_compatible_types(&type1
, &type2
));
7806 case TOK_builtin_constant_p
:
7808 int saved_nocode_wanted
, res
;
7811 saved_nocode_wanted
= nocode_wanted
;
7814 res
= (vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
7816 nocode_wanted
= saved_nocode_wanted
;
7821 case TOK_builtin_frame_address
:
7826 if (tok
!= TOK_CINT
) {
7827 error("__builtin_frame_address only takes integers");
7830 error("TCC only supports __builtin_frame_address(0)");
7836 vset(&type
, VT_LOCAL
, 0);
7839 #ifdef TCC_TARGET_X86_64
7840 case TOK_builtin_malloc
:
7842 goto tok_identifier
;
7843 case TOK_builtin_free
:
7845 goto tok_identifier
;
7862 goto tok_identifier
;
7864 /* allow to take the address of a label */
7865 if (tok
< TOK_UIDENT
)
7866 expect("label identifier");
7867 s
= label_find(tok
);
7869 s
= label_push(&global_label_stack
, tok
, LABEL_FORWARD
);
7871 if (s
->r
== LABEL_DECLARED
)
7872 s
->r
= LABEL_FORWARD
;
7875 s
->type
.t
= VT_VOID
;
7876 mk_pointer(&s
->type
);
7877 s
->type
.t
|= VT_STATIC
;
7879 vset(&s
->type
, VT_CONST
| VT_SYM
, 0);
7888 expect("identifier");
7892 error("'%s' undeclared", get_tok_str(t
, NULL
));
7893 /* for simple function calls, we tolerate undeclared
7894 external reference to int() function */
7895 if (tcc_state
->warn_implicit_function_declaration
)
7896 warning("implicit declaration of function '%s'",
7897 get_tok_str(t
, NULL
));
7898 s
= external_global_sym(t
, &func_old_type
, 0);
7900 if ((s
->type
.t
& (VT_STATIC
| VT_INLINE
| VT_BTYPE
)) ==
7901 (VT_STATIC
| VT_INLINE
| VT_FUNC
)) {
7902 /* if referencing an inline function, then we generate a
7903 symbol to it if not already done. It will have the
7904 effect to generate code for it at the end of the
7905 compilation unit. Inline function as always
7906 generated in the text section. */
7908 put_extern_sym(s
, text_section
, 0, 0);
7909 r
= VT_SYM
| VT_CONST
;
7913 vset(&s
->type
, r
, s
->c
);
7914 /* if forward reference, we must point to s */
7915 if (vtop
->r
& VT_SYM
) {
7922 /* post operations */
7924 if (tok
== TOK_INC
|| tok
== TOK_DEC
) {
7927 } else if (tok
== '.' || tok
== TOK_ARROW
) {
7929 if (tok
== TOK_ARROW
)
7934 /* expect pointer on structure */
7935 if ((vtop
->type
.t
& VT_BTYPE
) != VT_STRUCT
)
7936 expect("struct or union");
7940 while ((s
= s
->next
) != NULL
) {
7945 error("field not found: %s", get_tok_str(tok
& ~SYM_FIELD
, NULL
));
7946 /* add field offset to pointer */
7947 vtop
->type
= char_pointer_type
; /* change type to 'char *' */
7950 /* change type to field type, and set to lvalue */
7951 vtop
->type
= s
->type
;
7952 /* an array is never an lvalue */
7953 if (!(vtop
->type
.t
& VT_ARRAY
)) {
7954 vtop
->r
|= lvalue_type(vtop
->type
.t
);
7955 /* if bound checking, the referenced pointer must be checked */
7956 if (do_bounds_check
)
7957 vtop
->r
|= VT_MUSTBOUND
;
7960 } else if (tok
== '[') {
7966 } else if (tok
== '(') {
7972 if ((vtop
->type
.t
& VT_BTYPE
) != VT_FUNC
) {
7973 /* pointer test (no array accepted) */
7974 if ((vtop
->type
.t
& (VT_BTYPE
| VT_ARRAY
)) == VT_PTR
) {
7975 vtop
->type
= *pointed_type(&vtop
->type
);
7976 if ((vtop
->type
.t
& VT_BTYPE
) != VT_FUNC
)
7980 expect("function pointer");
7983 vtop
->r
&= ~VT_LVAL
; /* no lvalue */
7985 /* get return type */
7988 sa
= s
->next
; /* first parameter */
7991 /* compute first implicit argument if a structure is returned */
7992 if ((s
->type
.t
& VT_BTYPE
) == VT_STRUCT
) {
7993 /* get some space for the returned structure */
7994 size
= type_size(&s
->type
, &align
);
7995 loc
= (loc
- size
) & -align
;
7997 ret
.r
= VT_LOCAL
| VT_LVAL
;
7998 /* pass it as 'int' to avoid structure arg passing
8000 vseti(VT_LOCAL
, loc
);
8005 /* return in register */
8006 if (is_float(ret
.type
.t
)) {
8007 ret
.r
= reg_fret(ret
.type
.t
);
8009 if ((ret
.type
.t
& VT_BTYPE
) == VT_LLONG
)
8018 gfunc_param_typed(s
, sa
);
8028 error("too few arguments to function");
8030 if (!nocode_wanted
) {
8031 gfunc_call(nb_args
);
8033 vtop
-= (nb_args
+ 1);
8036 vsetc(&ret
.type
, ret
.r
, &ret
.c
);
8044 static void uneq(void)
8050 (tok
>= TOK_A_MOD
&& tok
<= TOK_A_DIV
) ||
8051 tok
== TOK_A_XOR
|| tok
== TOK_A_OR
||
8052 tok
== TOK_A_SHL
|| tok
== TOK_A_SAR
) {
8067 static void expr_prod(void)
8072 while (tok
== '*' || tok
== '/' || tok
== '%') {
8080 static void expr_sum(void)
8085 while (tok
== '+' || tok
== '-') {
8093 static void expr_shift(void)
8098 while (tok
== TOK_SHL
|| tok
== TOK_SAR
) {
8106 static void expr_cmp(void)
8111 while ((tok
>= TOK_ULE
&& tok
<= TOK_GT
) ||
8112 tok
== TOK_ULT
|| tok
== TOK_UGE
) {
8120 static void expr_cmpeq(void)
8125 while (tok
== TOK_EQ
|| tok
== TOK_NE
) {
8133 static void expr_and(void)
8136 while (tok
== '&') {
8143 static void expr_xor(void)
8146 while (tok
== '^') {
8153 static void expr_or(void)
8156 while (tok
== '|') {
8163 /* XXX: fix this mess */
8164 static void expr_land_const(void)
8167 while (tok
== TOK_LAND
) {
8174 /* XXX: fix this mess */
8175 static void expr_lor_const(void)
8178 while (tok
== TOK_LOR
) {
8185 /* only used if non constant */
8186 static void expr_land(void)
8191 if (tok
== TOK_LAND
) {
8196 if (tok
!= TOK_LAND
) {
8206 static void expr_lor(void)
8211 if (tok
== TOK_LOR
) {
8216 if (tok
!= TOK_LOR
) {
8226 /* XXX: better constant handling */
8227 static void expr_eq(void)
8229 int tt
, u
, r1
, r2
, rc
, t1
, t2
, bt1
, bt2
;
8231 CType type
, type1
, type2
;
8238 boolean
.t
= VT_BOOL
;
8244 if (tok
!= ':' || !gnu_ext
) {
8259 if (vtop
!= vstack
) {
8260 /* needed to avoid having different registers saved in
8262 if (is_float(vtop
->type
.t
)) {
8264 #ifdef TCC_TARGET_X86_64
8265 if ((vtop
->type
.t
& VT_BTYPE
) == VT_LDOUBLE
) {
8275 if (tok
== ':' && gnu_ext
) {
8283 sv
= *vtop
; /* save value to handle it later */
8284 vtop
--; /* no vpop so that FP stack is not flushed */
8292 bt1
= t1
& VT_BTYPE
;
8294 bt2
= t2
& VT_BTYPE
;
8295 /* cast operands to correct type according to ISOC rules */
8296 if (is_float(bt1
) || is_float(bt2
)) {
8297 if (bt1
== VT_LDOUBLE
|| bt2
== VT_LDOUBLE
) {
8298 type
.t
= VT_LDOUBLE
;
8299 } else if (bt1
== VT_DOUBLE
|| bt2
== VT_DOUBLE
) {
8304 } else if (bt1
== VT_LLONG
|| bt2
== VT_LLONG
) {
8305 /* cast to biggest op */
8307 /* convert to unsigned if it does not fit in a long long */
8308 if ((t1
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_LLONG
| VT_UNSIGNED
) ||
8309 (t2
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_LLONG
| VT_UNSIGNED
))
8310 type
.t
|= VT_UNSIGNED
;
8311 } else if (bt1
== VT_PTR
|| bt2
== VT_PTR
) {
8312 /* XXX: test pointer compatibility */
8314 } else if (bt1
== VT_FUNC
|| bt2
== VT_FUNC
) {
8315 /* XXX: test function pointer compatibility */
8317 } else if (bt1
== VT_STRUCT
|| bt2
== VT_STRUCT
) {
8318 /* XXX: test structure compatibility */
8320 } else if (bt1
== VT_VOID
|| bt2
== VT_VOID
) {
8321 /* NOTE: as an extension, we accept void on only one side */
8324 /* integer operations */
8326 /* convert to unsigned if it does not fit in an integer */
8327 if ((t1
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
) ||
8328 (t2
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
))
8329 type
.t
|= VT_UNSIGNED
;
8332 /* now we convert second operand */
8334 if (VT_STRUCT
== (vtop
->type
.t
& VT_BTYPE
))
8337 if (is_float(type
.t
)) {
8339 #ifdef TCC_TARGET_X86_64
8340 if ((type
.t
& VT_BTYPE
) == VT_LDOUBLE
) {
8344 } else if ((type
.t
& VT_BTYPE
) == VT_LLONG
) {
8345 /* for long longs, we use fixed registers to avoid having
8346 to handle a complicated move */
8351 /* this is horrible, but we must also convert first
8355 /* put again first value and cast it */
8358 if (VT_STRUCT
== (vtop
->type
.t
& VT_BTYPE
))
8368 static void gexpr(void)
8379 /* parse an expression and return its type without any side effect. */
8380 static void expr_type(CType
*type
)
8382 int saved_nocode_wanted
;
8384 saved_nocode_wanted
= nocode_wanted
;
8389 nocode_wanted
= saved_nocode_wanted
;
8392 /* parse a unary expression and return its type without any side
8394 static void unary_type(CType
*type
)
8406 /* parse a constant expression and return value in vtop. */
8407 static void expr_const1(void)
8416 /* parse an integer constant and return its value. */
8417 static int expr_const(void)
8421 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) != VT_CONST
)
8422 expect("constant expression");
8428 /* return the label token if current token is a label, otherwise
8430 static int is_label(void)
8434 /* fast test first */
8435 if (tok
< TOK_UIDENT
)
8437 /* no need to save tokc because tok is an identifier */
8444 unget_tok(last_tok
);
8449 static void block(int *bsym
, int *csym
, int *case_sym
, int *def_sym
,
8450 int case_reg
, int is_expr
)
8455 /* generate line number info */
8457 (last_line_num
!= file
->line_num
|| last_ind
!= ind
)) {
8458 put_stabn(N_SLINE
, 0, file
->line_num
, ind
- func_ind
);
8460 last_line_num
= file
->line_num
;
8464 /* default return value is (void) */
8466 vtop
->type
.t
= VT_VOID
;
8469 if (tok
== TOK_IF
) {
8476 block(bsym
, csym
, case_sym
, def_sym
, case_reg
, 0);
8478 if (c
== TOK_ELSE
) {
8482 block(bsym
, csym
, case_sym
, def_sym
, case_reg
, 0);
8483 gsym(d
); /* patch else jmp */
8486 } else if (tok
== TOK_WHILE
) {
8494 block(&a
, &b
, case_sym
, def_sym
, case_reg
, 0);
8498 } else if (tok
== '{') {
8502 /* record local declaration stack position */
8504 llabel
= local_label_stack
;
8505 /* handle local labels declarations */
8506 if (tok
== TOK_LABEL
) {
8509 if (tok
< TOK_UIDENT
)
8510 expect("label identifier");
8511 label_push(&local_label_stack
, tok
, LABEL_DECLARED
);
8521 while (tok
!= '}') {
8526 block(bsym
, csym
, case_sym
, def_sym
, case_reg
, is_expr
);
8529 /* pop locally defined labels */
8530 label_pop(&local_label_stack
, llabel
);
8531 /* pop locally defined symbols */
8533 /* XXX: this solution makes only valgrind happy...
8534 triggered by gcc.c-torture/execute/20000917-1.c */
8536 switch(vtop
->type
.t
& VT_BTYPE
) {
8541 for(p
=vtop
->type
.ref
;p
;p
=p
->prev
)
8543 error("unsupported expression type");
8546 sym_pop(&local_stack
, s
);
8548 } else if (tok
== TOK_RETURN
) {
8552 gen_assign_cast(&func_vt
);
8553 if ((func_vt
.t
& VT_BTYPE
) == VT_STRUCT
) {
8555 /* if returning structure, must copy it to implicit
8556 first pointer arg location */
8559 size
= type_size(&func_vt
,&align
);
8562 if((vtop
->r
!= (VT_LOCAL
| VT_LVAL
) || (vtop
->c
.i
& 3))
8566 loc
= (loc
- size
) & -4;
8569 vset(&type
, VT_LOCAL
| VT_LVAL
, addr
);
8572 vset(&int_type
, VT_LOCAL
| VT_LVAL
, addr
);
8574 vtop
->type
= int_type
;
8580 vset(&type
, VT_LOCAL
| VT_LVAL
, func_vc
);
8583 /* copy structure value to pointer */
8588 } else if (is_float(func_vt
.t
)) {
8589 gv(rc_fret(func_vt
.t
));
8593 vtop
--; /* NOT vpop() because on x86 it would flush the fp stack */
8596 rsym
= gjmp(rsym
); /* jmp */
8597 } else if (tok
== TOK_BREAK
) {
8600 error("cannot break");
8601 *bsym
= gjmp(*bsym
);
8604 } else if (tok
== TOK_CONTINUE
) {
8607 error("cannot continue");
8608 *csym
= gjmp(*csym
);
8611 } else if (tok
== TOK_FOR
) {
8638 block(&a
, &b
, case_sym
, def_sym
, case_reg
, 0);
8643 if (tok
== TOK_DO
) {
8648 block(&a
, &b
, case_sym
, def_sym
, case_reg
, 0);
8659 if (tok
== TOK_SWITCH
) {
8663 /* XXX: other types than integer */
8664 case_reg
= gv(RC_INT
);
8668 b
= gjmp(0); /* jump to first case */
8670 block(&a
, csym
, &b
, &c
, case_reg
, 0);
8671 /* if no default, jmp after switch */
8679 if (tok
== TOK_CASE
) {
8686 if (gnu_ext
&& tok
== TOK_DOTS
) {
8690 warning("empty case range");
8692 /* since a case is like a label, we must skip it with a jmp */
8699 *case_sym
= gtst(1, 0);
8702 *case_sym
= gtst(1, 0);
8706 *case_sym
= gtst(1, *case_sym
);
8711 goto block_after_label
;
8713 if (tok
== TOK_DEFAULT
) {
8719 error("too many 'default'");
8722 goto block_after_label
;
8724 if (tok
== TOK_GOTO
) {
8726 if (tok
== '*' && gnu_ext
) {
8730 if ((vtop
->type
.t
& VT_BTYPE
) != VT_PTR
)
8733 } else if (tok
>= TOK_UIDENT
) {
8734 s
= label_find(tok
);
8735 /* put forward definition if needed */
8737 s
= label_push(&global_label_stack
, tok
, LABEL_FORWARD
);
8739 if (s
->r
== LABEL_DECLARED
)
8740 s
->r
= LABEL_FORWARD
;
8742 /* label already defined */
8743 if (s
->r
& LABEL_FORWARD
)
8744 s
->next
= (void *)gjmp((long)s
->next
);
8746 gjmp_addr((long)s
->next
);
8749 expect("label identifier");
8752 } else if (tok
== TOK_ASM1
|| tok
== TOK_ASM2
|| tok
== TOK_ASM3
) {
8760 if (s
->r
== LABEL_DEFINED
)
8761 error("duplicate label '%s'", get_tok_str(s
->v
, NULL
));
8762 gsym((long)s
->next
);
8763 s
->r
= LABEL_DEFINED
;
8765 s
= label_push(&global_label_stack
, b
, LABEL_DEFINED
);
8767 s
->next
= (void *)ind
;
8768 /* we accept this, but it is a mistake */
8771 warning("deprecated use of label at end of compound statement");
8775 block(bsym
, csym
, case_sym
, def_sym
, case_reg
, is_expr
);
8778 /* expression case */
8793 /* t is the array or struct type. c is the array or struct
8794 address. cur_index/cur_field is the pointer to the current
8795 value. 'size_only' is true if only size info is needed (only used
8797 static void decl_designator(CType
*type
, Section
*sec
, unsigned long c
,
8798 int *cur_index
, Sym
**cur_field
,
8802 int notfirst
, index
, index_last
, align
, l
, nb_elems
, elem_size
;
8808 if (gnu_ext
&& (l
= is_label()) != 0)
8810 while (tok
== '[' || tok
== '.') {
8812 if (!(type
->t
& VT_ARRAY
))
8813 expect("array type");
8816 index
= expr_const();
8817 if (index
< 0 || (s
->c
>= 0 && index
>= s
->c
))
8818 expect("invalid index");
8819 if (tok
== TOK_DOTS
&& gnu_ext
) {
8821 index_last
= expr_const();
8822 if (index_last
< 0 ||
8823 (s
->c
>= 0 && index_last
>= s
->c
) ||
8825 expect("invalid index");
8831 *cur_index
= index_last
;
8832 type
= pointed_type(type
);
8833 elem_size
= type_size(type
, &align
);
8834 c
+= index
* elem_size
;
8835 /* NOTE: we only support ranges for last designator */
8836 nb_elems
= index_last
- index
+ 1;
8837 if (nb_elems
!= 1) {
8846 if ((type
->t
& VT_BTYPE
) != VT_STRUCT
)
8847 expect("struct/union type");
8860 /* XXX: fix this mess by using explicit storage field */
8862 type1
.t
|= (type
->t
& ~VT_TYPE
);
8876 if (type
->t
& VT_ARRAY
) {
8878 type
= pointed_type(type
);
8879 c
+= index
* type_size(type
, &align
);
8883 error("too many field init");
8884 /* XXX: fix this mess by using explicit storage field */
8886 type1
.t
|= (type
->t
& ~VT_TYPE
);
8891 decl_initializer(type
, sec
, c
, 0, size_only
);
8893 /* XXX: make it more general */
8894 if (!size_only
&& nb_elems
> 1) {
8895 unsigned long c_end
;
8900 error("range init not supported yet for dynamic storage");
8901 c_end
= c
+ nb_elems
* elem_size
;
8902 if (c_end
> sec
->data_allocated
)
8903 section_realloc(sec
, c_end
);
8904 src
= sec
->data
+ c
;
8906 for(i
= 1; i
< nb_elems
; i
++) {
8908 memcpy(dst
, src
, elem_size
);
8914 #define EXPR_CONST 1
8917 /* store a value or an expression directly in global data or in local array */
8918 static void init_putv(CType
*type
, Section
*sec
, unsigned long c
,
8919 int v
, int expr_type
)
8921 int saved_global_expr
, bt
, bit_pos
, bit_size
;
8923 unsigned long long bit_mask
;
8931 /* compound literals must be allocated globally in this case */
8932 saved_global_expr
= global_expr
;
8935 global_expr
= saved_global_expr
;
8936 /* NOTE: symbols are accepted */
8937 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
)) != VT_CONST
)
8938 error("initializer element is not constant");
8946 dtype
.t
&= ~VT_CONSTANT
; /* need to do that to avoid false warning */
8949 /* XXX: not portable */
8950 /* XXX: generate error if incorrect relocation */
8951 gen_assign_cast(&dtype
);
8952 bt
= type
->t
& VT_BTYPE
;
8953 /* we'll write at most 12 bytes */
8954 if (c
+ 12 > sec
->data_allocated
) {
8955 section_realloc(sec
, c
+ 12);
8957 ptr
= sec
->data
+ c
;
8958 /* XXX: make code faster ? */
8959 if (!(type
->t
& VT_BITFIELD
)) {
8964 bit_pos
= (vtop
->type
.t
>> VT_STRUCT_SHIFT
) & 0x3f;
8965 bit_size
= (vtop
->type
.t
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f;
8966 bit_mask
= (1LL << bit_size
) - 1;
8968 if ((vtop
->r
& VT_SYM
) &&
8974 (bt
== VT_INT
&& bit_size
!= 32)))
8975 error("initializer element is not computable at load time");
8978 vtop
->c
.i
= (vtop
->c
.i
!= 0);
8980 *(char *)ptr
|= (vtop
->c
.i
& bit_mask
) << bit_pos
;
8983 *(short *)ptr
|= (vtop
->c
.i
& bit_mask
) << bit_pos
;
8986 *(double *)ptr
= vtop
->c
.d
;
8989 *(long double *)ptr
= vtop
->c
.ld
;
8992 *(long long *)ptr
|= (vtop
->c
.ll
& bit_mask
) << bit_pos
;
8995 if (vtop
->r
& VT_SYM
) {
8996 greloc(sec
, vtop
->sym
, c
, R_DATA_32
);
8998 *(int *)ptr
|= (vtop
->c
.i
& bit_mask
) << bit_pos
;
9003 vset(&dtype
, VT_LOCAL
|VT_LVAL
, c
);
9010 /* put zeros for variable based init */
9011 static void init_putz(CType
*t
, Section
*sec
, unsigned long c
, int size
)
9014 /* nothing to do because globals are already set to zero */
9016 vpush_global_sym(&func_old_type
, TOK_memset
);
9024 /* 't' contains the type and storage info. 'c' is the offset of the
9025 object in section 'sec'. If 'sec' is NULL, it means stack based
9026 allocation. 'first' is true if array '{' must be read (multi
9027 dimension implicit array init handling). 'size_only' is true if
9028 size only evaluation is wanted (only for arrays). */
9029 static void decl_initializer(CType
*type
, Section
*sec
, unsigned long c
,
9030 int first
, int size_only
)
9032 int index
, array_length
, n
, no_oblock
, nb
, parlevel
, i
;
9033 int size1
, align1
, expr_type
;
9037 if (type
->t
& VT_ARRAY
) {
9041 t1
= pointed_type(type
);
9042 size1
= type_size(t1
, &align1
);
9045 if ((first
&& tok
!= TOK_LSTR
&& tok
!= TOK_STR
) ||
9051 /* only parse strings here if correct type (otherwise: handle
9052 them as ((w)char *) expressions */
9053 if ((tok
== TOK_LSTR
&&
9054 #ifdef TCC_TARGET_PE
9055 (t1
->t
& VT_BTYPE
) == VT_SHORT
&& (t1
->t
& VT_UNSIGNED
)
9057 (t1
->t
& VT_BTYPE
) == VT_INT
9059 ) || (tok
== TOK_STR
&& (t1
->t
& VT_BTYPE
) == VT_BYTE
)) {
9060 while (tok
== TOK_STR
|| tok
== TOK_LSTR
) {
9065 /* compute maximum number of chars wanted */
9067 cstr_len
= cstr
->size
;
9069 cstr_len
= cstr
->size
/ sizeof(nwchar_t
);
9072 if (n
>= 0 && nb
> (n
- array_length
))
9073 nb
= n
- array_length
;
9076 warning("initializer-string for array is too long");
9077 /* in order to go faster for common case (char
9078 string in global variable, we handle it
9080 if (sec
&& tok
== TOK_STR
&& size1
== 1) {
9081 memcpy(sec
->data
+ c
+ array_length
, cstr
->data
, nb
);
9085 ch
= ((unsigned char *)cstr
->data
)[i
];
9087 ch
= ((nwchar_t
*)cstr
->data
)[i
];
9088 init_putv(t1
, sec
, c
+ (array_length
+ i
) * size1
,
9096 /* only add trailing zero if enough storage (no
9097 warning in this case since it is standard) */
9098 if (n
< 0 || array_length
< n
) {
9100 init_putv(t1
, sec
, c
+ (array_length
* size1
), 0, EXPR_VAL
);
9106 while (tok
!= '}') {
9107 decl_designator(type
, sec
, c
, &index
, NULL
, size_only
);
9108 if (n
>= 0 && index
>= n
)
9109 error("index too large");
9110 /* must put zero in holes (note that doing it that way
9111 ensures that it even works with designators) */
9112 if (!size_only
&& array_length
< index
) {
9113 init_putz(t1
, sec
, c
+ array_length
* size1
,
9114 (index
- array_length
) * size1
);
9117 if (index
> array_length
)
9118 array_length
= index
;
9119 /* special test for multi dimensional arrays (may not
9120 be strictly correct if designators are used at the
9122 if (index
>= n
&& no_oblock
)
9131 /* put zeros at the end */
9132 if (!size_only
&& n
>= 0 && array_length
< n
) {
9133 init_putz(t1
, sec
, c
+ array_length
* size1
,
9134 (n
- array_length
) * size1
);
9136 /* patch type size if needed */
9138 s
->c
= array_length
;
9139 } else if ((type
->t
& VT_BTYPE
) == VT_STRUCT
&&
9140 (sec
|| !first
|| tok
== '{')) {
9143 /* NOTE: the previous test is a specific case for automatic
9144 struct/union init */
9145 /* XXX: union needs only one init */
9147 /* XXX: this test is incorrect for local initializers
9148 beginning with ( without {. It would be much more difficult
9149 to do it correctly (ideally, the expression parser should
9150 be used in all cases) */
9156 while (tok
== '(') {
9160 if (!parse_btype(&type1
, &ad1
))
9162 type_decl(&type1
, &ad1
, &n
, TYPE_ABSTRACT
);
9164 if (!is_assignable_types(type
, &type1
))
9165 error("invalid type for cast");
9170 if (first
|| tok
== '{') {
9179 while (tok
!= '}') {
9180 decl_designator(type
, sec
, c
, NULL
, &f
, size_only
);
9182 if (!size_only
&& array_length
< index
) {
9183 init_putz(type
, sec
, c
+ array_length
,
9184 index
- array_length
);
9186 index
= index
+ type_size(&f
->type
, &align1
);
9187 if (index
> array_length
)
9188 array_length
= index
;
9190 if (no_oblock
&& f
== NULL
)
9196 /* put zeros at the end */
9197 if (!size_only
&& array_length
< n
) {
9198 init_putz(type
, sec
, c
+ array_length
,
9207 } else if (tok
== '{') {
9209 decl_initializer(type
, sec
, c
, first
, size_only
);
9211 } else if (size_only
) {
9212 /* just skip expression */
9214 while ((parlevel
> 0 || (tok
!= '}' && tok
!= ',')) &&
9218 else if (tok
== ')')
9223 /* currently, we always use constant expression for globals
9224 (may change for scripting case) */
9225 expr_type
= EXPR_CONST
;
9227 expr_type
= EXPR_ANY
;
9228 init_putv(type
, sec
, c
, 0, expr_type
);
9232 /* parse an initializer for type 't' if 'has_init' is non zero, and
9233 allocate space in local or global data space ('r' is either
9234 VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
9235 variable 'v' of scope 'scope' is declared before initializers are
9236 parsed. If 'v' is zero, then a reference to the new object is put
9237 in the value stack. If 'has_init' is 2, a special parsing is done
9238 to handle string constants. */
9239 static void decl_initializer_alloc(CType
*type
, AttributeDef
*ad
, int r
,
9240 int has_init
, int v
, int scope
)
9242 int size
, align
, addr
, data_offset
;
9244 ParseState saved_parse_state
= {0};
9245 TokenString init_str
;
9248 size
= type_size(type
, &align
);
9249 /* If unknown size, we must evaluate it before
9250 evaluating initializers because
9251 initializers can generate global data too
9252 (e.g. string pointers or ISOC99 compound
9253 literals). It also simplifies local
9254 initializers handling */
9255 tok_str_new(&init_str
);
9258 error("unknown type size");
9259 /* get all init string */
9260 if (has_init
== 2) {
9261 /* only get strings */
9262 while (tok
== TOK_STR
|| tok
== TOK_LSTR
) {
9263 tok_str_add_tok(&init_str
);
9268 while (level
> 0 || (tok
!= ',' && tok
!= ';')) {
9270 error("unexpected end of file in initializer");
9271 tok_str_add_tok(&init_str
);
9274 else if (tok
== '}') {
9284 tok_str_add(&init_str
, -1);
9285 tok_str_add(&init_str
, 0);
9288 save_parse_state(&saved_parse_state
);
9290 macro_ptr
= init_str
.str
;
9292 decl_initializer(type
, NULL
, 0, 1, 1);
9293 /* prepare second initializer parsing */
9294 macro_ptr
= init_str
.str
;
9297 /* if still unknown size, error */
9298 size
= type_size(type
, &align
);
9300 error("unknown type size");
9302 /* take into account specified alignment if bigger */
9304 if (ad
->aligned
> align
)
9305 align
= ad
->aligned
;
9306 } else if (ad
->packed
) {
9309 if ((r
& VT_VALMASK
) == VT_LOCAL
) {
9311 if (do_bounds_check
&& (type
->t
& VT_ARRAY
))
9313 loc
= (loc
- size
) & -align
;
9315 /* handles bounds */
9316 /* XXX: currently, since we do only one pass, we cannot track
9317 '&' operators, so we add only arrays */
9318 if (do_bounds_check
&& (type
->t
& VT_ARRAY
)) {
9319 unsigned long *bounds_ptr
;
9320 /* add padding between regions */
9322 /* then add local bound info */
9323 bounds_ptr
= section_ptr_add(lbounds_section
, 2 * sizeof(unsigned long));
9324 bounds_ptr
[0] = addr
;
9325 bounds_ptr
[1] = size
;
9328 /* local variable */
9329 sym_push(v
, type
, r
, addr
);
9331 /* push local reference */
9332 vset(type
, r
, addr
);
9338 if (v
&& scope
== VT_CONST
) {
9339 /* see if the symbol was already defined */
9342 if (!is_compatible_types(&sym
->type
, type
))
9343 error("incompatible types for redefinition of '%s'",
9344 get_tok_str(v
, NULL
));
9345 if (sym
->type
.t
& VT_EXTERN
) {
9346 /* if the variable is extern, it was not allocated */
9347 sym
->type
.t
&= ~VT_EXTERN
;
9348 /* set array size if it was ommited in extern
9350 if ((sym
->type
.t
& VT_ARRAY
) &&
9351 sym
->type
.ref
->c
< 0 &&
9353 sym
->type
.ref
->c
= type
->ref
->c
;
9355 /* we accept several definitions of the same
9356 global variable. this is tricky, because we
9357 must play with the SHN_COMMON type of the symbol */
9358 /* XXX: should check if the variable was already
9359 initialized. It is incorrect to initialized it
9361 /* no init data, we won't add more to the symbol */
9368 /* allocate symbol in corresponding section */
9373 else if (tcc_state
->nocommon
)
9377 data_offset
= sec
->data_offset
;
9378 data_offset
= (data_offset
+ align
- 1) & -align
;
9380 /* very important to increment global pointer at this time
9381 because initializers themselves can create new initializers */
9382 data_offset
+= size
;
9383 /* add padding if bound check */
9384 if (do_bounds_check
)
9386 sec
->data_offset
= data_offset
;
9387 /* allocate section space to put the data */
9388 if (sec
->sh_type
!= SHT_NOBITS
&&
9389 data_offset
> sec
->data_allocated
)
9390 section_realloc(sec
, data_offset
);
9391 /* align section if needed */
9392 if (align
> sec
->sh_addralign
)
9393 sec
->sh_addralign
= align
;
9395 addr
= 0; /* avoid warning */
9399 if (scope
!= VT_CONST
|| !sym
) {
9400 sym
= sym_push(v
, type
, r
| VT_SYM
, 0);
9402 /* update symbol definition */
9404 put_extern_sym(sym
, sec
, addr
, size
);
9407 /* put a common area */
9408 put_extern_sym(sym
, NULL
, align
, size
);
9409 /* XXX: find a nicer way */
9410 esym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym
->c
];
9411 esym
->st_shndx
= SHN_COMMON
;
9416 /* push global reference */
9417 sym
= get_sym_ref(type
, sec
, addr
, size
);
9419 vsetc(type
, VT_CONST
| VT_SYM
, &cval
);
9423 /* handles bounds now because the symbol must be defined
9424 before for the relocation */
9425 if (do_bounds_check
) {
9426 unsigned long *bounds_ptr
;
9428 greloc(bounds_section
, sym
, bounds_section
->data_offset
, R_DATA_32
);
9429 /* then add global bound info */
9430 bounds_ptr
= section_ptr_add(bounds_section
, 2 * sizeof(long));
9431 bounds_ptr
[0] = 0; /* relocated */
9432 bounds_ptr
[1] = size
;
9436 decl_initializer(type
, sec
, addr
, 1, 0);
9437 /* restore parse state if needed */
9439 tok_str_free(init_str
.str
);
9440 restore_parse_state(&saved_parse_state
);
9446 void put_func_debug(Sym
*sym
)
9451 /* XXX: we put here a dummy type */
9452 snprintf(buf
, sizeof(buf
), "%s:%c1",
9453 funcname
, sym
->type
.t
& VT_STATIC
? 'f' : 'F');
9454 put_stabs_r(buf
, N_FUN
, 0, file
->line_num
, 0,
9455 cur_text_section
, sym
->c
);
9456 /* //gr gdb wants a line at the function */
9457 put_stabn(N_SLINE
, 0, file
->line_num
, 0);
9462 /* parse an old style function declaration list */
9463 /* XXX: check multiple parameter */
9464 static void func_decl_list(Sym
*func_sym
)
9471 /* parse each declaration */
9472 while (tok
!= '{' && tok
!= ';' && tok
!= ',' && tok
!= TOK_EOF
) {
9473 if (!parse_btype(&btype
, &ad
))
9474 expect("declaration list");
9475 if (((btype
.t
& VT_BTYPE
) == VT_ENUM
||
9476 (btype
.t
& VT_BTYPE
) == VT_STRUCT
) &&
9478 /* we accept no variable after */
9482 type_decl(&type
, &ad
, &v
, TYPE_DIRECT
);
9483 /* find parameter in function parameter list */
9486 if ((s
->v
& ~SYM_FIELD
) == v
)
9490 error("declaration for parameter '%s' but no such parameter",
9491 get_tok_str(v
, NULL
));
9493 /* check that no storage specifier except 'register' was given */
9494 if (type
.t
& VT_STORAGE
)
9495 error("storage class specified for '%s'", get_tok_str(v
, NULL
));
9496 convert_parameter_type(&type
);
9497 /* we can add the type (NOTE: it could be local to the function) */
9499 /* accept other parameters */
9510 /* parse a function defined by symbol 'sym' and generate its code in
9511 'cur_text_section' */
9512 static void gen_function(Sym
*sym
)
9514 int saved_nocode_wanted
= nocode_wanted
;
9516 ind
= cur_text_section
->data_offset
;
9517 /* NOTE: we patch the symbol size later */
9518 put_extern_sym(sym
, cur_text_section
, ind
, 0);
9519 funcname
= get_tok_str(sym
->v
, NULL
);
9521 /* put debug symbol */
9523 put_func_debug(sym
);
9524 /* push a dummy symbol to enable local sym storage */
9525 sym_push2(&local_stack
, SYM_FIELD
, 0, 0);
9526 gfunc_prolog(&sym
->type
);
9528 block(NULL
, NULL
, NULL
, NULL
, 0, 0);
9531 cur_text_section
->data_offset
= ind
;
9532 label_pop(&global_label_stack
, NULL
);
9533 sym_pop(&local_stack
, NULL
); /* reset local stack */
9534 /* end of function */
9535 /* patch symbol size */
9536 ((ElfW(Sym
) *)symtab_section
->data
)[sym
->c
].st_size
=
9539 put_stabn(N_FUN
, 0, 0, ind
- func_ind
);
9541 /* It's better to crash than to generate wrong code */
9542 cur_text_section
= NULL
;
9543 funcname
= ""; /* for safety */
9544 func_vt
.t
= VT_VOID
; /* for safety */
9545 ind
= 0; /* for safety */
9546 nocode_wanted
= saved_nocode_wanted
;
9549 static void gen_inline_functions(void)
9553 int *str
, inline_generated
;
9555 /* iterate while inline function are referenced */
9557 inline_generated
= 0;
9558 for(sym
= global_stack
; sym
!= NULL
; sym
= sym
->prev
) {
9560 if (((type
->t
& VT_BTYPE
) == VT_FUNC
) &&
9561 (type
->t
& (VT_STATIC
| VT_INLINE
)) ==
9562 (VT_STATIC
| VT_INLINE
) &&
9564 /* the function was used: generate its code and
9565 convert it to a normal function */
9566 str
= INLINE_DEF(sym
->r
);
9567 sym
->r
= VT_SYM
| VT_CONST
;
9568 sym
->type
.t
&= ~VT_INLINE
;
9572 cur_text_section
= text_section
;
9574 macro_ptr
= NULL
; /* fail safe */
9577 inline_generated
= 1;
9580 if (!inline_generated
)
9584 /* free all remaining inline function tokens */
9585 for(sym
= global_stack
; sym
!= NULL
; sym
= sym
->prev
) {
9587 if (((type
->t
& VT_BTYPE
) == VT_FUNC
) &&
9588 (type
->t
& (VT_STATIC
| VT_INLINE
)) ==
9589 (VT_STATIC
| VT_INLINE
)) {
9590 //gr printf("sym %d %s\n", sym->r, get_tok_str(sym->v, NULL));
9591 if (sym
->r
== (VT_SYM
| VT_CONST
)) //gr beware!
9593 str
= INLINE_DEF(sym
->r
);
9595 sym
->r
= 0; /* fail safe */
9600 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
9601 static void decl(int l
)
9609 if (!parse_btype(&btype
, &ad
)) {
9610 /* skip redundant ';' */
9611 /* XXX: find more elegant solution */
9616 if (l
== VT_CONST
&&
9617 (tok
== TOK_ASM1
|| tok
== TOK_ASM2
|| tok
== TOK_ASM3
)) {
9618 /* global asm block */
9622 /* special test for old K&R protos without explicit int
9623 type. Only accepted when defining global data */
9624 if (l
== VT_LOCAL
|| tok
< TOK_DEFINE
)
9628 if (((btype
.t
& VT_BTYPE
) == VT_ENUM
||
9629 (btype
.t
& VT_BTYPE
) == VT_STRUCT
) &&
9631 /* we accept no variable after */
9635 while (1) { /* iterate thru each declaration */
9637 type_decl(&type
, &ad
, &v
, TYPE_DIRECT
);
9641 type_to_str(buf
, sizeof(buf
), t
, get_tok_str(v
, NULL
));
9642 printf("type = '%s'\n", buf
);
9645 if ((type
.t
& VT_BTYPE
) == VT_FUNC
) {
9646 /* if old style function prototype, we accept a
9649 if (sym
->c
== FUNC_OLD
)
9650 func_decl_list(sym
);
9655 error("cannot use local functions");
9656 if ((type
.t
& VT_BTYPE
) != VT_FUNC
)
9657 expect("function definition");
9659 /* reject abstract declarators in function definition */
9661 while ((sym
= sym
->next
) != NULL
)
9662 if (!(sym
->v
& ~SYM_FIELD
))
9663 expect("identifier");
9665 /* XXX: cannot do better now: convert extern line to static inline */
9666 if ((type
.t
& (VT_EXTERN
| VT_INLINE
)) == (VT_EXTERN
| VT_INLINE
))
9667 type
.t
= (type
.t
& ~VT_EXTERN
) | VT_STATIC
;
9671 if ((sym
->type
.t
& VT_BTYPE
) != VT_FUNC
)
9673 /* specific case: if not func_call defined, we put
9674 the one of the prototype */
9675 /* XXX: should have default value */
9676 r
= sym
->type
.ref
->r
;
9677 if (FUNC_CALL(r
) != FUNC_CDECL
9678 && FUNC_CALL(type
.ref
->r
) == FUNC_CDECL
)
9679 FUNC_CALL(type
.ref
->r
) = FUNC_CALL(r
);
9681 FUNC_EXPORT(type
.ref
->r
) = 1;
9683 if (!is_compatible_types(&sym
->type
, &type
)) {
9685 error("incompatible types for redefinition of '%s'",
9686 get_tok_str(v
, NULL
));
9688 /* if symbol is already defined, then put complete type */
9691 /* put function symbol */
9692 sym
= global_identifier_push(v
, type
.t
, 0);
9693 sym
->type
.ref
= type
.ref
;
9696 /* static inline functions are just recorded as a kind
9697 of macro. Their code will be emitted at the end of
9698 the compilation unit only if they are used */
9699 if ((type
.t
& (VT_INLINE
| VT_STATIC
)) ==
9700 (VT_INLINE
| VT_STATIC
)) {
9701 TokenString func_str
;
9704 tok_str_new(&func_str
);
9710 error("unexpected end of file");
9711 tok_str_add_tok(&func_str
);
9716 } else if (t
== '}') {
9718 if (block_level
== 0)
9722 tok_str_add(&func_str
, -1);
9723 tok_str_add(&func_str
, 0);
9724 INLINE_DEF(sym
->r
) = func_str
.str
;
9726 /* compute text section */
9727 cur_text_section
= ad
.section
;
9728 if (!cur_text_section
)
9729 cur_text_section
= text_section
;
9730 sym
->r
= VT_SYM
| VT_CONST
;
9735 if (btype
.t
& VT_TYPEDEF
) {
9736 /* save typedefed type */
9737 /* XXX: test storage specifiers ? */
9738 sym
= sym_push(v
, &type
, 0, 0);
9739 sym
->type
.t
|= VT_TYPEDEF
;
9740 } else if ((type
.t
& VT_BTYPE
) == VT_FUNC
) {
9741 /* external function definition */
9742 /* specific case for func_call attribute */
9744 type
.ref
->r
= ad
.func_attr
;
9745 external_sym(v
, &type
, 0);
9747 /* not lvalue if array */
9749 if (!(type
.t
& VT_ARRAY
))
9750 r
|= lvalue_type(type
.t
);
9751 has_init
= (tok
== '=');
9752 if ((btype
.t
& VT_EXTERN
) ||
9753 ((type
.t
& VT_ARRAY
) && (type
.t
& VT_STATIC
) &&
9754 !has_init
&& l
== VT_CONST
&& type
.ref
->c
< 0)) {
9755 /* external variable */
9756 /* NOTE: as GCC, uninitialized global static
9757 arrays of null size are considered as
9759 external_sym(v
, &type
, r
);
9761 type
.t
|= (btype
.t
& VT_STATIC
); /* Retain "static". */
9762 if (type
.t
& VT_STATIC
)
9768 decl_initializer_alloc(&type
, &ad
, r
,
9782 /* better than nothing, but needs extension to handle '-E' option
9784 static void preprocess_init(TCCState
*s1
)
9786 s1
->include_stack_ptr
= s1
->include_stack
;
9787 /* XXX: move that before to avoid having to initialize
9788 file->ifdef_stack_ptr ? */
9789 s1
->ifdef_stack_ptr
= s1
->ifdef_stack
;
9790 file
->ifdef_stack_ptr
= s1
->ifdef_stack_ptr
;
9792 /* XXX: not ANSI compliant: bound checking says error */
9794 s1
->pack_stack
[0] = 0;
9795 s1
->pack_stack_ptr
= s1
->pack_stack
;
9798 /* compile the C file opened in 'file'. Return non zero if errors. */
9799 static int tcc_compile(TCCState
*s1
)
9803 volatile int section_sym
;
9806 printf("%s: **** new file\n", file
->filename
);
9808 preprocess_init(s1
);
9810 cur_text_section
= NULL
;
9812 anon_sym
= SYM_FIRST_ANOM
;
9814 /* file info: full path + filename */
9815 section_sym
= 0; /* avoid warning */
9817 section_sym
= put_elf_sym(symtab_section
, 0, 0,
9818 ELFW(ST_INFO
)(STB_LOCAL
, STT_SECTION
), 0,
9819 text_section
->sh_num
, NULL
);
9820 getcwd(buf
, sizeof(buf
));
9822 normalize_slashes(buf
);
9824 pstrcat(buf
, sizeof(buf
), "/");
9825 put_stabs_r(buf
, N_SO
, 0, 0,
9826 text_section
->data_offset
, text_section
, section_sym
);
9827 put_stabs_r(file
->filename
, N_SO
, 0, 0,
9828 text_section
->data_offset
, text_section
, section_sym
);
9830 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
9831 symbols can be safely used */
9832 put_elf_sym(symtab_section
, 0, 0,
9833 ELFW(ST_INFO
)(STB_LOCAL
, STT_FILE
), 0,
9834 SHN_ABS
, file
->filename
);
9836 /* define some often used types */
9837 int_type
.t
= VT_INT
;
9839 char_pointer_type
.t
= VT_BYTE
;
9840 mk_pointer(&char_pointer_type
);
9842 func_old_type
.t
= VT_FUNC
;
9843 func_old_type
.ref
= sym_push(SYM_FIELD
, &int_type
, FUNC_CDECL
, FUNC_OLD
);
9845 #if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)
9846 float_type
.t
= VT_FLOAT
;
9847 double_type
.t
= VT_DOUBLE
;
9849 func_float_type
.t
= VT_FUNC
;
9850 func_float_type
.ref
= sym_push(SYM_FIELD
, &float_type
, FUNC_CDECL
, FUNC_OLD
);
9851 func_double_type
.t
= VT_FUNC
;
9852 func_double_type
.ref
= sym_push(SYM_FIELD
, &double_type
, FUNC_CDECL
, FUNC_OLD
);
9856 /* define 'void *alloca(unsigned int)' builtin function */
9861 sym
= sym_push(p
, mk_pointer(VT_VOID
), FUNC_CDECL
, FUNC_NEW
);
9862 s1
= sym_push(SYM_FIELD
, VT_UNSIGNED
| VT_INT
, 0, 0);
9865 sym_push(TOK_alloca
, VT_FUNC
| (p
<< VT_STRUCT_SHIFT
), VT_CONST
, 0);
9869 define_start
= define_stack
;
9872 if (setjmp(s1
->error_jmp_buf
) == 0) {
9874 s1
->error_set_jmp_enabled
= 1;
9876 ch
= file
->buf_ptr
[0];
9877 tok_flags
= TOK_FLAG_BOL
| TOK_FLAG_BOF
;
9878 parse_flags
= PARSE_FLAG_PREPROCESS
| PARSE_FLAG_TOK_NUM
;
9882 expect("declaration");
9884 /* end of translation unit info */
9886 put_stabs_r(NULL
, N_SO
, 0, 0,
9887 text_section
->data_offset
, text_section
, section_sym
);
9890 s1
->error_set_jmp_enabled
= 0;
9892 /* reset define stack, but leave -Dsymbols (may be incorrect if
9893 they are undefined) */
9894 free_defines(define_start
);
9896 gen_inline_functions();
9898 sym_pop(&global_stack
, NULL
);
9899 sym_pop(&local_stack
, NULL
);
9901 return s1
->nb_errors
!= 0 ? -1 : 0;
9904 /* Preprocess the current file */
9905 static int tcc_preprocess(TCCState
*s1
)
9908 BufferedFile
*file_ref
;
9909 int token_seen
, line_ref
;
9911 preprocess_init(s1
);
9912 define_start
= define_stack
;
9913 ch
= file
->buf_ptr
[0];
9914 tok_flags
= TOK_FLAG_BOL
| TOK_FLAG_BOF
;
9915 parse_flags
= PARSE_FLAG_ASM_COMMENTS
| PARSE_FLAG_PREPROCESS
|
9916 PARSE_FLAG_LINEFEED
| PARSE_FLAG_SPACES
;
9923 if (tok
== TOK_EOF
) {
9925 } else if (tok
== TOK_LINEFEED
) {
9930 } else if (!token_seen
) {
9931 int d
= file
->line_num
- line_ref
;
9932 if (file
!= file_ref
|| d
< 0 || d
>= 8)
9933 fprintf(s1
->outfile
, "# %d \"%s\"\n", file
->line_num
, file
->filename
);
9936 fputs("\n", s1
->outfile
), --d
;
9937 line_ref
= (file_ref
= file
)->line_num
;
9940 fputs(get_tok_str(tok
, &tokc
), s1
->outfile
);
9942 free_defines(define_start
);
9947 int tcc_compile_string(TCCState
*s
, const char *str
)
9949 BufferedFile bf1
, *bf
= &bf1
;
9953 /* init file structure */
9955 /* XXX: avoid copying */
9957 buf
= tcc_malloc(len
+ 1);
9960 memcpy(buf
, str
, len
);
9963 bf
->buf_end
= buf
+ len
;
9964 pstrcpy(bf
->filename
, sizeof(bf
->filename
), "<string>");
9967 ret
= tcc_compile(s
);
9971 /* currently, no need to close */
9976 /* define a preprocessor symbol. A value can also be provided with the '=' operator */
9977 void tcc_define_symbol(TCCState
*s1
, const char *sym
, const char *value
)
9979 BufferedFile bf1
, *bf
= &bf1
;
9981 pstrcpy(bf
->buffer
, IO_BUF_SIZE
, sym
);
9982 pstrcat(bf
->buffer
, IO_BUF_SIZE
, " ");
9986 pstrcat(bf
->buffer
, IO_BUF_SIZE
, value
);
9988 /* init file structure */
9990 bf
->buf_ptr
= bf
->buffer
;
9991 bf
->buf_end
= bf
->buffer
+ strlen(bf
->buffer
);
9992 *bf
->buf_end
= CH_EOB
;
9993 bf
->filename
[0] = '\0';
9997 s1
->include_stack_ptr
= s1
->include_stack
;
9999 /* parse with define parser */
10000 ch
= file
->buf_ptr
[0];
10006 /* undefine a preprocessor symbol */
10007 void tcc_undefine_symbol(TCCState
*s1
, const char *sym
)
10011 ts
= tok_alloc(sym
, strlen(sym
));
10012 s
= define_find(ts
->tok
);
10013 /* undefine symbol by putting an invalid name */
10018 #ifdef CONFIG_TCC_ASM
10020 #ifdef TCC_TARGET_I386
10021 #include "i386-asm.c"
10023 #include "tccasm.c"
10026 static void asm_instr(void)
10028 error("inline asm() not supported");
10030 static void asm_global_instr(void)
10032 error("inline asm() not supported");
10036 #include "tccelf.c"
10038 #ifdef TCC_TARGET_COFF
10039 #include "tcccoff.c"
10042 #ifdef TCC_TARGET_PE
10046 /* print the position in the source file of PC value 'pc' by reading
10047 the stabs debug information */
10048 static void rt_printline(unsigned long wanted_pc
)
10050 Stab_Sym
*sym
, *sym_end
;
10051 char func_name
[128], last_func_name
[128];
10052 unsigned long func_addr
, last_pc
, pc
;
10053 const char *incl_files
[INCLUDE_STACK_SIZE
];
10054 int incl_index
, len
, last_line_num
, i
;
10055 const char *str
, *p
;
10057 fprintf(stderr
, "0x%08lx:", wanted_pc
);
10059 func_name
[0] = '\0';
10062 last_func_name
[0] = '\0';
10063 last_pc
= 0xffffffff;
10065 sym
= (Stab_Sym
*)stab_section
->data
+ 1;
10066 sym_end
= (Stab_Sym
*)(stab_section
->data
+ stab_section
->data_offset
);
10067 while (sym
< sym_end
) {
10068 switch(sym
->n_type
) {
10069 /* function start or end */
10071 if (sym
->n_strx
== 0) {
10072 /* we test if between last line and end of function */
10073 pc
= sym
->n_value
+ func_addr
;
10074 if (wanted_pc
>= last_pc
&& wanted_pc
< pc
)
10076 func_name
[0] = '\0';
10079 str
= stabstr_section
->data
+ sym
->n_strx
;
10080 p
= strchr(str
, ':');
10082 pstrcpy(func_name
, sizeof(func_name
), str
);
10085 if (len
> sizeof(func_name
) - 1)
10086 len
= sizeof(func_name
) - 1;
10087 memcpy(func_name
, str
, len
);
10088 func_name
[len
] = '\0';
10090 func_addr
= sym
->n_value
;
10093 /* line number info */
10095 pc
= sym
->n_value
+ func_addr
;
10096 if (wanted_pc
>= last_pc
&& wanted_pc
< pc
)
10099 last_line_num
= sym
->n_desc
;
10101 strcpy(last_func_name
, func_name
);
10103 /* include files */
10105 str
= stabstr_section
->data
+ sym
->n_strx
;
10107 if (incl_index
< INCLUDE_STACK_SIZE
) {
10108 incl_files
[incl_index
++] = str
;
10112 if (incl_index
> 1)
10116 if (sym
->n_strx
== 0) {
10117 incl_index
= 0; /* end of translation unit */
10119 str
= stabstr_section
->data
+ sym
->n_strx
;
10120 /* do not add path */
10122 if (len
> 0 && str
[len
- 1] != '/')
10130 /* second pass: we try symtab symbols (no line number info) */
10133 ElfW(Sym
) *sym
, *sym_end
;
10136 sym_end
= (ElfW(Sym
) *)(symtab_section
->data
+ symtab_section
->data_offset
);
10137 for(sym
= (ElfW(Sym
) *)symtab_section
->data
+ 1;
10140 type
= ELFW(ST_TYPE
)(sym
->st_info
);
10141 if (type
== STT_FUNC
) {
10142 if (wanted_pc
>= sym
->st_value
&&
10143 wanted_pc
< sym
->st_value
+ sym
->st_size
) {
10144 pstrcpy(last_func_name
, sizeof(last_func_name
),
10145 strtab_section
->data
+ sym
->st_name
);
10151 /* did not find any info: */
10152 fprintf(stderr
, " ???\n");
10155 if (last_func_name
[0] != '\0') {
10156 fprintf(stderr
, " %s()", last_func_name
);
10158 if (incl_index
> 0) {
10159 fprintf(stderr
, " (%s:%d",
10160 incl_files
[incl_index
- 1], last_line_num
);
10161 for(i
= incl_index
- 2; i
>= 0; i
--)
10162 fprintf(stderr
, ", included from %s", incl_files
[i
]);
10163 fprintf(stderr
, ")");
10165 fprintf(stderr
, "\n");
10168 #if !defined(_WIN32) && !defined(CONFIG_TCCBOOT)
10172 /* fix for glibc 2.1 */
10174 #define REG_EIP EIP
10175 #define REG_EBP EBP
10178 /* return the PC at frame level 'level'. Return non zero if not found */
10179 static int rt_get_caller_pc(unsigned long *paddr
,
10180 ucontext_t
*uc
, int level
)
10186 #if defined(__FreeBSD__)
10187 *paddr
= uc
->uc_mcontext
.mc_eip
;
10188 #elif defined(__dietlibc__)
10189 *paddr
= uc
->uc_mcontext
.eip
;
10191 *paddr
= uc
->uc_mcontext
.gregs
[REG_EIP
];
10195 #if defined(__FreeBSD__)
10196 fp
= uc
->uc_mcontext
.mc_ebp
;
10197 #elif defined(__dietlibc__)
10198 fp
= uc
->uc_mcontext
.ebp
;
10200 fp
= uc
->uc_mcontext
.gregs
[REG_EBP
];
10202 for(i
=1;i
<level
;i
++) {
10203 /* XXX: check address validity with program info */
10204 if (fp
<= 0x1000 || fp
>= 0xc0000000)
10206 fp
= ((unsigned long *)fp
)[0];
10208 *paddr
= ((unsigned long *)fp
)[1];
10212 #elif defined(__x86_64__)
10213 /* return the PC at frame level 'level'. Return non zero if not found */
10214 static int rt_get_caller_pc(unsigned long *paddr
,
10215 ucontext_t
*uc
, int level
)
10221 /* XXX: only support linux */
10222 *paddr
= uc
->uc_mcontext
.gregs
[REG_RIP
];
10225 fp
= uc
->uc_mcontext
.gregs
[REG_RBP
];
10226 for(i
=1;i
<level
;i
++) {
10227 /* XXX: check address validity with program info */
10230 fp
= ((unsigned long *)fp
)[0];
10232 *paddr
= ((unsigned long *)fp
)[1];
10238 #warning add arch specific rt_get_caller_pc()
10240 static int rt_get_caller_pc(unsigned long *paddr
,
10241 ucontext_t
*uc
, int level
)
10247 /* emit a run time error at position 'pc' */
10248 void rt_error(ucontext_t
*uc
, const char *fmt
, ...)
10255 fprintf(stderr
, "Runtime error: ");
10256 vfprintf(stderr
, fmt
, ap
);
10257 fprintf(stderr
, "\n");
10258 for(i
=0;i
<num_callers
;i
++) {
10259 if (rt_get_caller_pc(&pc
, uc
, i
) < 0)
10262 fprintf(stderr
, "at ");
10264 fprintf(stderr
, "by ");
10271 /* signal handler for fatal errors */
10272 static void sig_error(int signum
, siginfo_t
*siginf
, void *puc
)
10274 ucontext_t
*uc
= puc
;
10278 switch(siginf
->si_code
) {
10281 rt_error(uc
, "division by zero");
10284 rt_error(uc
, "floating point exception");
10290 if (rt_bound_error_msg
&& *rt_bound_error_msg
)
10291 rt_error(uc
, *rt_bound_error_msg
);
10293 rt_error(uc
, "dereferencing invalid pointer");
10296 rt_error(uc
, "illegal instruction");
10299 rt_error(uc
, "abort() called");
10302 rt_error(uc
, "caught signal %d", signum
);
10309 /* copy code into memory passed in by the caller and do all relocations
10310 (needed before using tcc_get_symbol()).
10311 returns -1 on error and required size if ptr is NULL */
10312 int tcc_relocate(TCCState
*s1
, void *ptr
)
10315 unsigned long offset
, length
, mem
;
10318 if (0 == s1
->runtime_added
) {
10319 s1
->runtime_added
= 1;
10321 #ifdef TCC_TARGET_PE
10322 pe_add_runtime(s1
);
10323 relocate_common_syms();
10324 tcc_add_linker_symbols(s1
);
10326 tcc_add_runtime(s1
);
10327 relocate_common_syms();
10328 tcc_add_linker_symbols(s1
);
10329 build_got_entries(s1
);
10333 offset
= 0, mem
= (unsigned long)ptr
;
10334 for(i
= 1; i
< s1
->nb_sections
; i
++) {
10335 s
= s1
->sections
[i
];
10336 if (0 == (s
->sh_flags
& SHF_ALLOC
))
10338 length
= s
->data_offset
;
10339 s
->sh_addr
= mem
? (mem
+ offset
+ 15) & ~15 : 0;
10340 offset
= (offset
+ length
+ 15) & ~15;
10343 /* relocate symbols */
10344 relocate_syms(s1
, 1);
10348 #ifdef TCC_TARGET_X86_64
10349 s1
->runtime_plt_and_got_offset
= 0;
10350 s1
->runtime_plt_and_got
= (char *)(mem
+ offset
);
10351 /* double the size of the buffer for got and plt entries
10352 XXX: calculate exact size for them? */
10357 return offset
+ 15;
10359 /* relocate each section */
10360 for(i
= 1; i
< s1
->nb_sections
; i
++) {
10361 s
= s1
->sections
[i
];
10363 relocate_section(s1
, s
);
10366 for(i
= 1; i
< s1
->nb_sections
; i
++) {
10367 s
= s1
->sections
[i
];
10368 if (0 == (s
->sh_flags
& SHF_ALLOC
))
10370 length
= s
->data_offset
;
10371 // printf("%-12s %08x %04x\n", s->name, s->sh_addr, length);
10372 ptr
= (void*)s
->sh_addr
;
10373 if (NULL
== s
->data
|| s
->sh_type
== SHT_NOBITS
)
10374 memset(ptr
, 0, length
);
10376 memcpy(ptr
, s
->data
, length
);
10377 /* mark executable sections as executable in memory */
10378 if (s
->sh_flags
& SHF_EXECINSTR
)
10379 set_pages_executable(ptr
, length
);
10381 #ifdef TCC_TARGET_X86_64
10382 set_pages_executable(s1
->runtime_plt_and_got
,
10383 s1
->runtime_plt_and_got_offset
);
10388 /* launch the compiled program with the given arguments */
10389 int tcc_run(TCCState
*s1
, int argc
, char **argv
)
10391 int (*prog_main
)(int, char **);
10395 ret
= tcc_relocate(s1
, NULL
);
10398 ptr
= tcc_malloc(ret
);
10399 tcc_relocate(s1
, ptr
);
10401 prog_main
= tcc_get_symbol_err(s1
, "main");
10404 #if defined(_WIN32) || defined(CONFIG_TCCBOOT)
10405 error("debug mode currently not available for Windows");
10407 struct sigaction sigact
;
10408 /* install TCC signal handlers to print debug info on fatal
10410 sigact
.sa_flags
= SA_SIGINFO
| SA_RESETHAND
;
10411 sigact
.sa_sigaction
= sig_error
;
10412 sigemptyset(&sigact
.sa_mask
);
10413 sigaction(SIGFPE
, &sigact
, NULL
);
10414 sigaction(SIGILL
, &sigact
, NULL
);
10415 sigaction(SIGSEGV
, &sigact
, NULL
);
10416 sigaction(SIGBUS
, &sigact
, NULL
);
10417 sigaction(SIGABRT
, &sigact
, NULL
);
10421 #ifdef CONFIG_TCC_BCHECK
10422 if (do_bounds_check
) {
10423 void (*bound_init
)(void);
10425 /* set error function */
10426 rt_bound_error_msg
= tcc_get_symbol_err(s1
, "__bound_error_msg");
10428 /* XXX: use .init section so that it also work in binary ? */
10429 bound_init
= (void *)tcc_get_symbol_err(s1
, "__bound_init");
10433 ret
= (*prog_main
)(argc
, argv
);
10438 void tcc_memstats(void)
10441 printf("memory in use: %d\n", mem_cur_size
);
10445 static void tcc_cleanup(void)
10449 if (NULL
== tcc_state
)
10453 /* free -D defines */
10454 free_defines(NULL
);
10457 n
= tok_ident
- TOK_IDENT
;
10458 for(i
= 0; i
< n
; i
++)
10459 tcc_free(table_ident
[i
]);
10460 tcc_free(table_ident
);
10462 /* free sym_pools */
10463 dynarray_reset(&sym_pools
, &nb_sym_pools
);
10464 /* string buffer */
10465 cstr_free(&tokcstr
);
10466 /* reset symbol stack */
10467 sym_free_first
= NULL
;
10468 /* cleanup from error/setjmp */
10472 TCCState
*tcc_new(void)
10481 s
= tcc_mallocz(sizeof(TCCState
));
10485 s
->output_type
= TCC_OUTPUT_MEMORY
;
10487 /* init isid table */
10488 for(i
=CH_EOF
;i
<256;i
++)
10489 isidnum_table
[i
-CH_EOF
] = isid(i
) || isnum(i
);
10491 /* add all tokens */
10492 table_ident
= NULL
;
10493 memset(hash_ident
, 0, TOK_HASH_SIZE
* sizeof(TokenSym
*));
10495 tok_ident
= TOK_IDENT
;
10504 ts
= tok_alloc(p
, r
- p
- 1);
10508 /* we add dummy defines for some special macros to speed up tests
10509 and to have working defined() */
10510 define_push(TOK___LINE__
, MACRO_OBJ
, NULL
, NULL
);
10511 define_push(TOK___FILE__
, MACRO_OBJ
, NULL
, NULL
);
10512 define_push(TOK___DATE__
, MACRO_OBJ
, NULL
, NULL
);
10513 define_push(TOK___TIME__
, MACRO_OBJ
, NULL
, NULL
);
10515 /* standard defines */
10516 tcc_define_symbol(s
, "__STDC__", NULL
);
10517 tcc_define_symbol(s
, "__STDC_VERSION__", "199901L");
10518 #if defined(TCC_TARGET_I386)
10519 tcc_define_symbol(s
, "__i386__", NULL
);
10521 #if defined(TCC_TARGET_X86_64)
10522 tcc_define_symbol(s
, "__x86_64__", NULL
);
10524 #if defined(TCC_TARGET_ARM)
10525 tcc_define_symbol(s
, "__ARM_ARCH_4__", NULL
);
10526 tcc_define_symbol(s
, "__arm_elf__", NULL
);
10527 tcc_define_symbol(s
, "__arm_elf", NULL
);
10528 tcc_define_symbol(s
, "arm_elf", NULL
);
10529 tcc_define_symbol(s
, "__arm__", NULL
);
10530 tcc_define_symbol(s
, "__arm", NULL
);
10531 tcc_define_symbol(s
, "arm", NULL
);
10532 tcc_define_symbol(s
, "__APCS_32__", NULL
);
10534 #ifdef TCC_TARGET_PE
10535 tcc_define_symbol(s
, "_WIN32", NULL
);
10537 tcc_define_symbol(s
, "__unix__", NULL
);
10538 tcc_define_symbol(s
, "__unix", NULL
);
10539 #if defined(__linux)
10540 tcc_define_symbol(s
, "__linux__", NULL
);
10541 tcc_define_symbol(s
, "__linux", NULL
);
10544 /* tiny C specific defines */
10545 tcc_define_symbol(s
, "__TINYC__", NULL
);
10547 /* tiny C & gcc defines */
10548 tcc_define_symbol(s
, "__SIZE_TYPE__", "unsigned int");
10549 tcc_define_symbol(s
, "__PTRDIFF_TYPE__", "int");
10550 #ifdef TCC_TARGET_PE
10551 tcc_define_symbol(s
, "__WCHAR_TYPE__", "unsigned short");
10553 tcc_define_symbol(s
, "__WCHAR_TYPE__", "int");
10556 #ifndef TCC_TARGET_PE
10557 /* default library paths */
10558 tcc_add_library_path(s
, CONFIG_SYSROOT
"/usr/local/lib");
10559 tcc_add_library_path(s
, CONFIG_SYSROOT
"/usr/lib");
10560 tcc_add_library_path(s
, CONFIG_SYSROOT
"/lib");
10563 /* no section zero */
10564 dynarray_add((void ***)&s
->sections
, &s
->nb_sections
, NULL
);
10566 /* create standard sections */
10567 text_section
= new_section(s
, ".text", SHT_PROGBITS
, SHF_ALLOC
| SHF_EXECINSTR
);
10568 data_section
= new_section(s
, ".data", SHT_PROGBITS
, SHF_ALLOC
| SHF_WRITE
);
10569 bss_section
= new_section(s
, ".bss", SHT_NOBITS
, SHF_ALLOC
| SHF_WRITE
);
10571 /* symbols are always generated for linking stage */
10572 symtab_section
= new_symtab(s
, ".symtab", SHT_SYMTAB
, 0,
10574 ".hashtab", SHF_PRIVATE
);
10575 strtab_section
= symtab_section
->link
;
10577 /* private symbol table for dynamic symbols */
10578 s
->dynsymtab_section
= new_symtab(s
, ".dynsymtab", SHT_SYMTAB
, SHF_PRIVATE
,
10580 ".dynhashtab", SHF_PRIVATE
);
10581 s
->alacarte_link
= 1;
10583 #ifdef CHAR_IS_UNSIGNED
10584 s
->char_is_unsigned
= 1;
10586 #if defined(TCC_TARGET_PE) && 0
10587 /* XXX: currently the PE linker is not ready to support that */
10588 s
->leading_underscore
= 1;
10593 void tcc_delete(TCCState
*s1
)
10599 /* free all sections */
10600 for(i
= 1; i
< s1
->nb_sections
; i
++)
10601 free_section(s1
->sections
[i
]);
10602 dynarray_reset(&s1
->sections
, &s1
->nb_sections
);
10604 for(i
= 0; i
< s1
->nb_priv_sections
; i
++)
10605 free_section(s1
->priv_sections
[i
]);
10606 dynarray_reset(&s1
->priv_sections
, &s1
->nb_priv_sections
);
10608 /* free any loaded DLLs */
10609 for ( i
= 0; i
< s1
->nb_loaded_dlls
; i
++) {
10610 DLLReference
*ref
= s1
->loaded_dlls
[i
];
10612 dlclose(ref
->handle
);
10615 /* free loaded dlls array */
10616 dynarray_reset(&s1
->loaded_dlls
, &s1
->nb_loaded_dlls
);
10618 /* free library paths */
10619 dynarray_reset(&s1
->library_paths
, &s1
->nb_library_paths
);
10621 /* free include paths */
10622 dynarray_reset(&s1
->cached_includes
, &s1
->nb_cached_includes
);
10623 dynarray_reset(&s1
->include_paths
, &s1
->nb_include_paths
);
10624 dynarray_reset(&s1
->sysinclude_paths
, &s1
->nb_sysinclude_paths
);
10629 int tcc_add_include_path(TCCState
*s1
, const char *pathname
)
10633 pathname1
= tcc_strdup(pathname
);
10634 dynarray_add((void ***)&s1
->include_paths
, &s1
->nb_include_paths
, pathname1
);
10638 int tcc_add_sysinclude_path(TCCState
*s1
, const char *pathname
)
10642 pathname1
= tcc_strdup(pathname
);
10643 dynarray_add((void ***)&s1
->sysinclude_paths
, &s1
->nb_sysinclude_paths
, pathname1
);
10647 static int tcc_add_file_internal(TCCState
*s1
, const char *filename
, int flags
)
10652 BufferedFile
*saved_file
;
10654 /* find source file type with extension */
10655 ext
= tcc_fileextension(filename
);
10659 /* open the file */
10661 file
= tcc_open(s1
, filename
);
10663 if (flags
& AFF_PRINT_ERROR
) {
10664 error_noabort("file '%s' not found", filename
);
10670 if (flags
& AFF_PREPROCESS
) {
10671 ret
= tcc_preprocess(s1
);
10672 } else if (!ext
[0] || !PATHCMP(ext
, "c")) {
10673 /* C file assumed */
10674 ret
= tcc_compile(s1
);
10676 #ifdef CONFIG_TCC_ASM
10677 if (!strcmp(ext
, "S")) {
10678 /* preprocessed assembler */
10679 ret
= tcc_assemble(s1
, 1);
10680 } else if (!strcmp(ext
, "s")) {
10681 /* non preprocessed assembler */
10682 ret
= tcc_assemble(s1
, 0);
10685 #ifdef TCC_TARGET_PE
10686 if (!PATHCMP(ext
, "def")) {
10687 ret
= pe_load_def_file(s1
, file
->fd
);
10692 /* assume executable format: auto guess file type */
10693 ret
= read(fd
, &ehdr
, sizeof(ehdr
));
10694 lseek(fd
, 0, SEEK_SET
);
10696 error_noabort("could not read header");
10698 } else if (ret
!= sizeof(ehdr
)) {
10699 goto try_load_script
;
10702 if (ehdr
.e_ident
[0] == ELFMAG0
&&
10703 ehdr
.e_ident
[1] == ELFMAG1
&&
10704 ehdr
.e_ident
[2] == ELFMAG2
&&
10705 ehdr
.e_ident
[3] == ELFMAG3
) {
10706 file
->line_num
= 0; /* do not display line number if error */
10707 if (ehdr
.e_type
== ET_REL
) {
10708 ret
= tcc_load_object_file(s1
, fd
, 0);
10709 } else if (ehdr
.e_type
== ET_DYN
) {
10710 if (s1
->output_type
== TCC_OUTPUT_MEMORY
) {
10711 #ifdef TCC_TARGET_PE
10715 h
= dlopen(filename
, RTLD_GLOBAL
| RTLD_LAZY
);
10722 ret
= tcc_load_dll(s1
, fd
, filename
,
10723 (flags
& AFF_REFERENCED_DLL
) != 0);
10726 error_noabort("unrecognized ELF file");
10729 } else if (memcmp((char *)&ehdr
, ARMAG
, 8) == 0) {
10730 file
->line_num
= 0; /* do not display line number if error */
10731 ret
= tcc_load_archive(s1
, fd
);
10733 #ifdef TCC_TARGET_COFF
10734 if (*(uint16_t *)(&ehdr
) == COFF_C67_MAGIC
) {
10735 ret
= tcc_load_coff(s1
, fd
);
10738 #ifdef TCC_TARGET_PE
10739 if (pe_test_res_file(&ehdr
, ret
)) {
10740 ret
= pe_load_res_file(s1
, fd
);
10744 /* as GNU ld, consider it is an ld script if not recognized */
10746 ret
= tcc_load_ldscript(s1
);
10748 error_noabort("unrecognized file type");
10763 int tcc_add_file(TCCState
*s
, const char *filename
)
10765 return tcc_add_file_internal(s
, filename
, AFF_PRINT_ERROR
);
10768 int tcc_add_library_path(TCCState
*s
, const char *pathname
)
10772 pathname1
= tcc_strdup(pathname
);
10773 dynarray_add((void ***)&s
->library_paths
, &s
->nb_library_paths
, pathname1
);
10777 /* find and load a dll. Return non zero if not found */
10778 /* XXX: add '-rpath' option support ? */
10779 static int tcc_add_dll(TCCState
*s
, const char *filename
, int flags
)
10784 for(i
= 0; i
< s
->nb_library_paths
; i
++) {
10785 snprintf(buf
, sizeof(buf
), "%s/%s",
10786 s
->library_paths
[i
], filename
);
10787 if (tcc_add_file_internal(s
, buf
, flags
) == 0)
10793 /* the library name is the same as the argument of the '-l' option */
10794 int tcc_add_library(TCCState
*s
, const char *libraryname
)
10799 /* first we look for the dynamic library if not static linking */
10800 if (!s
->static_link
) {
10801 #ifdef TCC_TARGET_PE
10802 snprintf(buf
, sizeof(buf
), "%s.def", libraryname
);
10804 snprintf(buf
, sizeof(buf
), "lib%s.so", libraryname
);
10806 if (tcc_add_dll(s
, buf
, 0) == 0)
10810 /* then we look for the static library */
10811 for(i
= 0; i
< s
->nb_library_paths
; i
++) {
10812 snprintf(buf
, sizeof(buf
), "%s/lib%s.a",
10813 s
->library_paths
[i
], libraryname
);
10814 if (tcc_add_file_internal(s
, buf
, 0) == 0)
10820 int tcc_add_symbol(TCCState
*s
, const char *name
, void *val
)
10822 add_elf_sym(symtab_section
, (unsigned long)val
, 0,
10823 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
10828 int tcc_set_output_type(TCCState
*s
, int output_type
)
10832 s
->output_type
= output_type
;
10834 if (!s
->nostdinc
) {
10835 /* default include paths */
10836 /* XXX: reverse order needed if -isystem support */
10837 #ifndef TCC_TARGET_PE
10838 tcc_add_sysinclude_path(s
, CONFIG_SYSROOT
"/usr/local/include");
10839 tcc_add_sysinclude_path(s
, CONFIG_SYSROOT
"/usr/include");
10841 snprintf(buf
, sizeof(buf
), "%s/include", tcc_lib_path
);
10842 tcc_add_sysinclude_path(s
, buf
);
10843 #ifdef TCC_TARGET_PE
10844 snprintf(buf
, sizeof(buf
), "%s/include/winapi", tcc_lib_path
);
10845 tcc_add_sysinclude_path(s
, buf
);
10849 /* if bound checking, then add corresponding sections */
10850 #ifdef CONFIG_TCC_BCHECK
10851 if (do_bounds_check
) {
10852 /* define symbol */
10853 tcc_define_symbol(s
, "__BOUNDS_CHECKING_ON", NULL
);
10854 /* create bounds sections */
10855 bounds_section
= new_section(s
, ".bounds",
10856 SHT_PROGBITS
, SHF_ALLOC
);
10857 lbounds_section
= new_section(s
, ".lbounds",
10858 SHT_PROGBITS
, SHF_ALLOC
);
10862 if (s
->char_is_unsigned
) {
10863 tcc_define_symbol(s
, "__CHAR_UNSIGNED__", NULL
);
10866 /* add debug sections */
10869 stab_section
= new_section(s
, ".stab", SHT_PROGBITS
, 0);
10870 stab_section
->sh_entsize
= sizeof(Stab_Sym
);
10871 stabstr_section
= new_section(s
, ".stabstr", SHT_STRTAB
, 0);
10872 put_elf_str(stabstr_section
, "");
10873 stab_section
->link
= stabstr_section
;
10874 /* put first entry */
10875 put_stabs("", 0, 0, 0, 0);
10878 /* add libc crt1/crti objects */
10879 #ifndef TCC_TARGET_PE
10880 if ((output_type
== TCC_OUTPUT_EXE
|| output_type
== TCC_OUTPUT_DLL
) &&
10882 if (output_type
!= TCC_OUTPUT_DLL
)
10883 tcc_add_file(s
, CONFIG_TCC_CRT_PREFIX
"/crt1.o");
10884 tcc_add_file(s
, CONFIG_TCC_CRT_PREFIX
"/crti.o");
10888 #ifdef TCC_TARGET_PE
10889 snprintf(buf
, sizeof(buf
), "%s/lib", tcc_lib_path
);
10890 tcc_add_library_path(s
, buf
);
10896 #define WD_ALL 0x0001 /* warning is activated when using -Wall */
10897 #define FD_INVERT 0x0002 /* invert value before storing */
10899 typedef struct FlagDef
{
10905 static const FlagDef warning_defs
[] = {
10906 { offsetof(TCCState
, warn_unsupported
), 0, "unsupported" },
10907 { offsetof(TCCState
, warn_write_strings
), 0, "write-strings" },
10908 { offsetof(TCCState
, warn_error
), 0, "error" },
10909 { offsetof(TCCState
, warn_implicit_function_declaration
), WD_ALL
,
10910 "implicit-function-declaration" },
10913 static int set_flag(TCCState
*s
, const FlagDef
*flags
, int nb_flags
,
10914 const char *name
, int value
)
10921 if (r
[0] == 'n' && r
[1] == 'o' && r
[2] == '-') {
10925 for(i
= 0, p
= flags
; i
< nb_flags
; i
++, p
++) {
10926 if (!strcmp(r
, p
->name
))
10931 if (p
->flags
& FD_INVERT
)
10933 *(int *)((uint8_t *)s
+ p
->offset
) = value
;
10938 /* set/reset a warning */
10939 int tcc_set_warning(TCCState
*s
, const char *warning_name
, int value
)
10944 if (!strcmp(warning_name
, "all")) {
10945 for(i
= 0, p
= warning_defs
; i
< countof(warning_defs
); i
++, p
++) {
10946 if (p
->flags
& WD_ALL
)
10947 *(int *)((uint8_t *)s
+ p
->offset
) = 1;
10951 return set_flag(s
, warning_defs
, countof(warning_defs
),
10952 warning_name
, value
);
10956 static const FlagDef flag_defs
[] = {
10957 { offsetof(TCCState
, char_is_unsigned
), 0, "unsigned-char" },
10958 { offsetof(TCCState
, char_is_unsigned
), FD_INVERT
, "signed-char" },
10959 { offsetof(TCCState
, nocommon
), FD_INVERT
, "common" },
10960 { offsetof(TCCState
, leading_underscore
), 0, "leading-underscore" },
10963 /* set/reset a flag */
10964 int tcc_set_flag(TCCState
*s
, const char *flag_name
, int value
)
10966 return set_flag(s
, flag_defs
, countof(flag_defs
),
10970 /* set CONFIG_TCCDIR at runtime */
10971 void tcc_set_lib_path(TCCState
*s
, const char *path
)
10973 tcc_lib_path
= tcc_strdup(path
);
10976 #if !defined(LIBTCC)
10978 static int64_t getclock_us(void)
10983 return (tb
.time
* 1000LL + tb
.millitm
) * 1000LL;
10986 gettimeofday(&tv
, NULL
);
10987 return tv
.tv_sec
* 1000000LL + tv
.tv_usec
;
10993 printf("tcc version " TCC_VERSION
" - Tiny C Compiler - Copyright (C) 2001-2006 Fabrice Bellard\n"
10994 "usage: tcc [-v] [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
10995 " [-Wwarn] [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-soname name]\n"
10996 " [-static] [infile1 infile2...] [-run infile args...]\n"
10998 "General options:\n"
10999 " -v display current version, increase verbosity\n"
11000 " -c compile only - generate an object file\n"
11001 " -o outfile set output filename\n"
11002 " -Bdir set tcc internal library path\n"
11003 " -bench output compilation statistics\n"
11004 " -run run compiled source\n"
11005 " -fflag set or reset (with 'no-' prefix) 'flag' (see man page)\n"
11006 " -Wwarning set or reset (with 'no-' prefix) 'warning' (see man page)\n"
11007 " -w disable all warnings\n"
11008 "Preprocessor options:\n"
11009 " -E preprocess only\n"
11010 " -Idir add include path 'dir'\n"
11011 " -Dsym[=val] define 'sym' with value 'val'\n"
11012 " -Usym undefine 'sym'\n"
11013 "Linker options:\n"
11014 " -Ldir add library path 'dir'\n"
11015 " -llib link with dynamic or static library 'lib'\n"
11016 " -shared generate a shared library\n"
11017 " -soname set name for shared library to be used at runtime\n"
11018 " -static static linking\n"
11019 " -rdynamic export all global symbols to dynamic linker\n"
11020 " -r generate (relocatable) object file\n"
11021 "Debugger options:\n"
11022 " -g generate runtime debug info\n"
11023 #ifdef CONFIG_TCC_BCHECK
11024 " -b compile with built-in memory and bounds checker (implies -g)\n"
11026 " -bt N show N callers in stack traces\n"
11030 #define TCC_OPTION_HAS_ARG 0x0001
11031 #define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
11033 typedef struct TCCOption
{
11062 TCC_OPTION_nostdinc
,
11063 TCC_OPTION_nostdlib
,
11064 TCC_OPTION_print_search_dirs
,
11065 TCC_OPTION_rdynamic
,
11073 static const TCCOption tcc_options
[] = {
11074 { "h", TCC_OPTION_HELP
, 0 },
11075 { "?", TCC_OPTION_HELP
, 0 },
11076 { "I", TCC_OPTION_I
, TCC_OPTION_HAS_ARG
},
11077 { "D", TCC_OPTION_D
, TCC_OPTION_HAS_ARG
},
11078 { "U", TCC_OPTION_U
, TCC_OPTION_HAS_ARG
},
11079 { "L", TCC_OPTION_L
, TCC_OPTION_HAS_ARG
},
11080 { "B", TCC_OPTION_B
, TCC_OPTION_HAS_ARG
},
11081 { "l", TCC_OPTION_l
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
11082 { "bench", TCC_OPTION_bench
, 0 },
11083 { "bt", TCC_OPTION_bt
, TCC_OPTION_HAS_ARG
},
11084 #ifdef CONFIG_TCC_BCHECK
11085 { "b", TCC_OPTION_b
, 0 },
11087 { "g", TCC_OPTION_g
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
11088 { "c", TCC_OPTION_c
, 0 },
11089 { "static", TCC_OPTION_static
, 0 },
11090 { "shared", TCC_OPTION_shared
, 0 },
11091 { "soname", TCC_OPTION_soname
, TCC_OPTION_HAS_ARG
},
11092 { "o", TCC_OPTION_o
, TCC_OPTION_HAS_ARG
},
11093 { "run", TCC_OPTION_run
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
11094 { "rdynamic", TCC_OPTION_rdynamic
, 0 },
11095 { "r", TCC_OPTION_r
, 0 },
11096 { "Wl,", TCC_OPTION_Wl
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
11097 { "W", TCC_OPTION_W
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
11098 { "O", TCC_OPTION_O
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
11099 { "m", TCC_OPTION_m
, TCC_OPTION_HAS_ARG
},
11100 { "f", TCC_OPTION_f
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
11101 { "nostdinc", TCC_OPTION_nostdinc
, 0 },
11102 { "nostdlib", TCC_OPTION_nostdlib
, 0 },
11103 { "print-search-dirs", TCC_OPTION_print_search_dirs
, 0 },
11104 { "v", TCC_OPTION_v
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
11105 { "w", TCC_OPTION_w
, 0 },
11106 { "pipe", TCC_OPTION_pipe
, 0},
11107 { "E", TCC_OPTION_E
, 0},
11111 /* convert 'str' into an array of space separated strings */
11112 static int expand_args(char ***pargv
, const char *str
)
11121 while (is_space(*str
))
11126 while (*str
!= '\0' && !is_space(*str
))
11129 arg
= tcc_malloc(len
+ 1);
11130 memcpy(arg
, s1
, len
);
11132 dynarray_add((void ***)&argv
, &argc
, arg
);
11138 static char **files
;
11139 static int nb_files
, nb_libraries
;
11140 static int multiple_files
;
11141 static int print_search_dirs
;
11142 static int output_type
;
11143 static int reloc_output
;
11144 static const char *outfile
;
11146 int parse_args(TCCState
*s
, int argc
, char **argv
)
11149 const TCCOption
*popt
;
11150 const char *optarg
, *p1
, *r1
;
11154 while (optind
< argc
) {
11156 r
= argv
[optind
++];
11157 if (r
[0] != '-' || r
[1] == '\0') {
11158 /* add a new file */
11159 dynarray_add((void ***)&files
, &nb_files
, r
);
11160 if (!multiple_files
) {
11162 /* argv[0] will be this file */
11166 /* find option in table (match only the first chars */
11167 popt
= tcc_options
;
11171 error("invalid option -- '%s'", r
);
11184 if (popt
->flags
& TCC_OPTION_HAS_ARG
) {
11185 if (*r1
!= '\0' || (popt
->flags
& TCC_OPTION_NOSEP
)) {
11188 if (optind
>= argc
)
11189 error("argument to '%s' is missing", r
);
11190 optarg
= argv
[optind
++];
11198 switch(popt
->index
) {
11199 case TCC_OPTION_HELP
:
11203 if (tcc_add_include_path(s
, optarg
) < 0)
11204 error("too many include paths");
11209 sym
= (char *)optarg
;
11210 value
= strchr(sym
, '=');
11215 tcc_define_symbol(s
, sym
, value
);
11219 tcc_undefine_symbol(s
, optarg
);
11222 tcc_add_library_path(s
, optarg
);
11225 /* set tcc utilities path (mainly for tcc development) */
11226 tcc_set_lib_path(s
, optarg
);
11229 dynarray_add((void ***)&files
, &nb_files
, r
);
11232 case TCC_OPTION_bench
:
11235 case TCC_OPTION_bt
:
11236 num_callers
= atoi(optarg
);
11238 #ifdef CONFIG_TCC_BCHECK
11240 do_bounds_check
= 1;
11248 multiple_files
= 1;
11249 output_type
= TCC_OUTPUT_OBJ
;
11251 case TCC_OPTION_static
:
11252 s
->static_link
= 1;
11254 case TCC_OPTION_shared
:
11255 output_type
= TCC_OUTPUT_DLL
;
11257 case TCC_OPTION_soname
:
11258 s
->soname
= optarg
;
11261 multiple_files
= 1;
11265 /* generate a .o merging several output files */
11267 output_type
= TCC_OUTPUT_OBJ
;
11269 case TCC_OPTION_nostdinc
:
11272 case TCC_OPTION_nostdlib
:
11275 case TCC_OPTION_print_search_dirs
:
11276 print_search_dirs
= 1;
11278 case TCC_OPTION_run
:
11282 argc1
= expand_args(&argv1
, optarg
);
11284 parse_args(s
, argc1
, argv1
);
11286 multiple_files
= 0;
11287 output_type
= TCC_OUTPUT_MEMORY
;
11292 if (0 == verbose
++)
11293 printf("tcc version %s\n", TCC_VERSION
);
11294 } while (*optarg
++ == 'v');
11297 if (tcc_set_flag(s
, optarg
, 1) < 0 && s
->warn_unsupported
)
11298 goto unsupported_option
;
11301 if (tcc_set_warning(s
, optarg
, 1) < 0 &&
11302 s
->warn_unsupported
)
11303 goto unsupported_option
;
11308 case TCC_OPTION_rdynamic
:
11311 case TCC_OPTION_Wl
:
11314 if (strstart(optarg
, "-Ttext,", &p
)) {
11315 s
->text_addr
= strtoul(p
, NULL
, 16);
11316 s
->has_text_addr
= 1;
11317 } else if (strstart(optarg
, "--oformat,", &p
)) {
11318 if (strstart(p
, "elf32-", NULL
)) {
11319 s
->output_format
= TCC_OUTPUT_FORMAT_ELF
;
11320 } else if (!strcmp(p
, "binary")) {
11321 s
->output_format
= TCC_OUTPUT_FORMAT_BINARY
;
11323 #ifdef TCC_TARGET_COFF
11324 if (!strcmp(p
, "coff")) {
11325 s
->output_format
= TCC_OUTPUT_FORMAT_COFF
;
11329 error("target %s not found", p
);
11332 error("unsupported linker option '%s'", optarg
);
11337 output_type
= TCC_OUTPUT_PREPROCESS
;
11340 if (s
->warn_unsupported
) {
11341 unsupported_option
:
11342 warning("unsupported option '%s'", r
);
11351 int main(int argc
, char **argv
)
11355 int nb_objfiles
, ret
, optind
;
11356 char objfilename
[1024];
11357 int64_t start_time
= 0;
11361 tcc_set_lib_path_w32(s
);
11363 output_type
= TCC_OUTPUT_EXE
;
11365 multiple_files
= 1;
11370 print_search_dirs
= 0;
11373 optind
= parse_args(s
, argc
- 1, argv
+ 1);
11374 if (print_search_dirs
) {
11375 /* enough for Linux kernel */
11376 printf("install: %s/\n", tcc_lib_path
);
11379 if (optind
== 0 || nb_files
== 0) {
11380 if (optind
&& verbose
)
11386 nb_objfiles
= nb_files
- nb_libraries
;
11388 /* if outfile provided without other options, we output an
11390 if (outfile
&& output_type
== TCC_OUTPUT_MEMORY
)
11391 output_type
= TCC_OUTPUT_EXE
;
11393 /* check -c consistency : only single file handled. XXX: checks file type */
11394 if (output_type
== TCC_OUTPUT_OBJ
&& !reloc_output
) {
11395 /* accepts only a single input file */
11396 if (nb_objfiles
!= 1)
11397 error("cannot specify multiple files with -c");
11398 if (nb_libraries
!= 0)
11399 error("cannot specify libraries with -c");
11403 if (output_type
== TCC_OUTPUT_PREPROCESS
) {
11405 s
->outfile
= stdout
;
11407 s
->outfile
= fopen(outfile
, "w");
11409 error("could not open '%s", outfile
);
11411 } else if (output_type
!= TCC_OUTPUT_MEMORY
) {
11413 /* compute default outfile name */
11416 strcmp(files
[0], "-") == 0 ? "a" : tcc_basename(files
[0]);
11417 pstrcpy(objfilename
, sizeof(objfilename
), name
);
11418 ext
= tcc_fileextension(objfilename
);
11419 #ifdef TCC_TARGET_PE
11420 if (output_type
== TCC_OUTPUT_DLL
)
11421 strcpy(ext
, ".dll");
11423 if (output_type
== TCC_OUTPUT_EXE
)
11424 strcpy(ext
, ".exe");
11427 if (output_type
== TCC_OUTPUT_OBJ
&& !reloc_output
&& *ext
)
11430 pstrcpy(objfilename
, sizeof(objfilename
), "a.out");
11431 outfile
= objfilename
;
11436 start_time
= getclock_us();
11439 tcc_set_output_type(s
, output_type
);
11441 /* compile or add each files or library */
11442 for(i
= 0; i
< nb_files
&& ret
== 0; i
++) {
11443 const char *filename
;
11445 filename
= files
[i
];
11446 if (output_type
== TCC_OUTPUT_PREPROCESS
) {
11447 if (tcc_add_file_internal(s
, filename
,
11448 AFF_PRINT_ERROR
| AFF_PREPROCESS
) < 0)
11450 } else if (filename
[0] == '-' && filename
[1]) {
11451 if (tcc_add_library(s
, filename
+ 2) < 0)
11452 error("cannot find %s", filename
);
11455 printf("-> %s\n", filename
);
11456 if (tcc_add_file(s
, filename
) < 0)
11461 /* free all files */
11469 total_time
= (double)(getclock_us() - start_time
) / 1000000.0;
11470 if (total_time
< 0.001)
11471 total_time
= 0.001;
11472 if (total_bytes
< 1)
11474 printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
11475 tok_ident
- TOK_IDENT
, total_lines
, total_bytes
,
11476 total_time
, (int)(total_lines
/ total_time
),
11477 total_bytes
/ total_time
/ 1000000.0);
11480 if (s
->output_type
== TCC_OUTPUT_PREPROCESS
) {
11482 fclose(s
->outfile
);
11483 } else if (s
->output_type
== TCC_OUTPUT_MEMORY
) {
11484 ret
= tcc_run(s
, argc
- optind
, argv
+ optind
);
11486 ret
= tcc_output_file(s
, outfile
) ? 1 : 0;
11488 /* XXX: cannot do it with bound checking because of the malloc hooks */
11489 if (!do_bounds_check
)
11494 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size
, mem_max_size
);