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 char *w32_tcc_lib_path(void)
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 return strdup(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 *macro_ptr1
, *start_macro_ptr
, *ptr
, *saved_macro_ptr
;
4434 const char *p1
, *p2
;
4436 TokenString macro_str1
;
4439 start_macro_ptr
= macro_str
;
4440 /* we search the first '##' */
4442 macro_ptr1
= macro_str
;
4443 TOK_GET(t
, macro_str
, cval
);
4444 /* nothing more to do if end of string */
4447 if (*macro_str
== TOK_TWOSHARPS
)
4451 /* we saw '##', so we need more processing to handle it */
4453 tok_str_new(¯o_str1
);
4457 /* add all tokens seen so far */
4458 for(ptr
= start_macro_ptr
; ptr
< macro_ptr1
;) {
4459 TOK_GET(t
, ptr
, cval
);
4460 tok_str_add2(¯o_str1
, t
, &cval
);
4462 saved_macro_ptr
= macro_ptr
;
4463 /* XXX: get rid of the use of macro_ptr here */
4464 macro_ptr
= (int *)macro_str
;
4466 while (*macro_ptr
== TOK_TWOSHARPS
) {
4468 macro_ptr1
= macro_ptr
;
4471 TOK_GET(t
, macro_ptr
, cval
);
4472 /* We concatenate the two tokens if we have an
4473 identifier or a preprocessing number */
4475 p1
= get_tok_str(tok
, &tokc
);
4476 cstr_cat(&cstr
, p1
);
4477 p2
= get_tok_str(t
, &cval
);
4478 cstr_cat(&cstr
, p2
);
4479 cstr_ccat(&cstr
, '\0');
4481 if ((tok
>= TOK_IDENT
|| tok
== TOK_PPNUM
) &&
4482 (t
>= TOK_IDENT
|| t
== TOK_PPNUM
)) {
4483 if (tok
== TOK_PPNUM
) {
4484 /* if number, then create a number token */
4485 /* NOTE: no need to allocate because
4486 tok_str_add2() does it */
4487 cstr_reset(&tokcstr
);
4490 tokc
.cstr
= &tokcstr
;
4492 /* if identifier, we must do a test to
4493 validate we have a correct identifier */
4494 if (t
== TOK_PPNUM
) {
4504 if (!isnum(c
) && !isid(c
))
4508 ts
= tok_alloc(cstr
.data
, strlen(cstr
.data
));
4509 tok
= ts
->tok
; /* modify current token */
4512 const char *str
= cstr
.data
;
4513 const unsigned char *q
;
4515 /* we look for a valid token */
4516 /* XXX: do more extensive checks */
4517 if (!strcmp(str
, ">>=")) {
4519 } else if (!strcmp(str
, "<<=")) {
4521 } else if (strlen(str
) == 2) {
4522 /* search in two bytes table */
4527 if (q
[0] == str
[0] && q
[1] == str
[1])
4534 /* NOTE: because get_tok_str use a static buffer,
4537 p1
= get_tok_str(tok
, &tokc
);
4538 cstr_cat(&cstr
, p1
);
4539 cstr_ccat(&cstr
, '\0');
4540 p2
= get_tok_str(t
, &cval
);
4541 warning("pasting \"%s\" and \"%s\" does not give a valid preprocessing token", cstr
.data
, p2
);
4542 /* cannot merge tokens: just add them separately */
4543 tok_str_add2(¯o_str1
, tok
, &tokc
);
4544 /* XXX: free associated memory ? */
4551 tok_str_add2(¯o_str1
, tok
, &tokc
);
4556 macro_ptr
= (int *)saved_macro_ptr
;
4558 tok_str_add(¯o_str1
, 0);
4559 return macro_str1
.str
;
4563 /* do macro substitution of macro_str and add result to
4564 (tok_str,tok_len). 'nested_list' is the list of all macros we got
4565 inside to avoid recursing. */
4566 static void macro_subst(TokenString
*tok_str
, Sym
**nested_list
,
4567 const int *macro_str
, struct macro_level
** can_read_stream
)
4574 struct macro_level ml
;
4576 /* first scan for '##' operator handling */
4578 macro_str1
= macro_twosharps(ptr
);
4583 /* NOTE: ptr == NULL can only happen if tokens are read from
4584 file stream due to a macro function call */
4587 TOK_GET(t
, ptr
, cval
);
4592 /* if nested substitution, do nothing */
4593 if (sym_find2(*nested_list
, t
))
4596 if (can_read_stream
)
4597 ml
.prev
= *can_read_stream
, *can_read_stream
= &ml
;
4598 macro_ptr
= (int *)ptr
;
4600 ret
= macro_subst_tok(tok_str
, nested_list
, s
, can_read_stream
);
4601 ptr
= (int *)macro_ptr
;
4603 if (can_read_stream
&& *can_read_stream
== &ml
)
4604 *can_read_stream
= ml
.prev
;
4609 if (!check_space(t
, &spc
))
4610 tok_str_add2(tok_str
, t
, &cval
);
4614 tok_str_free(macro_str1
);
4617 /* return next token with macro substitution */
4618 static void next(void)
4620 Sym
*nested_list
, *s
;
4622 struct macro_level
*ml
;
4625 if (parse_flags
& PARSE_FLAG_SPACES
)
4630 /* if not reading from macro substituted string, then try
4631 to substitute macros */
4632 if (tok
>= TOK_IDENT
&&
4633 (parse_flags
& PARSE_FLAG_PREPROCESS
)) {
4634 s
= define_find(tok
);
4636 /* we have a macro: we try to substitute */
4640 if (macro_subst_tok(&str
, &nested_list
, s
, &ml
) == 0) {
4641 /* substitution done, NOTE: maybe empty */
4642 tok_str_add(&str
, 0);
4643 macro_ptr
= str
.str
;
4644 macro_ptr_allocated
= str
.str
;
4651 /* end of macro or end of unget buffer */
4652 if (unget_buffer_enabled
) {
4653 macro_ptr
= unget_saved_macro_ptr
;
4654 unget_buffer_enabled
= 0;
4656 /* end of macro string: free it */
4657 tok_str_free(macro_ptr_allocated
);
4664 /* convert preprocessor tokens into C tokens */
4665 if (tok
== TOK_PPNUM
&&
4666 (parse_flags
& PARSE_FLAG_TOK_NUM
)) {
4667 parse_number((char *)tokc
.cstr
->data
);
4671 /* push back current token and set current token to 'last_tok'. Only
4672 identifier case handled for labels. */
4673 static inline void unget_tok(int last_tok
)
4677 unget_saved_macro_ptr
= macro_ptr
;
4678 unget_buffer_enabled
= 1;
4679 q
= unget_saved_buffer
;
4682 n
= tok_ext_size(tok
) - 1;
4685 *q
= 0; /* end of token string */
4690 void swap(int *p
, int *q
)
4698 void vsetc(CType
*type
, int r
, CValue
*vc
)
4702 if (vtop
>= vstack
+ (VSTACK_SIZE
- 1))
4703 error("memory full");
4704 /* cannot let cpu flags if other instruction are generated. Also
4705 avoid leaving VT_JMP anywhere except on the top of the stack
4706 because it would complicate the code generator. */
4707 if (vtop
>= vstack
) {
4708 v
= vtop
->r
& VT_VALMASK
;
4709 if (v
== VT_CMP
|| (v
& ~1) == VT_JMP
)
4715 vtop
->r2
= VT_CONST
;
4719 /* push integer constant */
4724 vsetc(&int_type
, VT_CONST
, &cval
);
4727 /* push long long constant */
4728 void vpushll(long long v
)
4734 vsetc(&ctype
, VT_CONST
, &cval
);
4737 /* Return a static symbol pointing to a section */
4738 static Sym
*get_sym_ref(CType
*type
, Section
*sec
,
4739 unsigned long offset
, unsigned long size
)
4745 sym
= global_identifier_push(v
, type
->t
| VT_STATIC
, 0);
4746 sym
->type
.ref
= type
->ref
;
4747 sym
->r
= VT_CONST
| VT_SYM
;
4748 put_extern_sym(sym
, sec
, offset
, size
);
4752 /* push a reference to a section offset by adding a dummy symbol */
4753 static void vpush_ref(CType
*type
, Section
*sec
, unsigned long offset
, unsigned long size
)
4758 vsetc(type
, VT_CONST
| VT_SYM
, &cval
);
4759 vtop
->sym
= get_sym_ref(type
, sec
, offset
, size
);
4762 /* define a new external reference to a symbol 'v' of type 'u' */
4763 static Sym
*external_global_sym(int v
, CType
*type
, int r
)
4769 /* push forward reference */
4770 s
= global_identifier_push(v
, type
->t
| VT_EXTERN
, 0);
4771 s
->type
.ref
= type
->ref
;
4772 s
->r
= r
| VT_CONST
| VT_SYM
;
4777 /* define a new external reference to a symbol 'v' of type 'u' */
4778 static Sym
*external_sym(int v
, CType
*type
, int r
)
4784 /* push forward reference */
4785 s
= sym_push(v
, type
, r
| VT_CONST
| VT_SYM
, 0);
4786 s
->type
.t
|= VT_EXTERN
;
4788 if (!is_compatible_types(&s
->type
, type
))
4789 error("incompatible types for redefinition of '%s'",
4790 get_tok_str(v
, NULL
));
4795 /* push a reference to global symbol v */
4796 static void vpush_global_sym(CType
*type
, int v
)
4801 sym
= external_global_sym(v
, type
, 0);
4803 vsetc(type
, VT_CONST
| VT_SYM
, &cval
);
4807 void vset(CType
*type
, int r
, int v
)
4812 vsetc(type
, r
, &cval
);
4815 void vseti(int r
, int v
)
4831 void vpushv(SValue
*v
)
4833 if (vtop
>= vstack
+ (VSTACK_SIZE
- 1))
4834 error("memory full");
4844 /* save r to the memory stack, and mark it as being free */
4845 void save_reg(int r
)
4847 int l
, saved
, size
, align
;
4851 /* modify all stack values */
4854 for(p
=vstack
;p
<=vtop
;p
++) {
4855 if ((p
->r
& VT_VALMASK
) == r
||
4856 ((p
->type
.t
& VT_BTYPE
) == VT_LLONG
&& (p
->r2
& VT_VALMASK
) == r
)) {
4857 /* must save value on stack if not already done */
4859 /* NOTE: must reload 'r' because r might be equal to r2 */
4860 r
= p
->r
& VT_VALMASK
;
4861 /* store register in the stack */
4863 if ((p
->r
& VT_LVAL
) ||
4864 (!is_float(type
->t
) && (type
->t
& VT_BTYPE
) != VT_LLONG
))
4865 #ifdef TCC_TARGET_X86_64
4866 type
= &char_pointer_type
;
4870 size
= type_size(type
, &align
);
4871 loc
= (loc
- size
) & -align
;
4872 sv
.type
.t
= type
->t
;
4873 sv
.r
= VT_LOCAL
| VT_LVAL
;
4876 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
4877 /* x86 specific: need to pop fp register ST0 if saved */
4878 if (r
== TREG_ST0
) {
4879 o(0xd9dd); /* fstp %st(1) */
4882 #ifndef TCC_TARGET_X86_64
4883 /* special long long case */
4884 if ((type
->t
& VT_BTYPE
) == VT_LLONG
) {
4892 /* mark that stack entry as being saved on the stack */
4893 if (p
->r
& VT_LVAL
) {
4894 /* also clear the bounded flag because the
4895 relocation address of the function was stored in
4897 p
->r
= (p
->r
& ~(VT_VALMASK
| VT_BOUNDED
)) | VT_LLOCAL
;
4899 p
->r
= lvalue_type(p
->type
.t
) | VT_LOCAL
;
4907 /* find a register of class 'rc2' with at most one reference on stack.
4908 * If none, call get_reg(rc) */
4909 int get_reg_ex(int rc
, int rc2
)
4914 for(r
=0;r
<NB_REGS
;r
++) {
4915 if (reg_classes
[r
] & rc2
) {
4918 for(p
= vstack
; p
<= vtop
; p
++) {
4919 if ((p
->r
& VT_VALMASK
) == r
||
4920 (p
->r2
& VT_VALMASK
) == r
)
4930 /* find a free register of class 'rc'. If none, save one register */
4936 /* find a free register */
4937 for(r
=0;r
<NB_REGS
;r
++) {
4938 if (reg_classes
[r
] & rc
) {
4939 for(p
=vstack
;p
<=vtop
;p
++) {
4940 if ((p
->r
& VT_VALMASK
) == r
||
4941 (p
->r2
& VT_VALMASK
) == r
)
4949 /* no register left : free the first one on the stack (VERY
4950 IMPORTANT to start from the bottom to ensure that we don't
4951 spill registers used in gen_opi()) */
4952 for(p
=vstack
;p
<=vtop
;p
++) {
4953 r
= p
->r
& VT_VALMASK
;
4954 if (r
< VT_CONST
&& (reg_classes
[r
] & rc
))
4956 /* also look at second register (if long long) */
4957 r
= p
->r2
& VT_VALMASK
;
4958 if (r
< VT_CONST
&& (reg_classes
[r
] & rc
)) {
4964 /* Should never comes here */
4968 /* save registers up to (vtop - n) stack entry */
4969 void save_regs(int n
)
4974 for(p
= vstack
;p
<= p1
; p
++) {
4975 r
= p
->r
& VT_VALMASK
;
4982 /* move register 's' to 'r', and flush previous value of r to memory
4984 void move_reg(int r
, int s
)
4997 /* get address of vtop (vtop MUST BE an lvalue) */
5000 vtop
->r
&= ~VT_LVAL
;
5001 /* tricky: if saved lvalue, then we can go back to lvalue */
5002 if ((vtop
->r
& VT_VALMASK
) == VT_LLOCAL
)
5003 vtop
->r
= (vtop
->r
& ~(VT_VALMASK
| VT_LVAL_TYPE
)) | VT_LOCAL
| VT_LVAL
;
5006 #ifdef CONFIG_TCC_BCHECK
5007 /* generate lvalue bound code */
5013 vtop
->r
&= ~VT_MUSTBOUND
;
5014 /* if lvalue, then use checking code before dereferencing */
5015 if (vtop
->r
& VT_LVAL
) {
5016 /* if not VT_BOUNDED value, then make one */
5017 if (!(vtop
->r
& VT_BOUNDED
)) {
5018 lval_type
= vtop
->r
& (VT_LVAL_TYPE
| VT_LVAL
);
5019 /* must save type because we must set it to int to get pointer */
5021 vtop
->type
.t
= VT_INT
;
5024 gen_bounded_ptr_add();
5025 vtop
->r
|= lval_type
;
5028 /* then check for dereferencing */
5029 gen_bounded_ptr_deref();
5034 /* store vtop a register belonging to class 'rc'. lvalues are
5035 converted to values. Cannot be used if cannot be converted to
5036 register value (such as structures). */
5039 int r
, rc2
, bit_pos
, bit_size
, size
, align
, i
;
5041 /* NOTE: get_reg can modify vstack[] */
5042 if (vtop
->type
.t
& VT_BITFIELD
) {
5045 bit_pos
= (vtop
->type
.t
>> VT_STRUCT_SHIFT
) & 0x3f;
5046 bit_size
= (vtop
->type
.t
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f;
5047 /* remove bit field info to avoid loops */
5048 vtop
->type
.t
&= ~(VT_BITFIELD
| (-1 << VT_STRUCT_SHIFT
));
5049 /* cast to int to propagate signedness in following ops */
5050 if ((vtop
->type
.t
& VT_BTYPE
) == VT_LLONG
) {
5055 if((vtop
->type
.t
& VT_UNSIGNED
) ||
5056 (vtop
->type
.t
& VT_BTYPE
) == VT_BOOL
)
5057 type
.t
|= VT_UNSIGNED
;
5059 /* generate shifts */
5060 vpushi(bits
- (bit_pos
+ bit_size
));
5062 vpushi(bits
- bit_size
);
5063 /* NOTE: transformed to SHR if unsigned */
5067 if (is_float(vtop
->type
.t
) &&
5068 (vtop
->r
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
) {
5071 unsigned long offset
;
5072 #if defined(TCC_TARGET_ARM) && !defined(TCC_ARM_VFP)
5076 /* XXX: unify with initializers handling ? */
5077 /* CPUs usually cannot use float constants, so we store them
5078 generically in data segment */
5079 size
= type_size(&vtop
->type
, &align
);
5080 offset
= (data_section
->data_offset
+ align
- 1) & -align
;
5081 data_section
->data_offset
= offset
;
5082 /* XXX: not portable yet */
5083 #if defined(__i386__) || defined(__x86_64__)
5084 /* Zero pad x87 tenbyte long doubles */
5085 if (size
== LDOUBLE_SIZE
)
5086 vtop
->c
.tab
[2] &= 0xffff;
5088 ptr
= section_ptr_add(data_section
, size
);
5090 #if defined(TCC_TARGET_ARM) && !defined(TCC_ARM_VFP)
5094 ptr
[i
] = vtop
->c
.tab
[size
-1-i
];
5098 ptr
[i
] = vtop
->c
.tab
[i
];
5099 sym
= get_sym_ref(&vtop
->type
, data_section
, offset
, size
<< 2);
5100 vtop
->r
|= VT_LVAL
| VT_SYM
;
5104 #ifdef CONFIG_TCC_BCHECK
5105 if (vtop
->r
& VT_MUSTBOUND
)
5109 r
= vtop
->r
& VT_VALMASK
;
5113 /* need to reload if:
5115 - lvalue (need to dereference pointer)
5116 - already a register, but not in the right class */
5117 if (r
>= VT_CONST
||
5118 (vtop
->r
& VT_LVAL
) ||
5119 !(reg_classes
[r
] & rc
) ||
5120 ((vtop
->type
.t
& VT_BTYPE
) == VT_LLONG
&&
5121 !(reg_classes
[vtop
->r2
] & rc2
))) {
5123 #ifndef TCC_TARGET_X86_64
5124 if ((vtop
->type
.t
& VT_BTYPE
) == VT_LLONG
) {
5126 unsigned long long ll
;
5127 /* two register type load : expand to two words
5129 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
) {
5132 vtop
->c
.ui
= ll
; /* first word */
5134 vtop
->r
= r
; /* save register value */
5135 vpushi(ll
>> 32); /* second word */
5136 } else if (r
>= VT_CONST
|| /* XXX: test to VT_CONST incorrect ? */
5137 (vtop
->r
& VT_LVAL
)) {
5138 /* We do not want to modifier the long long
5139 pointer here, so the safest (and less
5140 efficient) is to save all the other registers
5141 in the stack. XXX: totally inefficient. */
5143 /* load from memory */
5146 vtop
[-1].r
= r
; /* save register value */
5147 /* increment pointer to get second word */
5148 vtop
->type
.t
= VT_INT
;
5154 /* move registers */
5157 vtop
[-1].r
= r
; /* save register value */
5158 vtop
->r
= vtop
[-1].r2
;
5160 /* allocate second register */
5164 /* write second register */
5168 if ((vtop
->r
& VT_LVAL
) && !is_float(vtop
->type
.t
)) {
5170 /* lvalue of scalar type : need to use lvalue type
5171 because of possible cast */
5174 /* compute memory access type */
5175 if (vtop
->r
& VT_LVAL_BYTE
)
5177 else if (vtop
->r
& VT_LVAL_SHORT
)
5179 if (vtop
->r
& VT_LVAL_UNSIGNED
)
5183 /* restore wanted type */
5186 /* one register type load */
5191 #ifdef TCC_TARGET_C67
5192 /* uses register pairs for doubles */
5193 if ((vtop
->type
.t
& VT_BTYPE
) == VT_DOUBLE
)
5200 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
5201 void gv2(int rc1
, int rc2
)
5205 /* generate more generic register first. But VT_JMP or VT_CMP
5206 values must be generated first in all cases to avoid possible
5208 v
= vtop
[0].r
& VT_VALMASK
;
5209 if (v
!= VT_CMP
&& (v
& ~1) != VT_JMP
&& rc1
<= rc2
) {
5214 /* test if reload is needed for first register */
5215 if ((vtop
[-1].r
& VT_VALMASK
) >= VT_CONST
) {
5225 /* test if reload is needed for first register */
5226 if ((vtop
[0].r
& VT_VALMASK
) >= VT_CONST
) {
5232 /* wrapper around RC_FRET to return a register by type */
5235 #ifdef TCC_TARGET_X86_64
5236 if (t
== VT_LDOUBLE
) {
5243 /* wrapper around REG_FRET to return a register by type */
5246 #ifdef TCC_TARGET_X86_64
5247 if (t
== VT_LDOUBLE
) {
5254 /* expand long long on stack in two int registers */
5259 u
= vtop
->type
.t
& VT_UNSIGNED
;
5262 vtop
[0].r
= vtop
[-1].r2
;
5263 vtop
[0].r2
= VT_CONST
;
5264 vtop
[-1].r2
= VT_CONST
;
5265 vtop
[0].type
.t
= VT_INT
| u
;
5266 vtop
[-1].type
.t
= VT_INT
| u
;
5269 #ifdef TCC_TARGET_ARM
5270 /* expand long long on stack */
5271 void lexpand_nr(void)
5275 u
= vtop
->type
.t
& VT_UNSIGNED
;
5277 vtop
->r2
= VT_CONST
;
5278 vtop
->type
.t
= VT_INT
| u
;
5279 v
=vtop
[-1].r
& (VT_VALMASK
| VT_LVAL
);
5280 if (v
== VT_CONST
) {
5281 vtop
[-1].c
.ui
= vtop
->c
.ull
;
5282 vtop
->c
.ui
= vtop
->c
.ull
>> 32;
5284 } else if (v
== (VT_LVAL
|VT_CONST
) || v
== (VT_LVAL
|VT_LOCAL
)) {
5286 vtop
->r
= vtop
[-1].r
;
5287 } else if (v
> VT_CONST
) {
5291 vtop
->r
= vtop
[-1].r2
;
5292 vtop
[-1].r2
= VT_CONST
;
5293 vtop
[-1].type
.t
= VT_INT
| u
;
5297 /* build a long long from two ints */
5300 gv2(RC_INT
, RC_INT
);
5301 vtop
[-1].r2
= vtop
[0].r
;
5302 vtop
[-1].type
.t
= t
;
5306 /* rotate n first stack elements to the bottom
5307 I1 ... In -> I2 ... In I1 [top is right]
5315 for(i
=-n
+1;i
!=0;i
++)
5316 vtop
[i
] = vtop
[i
+1];
5320 /* rotate n first stack elements to the top
5321 I1 ... In -> In I1 ... I(n-1) [top is right]
5329 for(i
= 0;i
< n
- 1; i
++)
5330 vtop
[-i
] = vtop
[-i
- 1];
5334 #ifdef TCC_TARGET_ARM
5335 /* like vrott but in other direction
5336 In ... I1 -> I(n-1) ... I1 In [top is right]
5344 for(i
= n
- 1; i
> 0; i
--)
5345 vtop
[-i
] = vtop
[-i
+ 1];
5350 /* pop stack value */
5354 v
= vtop
->r
& VT_VALMASK
;
5355 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
5356 /* for x86, we need to pop the FP stack */
5357 if (v
== TREG_ST0
&& !nocode_wanted
) {
5358 o(0xd9dd); /* fstp %st(1) */
5361 if (v
== VT_JMP
|| v
== VT_JMPI
) {
5362 /* need to put correct jump if && or || without test */
5368 /* convert stack entry to register and duplicate its value in another
5376 if ((t
& VT_BTYPE
) == VT_LLONG
) {
5383 /* stack: H L L1 H1 */
5391 /* duplicate value */
5396 #ifdef TCC_TARGET_X86_64
5397 if ((t
& VT_BTYPE
) == VT_LDOUBLE
) {
5407 load(r1
, &sv
); /* move r to r1 */
5409 /* duplicates value */
5414 #ifndef TCC_TARGET_X86_64
5415 /* generate CPU independent (unsigned) long long operations */
5416 void gen_opl(int op
)
5418 int t
, a
, b
, op1
, c
, i
;
5420 unsigned short reg_iret
= REG_IRET
;
5421 unsigned short reg_lret
= REG_LRET
;
5427 func
= TOK___divdi3
;
5430 func
= TOK___udivdi3
;
5433 func
= TOK___moddi3
;
5436 func
= TOK___umoddi3
;
5443 /* call generic long long function */
5444 vpush_global_sym(&func_old_type
, func
);
5449 vtop
->r2
= reg_lret
;
5462 /* stack: L1 H1 L2 H2 */
5467 vtop
[-2] = vtop
[-3];
5470 /* stack: H1 H2 L1 L2 */
5476 /* stack: H1 H2 L1 L2 ML MH */
5479 /* stack: ML MH H1 H2 L1 L2 */
5483 /* stack: ML MH H1 L2 H2 L1 */
5488 /* stack: ML MH M1 M2 */
5491 } else if (op
== '+' || op
== '-') {
5492 /* XXX: add non carry method too (for MIPS or alpha) */
5498 /* stack: H1 H2 (L1 op L2) */
5501 gen_op(op1
+ 1); /* TOK_xxxC2 */
5504 /* stack: H1 H2 (L1 op L2) */
5507 /* stack: (L1 op L2) H1 H2 */
5509 /* stack: (L1 op L2) (H1 op H2) */
5517 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
) {
5518 t
= vtop
[-1].type
.t
;
5522 /* stack: L H shift */
5524 /* constant: simpler */
5525 /* NOTE: all comments are for SHL. the other cases are
5526 done by swaping words */
5537 if (op
!= TOK_SAR
) {
5570 /* XXX: should provide a faster fallback on x86 ? */
5573 func
= TOK___ashrdi3
;
5576 func
= TOK___lshrdi3
;
5579 func
= TOK___ashldi3
;
5585 /* compare operations */
5591 /* stack: L1 H1 L2 H2 */
5593 vtop
[-1] = vtop
[-2];
5595 /* stack: L1 L2 H1 H2 */
5598 /* when values are equal, we need to compare low words. since
5599 the jump is inverted, we invert the test too. */
5602 else if (op1
== TOK_GT
)
5604 else if (op1
== TOK_ULT
)
5606 else if (op1
== TOK_UGT
)
5611 if (op1
!= TOK_NE
) {
5615 /* generate non equal test */
5616 /* XXX: NOT PORTABLE yet */
5620 #if defined(TCC_TARGET_I386)
5621 b
= psym(0x850f, 0);
5622 #elif defined(TCC_TARGET_ARM)
5624 o(0x1A000000 | encbranch(ind
, 0, 1));
5625 #elif defined(TCC_TARGET_C67)
5626 error("not implemented");
5628 #error not supported
5632 /* compare low. Always unsigned */
5636 else if (op1
== TOK_LE
)
5638 else if (op1
== TOK_GT
)
5640 else if (op1
== TOK_GE
)
5651 /* handle integer constant optimizations and various machine
5653 void gen_opic(int op
)
5655 int c1
, c2
, t1
, t2
, n
;
5658 typedef unsigned long long U
;
5662 t1
= v1
->type
.t
& VT_BTYPE
;
5663 t2
= v2
->type
.t
& VT_BTYPE
;
5667 else if (v1
->type
.t
& VT_UNSIGNED
)
5674 else if (v2
->type
.t
& VT_UNSIGNED
)
5679 /* currently, we cannot do computations with forward symbols */
5680 c1
= (v1
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
5681 c2
= (v2
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
5684 case '+': l1
+= l2
; break;
5685 case '-': l1
-= l2
; break;
5686 case '&': l1
&= l2
; break;
5687 case '^': l1
^= l2
; break;
5688 case '|': l1
|= l2
; break;
5689 case '*': l1
*= l2
; break;
5696 /* if division by zero, generate explicit division */
5699 error("division by zero in constant");
5703 default: l1
/= l2
; break;
5704 case '%': l1
%= l2
; break;
5705 case TOK_UDIV
: l1
= (U
)l1
/ l2
; break;
5706 case TOK_UMOD
: l1
= (U
)l1
% l2
; break;
5709 case TOK_SHL
: l1
<<= l2
; break;
5710 case TOK_SHR
: l1
= (U
)l1
>> l2
; break;
5711 case TOK_SAR
: l1
>>= l2
; break;
5713 case TOK_ULT
: l1
= (U
)l1
< (U
)l2
; break;
5714 case TOK_UGE
: l1
= (U
)l1
>= (U
)l2
; break;
5715 case TOK_EQ
: l1
= l1
== l2
; break;
5716 case TOK_NE
: l1
= l1
!= l2
; break;
5717 case TOK_ULE
: l1
= (U
)l1
<= (U
)l2
; break;
5718 case TOK_UGT
: l1
= (U
)l1
> (U
)l2
; break;
5719 case TOK_LT
: l1
= l1
< l2
; break;
5720 case TOK_GE
: l1
= l1
>= l2
; break;
5721 case TOK_LE
: l1
= l1
<= l2
; break;
5722 case TOK_GT
: l1
= l1
> l2
; break;
5724 case TOK_LAND
: l1
= l1
&& l2
; break;
5725 case TOK_LOR
: l1
= l1
|| l2
; break;
5732 /* if commutative ops, put c2 as constant */
5733 if (c1
&& (op
== '+' || op
== '&' || op
== '^' ||
5734 op
== '|' || op
== '*')) {
5736 c2
= c1
; //c = c1, c1 = c2, c2 = c;
5737 l2
= l1
; //l = l1, l1 = l2, l2 = l;
5739 /* Filter out NOP operations like x*1, x-0, x&-1... */
5740 if (c2
&& (((op
== '*' || op
== '/' || op
== TOK_UDIV
||
5743 ((op
== '+' || op
== '-' || op
== '|' || op
== '^' ||
5744 op
== TOK_SHL
|| op
== TOK_SHR
|| op
== TOK_SAR
) &&
5750 } else if (c2
&& (op
== '*' || op
== TOK_PDIV
|| op
== TOK_UDIV
)) {
5751 /* try to use shifts instead of muls or divs */
5752 if (l2
> 0 && (l2
& (l2
- 1)) == 0) {
5761 else if (op
== TOK_PDIV
)
5767 } else if (c2
&& (op
== '+' || op
== '-') &&
5768 ((vtop
[-1].r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) ==
5769 (VT_CONST
| VT_SYM
) ||
5770 (vtop
[-1].r
& (VT_VALMASK
| VT_LVAL
)) == VT_LOCAL
)) {
5771 /* symbol + constant case */
5778 if (!nocode_wanted
) {
5779 /* call low level op generator */
5780 if (t1
== VT_LLONG
|| t2
== VT_LLONG
)
5791 /* generate a floating point operation with constant propagation */
5792 void gen_opif(int op
)
5800 /* currently, we cannot do computations with forward symbols */
5801 c1
= (v1
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
5802 c2
= (v2
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
5804 if (v1
->type
.t
== VT_FLOAT
) {
5807 } else if (v1
->type
.t
== VT_DOUBLE
) {
5815 /* NOTE: we only do constant propagation if finite number (not
5816 NaN or infinity) (ANSI spec) */
5817 if (!ieee_finite(f1
) || !ieee_finite(f2
))
5821 case '+': f1
+= f2
; break;
5822 case '-': f1
-= f2
; break;
5823 case '*': f1
*= f2
; break;
5827 error("division by zero in constant");
5832 /* XXX: also handles tests ? */
5836 /* XXX: overflow test ? */
5837 if (v1
->type
.t
== VT_FLOAT
) {
5839 } else if (v1
->type
.t
== VT_DOUBLE
) {
5847 if (!nocode_wanted
) {
5855 static int pointed_size(CType
*type
)
5858 return type_size(pointed_type(type
), &align
);
5861 static inline int is_null_pointer(SValue
*p
)
5863 if ((p
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) != VT_CONST
)
5865 return ((p
->type
.t
& VT_BTYPE
) == VT_INT
&& p
->c
.i
== 0) ||
5866 ((p
->type
.t
& VT_BTYPE
) == VT_LLONG
&& p
->c
.ll
== 0);
5869 static inline int is_integer_btype(int bt
)
5871 return (bt
== VT_BYTE
|| bt
== VT_SHORT
||
5872 bt
== VT_INT
|| bt
== VT_LLONG
);
5875 /* check types for comparison or substraction of pointers */
5876 static void check_comparison_pointer_types(SValue
*p1
, SValue
*p2
, int op
)
5878 CType
*type1
, *type2
, tmp_type1
, tmp_type2
;
5881 /* null pointers are accepted for all comparisons as gcc */
5882 if (is_null_pointer(p1
) || is_null_pointer(p2
))
5886 bt1
= type1
->t
& VT_BTYPE
;
5887 bt2
= type2
->t
& VT_BTYPE
;
5888 /* accept comparison between pointer and integer with a warning */
5889 if ((is_integer_btype(bt1
) || is_integer_btype(bt2
)) && op
!= '-') {
5890 if (op
!= TOK_LOR
&& op
!= TOK_LAND
)
5891 warning("comparison between pointer and integer");
5895 /* both must be pointers or implicit function pointers */
5896 if (bt1
== VT_PTR
) {
5897 type1
= pointed_type(type1
);
5898 } else if (bt1
!= VT_FUNC
)
5899 goto invalid_operands
;
5901 if (bt2
== VT_PTR
) {
5902 type2
= pointed_type(type2
);
5903 } else if (bt2
!= VT_FUNC
) {
5905 error("invalid operands to binary %s", get_tok_str(op
, NULL
));
5907 if ((type1
->t
& VT_BTYPE
) == VT_VOID
||
5908 (type2
->t
& VT_BTYPE
) == VT_VOID
)
5912 tmp_type1
.t
&= ~(VT_UNSIGNED
| VT_CONSTANT
| VT_VOLATILE
);
5913 tmp_type2
.t
&= ~(VT_UNSIGNED
| VT_CONSTANT
| VT_VOLATILE
);
5914 if (!is_compatible_types(&tmp_type1
, &tmp_type2
)) {
5915 /* gcc-like error if '-' is used */
5917 goto invalid_operands
;
5919 warning("comparison of distinct pointer types lacks a cast");
5923 /* generic gen_op: handles types problems */
5926 int u
, t1
, t2
, bt1
, bt2
, t
;
5929 t1
= vtop
[-1].type
.t
;
5930 t2
= vtop
[0].type
.t
;
5931 bt1
= t1
& VT_BTYPE
;
5932 bt2
= t2
& VT_BTYPE
;
5934 if (bt1
== VT_PTR
|| bt2
== VT_PTR
) {
5935 /* at least one operand is a pointer */
5936 /* relationnal op: must be both pointers */
5937 if (op
>= TOK_ULT
&& op
<= TOK_LOR
) {
5938 check_comparison_pointer_types(vtop
- 1, vtop
, op
);
5939 /* pointers are handled are unsigned */
5940 #ifdef TCC_TARGET_X86_64
5941 t
= VT_LLONG
| VT_UNSIGNED
;
5943 t
= VT_INT
| VT_UNSIGNED
;
5947 /* if both pointers, then it must be the '-' op */
5948 if (bt1
== VT_PTR
&& bt2
== VT_PTR
) {
5950 error("cannot use pointers here");
5951 check_comparison_pointer_types(vtop
- 1, vtop
, op
);
5952 /* XXX: check that types are compatible */
5953 u
= pointed_size(&vtop
[-1].type
);
5955 /* set to integer type */
5956 #ifdef TCC_TARGET_X86_64
5957 vtop
->type
.t
= VT_LLONG
;
5959 vtop
->type
.t
= VT_INT
;
5964 /* exactly one pointer : must be '+' or '-'. */
5965 if (op
!= '-' && op
!= '+')
5966 error("cannot use pointers here");
5967 /* Put pointer as first operand */
5968 if (bt2
== VT_PTR
) {
5972 type1
= vtop
[-1].type
;
5973 #ifdef TCC_TARGET_X86_64
5974 vpushll(pointed_size(&vtop
[-1].type
));
5976 /* XXX: cast to int ? (long long case) */
5977 vpushi(pointed_size(&vtop
[-1].type
));
5980 #ifdef CONFIG_TCC_BCHECK
5981 /* if evaluating constant expression, no code should be
5982 generated, so no bound check */
5983 if (do_bounds_check
&& !const_wanted
) {
5984 /* if bounded pointers, we generate a special code to
5991 gen_bounded_ptr_add();
5997 /* put again type if gen_opic() swaped operands */
6000 } else if (is_float(bt1
) || is_float(bt2
)) {
6001 /* compute bigger type and do implicit casts */
6002 if (bt1
== VT_LDOUBLE
|| bt2
== VT_LDOUBLE
) {
6004 } else if (bt1
== VT_DOUBLE
|| bt2
== VT_DOUBLE
) {
6009 /* floats can only be used for a few operations */
6010 if (op
!= '+' && op
!= '-' && op
!= '*' && op
!= '/' &&
6011 (op
< TOK_ULT
|| op
> TOK_GT
))
6012 error("invalid operands for binary operation");
6014 } else if (bt1
== VT_LLONG
|| bt2
== VT_LLONG
) {
6015 /* cast to biggest op */
6017 /* convert to unsigned if it does not fit in a long long */
6018 if ((t1
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_LLONG
| VT_UNSIGNED
) ||
6019 (t2
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_LLONG
| VT_UNSIGNED
))
6023 /* integer operations */
6025 /* convert to unsigned if it does not fit in an integer */
6026 if ((t1
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
) ||
6027 (t2
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
))
6030 /* XXX: currently, some unsigned operations are explicit, so
6031 we modify them here */
6032 if (t
& VT_UNSIGNED
) {
6039 else if (op
== TOK_LT
)
6041 else if (op
== TOK_GT
)
6043 else if (op
== TOK_LE
)
6045 else if (op
== TOK_GE
)
6052 /* special case for shifts and long long: we keep the shift as
6054 if (op
== TOK_SHR
|| op
== TOK_SAR
|| op
== TOK_SHL
)
6061 if (op
>= TOK_ULT
&& op
<= TOK_GT
) {
6062 /* relationnal op: the result is an int */
6063 vtop
->type
.t
= VT_INT
;
6070 #ifndef TCC_TARGET_ARM
6071 /* generic itof for unsigned long long case */
6072 void gen_cvt_itof1(int t
)
6074 if ((vtop
->type
.t
& (VT_BTYPE
| VT_UNSIGNED
)) ==
6075 (VT_LLONG
| VT_UNSIGNED
)) {
6078 vpush_global_sym(&func_old_type
, TOK___floatundisf
);
6079 #if LDOUBLE_SIZE != 8
6080 else if (t
== VT_LDOUBLE
)
6081 vpush_global_sym(&func_old_type
, TOK___floatundixf
);
6084 vpush_global_sym(&func_old_type
, TOK___floatundidf
);
6088 vtop
->r
= reg_fret(t
);
6095 /* generic ftoi for unsigned long long case */
6096 void gen_cvt_ftoi1(int t
)
6100 if (t
== (VT_LLONG
| VT_UNSIGNED
)) {
6101 /* not handled natively */
6102 st
= vtop
->type
.t
& VT_BTYPE
;
6104 vpush_global_sym(&func_old_type
, TOK___fixunssfdi
);
6105 #if LDOUBLE_SIZE != 8
6106 else if (st
== VT_LDOUBLE
)
6107 vpush_global_sym(&func_old_type
, TOK___fixunsxfdi
);
6110 vpush_global_sym(&func_old_type
, TOK___fixunsdfdi
);
6115 vtop
->r2
= REG_LRET
;
6121 /* force char or short cast */
6122 void force_charshort_cast(int t
)
6126 /* XXX: add optimization if lvalue : just change type and offset */
6131 if (t
& VT_UNSIGNED
) {
6132 vpushi((1 << bits
) - 1);
6138 /* result must be signed or the SAR is converted to an SHL
6139 This was not the case when "t" was a signed short
6140 and the last value on the stack was an unsigned int */
6141 vtop
->type
.t
&= ~VT_UNSIGNED
;
6147 /* cast 'vtop' to 'type'. Casting to bitfields is forbidden. */
6148 static void gen_cast(CType
*type
)
6150 int sbt
, dbt
, sf
, df
, c
, p
;
6152 /* special delayed cast for char/short */
6153 /* XXX: in some cases (multiple cascaded casts), it may still
6155 if (vtop
->r
& VT_MUSTCAST
) {
6156 vtop
->r
&= ~VT_MUSTCAST
;
6157 force_charshort_cast(vtop
->type
.t
);
6160 /* bitfields first get cast to ints */
6161 if (vtop
->type
.t
& VT_BITFIELD
) {
6165 dbt
= type
->t
& (VT_BTYPE
| VT_UNSIGNED
);
6166 sbt
= vtop
->type
.t
& (VT_BTYPE
| VT_UNSIGNED
);
6171 c
= (vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
6172 p
= (vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == (VT_CONST
| VT_SYM
);
6174 /* constant case: we can do it now */
6175 /* XXX: in ISOC, cannot do it if error in convert */
6176 if (sbt
== VT_FLOAT
)
6177 vtop
->c
.ld
= vtop
->c
.f
;
6178 else if (sbt
== VT_DOUBLE
)
6179 vtop
->c
.ld
= vtop
->c
.d
;
6182 if ((sbt
& VT_BTYPE
) == VT_LLONG
) {
6183 if (sbt
& VT_UNSIGNED
)
6184 vtop
->c
.ld
= vtop
->c
.ull
;
6186 vtop
->c
.ld
= vtop
->c
.ll
;
6188 if (sbt
& VT_UNSIGNED
)
6189 vtop
->c
.ld
= vtop
->c
.ui
;
6191 vtop
->c
.ld
= vtop
->c
.i
;
6194 if (dbt
== VT_FLOAT
)
6195 vtop
->c
.f
= (float)vtop
->c
.ld
;
6196 else if (dbt
== VT_DOUBLE
)
6197 vtop
->c
.d
= (double)vtop
->c
.ld
;
6198 } else if (sf
&& dbt
== (VT_LLONG
|VT_UNSIGNED
)) {
6199 vtop
->c
.ull
= (unsigned long long)vtop
->c
.ld
;
6200 } else if (sf
&& dbt
== VT_BOOL
) {
6201 vtop
->c
.i
= (vtop
->c
.ld
!= 0);
6204 vtop
->c
.ll
= (long long)vtop
->c
.ld
;
6205 else if (sbt
== (VT_LLONG
|VT_UNSIGNED
))
6206 vtop
->c
.ll
= vtop
->c
.ull
;
6207 else if (sbt
& VT_UNSIGNED
)
6208 vtop
->c
.ll
= vtop
->c
.ui
;
6209 else if (sbt
!= VT_LLONG
)
6210 vtop
->c
.ll
= vtop
->c
.i
;
6212 if (dbt
== (VT_LLONG
|VT_UNSIGNED
))
6213 vtop
->c
.ull
= vtop
->c
.ll
;
6214 else if (dbt
== VT_BOOL
)
6215 vtop
->c
.i
= (vtop
->c
.ll
!= 0);
6216 else if (dbt
!= VT_LLONG
) {
6218 if ((dbt
& VT_BTYPE
) == VT_BYTE
)
6220 else if ((dbt
& VT_BTYPE
) == VT_SHORT
)
6223 if(dbt
& VT_UNSIGNED
)
6224 vtop
->c
.ui
= ((unsigned int)vtop
->c
.ll
<< s
) >> s
;
6226 vtop
->c
.i
= ((int)vtop
->c
.ll
<< s
) >> s
;
6229 } else if (p
&& dbt
== VT_BOOL
) {
6232 } else if (!nocode_wanted
) {
6233 /* non constant case: generate code */
6235 /* convert from fp to fp */
6238 /* convert int to fp */
6241 /* convert fp to int */
6242 if (dbt
== VT_BOOL
) {
6246 /* we handle char/short/etc... with generic code */
6247 if (dbt
!= (VT_INT
| VT_UNSIGNED
) &&
6248 dbt
!= (VT_LLONG
| VT_UNSIGNED
) &&
6252 if (dbt
== VT_INT
&& (type
->t
& (VT_BTYPE
| VT_UNSIGNED
)) != dbt
) {
6253 /* additional cast for char/short... */
6258 #ifndef TCC_TARGET_X86_64
6259 } else if ((dbt
& VT_BTYPE
) == VT_LLONG
) {
6260 if ((sbt
& VT_BTYPE
) != VT_LLONG
) {
6261 /* scalar to long long */
6262 /* machine independent conversion */
6264 /* generate high word */
6265 if (sbt
== (VT_INT
| VT_UNSIGNED
)) {
6269 if (sbt
== VT_PTR
) {
6270 /* cast from pointer to int before we apply
6271 shift operation, which pointers don't support*/
6272 gen_cast(&int_type
);
6278 /* patch second register */
6279 vtop
[-1].r2
= vtop
->r
;
6283 } else if ((dbt
& VT_BTYPE
) == VT_LLONG
||
6284 (dbt
& VT_BTYPE
) == VT_PTR
) {
6285 /* XXX: not sure if this is perfect... need more tests */
6286 if ((sbt
& VT_BTYPE
) != VT_LLONG
) {
6288 if (sbt
!= (VT_INT
| VT_UNSIGNED
) &&
6289 sbt
!= VT_PTR
&& sbt
!= VT_FUNC
) {
6290 /* x86_64 specific: movslq */
6292 o(0xc0 + (REG_VALUE(r
) << 3) + REG_VALUE(r
));
6296 } else if (dbt
== VT_BOOL
) {
6297 /* scalar to bool */
6300 } else if ((dbt
& VT_BTYPE
) == VT_BYTE
||
6301 (dbt
& VT_BTYPE
) == VT_SHORT
) {
6302 if (sbt
== VT_PTR
) {
6303 vtop
->type
.t
= VT_INT
;
6304 warning("nonportable conversion from pointer to char/short");
6306 force_charshort_cast(dbt
);
6307 } else if ((dbt
& VT_BTYPE
) == VT_INT
) {
6309 if (sbt
== VT_LLONG
) {
6310 /* from long long: just take low order word */
6314 /* if lvalue and single word type, nothing to do because
6315 the lvalue already contains the real type size (see
6316 VT_LVAL_xxx constants) */
6319 } else if ((dbt
& VT_BTYPE
) == VT_PTR
&& !(vtop
->r
& VT_LVAL
)) {
6320 /* if we are casting between pointer types,
6321 we must update the VT_LVAL_xxx size */
6322 vtop
->r
= (vtop
->r
& ~VT_LVAL_TYPE
)
6323 | (lvalue_type(type
->ref
->type
.t
) & VT_LVAL_TYPE
);
6328 /* return type size. Put alignment at 'a' */
6329 static int type_size(CType
*type
, int *a
)
6334 bt
= type
->t
& VT_BTYPE
;
6335 if (bt
== VT_STRUCT
) {
6340 } else if (bt
== VT_PTR
) {
6341 if (type
->t
& VT_ARRAY
) {
6345 ts
= type_size(&s
->type
, a
);
6347 if (ts
< 0 && s
->c
< 0)
6355 } else if (bt
== VT_LDOUBLE
) {
6357 return LDOUBLE_SIZE
;
6358 } else if (bt
== VT_DOUBLE
|| bt
== VT_LLONG
) {
6359 #ifdef TCC_TARGET_I386
6360 #ifdef TCC_TARGET_PE
6365 #elif defined(TCC_TARGET_ARM)
6375 } else if (bt
== VT_INT
|| bt
== VT_ENUM
|| bt
== VT_FLOAT
) {
6378 } else if (bt
== VT_SHORT
) {
6382 /* char, void, function, _Bool */
6388 /* return the pointed type of t */
6389 static inline CType
*pointed_type(CType
*type
)
6391 return &type
->ref
->type
;
6394 /* modify type so that its it is a pointer to type. */
6395 static void mk_pointer(CType
*type
)
6398 s
= sym_push(SYM_FIELD
, type
, 0, -1);
6399 type
->t
= VT_PTR
| (type
->t
& ~VT_TYPE
);
6403 /* compare function types. OLD functions match any new functions */
6404 static int is_compatible_func(CType
*type1
, CType
*type2
)
6410 if (!is_compatible_types(&s1
->type
, &s2
->type
))
6412 /* check func_call */
6413 if (FUNC_CALL(s1
->r
) != FUNC_CALL(s2
->r
))
6415 /* XXX: not complete */
6416 if (s1
->c
== FUNC_OLD
|| s2
->c
== FUNC_OLD
)
6420 while (s1
!= NULL
) {
6423 if (!is_compatible_parameter_types(&s1
->type
, &s2
->type
))
6433 /* return true if type1 and type2 are the same. If unqualified is
6434 true, qualifiers on the types are ignored.
6436 - enums are not checked as gcc __builtin_types_compatible_p ()
6438 static int compare_types(CType
*type1
, CType
*type2
, int unqualified
)
6442 t1
= type1
->t
& VT_TYPE
;
6443 t2
= type2
->t
& VT_TYPE
;
6445 /* strip qualifiers before comparing */
6446 t1
&= ~(VT_CONSTANT
| VT_VOLATILE
);
6447 t2
&= ~(VT_CONSTANT
| VT_VOLATILE
);
6449 /* XXX: bitfields ? */
6452 /* test more complicated cases */
6453 bt1
= t1
& VT_BTYPE
;
6454 if (bt1
== VT_PTR
) {
6455 type1
= pointed_type(type1
);
6456 type2
= pointed_type(type2
);
6457 return is_compatible_types(type1
, type2
);
6458 } else if (bt1
== VT_STRUCT
) {
6459 return (type1
->ref
== type2
->ref
);
6460 } else if (bt1
== VT_FUNC
) {
6461 return is_compatible_func(type1
, type2
);
6467 /* return true if type1 and type2 are exactly the same (including
6470 static int is_compatible_types(CType
*type1
, CType
*type2
)
6472 return compare_types(type1
,type2
,0);
6475 /* return true if type1 and type2 are the same (ignoring qualifiers).
6477 static int is_compatible_parameter_types(CType
*type1
, CType
*type2
)
6479 return compare_types(type1
,type2
,1);
6482 /* print a type. If 'varstr' is not NULL, then the variable is also
6483 printed in the type */
6485 /* XXX: add array and function pointers */
6486 void type_to_str(char *buf
, int buf_size
,
6487 CType
*type
, const char *varstr
)
6494 t
= type
->t
& VT_TYPE
;
6497 if (t
& VT_CONSTANT
)
6498 pstrcat(buf
, buf_size
, "const ");
6499 if (t
& VT_VOLATILE
)
6500 pstrcat(buf
, buf_size
, "volatile ");
6501 if (t
& VT_UNSIGNED
)
6502 pstrcat(buf
, buf_size
, "unsigned ");
6532 tstr
= "long double";
6534 pstrcat(buf
, buf_size
, tstr
);
6538 if (bt
== VT_STRUCT
)
6542 pstrcat(buf
, buf_size
, tstr
);
6543 v
= type
->ref
->v
& ~SYM_STRUCT
;
6544 if (v
>= SYM_FIRST_ANOM
)
6545 pstrcat(buf
, buf_size
, "<anonymous>");
6547 pstrcat(buf
, buf_size
, get_tok_str(v
, NULL
));
6551 type_to_str(buf
, buf_size
, &s
->type
, varstr
);
6552 pstrcat(buf
, buf_size
, "(");
6554 while (sa
!= NULL
) {
6555 type_to_str(buf1
, sizeof(buf1
), &sa
->type
, NULL
);
6556 pstrcat(buf
, buf_size
, buf1
);
6559 pstrcat(buf
, buf_size
, ", ");
6561 pstrcat(buf
, buf_size
, ")");
6565 pstrcpy(buf1
, sizeof(buf1
), "*");
6567 pstrcat(buf1
, sizeof(buf1
), varstr
);
6568 type_to_str(buf
, buf_size
, &s
->type
, buf1
);
6572 pstrcat(buf
, buf_size
, " ");
6573 pstrcat(buf
, buf_size
, varstr
);
6578 /* verify type compatibility to store vtop in 'dt' type, and generate
6580 static void gen_assign_cast(CType
*dt
)
6582 CType
*st
, *type1
, *type2
, tmp_type1
, tmp_type2
;
6583 char buf1
[256], buf2
[256];
6586 st
= &vtop
->type
; /* source type */
6587 dbt
= dt
->t
& VT_BTYPE
;
6588 sbt
= st
->t
& VT_BTYPE
;
6589 if (dt
->t
& VT_CONSTANT
)
6590 warning("assignment of read-only location");
6593 /* special cases for pointers */
6594 /* '0' can also be a pointer */
6595 if (is_null_pointer(vtop
))
6597 /* accept implicit pointer to integer cast with warning */
6598 if (is_integer_btype(sbt
)) {
6599 warning("assignment makes pointer from integer without a cast");
6602 type1
= pointed_type(dt
);
6603 /* a function is implicitely a function pointer */
6604 if (sbt
== VT_FUNC
) {
6605 if ((type1
->t
& VT_BTYPE
) != VT_VOID
&&
6606 !is_compatible_types(pointed_type(dt
), st
))
6613 type2
= pointed_type(st
);
6614 if ((type1
->t
& VT_BTYPE
) == VT_VOID
||
6615 (type2
->t
& VT_BTYPE
) == VT_VOID
) {
6616 /* void * can match anything */
6618 /* exact type match, except for unsigned */
6621 tmp_type1
.t
&= ~(VT_UNSIGNED
| VT_CONSTANT
| VT_VOLATILE
);
6622 tmp_type2
.t
&= ~(VT_UNSIGNED
| VT_CONSTANT
| VT_VOLATILE
);
6623 if (!is_compatible_types(&tmp_type1
, &tmp_type2
))
6624 warning("assignment from incompatible pointer type");
6626 /* check const and volatile */
6627 if ((!(type1
->t
& VT_CONSTANT
) && (type2
->t
& VT_CONSTANT
)) ||
6628 (!(type1
->t
& VT_VOLATILE
) && (type2
->t
& VT_VOLATILE
)))
6629 warning("assignment discards qualifiers from pointer target type");
6635 if (sbt
== VT_PTR
|| sbt
== VT_FUNC
) {
6636 warning("assignment makes integer from pointer without a cast");
6638 /* XXX: more tests */
6643 tmp_type1
.t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
6644 tmp_type2
.t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
6645 if (!is_compatible_types(&tmp_type1
, &tmp_type2
)) {
6647 type_to_str(buf1
, sizeof(buf1
), st
, NULL
);
6648 type_to_str(buf2
, sizeof(buf2
), dt
, NULL
);
6649 error("cannot cast '%s' to '%s'", buf1
, buf2
);
6657 /* store vtop in lvalue pushed on stack */
6660 int sbt
, dbt
, ft
, r
, t
, size
, align
, bit_size
, bit_pos
, rc
, delayed_cast
;
6662 ft
= vtop
[-1].type
.t
;
6663 sbt
= vtop
->type
.t
& VT_BTYPE
;
6664 dbt
= ft
& VT_BTYPE
;
6665 if (((sbt
== VT_INT
|| sbt
== VT_SHORT
) && dbt
== VT_BYTE
) ||
6666 (sbt
== VT_INT
&& dbt
== VT_SHORT
)) {
6667 /* optimize char/short casts */
6668 delayed_cast
= VT_MUSTCAST
;
6669 vtop
->type
.t
= ft
& (VT_TYPE
& ~(VT_BITFIELD
| (-1 << VT_STRUCT_SHIFT
)));
6670 /* XXX: factorize */
6671 if (ft
& VT_CONSTANT
)
6672 warning("assignment of read-only location");
6675 if (!(ft
& VT_BITFIELD
))
6676 gen_assign_cast(&vtop
[-1].type
);
6679 if (sbt
== VT_STRUCT
) {
6680 /* if structure, only generate pointer */
6681 /* structure assignment : generate memcpy */
6682 /* XXX: optimize if small size */
6683 if (!nocode_wanted
) {
6684 size
= type_size(&vtop
->type
, &align
);
6688 vpush_global_sym(&func_old_type
, TOK_memcpy8
);
6689 else if(!(align
& 3))
6690 vpush_global_sym(&func_old_type
, TOK_memcpy4
);
6693 vpush_global_sym(&func_old_type
, TOK_memcpy
);
6697 vtop
->type
.t
= VT_PTR
;
6701 vtop
->type
.t
= VT_PTR
;
6713 /* leave source on stack */
6714 } else if (ft
& VT_BITFIELD
) {
6715 /* bitfield store handling */
6716 bit_pos
= (ft
>> VT_STRUCT_SHIFT
) & 0x3f;
6717 bit_size
= (ft
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f;
6718 /* remove bit field info to avoid loops */
6719 vtop
[-1].type
.t
= ft
& ~(VT_BITFIELD
| (-1 << VT_STRUCT_SHIFT
));
6721 /* duplicate source into other register */
6726 if((ft
& VT_BTYPE
) == VT_BOOL
) {
6727 gen_cast(&vtop
[-1].type
);
6728 vtop
[-1].type
.t
= (vtop
[-1].type
.t
& ~VT_BTYPE
) | (VT_BYTE
| VT_UNSIGNED
);
6731 /* duplicate destination */
6733 vtop
[-1] = vtop
[-2];
6735 /* mask and shift source */
6736 if((ft
& VT_BTYPE
) != VT_BOOL
) {
6737 if((ft
& VT_BTYPE
) == VT_LLONG
) {
6738 vpushll((1ULL << bit_size
) - 1ULL);
6740 vpushi((1 << bit_size
) - 1);
6746 /* load destination, mask and or with source */
6748 if((ft
& VT_BTYPE
) == VT_LLONG
) {
6749 vpushll(~(((1ULL << bit_size
) - 1ULL) << bit_pos
));
6751 vpushi(~(((1 << bit_size
) - 1) << bit_pos
));
6758 /* pop off shifted source from "duplicate source..." above */
6762 #ifdef CONFIG_TCC_BCHECK
6763 /* bound check case */
6764 if (vtop
[-1].r
& VT_MUSTBOUND
) {
6770 if (!nocode_wanted
) {
6774 #ifdef TCC_TARGET_X86_64
6775 if ((ft
& VT_BTYPE
) == VT_LDOUBLE
) {
6780 r
= gv(rc
); /* generate value */
6781 /* if lvalue was saved on stack, must read it */
6782 if ((vtop
[-1].r
& VT_VALMASK
) == VT_LLOCAL
) {
6784 t
= get_reg(RC_INT
);
6785 #ifdef TCC_TARGET_X86_64
6790 sv
.r
= VT_LOCAL
| VT_LVAL
;
6791 sv
.c
.ul
= vtop
[-1].c
.ul
;
6793 vtop
[-1].r
= t
| VT_LVAL
;
6796 #ifndef TCC_TARGET_X86_64
6797 /* two word case handling : store second register at word + 4 */
6798 if ((ft
& VT_BTYPE
) == VT_LLONG
) {
6800 /* convert to int to increment easily */
6801 vtop
->type
.t
= VT_INT
;
6807 /* XXX: it works because r2 is spilled last ! */
6808 store(vtop
->r2
, vtop
- 1);
6813 vtop
--; /* NOT vpop() because on x86 it would flush the fp stack */
6814 vtop
->r
|= delayed_cast
;
6818 /* post defines POST/PRE add. c is the token ++ or -- */
6819 void inc(int post
, int c
)
6822 vdup(); /* save lvalue */
6824 gv_dup(); /* duplicate value */
6829 vpushi(c
- TOK_MID
);
6831 vstore(); /* store value */
6833 vpop(); /* if post op, return saved value */
6836 /* Parse GNUC __attribute__ extension. Currently, the following
6837 extensions are recognized:
6838 - aligned(n) : set data/function alignment.
6839 - packed : force data alignment to 1
6840 - section(x) : generate data/code in this section.
6841 - unused : currently ignored, but may be used someday.
6842 - regparm(n) : pass function parameters in registers (i386 only)
6844 static void parse_attribute(AttributeDef
*ad
)
6848 while (tok
== TOK_ATTRIBUTE1
|| tok
== TOK_ATTRIBUTE2
) {
6852 while (tok
!= ')') {
6853 if (tok
< TOK_IDENT
)
6854 expect("attribute name");
6862 expect("section name");
6863 ad
->section
= find_section(tcc_state
, (char *)tokc
.cstr
->data
);
6872 if (n
<= 0 || (n
& (n
- 1)) != 0)
6873 error("alignment must be a positive power of two");
6886 /* currently, no need to handle it because tcc does not
6887 track unused objects */
6891 /* currently, no need to handle it because tcc does not
6892 track unused objects */
6897 FUNC_CALL(ad
->func_attr
) = FUNC_CDECL
;
6902 FUNC_CALL(ad
->func_attr
) = FUNC_STDCALL
;
6904 #ifdef TCC_TARGET_I386
6914 FUNC_CALL(ad
->func_attr
) = FUNC_FASTCALL1
+ n
- 1;
6920 FUNC_CALL(ad
->func_attr
) = FUNC_FASTCALLW
;
6924 FUNC_EXPORT(ad
->func_attr
) = 1;
6927 if (tcc_state
->warn_unsupported
)
6928 warning("'%s' attribute ignored", get_tok_str(t
, NULL
));
6929 /* skip parameters */
6931 int parenthesis
= 0;
6935 else if (tok
== ')')
6938 } while (parenthesis
&& tok
!= -1);
6951 /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
6952 static void struct_decl(CType
*type
, int u
)
6954 int a
, v
, size
, align
, maxalign
, c
, offset
;
6955 int bit_size
, bit_pos
, bsize
, bt
, lbit_pos
, prevbt
;
6956 Sym
*s
, *ss
, *ass
, **ps
;
6960 a
= tok
; /* save decl type */
6965 /* struct already defined ? return it */
6967 expect("struct/union/enum name");
6971 error("invalid type");
6978 /* we put an undefined size for struct/union */
6979 s
= sym_push(v
| SYM_STRUCT
, &type1
, 0, -1);
6980 s
->r
= 0; /* default alignment is zero as gcc */
6981 /* put struct/union/enum name in type */
6989 error("struct/union/enum already defined");
6990 /* cannot be empty */
6992 /* non empty enums are not allowed */
6993 if (a
== TOK_ENUM
) {
6997 expect("identifier");
7003 /* enum symbols have static storage */
7004 ss
= sym_push(v
, &int_type
, VT_CONST
, c
);
7005 ss
->type
.t
|= VT_STATIC
;
7010 /* NOTE: we accept a trailing comma */
7021 while (tok
!= '}') {
7022 parse_btype(&btype
, &ad
);
7028 type_decl(&type1
, &ad
, &v
, TYPE_DIRECT
| TYPE_ABSTRACT
);
7029 if (v
== 0 && (type1
.t
& VT_BTYPE
) != VT_STRUCT
)
7030 expect("identifier");
7031 if ((type1
.t
& VT_BTYPE
) == VT_FUNC
||
7032 (type1
.t
& (VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
| VT_INLINE
)))
7033 error("invalid type for '%s'",
7034 get_tok_str(v
, NULL
));
7038 bit_size
= expr_const();
7039 /* XXX: handle v = 0 case for messages */
7041 error("negative width in bit-field '%s'",
7042 get_tok_str(v
, NULL
));
7043 if (v
&& bit_size
== 0)
7044 error("zero width for bit-field '%s'",
7045 get_tok_str(v
, NULL
));
7047 size
= type_size(&type1
, &align
);
7049 if (align
< ad
.aligned
)
7051 } else if (ad
.packed
) {
7053 } else if (*tcc_state
->pack_stack_ptr
) {
7054 if (align
> *tcc_state
->pack_stack_ptr
)
7055 align
= *tcc_state
->pack_stack_ptr
;
7058 if (bit_size
>= 0) {
7059 bt
= type1
.t
& VT_BTYPE
;
7066 error("bitfields must have scalar type");
7068 if (bit_size
> bsize
) {
7069 error("width of '%s' exceeds its type",
7070 get_tok_str(v
, NULL
));
7071 } else if (bit_size
== bsize
) {
7072 /* no need for bit fields */
7074 } else if (bit_size
== 0) {
7075 /* XXX: what to do if only padding in a
7077 /* zero size: means to pad */
7080 /* we do not have enough room ?
7081 did the type change?
7083 if ((bit_pos
+ bit_size
) > bsize
||
7084 bt
!= prevbt
|| a
== TOK_UNION
)
7087 /* XXX: handle LSB first */
7088 type1
.t
|= VT_BITFIELD
|
7089 (bit_pos
<< VT_STRUCT_SHIFT
) |
7090 (bit_size
<< (VT_STRUCT_SHIFT
+ 6));
7091 bit_pos
+= bit_size
;
7097 if (v
!= 0 || (type1
.t
& VT_BTYPE
) == VT_STRUCT
) {
7098 /* add new memory data only if starting
7100 if (lbit_pos
== 0) {
7101 if (a
== TOK_STRUCT
) {
7102 c
= (c
+ align
- 1) & -align
;
7111 if (align
> maxalign
)
7115 printf("add field %s offset=%d",
7116 get_tok_str(v
, NULL
), offset
);
7117 if (type1
.t
& VT_BITFIELD
) {
7118 printf(" pos=%d size=%d",
7119 (type1
.t
>> VT_STRUCT_SHIFT
) & 0x3f,
7120 (type1
.t
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f);
7125 if (v
== 0 && (type1
.t
& VT_BTYPE
) == VT_STRUCT
) {
7127 while ((ass
= ass
->next
) != NULL
) {
7128 ss
= sym_push(ass
->v
, &ass
->type
, 0, offset
+ ass
->c
);
7133 ss
= sym_push(v
| SYM_FIELD
, &type1
, 0, offset
);
7137 if (tok
== ';' || tok
== TOK_EOF
)
7144 /* store size and alignment */
7145 s
->c
= (c
+ maxalign
- 1) & -maxalign
;
7151 /* return 0 if no type declaration. otherwise, return the basic type
7154 static int parse_btype(CType
*type
, AttributeDef
*ad
)
7156 int t
, u
, type_found
, typespec_found
, typedef_found
;
7160 memset(ad
, 0, sizeof(AttributeDef
));
7168 /* currently, we really ignore extension */
7178 if ((t
& VT_BTYPE
) != 0)
7179 error("too many basic types");
7195 if ((t
& VT_BTYPE
) == VT_DOUBLE
) {
7196 t
= (t
& ~VT_BTYPE
) | VT_LDOUBLE
;
7197 } else if ((t
& VT_BTYPE
) == VT_LONG
) {
7198 t
= (t
& ~VT_BTYPE
) | VT_LLONG
;
7212 if ((t
& VT_BTYPE
) == VT_LONG
) {
7213 t
= (t
& ~VT_BTYPE
) | VT_LDOUBLE
;
7220 struct_decl(&type1
, VT_ENUM
);
7223 type
->ref
= type1
.ref
;
7227 struct_decl(&type1
, VT_STRUCT
);
7230 /* type modifiers */
7283 /* GNUC attribute */
7284 case TOK_ATTRIBUTE1
:
7285 case TOK_ATTRIBUTE2
:
7286 parse_attribute(ad
);
7293 parse_expr_type(&type1
);
7296 if (typespec_found
|| typedef_found
)
7299 if (!s
|| !(s
->type
.t
& VT_TYPEDEF
))
7302 t
|= (s
->type
.t
& ~VT_TYPEDEF
);
7303 type
->ref
= s
->type
.ref
;
7311 if ((t
& (VT_SIGNED
|VT_UNSIGNED
)) == (VT_SIGNED
|VT_UNSIGNED
))
7312 error("signed and unsigned modifier");
7313 if (tcc_state
->char_is_unsigned
) {
7314 if ((t
& (VT_SIGNED
|VT_UNSIGNED
|VT_BTYPE
)) == VT_BYTE
)
7319 /* long is never used as type */
7320 if ((t
& VT_BTYPE
) == VT_LONG
)
7321 #ifndef TCC_TARGET_X86_64
7322 t
= (t
& ~VT_BTYPE
) | VT_INT
;
7324 t
= (t
& ~VT_BTYPE
) | VT_LLONG
;
7330 /* convert a function parameter type (array to pointer and function to
7331 function pointer) */
7332 static inline void convert_parameter_type(CType
*pt
)
7334 /* remove const and volatile qualifiers (XXX: const could be used
7335 to indicate a const function parameter */
7336 pt
->t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
7337 /* array must be transformed to pointer according to ANSI C */
7339 if ((pt
->t
& VT_BTYPE
) == VT_FUNC
) {
7344 static void post_type(CType
*type
, AttributeDef
*ad
)
7346 int n
, l
, t1
, arg_size
, align
;
7347 Sym
**plast
, *s
, *first
;
7352 /* function declaration */
7360 /* read param name and compute offset */
7361 if (l
!= FUNC_OLD
) {
7362 if (!parse_btype(&pt
, &ad1
)) {
7364 error("invalid type");
7371 if ((pt
.t
& VT_BTYPE
) == VT_VOID
&& tok
== ')')
7373 type_decl(&pt
, &ad1
, &n
, TYPE_DIRECT
| TYPE_ABSTRACT
);
7374 if ((pt
.t
& VT_BTYPE
) == VT_VOID
)
7375 error("parameter declared as void");
7376 arg_size
+= (type_size(&pt
, &align
) + 3) & ~3;
7381 expect("identifier");
7385 convert_parameter_type(&pt
);
7386 s
= sym_push(n
| SYM_FIELD
, &pt
, 0, 0);
7392 if (l
== FUNC_NEW
&& tok
== TOK_DOTS
) {
7399 /* if no parameters, then old type prototype */
7403 t1
= type
->t
& VT_STORAGE
;
7404 /* NOTE: const is ignored in returned type as it has a special
7405 meaning in gcc / C++ */
7406 type
->t
&= ~(VT_STORAGE
| VT_CONSTANT
);
7407 post_type(type
, ad
);
7408 /* we push a anonymous symbol which will contain the function prototype */
7409 FUNC_ARGS(ad
->func_attr
) = arg_size
;
7410 s
= sym_push(SYM_FIELD
, type
, ad
->func_attr
, l
);
7412 type
->t
= t1
| VT_FUNC
;
7414 } else if (tok
== '[') {
7415 /* array definition */
7417 if (tok
== TOK_RESTRICT1
)
7423 error("invalid array size");
7426 /* parse next post type */
7427 t1
= type
->t
& VT_STORAGE
;
7428 type
->t
&= ~VT_STORAGE
;
7429 post_type(type
, ad
);
7431 /* we push a anonymous symbol which will contain the array
7433 s
= sym_push(SYM_FIELD
, type
, 0, n
);
7434 type
->t
= t1
| VT_ARRAY
| VT_PTR
;
7439 /* Parse a type declaration (except basic type), and return the type
7440 in 'type'. 'td' is a bitmask indicating which kind of type decl is
7441 expected. 'type' should contain the basic type. 'ad' is the
7442 attribute definition of the basic type. It can be modified by
7445 static void type_decl(CType
*type
, AttributeDef
*ad
, int *v
, int td
)
7448 CType type1
, *type2
;
7451 while (tok
== '*') {
7459 qualifiers
|= VT_CONSTANT
;
7464 qualifiers
|= VT_VOLATILE
;
7472 type
->t
|= qualifiers
;
7475 /* XXX: clarify attribute handling */
7476 if (tok
== TOK_ATTRIBUTE1
|| tok
== TOK_ATTRIBUTE2
)
7477 parse_attribute(ad
);
7479 /* recursive type */
7480 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
7481 type1
.t
= 0; /* XXX: same as int */
7484 /* XXX: this is not correct to modify 'ad' at this point, but
7485 the syntax is not clear */
7486 if (tok
== TOK_ATTRIBUTE1
|| tok
== TOK_ATTRIBUTE2
)
7487 parse_attribute(ad
);
7488 type_decl(&type1
, ad
, v
, td
);
7491 /* type identifier */
7492 if (tok
>= TOK_IDENT
&& (td
& TYPE_DIRECT
)) {
7496 if (!(td
& TYPE_ABSTRACT
))
7497 expect("identifier");
7501 post_type(type
, ad
);
7502 if (tok
== TOK_ATTRIBUTE1
|| tok
== TOK_ATTRIBUTE2
)
7503 parse_attribute(ad
);
7506 /* append type at the end of type1 */
7519 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
7520 static int lvalue_type(int t
)
7525 if (bt
== VT_BYTE
|| bt
== VT_BOOL
)
7527 else if (bt
== VT_SHORT
)
7531 if (t
& VT_UNSIGNED
)
7532 r
|= VT_LVAL_UNSIGNED
;
7536 /* indirection with full error checking and bound check */
7537 static void indir(void)
7539 if ((vtop
->type
.t
& VT_BTYPE
) != VT_PTR
) {
7540 if ((vtop
->type
.t
& VT_BTYPE
) == VT_FUNC
)
7544 if ((vtop
->r
& VT_LVAL
) && !nocode_wanted
)
7546 vtop
->type
= *pointed_type(&vtop
->type
);
7547 /* Arrays and functions are never lvalues */
7548 if (!(vtop
->type
.t
& VT_ARRAY
)
7549 && (vtop
->type
.t
& VT_BTYPE
) != VT_FUNC
) {
7550 vtop
->r
|= lvalue_type(vtop
->type
.t
);
7551 /* if bound checking, the referenced pointer must be checked */
7552 if (do_bounds_check
)
7553 vtop
->r
|= VT_MUSTBOUND
;
7557 /* pass a parameter to a function and do type checking and casting */
7558 static void gfunc_param_typed(Sym
*func
, Sym
*arg
)
7563 func_type
= func
->c
;
7564 if (func_type
== FUNC_OLD
||
7565 (func_type
== FUNC_ELLIPSIS
&& arg
== NULL
)) {
7566 /* default casting : only need to convert float to double */
7567 if ((vtop
->type
.t
& VT_BTYPE
) == VT_FLOAT
) {
7571 } else if (arg
== NULL
) {
7572 error("too many arguments to function");
7575 type
.t
&= ~VT_CONSTANT
; /* need to do that to avoid false warning */
7576 gen_assign_cast(&type
);
7580 /* parse an expression of the form '(type)' or '(expr)' and return its
7582 static void parse_expr_type(CType
*type
)
7588 if (parse_btype(type
, &ad
)) {
7589 type_decl(type
, &ad
, &n
, TYPE_ABSTRACT
);
7596 static void parse_type(CType
*type
)
7601 if (!parse_btype(type
, &ad
)) {
7604 type_decl(type
, &ad
, &n
, TYPE_ABSTRACT
);
7607 static void vpush_tokc(int t
)
7611 vsetc(&type
, VT_CONST
, &tokc
);
7614 static void unary(void)
7616 int n
, t
, align
, size
, r
;
7621 /* XXX: GCC 2.95.3 does not generate a table although it should be
7635 vpush_tokc(VT_INT
| VT_UNSIGNED
);
7639 vpush_tokc(VT_LLONG
);
7643 vpush_tokc(VT_LLONG
| VT_UNSIGNED
);
7647 vpush_tokc(VT_FLOAT
);
7651 vpush_tokc(VT_DOUBLE
);
7655 vpush_tokc(VT_LDOUBLE
);
7658 case TOK___FUNCTION__
:
7660 goto tok_identifier
;
7666 /* special function name identifier */
7667 len
= strlen(funcname
) + 1;
7668 /* generate char[len] type */
7673 vpush_ref(&type
, data_section
, data_section
->data_offset
, len
);
7674 ptr
= section_ptr_add(data_section
, len
);
7675 memcpy(ptr
, funcname
, len
);
7680 #ifdef TCC_TARGET_PE
7681 t
= VT_SHORT
| VT_UNSIGNED
;
7687 /* string parsing */
7690 if (tcc_state
->warn_write_strings
)
7695 memset(&ad
, 0, sizeof(AttributeDef
));
7696 decl_initializer_alloc(&type
, &ad
, VT_CONST
, 2, 0, 0);
7701 if (parse_btype(&type
, &ad
)) {
7702 type_decl(&type
, &ad
, &n
, TYPE_ABSTRACT
);
7704 /* check ISOC99 compound literal */
7706 /* data is allocated locally by default */
7711 /* all except arrays are lvalues */
7712 if (!(type
.t
& VT_ARRAY
))
7713 r
|= lvalue_type(type
.t
);
7714 memset(&ad
, 0, sizeof(AttributeDef
));
7715 decl_initializer_alloc(&type
, &ad
, r
, 1, 0, 0);
7720 } else if (tok
== '{') {
7721 /* save all registers */
7723 /* statement expression : we do not accept break/continue
7724 inside as GCC does */
7725 block(NULL
, NULL
, NULL
, NULL
, 0, 1);
7740 /* functions names must be treated as function pointers,
7741 except for unary '&' and sizeof. Since we consider that
7742 functions are not lvalues, we only have to handle it
7743 there and in function calls. */
7744 /* arrays can also be used although they are not lvalues */
7745 if ((vtop
->type
.t
& VT_BTYPE
) != VT_FUNC
&&
7746 !(vtop
->type
.t
& VT_ARRAY
) && !(vtop
->type
.t
& VT_LLOCAL
))
7748 mk_pointer(&vtop
->type
);
7754 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
) {
7756 boolean
.t
= VT_BOOL
;
7758 vtop
->c
.i
= !vtop
->c
.i
;
7759 } else if ((vtop
->r
& VT_VALMASK
) == VT_CMP
)
7760 vtop
->c
.i
= vtop
->c
.i
^ 1;
7763 vseti(VT_JMP
, gtst(1, 0));
7774 /* in order to force cast, we add zero */
7776 if ((vtop
->type
.t
& VT_BTYPE
) == VT_PTR
)
7777 error("pointer not accepted for unary plus");
7787 parse_expr_type(&type
);
7791 size
= type_size(&type
, &align
);
7792 if (t
== TOK_SIZEOF
) {
7794 error("sizeof applied to an incomplete type");
7799 vtop
->type
.t
|= VT_UNSIGNED
;
7802 case TOK_builtin_types_compatible_p
:
7811 type1
.t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
7812 type2
.t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
7813 vpushi(is_compatible_types(&type1
, &type2
));
7816 case TOK_builtin_constant_p
:
7818 int saved_nocode_wanted
, res
;
7821 saved_nocode_wanted
= nocode_wanted
;
7824 res
= (vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
7826 nocode_wanted
= saved_nocode_wanted
;
7831 case TOK_builtin_frame_address
:
7836 if (tok
!= TOK_CINT
) {
7837 error("__builtin_frame_address only takes integers");
7840 error("TCC only supports __builtin_frame_address(0)");
7846 vset(&type
, VT_LOCAL
, 0);
7849 #ifdef TCC_TARGET_X86_64
7850 case TOK_builtin_malloc
:
7852 goto tok_identifier
;
7853 case TOK_builtin_free
:
7855 goto tok_identifier
;
7872 goto tok_identifier
;
7874 /* allow to take the address of a label */
7875 if (tok
< TOK_UIDENT
)
7876 expect("label identifier");
7877 s
= label_find(tok
);
7879 s
= label_push(&global_label_stack
, tok
, LABEL_FORWARD
);
7881 if (s
->r
== LABEL_DECLARED
)
7882 s
->r
= LABEL_FORWARD
;
7885 s
->type
.t
= VT_VOID
;
7886 mk_pointer(&s
->type
);
7887 s
->type
.t
|= VT_STATIC
;
7889 vset(&s
->type
, VT_CONST
| VT_SYM
, 0);
7898 expect("identifier");
7902 error("'%s' undeclared", get_tok_str(t
, NULL
));
7903 /* for simple function calls, we tolerate undeclared
7904 external reference to int() function */
7905 if (tcc_state
->warn_implicit_function_declaration
)
7906 warning("implicit declaration of function '%s'",
7907 get_tok_str(t
, NULL
));
7908 s
= external_global_sym(t
, &func_old_type
, 0);
7910 if ((s
->type
.t
& (VT_STATIC
| VT_INLINE
| VT_BTYPE
)) ==
7911 (VT_STATIC
| VT_INLINE
| VT_FUNC
)) {
7912 /* if referencing an inline function, then we generate a
7913 symbol to it if not already done. It will have the
7914 effect to generate code for it at the end of the
7915 compilation unit. Inline function as always
7916 generated in the text section. */
7918 put_extern_sym(s
, text_section
, 0, 0);
7919 r
= VT_SYM
| VT_CONST
;
7923 vset(&s
->type
, r
, s
->c
);
7924 /* if forward reference, we must point to s */
7925 if (vtop
->r
& VT_SYM
) {
7932 /* post operations */
7934 if (tok
== TOK_INC
|| tok
== TOK_DEC
) {
7937 } else if (tok
== '.' || tok
== TOK_ARROW
) {
7939 if (tok
== TOK_ARROW
)
7944 /* expect pointer on structure */
7945 if ((vtop
->type
.t
& VT_BTYPE
) != VT_STRUCT
)
7946 expect("struct or union");
7950 while ((s
= s
->next
) != NULL
) {
7955 error("field not found: %s", get_tok_str(tok
& ~SYM_FIELD
, NULL
));
7956 /* add field offset to pointer */
7957 vtop
->type
= char_pointer_type
; /* change type to 'char *' */
7960 /* change type to field type, and set to lvalue */
7961 vtop
->type
= s
->type
;
7962 /* an array is never an lvalue */
7963 if (!(vtop
->type
.t
& VT_ARRAY
)) {
7964 vtop
->r
|= lvalue_type(vtop
->type
.t
);
7965 /* if bound checking, the referenced pointer must be checked */
7966 if (do_bounds_check
)
7967 vtop
->r
|= VT_MUSTBOUND
;
7970 } else if (tok
== '[') {
7976 } else if (tok
== '(') {
7982 if ((vtop
->type
.t
& VT_BTYPE
) != VT_FUNC
) {
7983 /* pointer test (no array accepted) */
7984 if ((vtop
->type
.t
& (VT_BTYPE
| VT_ARRAY
)) == VT_PTR
) {
7985 vtop
->type
= *pointed_type(&vtop
->type
);
7986 if ((vtop
->type
.t
& VT_BTYPE
) != VT_FUNC
)
7990 expect("function pointer");
7993 vtop
->r
&= ~VT_LVAL
; /* no lvalue */
7995 /* get return type */
7998 sa
= s
->next
; /* first parameter */
8001 /* compute first implicit argument if a structure is returned */
8002 if ((s
->type
.t
& VT_BTYPE
) == VT_STRUCT
) {
8003 /* get some space for the returned structure */
8004 size
= type_size(&s
->type
, &align
);
8005 loc
= (loc
- size
) & -align
;
8007 ret
.r
= VT_LOCAL
| VT_LVAL
;
8008 /* pass it as 'int' to avoid structure arg passing
8010 vseti(VT_LOCAL
, loc
);
8015 /* return in register */
8016 if (is_float(ret
.type
.t
)) {
8017 ret
.r
= reg_fret(ret
.type
.t
);
8019 if ((ret
.type
.t
& VT_BTYPE
) == VT_LLONG
)
8028 gfunc_param_typed(s
, sa
);
8038 error("too few arguments to function");
8040 if (!nocode_wanted
) {
8041 gfunc_call(nb_args
);
8043 vtop
-= (nb_args
+ 1);
8046 vsetc(&ret
.type
, ret
.r
, &ret
.c
);
8054 static void uneq(void)
8060 (tok
>= TOK_A_MOD
&& tok
<= TOK_A_DIV
) ||
8061 tok
== TOK_A_XOR
|| tok
== TOK_A_OR
||
8062 tok
== TOK_A_SHL
|| tok
== TOK_A_SAR
) {
8077 static void expr_prod(void)
8082 while (tok
== '*' || tok
== '/' || tok
== '%') {
8090 static void expr_sum(void)
8095 while (tok
== '+' || tok
== '-') {
8103 static void expr_shift(void)
8108 while (tok
== TOK_SHL
|| tok
== TOK_SAR
) {
8116 static void expr_cmp(void)
8121 while ((tok
>= TOK_ULE
&& tok
<= TOK_GT
) ||
8122 tok
== TOK_ULT
|| tok
== TOK_UGE
) {
8130 static void expr_cmpeq(void)
8135 while (tok
== TOK_EQ
|| tok
== TOK_NE
) {
8143 static void expr_and(void)
8146 while (tok
== '&') {
8153 static void expr_xor(void)
8156 while (tok
== '^') {
8163 static void expr_or(void)
8166 while (tok
== '|') {
8173 /* XXX: fix this mess */
8174 static void expr_land_const(void)
8177 while (tok
== TOK_LAND
) {
8184 /* XXX: fix this mess */
8185 static void expr_lor_const(void)
8188 while (tok
== TOK_LOR
) {
8195 /* only used if non constant */
8196 static void expr_land(void)
8201 if (tok
== TOK_LAND
) {
8206 if (tok
!= TOK_LAND
) {
8216 static void expr_lor(void)
8221 if (tok
== TOK_LOR
) {
8226 if (tok
!= TOK_LOR
) {
8236 /* XXX: better constant handling */
8237 static void expr_eq(void)
8239 int tt
, u
, r1
, r2
, rc
, t1
, t2
, bt1
, bt2
;
8241 CType type
, type1
, type2
;
8248 boolean
.t
= VT_BOOL
;
8254 if (tok
!= ':' || !gnu_ext
) {
8269 if (vtop
!= vstack
) {
8270 /* needed to avoid having different registers saved in
8272 if (is_float(vtop
->type
.t
)) {
8274 #ifdef TCC_TARGET_X86_64
8275 if ((vtop
->type
.t
& VT_BTYPE
) == VT_LDOUBLE
) {
8285 if (tok
== ':' && gnu_ext
) {
8293 sv
= *vtop
; /* save value to handle it later */
8294 vtop
--; /* no vpop so that FP stack is not flushed */
8302 bt1
= t1
& VT_BTYPE
;
8304 bt2
= t2
& VT_BTYPE
;
8305 /* cast operands to correct type according to ISOC rules */
8306 if (is_float(bt1
) || is_float(bt2
)) {
8307 if (bt1
== VT_LDOUBLE
|| bt2
== VT_LDOUBLE
) {
8308 type
.t
= VT_LDOUBLE
;
8309 } else if (bt1
== VT_DOUBLE
|| bt2
== VT_DOUBLE
) {
8314 } else if (bt1
== VT_LLONG
|| bt2
== VT_LLONG
) {
8315 /* cast to biggest op */
8317 /* convert to unsigned if it does not fit in a long long */
8318 if ((t1
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_LLONG
| VT_UNSIGNED
) ||
8319 (t2
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_LLONG
| VT_UNSIGNED
))
8320 type
.t
|= VT_UNSIGNED
;
8321 } else if (bt1
== VT_PTR
|| bt2
== VT_PTR
) {
8322 /* XXX: test pointer compatibility */
8324 } else if (bt1
== VT_FUNC
|| bt2
== VT_FUNC
) {
8325 /* XXX: test function pointer compatibility */
8327 } else if (bt1
== VT_STRUCT
|| bt2
== VT_STRUCT
) {
8328 /* XXX: test structure compatibility */
8330 } else if (bt1
== VT_VOID
|| bt2
== VT_VOID
) {
8331 /* NOTE: as an extension, we accept void on only one side */
8334 /* integer operations */
8336 /* convert to unsigned if it does not fit in an integer */
8337 if ((t1
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
) ||
8338 (t2
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
))
8339 type
.t
|= VT_UNSIGNED
;
8342 /* now we convert second operand */
8344 if (VT_STRUCT
== (vtop
->type
.t
& VT_BTYPE
))
8347 if (is_float(type
.t
)) {
8349 #ifdef TCC_TARGET_X86_64
8350 if ((type
.t
& VT_BTYPE
) == VT_LDOUBLE
) {
8354 } else if ((type
.t
& VT_BTYPE
) == VT_LLONG
) {
8355 /* for long longs, we use fixed registers to avoid having
8356 to handle a complicated move */
8361 /* this is horrible, but we must also convert first
8365 /* put again first value and cast it */
8368 if (VT_STRUCT
== (vtop
->type
.t
& VT_BTYPE
))
8378 static void gexpr(void)
8389 /* parse an expression and return its type without any side effect. */
8390 static void expr_type(CType
*type
)
8392 int saved_nocode_wanted
;
8394 saved_nocode_wanted
= nocode_wanted
;
8399 nocode_wanted
= saved_nocode_wanted
;
8402 /* parse a unary expression and return its type without any side
8404 static void unary_type(CType
*type
)
8416 /* parse a constant expression and return value in vtop. */
8417 static void expr_const1(void)
8426 /* parse an integer constant and return its value. */
8427 static int expr_const(void)
8431 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) != VT_CONST
)
8432 expect("constant expression");
8438 /* return the label token if current token is a label, otherwise
8440 static int is_label(void)
8444 /* fast test first */
8445 if (tok
< TOK_UIDENT
)
8447 /* no need to save tokc because tok is an identifier */
8454 unget_tok(last_tok
);
8459 static void block(int *bsym
, int *csym
, int *case_sym
, int *def_sym
,
8460 int case_reg
, int is_expr
)
8465 /* generate line number info */
8467 (last_line_num
!= file
->line_num
|| last_ind
!= ind
)) {
8468 put_stabn(N_SLINE
, 0, file
->line_num
, ind
- func_ind
);
8470 last_line_num
= file
->line_num
;
8474 /* default return value is (void) */
8476 vtop
->type
.t
= VT_VOID
;
8479 if (tok
== TOK_IF
) {
8486 block(bsym
, csym
, case_sym
, def_sym
, case_reg
, 0);
8488 if (c
== TOK_ELSE
) {
8492 block(bsym
, csym
, case_sym
, def_sym
, case_reg
, 0);
8493 gsym(d
); /* patch else jmp */
8496 } else if (tok
== TOK_WHILE
) {
8504 block(&a
, &b
, case_sym
, def_sym
, case_reg
, 0);
8508 } else if (tok
== '{') {
8512 /* record local declaration stack position */
8514 llabel
= local_label_stack
;
8515 /* handle local labels declarations */
8516 if (tok
== TOK_LABEL
) {
8519 if (tok
< TOK_UIDENT
)
8520 expect("label identifier");
8521 label_push(&local_label_stack
, tok
, LABEL_DECLARED
);
8531 while (tok
!= '}') {
8536 block(bsym
, csym
, case_sym
, def_sym
, case_reg
, is_expr
);
8539 /* pop locally defined labels */
8540 label_pop(&local_label_stack
, llabel
);
8541 /* pop locally defined symbols */
8543 /* XXX: this solution makes only valgrind happy...
8544 triggered by gcc.c-torture/execute/20000917-1.c */
8546 switch(vtop
->type
.t
& VT_BTYPE
) {
8551 for(p
=vtop
->type
.ref
;p
;p
=p
->prev
)
8553 error("unsupported expression type");
8556 sym_pop(&local_stack
, s
);
8558 } else if (tok
== TOK_RETURN
) {
8562 gen_assign_cast(&func_vt
);
8563 if ((func_vt
.t
& VT_BTYPE
) == VT_STRUCT
) {
8565 /* if returning structure, must copy it to implicit
8566 first pointer arg location */
8569 size
= type_size(&func_vt
,&align
);
8572 if((vtop
->r
!= (VT_LOCAL
| VT_LVAL
) || (vtop
->c
.i
& 3))
8576 loc
= (loc
- size
) & -4;
8579 vset(&type
, VT_LOCAL
| VT_LVAL
, addr
);
8582 vset(&int_type
, VT_LOCAL
| VT_LVAL
, addr
);
8584 vtop
->type
= int_type
;
8590 vset(&type
, VT_LOCAL
| VT_LVAL
, func_vc
);
8593 /* copy structure value to pointer */
8598 } else if (is_float(func_vt
.t
)) {
8599 gv(rc_fret(func_vt
.t
));
8603 vtop
--; /* NOT vpop() because on x86 it would flush the fp stack */
8606 rsym
= gjmp(rsym
); /* jmp */
8607 } else if (tok
== TOK_BREAK
) {
8610 error("cannot break");
8611 *bsym
= gjmp(*bsym
);
8614 } else if (tok
== TOK_CONTINUE
) {
8617 error("cannot continue");
8618 *csym
= gjmp(*csym
);
8621 } else if (tok
== TOK_FOR
) {
8648 block(&a
, &b
, case_sym
, def_sym
, case_reg
, 0);
8653 if (tok
== TOK_DO
) {
8658 block(&a
, &b
, case_sym
, def_sym
, case_reg
, 0);
8669 if (tok
== TOK_SWITCH
) {
8673 /* XXX: other types than integer */
8674 case_reg
= gv(RC_INT
);
8678 b
= gjmp(0); /* jump to first case */
8680 block(&a
, csym
, &b
, &c
, case_reg
, 0);
8681 /* if no default, jmp after switch */
8689 if (tok
== TOK_CASE
) {
8696 if (gnu_ext
&& tok
== TOK_DOTS
) {
8700 warning("empty case range");
8702 /* since a case is like a label, we must skip it with a jmp */
8709 *case_sym
= gtst(1, 0);
8712 *case_sym
= gtst(1, 0);
8716 *case_sym
= gtst(1, *case_sym
);
8721 goto block_after_label
;
8723 if (tok
== TOK_DEFAULT
) {
8729 error("too many 'default'");
8732 goto block_after_label
;
8734 if (tok
== TOK_GOTO
) {
8736 if (tok
== '*' && gnu_ext
) {
8740 if ((vtop
->type
.t
& VT_BTYPE
) != VT_PTR
)
8743 } else if (tok
>= TOK_UIDENT
) {
8744 s
= label_find(tok
);
8745 /* put forward definition if needed */
8747 s
= label_push(&global_label_stack
, tok
, LABEL_FORWARD
);
8749 if (s
->r
== LABEL_DECLARED
)
8750 s
->r
= LABEL_FORWARD
;
8752 /* label already defined */
8753 if (s
->r
& LABEL_FORWARD
)
8754 s
->next
= (void *)gjmp((long)s
->next
);
8756 gjmp_addr((long)s
->next
);
8759 expect("label identifier");
8762 } else if (tok
== TOK_ASM1
|| tok
== TOK_ASM2
|| tok
== TOK_ASM3
) {
8770 if (s
->r
== LABEL_DEFINED
)
8771 error("duplicate label '%s'", get_tok_str(s
->v
, NULL
));
8772 gsym((long)s
->next
);
8773 s
->r
= LABEL_DEFINED
;
8775 s
= label_push(&global_label_stack
, b
, LABEL_DEFINED
);
8777 s
->next
= (void *)ind
;
8778 /* we accept this, but it is a mistake */
8781 warning("deprecated use of label at end of compound statement");
8785 block(bsym
, csym
, case_sym
, def_sym
, case_reg
, is_expr
);
8788 /* expression case */
8803 /* t is the array or struct type. c is the array or struct
8804 address. cur_index/cur_field is the pointer to the current
8805 value. 'size_only' is true if only size info is needed (only used
8807 static void decl_designator(CType
*type
, Section
*sec
, unsigned long c
,
8808 int *cur_index
, Sym
**cur_field
,
8812 int notfirst
, index
, index_last
, align
, l
, nb_elems
, elem_size
;
8818 if (gnu_ext
&& (l
= is_label()) != 0)
8820 while (tok
== '[' || tok
== '.') {
8822 if (!(type
->t
& VT_ARRAY
))
8823 expect("array type");
8826 index
= expr_const();
8827 if (index
< 0 || (s
->c
>= 0 && index
>= s
->c
))
8828 expect("invalid index");
8829 if (tok
== TOK_DOTS
&& gnu_ext
) {
8831 index_last
= expr_const();
8832 if (index_last
< 0 ||
8833 (s
->c
>= 0 && index_last
>= s
->c
) ||
8835 expect("invalid index");
8841 *cur_index
= index_last
;
8842 type
= pointed_type(type
);
8843 elem_size
= type_size(type
, &align
);
8844 c
+= index
* elem_size
;
8845 /* NOTE: we only support ranges for last designator */
8846 nb_elems
= index_last
- index
+ 1;
8847 if (nb_elems
!= 1) {
8856 if ((type
->t
& VT_BTYPE
) != VT_STRUCT
)
8857 expect("struct/union type");
8870 /* XXX: fix this mess by using explicit storage field */
8872 type1
.t
|= (type
->t
& ~VT_TYPE
);
8886 if (type
->t
& VT_ARRAY
) {
8888 type
= pointed_type(type
);
8889 c
+= index
* type_size(type
, &align
);
8893 error("too many field init");
8894 /* XXX: fix this mess by using explicit storage field */
8896 type1
.t
|= (type
->t
& ~VT_TYPE
);
8901 decl_initializer(type
, sec
, c
, 0, size_only
);
8903 /* XXX: make it more general */
8904 if (!size_only
&& nb_elems
> 1) {
8905 unsigned long c_end
;
8910 error("range init not supported yet for dynamic storage");
8911 c_end
= c
+ nb_elems
* elem_size
;
8912 if (c_end
> sec
->data_allocated
)
8913 section_realloc(sec
, c_end
);
8914 src
= sec
->data
+ c
;
8916 for(i
= 1; i
< nb_elems
; i
++) {
8918 memcpy(dst
, src
, elem_size
);
8924 #define EXPR_CONST 1
8927 /* store a value or an expression directly in global data or in local array */
8928 static void init_putv(CType
*type
, Section
*sec
, unsigned long c
,
8929 int v
, int expr_type
)
8931 int saved_global_expr
, bt
, bit_pos
, bit_size
;
8933 unsigned long long bit_mask
;
8941 /* compound literals must be allocated globally in this case */
8942 saved_global_expr
= global_expr
;
8945 global_expr
= saved_global_expr
;
8946 /* NOTE: symbols are accepted */
8947 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
)) != VT_CONST
)
8948 error("initializer element is not constant");
8956 dtype
.t
&= ~VT_CONSTANT
; /* need to do that to avoid false warning */
8959 /* XXX: not portable */
8960 /* XXX: generate error if incorrect relocation */
8961 gen_assign_cast(&dtype
);
8962 bt
= type
->t
& VT_BTYPE
;
8963 /* we'll write at most 12 bytes */
8964 if (c
+ 12 > sec
->data_allocated
) {
8965 section_realloc(sec
, c
+ 12);
8967 ptr
= sec
->data
+ c
;
8968 /* XXX: make code faster ? */
8969 if (!(type
->t
& VT_BITFIELD
)) {
8974 bit_pos
= (vtop
->type
.t
>> VT_STRUCT_SHIFT
) & 0x3f;
8975 bit_size
= (vtop
->type
.t
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f;
8976 bit_mask
= (1LL << bit_size
) - 1;
8978 if ((vtop
->r
& VT_SYM
) &&
8984 (bt
== VT_INT
&& bit_size
!= 32)))
8985 error("initializer element is not computable at load time");
8988 vtop
->c
.i
= (vtop
->c
.i
!= 0);
8990 *(char *)ptr
|= (vtop
->c
.i
& bit_mask
) << bit_pos
;
8993 *(short *)ptr
|= (vtop
->c
.i
& bit_mask
) << bit_pos
;
8996 *(double *)ptr
= vtop
->c
.d
;
8999 *(long double *)ptr
= vtop
->c
.ld
;
9002 *(long long *)ptr
|= (vtop
->c
.ll
& bit_mask
) << bit_pos
;
9005 if (vtop
->r
& VT_SYM
) {
9006 greloc(sec
, vtop
->sym
, c
, R_DATA_32
);
9008 *(int *)ptr
|= (vtop
->c
.i
& bit_mask
) << bit_pos
;
9013 vset(&dtype
, VT_LOCAL
|VT_LVAL
, c
);
9020 /* put zeros for variable based init */
9021 static void init_putz(CType
*t
, Section
*sec
, unsigned long c
, int size
)
9024 /* nothing to do because globals are already set to zero */
9026 vpush_global_sym(&func_old_type
, TOK_memset
);
9034 /* 't' contains the type and storage info. 'c' is the offset of the
9035 object in section 'sec'. If 'sec' is NULL, it means stack based
9036 allocation. 'first' is true if array '{' must be read (multi
9037 dimension implicit array init handling). 'size_only' is true if
9038 size only evaluation is wanted (only for arrays). */
9039 static void decl_initializer(CType
*type
, Section
*sec
, unsigned long c
,
9040 int first
, int size_only
)
9042 int index
, array_length
, n
, no_oblock
, nb
, parlevel
, i
;
9043 int size1
, align1
, expr_type
;
9047 if (type
->t
& VT_ARRAY
) {
9051 t1
= pointed_type(type
);
9052 size1
= type_size(t1
, &align1
);
9055 if ((first
&& tok
!= TOK_LSTR
&& tok
!= TOK_STR
) ||
9061 /* only parse strings here if correct type (otherwise: handle
9062 them as ((w)char *) expressions */
9063 if ((tok
== TOK_LSTR
&&
9064 #ifdef TCC_TARGET_PE
9065 (t1
->t
& VT_BTYPE
) == VT_SHORT
&& (t1
->t
& VT_UNSIGNED
)
9067 (t1
->t
& VT_BTYPE
) == VT_INT
9069 ) || (tok
== TOK_STR
&& (t1
->t
& VT_BTYPE
) == VT_BYTE
)) {
9070 while (tok
== TOK_STR
|| tok
== TOK_LSTR
) {
9075 /* compute maximum number of chars wanted */
9077 cstr_len
= cstr
->size
;
9079 cstr_len
= cstr
->size
/ sizeof(nwchar_t
);
9082 if (n
>= 0 && nb
> (n
- array_length
))
9083 nb
= n
- array_length
;
9086 warning("initializer-string for array is too long");
9087 /* in order to go faster for common case (char
9088 string in global variable, we handle it
9090 if (sec
&& tok
== TOK_STR
&& size1
== 1) {
9091 memcpy(sec
->data
+ c
+ array_length
, cstr
->data
, nb
);
9095 ch
= ((unsigned char *)cstr
->data
)[i
];
9097 ch
= ((nwchar_t
*)cstr
->data
)[i
];
9098 init_putv(t1
, sec
, c
+ (array_length
+ i
) * size1
,
9106 /* only add trailing zero if enough storage (no
9107 warning in this case since it is standard) */
9108 if (n
< 0 || array_length
< n
) {
9110 init_putv(t1
, sec
, c
+ (array_length
* size1
), 0, EXPR_VAL
);
9116 while (tok
!= '}') {
9117 decl_designator(type
, sec
, c
, &index
, NULL
, size_only
);
9118 if (n
>= 0 && index
>= n
)
9119 error("index too large");
9120 /* must put zero in holes (note that doing it that way
9121 ensures that it even works with designators) */
9122 if (!size_only
&& array_length
< index
) {
9123 init_putz(t1
, sec
, c
+ array_length
* size1
,
9124 (index
- array_length
) * size1
);
9127 if (index
> array_length
)
9128 array_length
= index
;
9129 /* special test for multi dimensional arrays (may not
9130 be strictly correct if designators are used at the
9132 if (index
>= n
&& no_oblock
)
9141 /* put zeros at the end */
9142 if (!size_only
&& n
>= 0 && array_length
< n
) {
9143 init_putz(t1
, sec
, c
+ array_length
* size1
,
9144 (n
- array_length
) * size1
);
9146 /* patch type size if needed */
9148 s
->c
= array_length
;
9149 } else if ((type
->t
& VT_BTYPE
) == VT_STRUCT
&&
9150 (sec
|| !first
|| tok
== '{')) {
9153 /* NOTE: the previous test is a specific case for automatic
9154 struct/union init */
9155 /* XXX: union needs only one init */
9157 /* XXX: this test is incorrect for local initializers
9158 beginning with ( without {. It would be much more difficult
9159 to do it correctly (ideally, the expression parser should
9160 be used in all cases) */
9166 while (tok
== '(') {
9170 if (!parse_btype(&type1
, &ad1
))
9172 type_decl(&type1
, &ad1
, &n
, TYPE_ABSTRACT
);
9174 if (!is_assignable_types(type
, &type1
))
9175 error("invalid type for cast");
9180 if (first
|| tok
== '{') {
9189 while (tok
!= '}') {
9190 decl_designator(type
, sec
, c
, NULL
, &f
, size_only
);
9192 if (!size_only
&& array_length
< index
) {
9193 init_putz(type
, sec
, c
+ array_length
,
9194 index
- array_length
);
9196 index
= index
+ type_size(&f
->type
, &align1
);
9197 if (index
> array_length
)
9198 array_length
= index
;
9200 if (no_oblock
&& f
== NULL
)
9206 /* put zeros at the end */
9207 if (!size_only
&& array_length
< n
) {
9208 init_putz(type
, sec
, c
+ array_length
,
9217 } else if (tok
== '{') {
9219 decl_initializer(type
, sec
, c
, first
, size_only
);
9221 } else if (size_only
) {
9222 /* just skip expression */
9224 while ((parlevel
> 0 || (tok
!= '}' && tok
!= ',')) &&
9228 else if (tok
== ')')
9233 /* currently, we always use constant expression for globals
9234 (may change for scripting case) */
9235 expr_type
= EXPR_CONST
;
9237 expr_type
= EXPR_ANY
;
9238 init_putv(type
, sec
, c
, 0, expr_type
);
9242 /* parse an initializer for type 't' if 'has_init' is non zero, and
9243 allocate space in local or global data space ('r' is either
9244 VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
9245 variable 'v' of scope 'scope' is declared before initializers are
9246 parsed. If 'v' is zero, then a reference to the new object is put
9247 in the value stack. If 'has_init' is 2, a special parsing is done
9248 to handle string constants. */
9249 static void decl_initializer_alloc(CType
*type
, AttributeDef
*ad
, int r
,
9250 int has_init
, int v
, int scope
)
9252 int size
, align
, addr
, data_offset
;
9254 ParseState saved_parse_state
= {0};
9255 TokenString init_str
;
9258 size
= type_size(type
, &align
);
9259 /* If unknown size, we must evaluate it before
9260 evaluating initializers because
9261 initializers can generate global data too
9262 (e.g. string pointers or ISOC99 compound
9263 literals). It also simplifies local
9264 initializers handling */
9265 tok_str_new(&init_str
);
9268 error("unknown type size");
9269 /* get all init string */
9270 if (has_init
== 2) {
9271 /* only get strings */
9272 while (tok
== TOK_STR
|| tok
== TOK_LSTR
) {
9273 tok_str_add_tok(&init_str
);
9278 while (level
> 0 || (tok
!= ',' && tok
!= ';')) {
9280 error("unexpected end of file in initializer");
9281 tok_str_add_tok(&init_str
);
9284 else if (tok
== '}') {
9294 tok_str_add(&init_str
, -1);
9295 tok_str_add(&init_str
, 0);
9298 save_parse_state(&saved_parse_state
);
9300 macro_ptr
= init_str
.str
;
9302 decl_initializer(type
, NULL
, 0, 1, 1);
9303 /* prepare second initializer parsing */
9304 macro_ptr
= init_str
.str
;
9307 /* if still unknown size, error */
9308 size
= type_size(type
, &align
);
9310 error("unknown type size");
9312 /* take into account specified alignment if bigger */
9314 if (ad
->aligned
> align
)
9315 align
= ad
->aligned
;
9316 } else if (ad
->packed
) {
9319 if ((r
& VT_VALMASK
) == VT_LOCAL
) {
9321 if (do_bounds_check
&& (type
->t
& VT_ARRAY
))
9323 loc
= (loc
- size
) & -align
;
9325 /* handles bounds */
9326 /* XXX: currently, since we do only one pass, we cannot track
9327 '&' operators, so we add only arrays */
9328 if (do_bounds_check
&& (type
->t
& VT_ARRAY
)) {
9329 unsigned long *bounds_ptr
;
9330 /* add padding between regions */
9332 /* then add local bound info */
9333 bounds_ptr
= section_ptr_add(lbounds_section
, 2 * sizeof(unsigned long));
9334 bounds_ptr
[0] = addr
;
9335 bounds_ptr
[1] = size
;
9338 /* local variable */
9339 sym_push(v
, type
, r
, addr
);
9341 /* push local reference */
9342 vset(type
, r
, addr
);
9348 if (v
&& scope
== VT_CONST
) {
9349 /* see if the symbol was already defined */
9352 if (!is_compatible_types(&sym
->type
, type
))
9353 error("incompatible types for redefinition of '%s'",
9354 get_tok_str(v
, NULL
));
9355 if (sym
->type
.t
& VT_EXTERN
) {
9356 /* if the variable is extern, it was not allocated */
9357 sym
->type
.t
&= ~VT_EXTERN
;
9358 /* set array size if it was ommited in extern
9360 if ((sym
->type
.t
& VT_ARRAY
) &&
9361 sym
->type
.ref
->c
< 0 &&
9363 sym
->type
.ref
->c
= type
->ref
->c
;
9365 /* we accept several definitions of the same
9366 global variable. this is tricky, because we
9367 must play with the SHN_COMMON type of the symbol */
9368 /* XXX: should check if the variable was already
9369 initialized. It is incorrect to initialized it
9371 /* no init data, we won't add more to the symbol */
9378 /* allocate symbol in corresponding section */
9383 else if (tcc_state
->nocommon
)
9387 data_offset
= sec
->data_offset
;
9388 data_offset
= (data_offset
+ align
- 1) & -align
;
9390 /* very important to increment global pointer at this time
9391 because initializers themselves can create new initializers */
9392 data_offset
+= size
;
9393 /* add padding if bound check */
9394 if (do_bounds_check
)
9396 sec
->data_offset
= data_offset
;
9397 /* allocate section space to put the data */
9398 if (sec
->sh_type
!= SHT_NOBITS
&&
9399 data_offset
> sec
->data_allocated
)
9400 section_realloc(sec
, data_offset
);
9401 /* align section if needed */
9402 if (align
> sec
->sh_addralign
)
9403 sec
->sh_addralign
= align
;
9405 addr
= 0; /* avoid warning */
9409 if (scope
!= VT_CONST
|| !sym
) {
9410 sym
= sym_push(v
, type
, r
| VT_SYM
, 0);
9412 /* update symbol definition */
9414 put_extern_sym(sym
, sec
, addr
, size
);
9417 /* put a common area */
9418 put_extern_sym(sym
, NULL
, align
, size
);
9419 /* XXX: find a nicer way */
9420 esym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym
->c
];
9421 esym
->st_shndx
= SHN_COMMON
;
9426 /* push global reference */
9427 sym
= get_sym_ref(type
, sec
, addr
, size
);
9429 vsetc(type
, VT_CONST
| VT_SYM
, &cval
);
9433 /* handles bounds now because the symbol must be defined
9434 before for the relocation */
9435 if (do_bounds_check
) {
9436 unsigned long *bounds_ptr
;
9438 greloc(bounds_section
, sym
, bounds_section
->data_offset
, R_DATA_32
);
9439 /* then add global bound info */
9440 bounds_ptr
= section_ptr_add(bounds_section
, 2 * sizeof(long));
9441 bounds_ptr
[0] = 0; /* relocated */
9442 bounds_ptr
[1] = size
;
9446 decl_initializer(type
, sec
, addr
, 1, 0);
9447 /* restore parse state if needed */
9449 tok_str_free(init_str
.str
);
9450 restore_parse_state(&saved_parse_state
);
9456 void put_func_debug(Sym
*sym
)
9461 /* XXX: we put here a dummy type */
9462 snprintf(buf
, sizeof(buf
), "%s:%c1",
9463 funcname
, sym
->type
.t
& VT_STATIC
? 'f' : 'F');
9464 put_stabs_r(buf
, N_FUN
, 0, file
->line_num
, 0,
9465 cur_text_section
, sym
->c
);
9466 /* //gr gdb wants a line at the function */
9467 put_stabn(N_SLINE
, 0, file
->line_num
, 0);
9472 /* parse an old style function declaration list */
9473 /* XXX: check multiple parameter */
9474 static void func_decl_list(Sym
*func_sym
)
9481 /* parse each declaration */
9482 while (tok
!= '{' && tok
!= ';' && tok
!= ',' && tok
!= TOK_EOF
) {
9483 if (!parse_btype(&btype
, &ad
))
9484 expect("declaration list");
9485 if (((btype
.t
& VT_BTYPE
) == VT_ENUM
||
9486 (btype
.t
& VT_BTYPE
) == VT_STRUCT
) &&
9488 /* we accept no variable after */
9492 type_decl(&type
, &ad
, &v
, TYPE_DIRECT
);
9493 /* find parameter in function parameter list */
9496 if ((s
->v
& ~SYM_FIELD
) == v
)
9500 error("declaration for parameter '%s' but no such parameter",
9501 get_tok_str(v
, NULL
));
9503 /* check that no storage specifier except 'register' was given */
9504 if (type
.t
& VT_STORAGE
)
9505 error("storage class specified for '%s'", get_tok_str(v
, NULL
));
9506 convert_parameter_type(&type
);
9507 /* we can add the type (NOTE: it could be local to the function) */
9509 /* accept other parameters */
9520 /* parse a function defined by symbol 'sym' and generate its code in
9521 'cur_text_section' */
9522 static void gen_function(Sym
*sym
)
9524 int saved_nocode_wanted
= nocode_wanted
;
9526 ind
= cur_text_section
->data_offset
;
9527 /* NOTE: we patch the symbol size later */
9528 put_extern_sym(sym
, cur_text_section
, ind
, 0);
9529 funcname
= get_tok_str(sym
->v
, NULL
);
9531 /* put debug symbol */
9533 put_func_debug(sym
);
9534 /* push a dummy symbol to enable local sym storage */
9535 sym_push2(&local_stack
, SYM_FIELD
, 0, 0);
9536 gfunc_prolog(&sym
->type
);
9538 block(NULL
, NULL
, NULL
, NULL
, 0, 0);
9541 cur_text_section
->data_offset
= ind
;
9542 label_pop(&global_label_stack
, NULL
);
9543 sym_pop(&local_stack
, NULL
); /* reset local stack */
9544 /* end of function */
9545 /* patch symbol size */
9546 ((ElfW(Sym
) *)symtab_section
->data
)[sym
->c
].st_size
=
9549 put_stabn(N_FUN
, 0, 0, ind
- func_ind
);
9551 /* It's better to crash than to generate wrong code */
9552 cur_text_section
= NULL
;
9553 funcname
= ""; /* for safety */
9554 func_vt
.t
= VT_VOID
; /* for safety */
9555 ind
= 0; /* for safety */
9556 nocode_wanted
= saved_nocode_wanted
;
9559 static void gen_inline_functions(void)
9563 int *str
, inline_generated
;
9565 /* iterate while inline function are referenced */
9567 inline_generated
= 0;
9568 for(sym
= global_stack
; sym
!= NULL
; sym
= sym
->prev
) {
9570 if (((type
->t
& VT_BTYPE
) == VT_FUNC
) &&
9571 (type
->t
& (VT_STATIC
| VT_INLINE
)) ==
9572 (VT_STATIC
| VT_INLINE
) &&
9574 /* the function was used: generate its code and
9575 convert it to a normal function */
9576 str
= INLINE_DEF(sym
->r
);
9577 sym
->r
= VT_SYM
| VT_CONST
;
9578 sym
->type
.t
&= ~VT_INLINE
;
9582 cur_text_section
= text_section
;
9584 macro_ptr
= NULL
; /* fail safe */
9587 inline_generated
= 1;
9590 if (!inline_generated
)
9594 /* free all remaining inline function tokens */
9595 for(sym
= global_stack
; sym
!= NULL
; sym
= sym
->prev
) {
9597 if (((type
->t
& VT_BTYPE
) == VT_FUNC
) &&
9598 (type
->t
& (VT_STATIC
| VT_INLINE
)) ==
9599 (VT_STATIC
| VT_INLINE
)) {
9600 //gr printf("sym %d %s\n", sym->r, get_tok_str(sym->v, NULL));
9601 if (sym
->r
== (VT_SYM
| VT_CONST
)) //gr beware!
9603 str
= INLINE_DEF(sym
->r
);
9605 sym
->r
= 0; /* fail safe */
9610 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
9611 static void decl(int l
)
9619 if (!parse_btype(&btype
, &ad
)) {
9620 /* skip redundant ';' */
9621 /* XXX: find more elegant solution */
9626 if (l
== VT_CONST
&&
9627 (tok
== TOK_ASM1
|| tok
== TOK_ASM2
|| tok
== TOK_ASM3
)) {
9628 /* global asm block */
9632 /* special test for old K&R protos without explicit int
9633 type. Only accepted when defining global data */
9634 if (l
== VT_LOCAL
|| tok
< TOK_DEFINE
)
9638 if (((btype
.t
& VT_BTYPE
) == VT_ENUM
||
9639 (btype
.t
& VT_BTYPE
) == VT_STRUCT
) &&
9641 /* we accept no variable after */
9645 while (1) { /* iterate thru each declaration */
9647 type_decl(&type
, &ad
, &v
, TYPE_DIRECT
);
9651 type_to_str(buf
, sizeof(buf
), t
, get_tok_str(v
, NULL
));
9652 printf("type = '%s'\n", buf
);
9655 if ((type
.t
& VT_BTYPE
) == VT_FUNC
) {
9656 /* if old style function prototype, we accept a
9659 if (sym
->c
== FUNC_OLD
)
9660 func_decl_list(sym
);
9665 error("cannot use local functions");
9666 if ((type
.t
& VT_BTYPE
) != VT_FUNC
)
9667 expect("function definition");
9669 /* reject abstract declarators in function definition */
9671 while ((sym
= sym
->next
) != NULL
)
9672 if (!(sym
->v
& ~SYM_FIELD
))
9673 expect("identifier");
9675 /* XXX: cannot do better now: convert extern line to static inline */
9676 if ((type
.t
& (VT_EXTERN
| VT_INLINE
)) == (VT_EXTERN
| VT_INLINE
))
9677 type
.t
= (type
.t
& ~VT_EXTERN
) | VT_STATIC
;
9681 if ((sym
->type
.t
& VT_BTYPE
) != VT_FUNC
)
9683 /* specific case: if not func_call defined, we put
9684 the one of the prototype */
9685 /* XXX: should have default value */
9686 r
= sym
->type
.ref
->r
;
9687 if (FUNC_CALL(r
) != FUNC_CDECL
9688 && FUNC_CALL(type
.ref
->r
) == FUNC_CDECL
)
9689 FUNC_CALL(type
.ref
->r
) = FUNC_CALL(r
);
9691 FUNC_EXPORT(type
.ref
->r
) = 1;
9693 if (!is_compatible_types(&sym
->type
, &type
)) {
9695 error("incompatible types for redefinition of '%s'",
9696 get_tok_str(v
, NULL
));
9698 /* if symbol is already defined, then put complete type */
9701 /* put function symbol */
9702 sym
= global_identifier_push(v
, type
.t
, 0);
9703 sym
->type
.ref
= type
.ref
;
9706 /* static inline functions are just recorded as a kind
9707 of macro. Their code will be emitted at the end of
9708 the compilation unit only if they are used */
9709 if ((type
.t
& (VT_INLINE
| VT_STATIC
)) ==
9710 (VT_INLINE
| VT_STATIC
)) {
9711 TokenString func_str
;
9714 tok_str_new(&func_str
);
9720 error("unexpected end of file");
9721 tok_str_add_tok(&func_str
);
9726 } else if (t
== '}') {
9728 if (block_level
== 0)
9732 tok_str_add(&func_str
, -1);
9733 tok_str_add(&func_str
, 0);
9734 INLINE_DEF(sym
->r
) = func_str
.str
;
9736 /* compute text section */
9737 cur_text_section
= ad
.section
;
9738 if (!cur_text_section
)
9739 cur_text_section
= text_section
;
9740 sym
->r
= VT_SYM
| VT_CONST
;
9745 if (btype
.t
& VT_TYPEDEF
) {
9746 /* save typedefed type */
9747 /* XXX: test storage specifiers ? */
9748 sym
= sym_push(v
, &type
, 0, 0);
9749 sym
->type
.t
|= VT_TYPEDEF
;
9750 } else if ((type
.t
& VT_BTYPE
) == VT_FUNC
) {
9751 /* external function definition */
9752 /* specific case for func_call attribute */
9754 type
.ref
->r
= ad
.func_attr
;
9755 external_sym(v
, &type
, 0);
9757 /* not lvalue if array */
9759 if (!(type
.t
& VT_ARRAY
))
9760 r
|= lvalue_type(type
.t
);
9761 has_init
= (tok
== '=');
9762 if ((btype
.t
& VT_EXTERN
) ||
9763 ((type
.t
& VT_ARRAY
) && (type
.t
& VT_STATIC
) &&
9764 !has_init
&& l
== VT_CONST
&& type
.ref
->c
< 0)) {
9765 /* external variable */
9766 /* NOTE: as GCC, uninitialized global static
9767 arrays of null size are considered as
9769 external_sym(v
, &type
, r
);
9771 type
.t
|= (btype
.t
& VT_STATIC
); /* Retain "static". */
9772 if (type
.t
& VT_STATIC
)
9778 decl_initializer_alloc(&type
, &ad
, r
,
9792 /* better than nothing, but needs extension to handle '-E' option
9794 static void preprocess_init(TCCState
*s1
)
9796 s1
->include_stack_ptr
= s1
->include_stack
;
9797 /* XXX: move that before to avoid having to initialize
9798 file->ifdef_stack_ptr ? */
9799 s1
->ifdef_stack_ptr
= s1
->ifdef_stack
;
9800 file
->ifdef_stack_ptr
= s1
->ifdef_stack_ptr
;
9802 /* XXX: not ANSI compliant: bound checking says error */
9804 s1
->pack_stack
[0] = 0;
9805 s1
->pack_stack_ptr
= s1
->pack_stack
;
9808 /* compile the C file opened in 'file'. Return non zero if errors. */
9809 static int tcc_compile(TCCState
*s1
)
9813 volatile int section_sym
;
9816 printf("%s: **** new file\n", file
->filename
);
9818 preprocess_init(s1
);
9820 cur_text_section
= NULL
;
9822 anon_sym
= SYM_FIRST_ANOM
;
9824 /* file info: full path + filename */
9825 section_sym
= 0; /* avoid warning */
9827 section_sym
= put_elf_sym(symtab_section
, 0, 0,
9828 ELFW(ST_INFO
)(STB_LOCAL
, STT_SECTION
), 0,
9829 text_section
->sh_num
, NULL
);
9830 getcwd(buf
, sizeof(buf
));
9832 normalize_slashes(buf
);
9834 pstrcat(buf
, sizeof(buf
), "/");
9835 put_stabs_r(buf
, N_SO
, 0, 0,
9836 text_section
->data_offset
, text_section
, section_sym
);
9837 put_stabs_r(file
->filename
, N_SO
, 0, 0,
9838 text_section
->data_offset
, text_section
, section_sym
);
9840 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
9841 symbols can be safely used */
9842 put_elf_sym(symtab_section
, 0, 0,
9843 ELFW(ST_INFO
)(STB_LOCAL
, STT_FILE
), 0,
9844 SHN_ABS
, file
->filename
);
9846 /* define some often used types */
9847 int_type
.t
= VT_INT
;
9849 char_pointer_type
.t
= VT_BYTE
;
9850 mk_pointer(&char_pointer_type
);
9852 func_old_type
.t
= VT_FUNC
;
9853 func_old_type
.ref
= sym_push(SYM_FIELD
, &int_type
, FUNC_CDECL
, FUNC_OLD
);
9855 #if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)
9856 float_type
.t
= VT_FLOAT
;
9857 double_type
.t
= VT_DOUBLE
;
9859 func_float_type
.t
= VT_FUNC
;
9860 func_float_type
.ref
= sym_push(SYM_FIELD
, &float_type
, FUNC_CDECL
, FUNC_OLD
);
9861 func_double_type
.t
= VT_FUNC
;
9862 func_double_type
.ref
= sym_push(SYM_FIELD
, &double_type
, FUNC_CDECL
, FUNC_OLD
);
9866 /* define 'void *alloca(unsigned int)' builtin function */
9871 sym
= sym_push(p
, mk_pointer(VT_VOID
), FUNC_CDECL
, FUNC_NEW
);
9872 s1
= sym_push(SYM_FIELD
, VT_UNSIGNED
| VT_INT
, 0, 0);
9875 sym_push(TOK_alloca
, VT_FUNC
| (p
<< VT_STRUCT_SHIFT
), VT_CONST
, 0);
9879 define_start
= define_stack
;
9882 if (setjmp(s1
->error_jmp_buf
) == 0) {
9884 s1
->error_set_jmp_enabled
= 1;
9886 ch
= file
->buf_ptr
[0];
9887 tok_flags
= TOK_FLAG_BOL
| TOK_FLAG_BOF
;
9888 parse_flags
= PARSE_FLAG_PREPROCESS
| PARSE_FLAG_TOK_NUM
;
9892 expect("declaration");
9894 /* end of translation unit info */
9896 put_stabs_r(NULL
, N_SO
, 0, 0,
9897 text_section
->data_offset
, text_section
, section_sym
);
9900 s1
->error_set_jmp_enabled
= 0;
9902 /* reset define stack, but leave -Dsymbols (may be incorrect if
9903 they are undefined) */
9904 free_defines(define_start
);
9906 gen_inline_functions();
9908 sym_pop(&global_stack
, NULL
);
9909 sym_pop(&local_stack
, NULL
);
9911 return s1
->nb_errors
!= 0 ? -1 : 0;
9914 /* Preprocess the current file */
9915 static int tcc_preprocess(TCCState
*s1
)
9918 BufferedFile
*file_ref
;
9919 int token_seen
, line_ref
;
9921 preprocess_init(s1
);
9922 define_start
= define_stack
;
9923 ch
= file
->buf_ptr
[0];
9924 tok_flags
= TOK_FLAG_BOL
| TOK_FLAG_BOF
;
9925 parse_flags
= PARSE_FLAG_ASM_COMMENTS
| PARSE_FLAG_PREPROCESS
|
9926 PARSE_FLAG_LINEFEED
| PARSE_FLAG_SPACES
;
9933 if (tok
== TOK_EOF
) {
9935 } else if (tok
== TOK_LINEFEED
) {
9940 } else if (!token_seen
) {
9941 int d
= file
->line_num
- line_ref
;
9942 if (file
!= file_ref
|| d
< 0 || d
>= 8)
9943 fprintf(s1
->outfile
, "# %d \"%s\"\n", file
->line_num
, file
->filename
);
9946 fputs("\n", s1
->outfile
), --d
;
9947 line_ref
= (file_ref
= file
)->line_num
;
9950 fputs(get_tok_str(tok
, &tokc
), s1
->outfile
);
9952 free_defines(define_start
);
9957 int tcc_compile_string(TCCState
*s
, const char *str
)
9959 BufferedFile bf1
, *bf
= &bf1
;
9963 /* init file structure */
9965 /* XXX: avoid copying */
9967 buf
= tcc_malloc(len
+ 1);
9970 memcpy(buf
, str
, len
);
9973 bf
->buf_end
= buf
+ len
;
9974 pstrcpy(bf
->filename
, sizeof(bf
->filename
), "<string>");
9977 ret
= tcc_compile(s
);
9981 /* currently, no need to close */
9986 /* define a preprocessor symbol. A value can also be provided with the '=' operator */
9987 void tcc_define_symbol(TCCState
*s1
, const char *sym
, const char *value
)
9989 BufferedFile bf1
, *bf
= &bf1
;
9991 pstrcpy(bf
->buffer
, IO_BUF_SIZE
, sym
);
9992 pstrcat(bf
->buffer
, IO_BUF_SIZE
, " ");
9996 pstrcat(bf
->buffer
, IO_BUF_SIZE
, value
);
9998 /* init file structure */
10000 bf
->buf_ptr
= bf
->buffer
;
10001 bf
->buf_end
= bf
->buffer
+ strlen(bf
->buffer
);
10002 *bf
->buf_end
= CH_EOB
;
10003 bf
->filename
[0] = '\0';
10007 s1
->include_stack_ptr
= s1
->include_stack
;
10009 /* parse with define parser */
10010 ch
= file
->buf_ptr
[0];
10016 /* undefine a preprocessor symbol */
10017 void tcc_undefine_symbol(TCCState
*s1
, const char *sym
)
10021 ts
= tok_alloc(sym
, strlen(sym
));
10022 s
= define_find(ts
->tok
);
10023 /* undefine symbol by putting an invalid name */
10028 #ifdef CONFIG_TCC_ASM
10030 #ifdef TCC_TARGET_I386
10031 #include "i386-asm.c"
10033 #include "tccasm.c"
10036 static void asm_instr(void)
10038 error("inline asm() not supported");
10040 static void asm_global_instr(void)
10042 error("inline asm() not supported");
10046 #include "tccelf.c"
10048 #ifdef TCC_TARGET_COFF
10049 #include "tcccoff.c"
10052 #ifdef TCC_TARGET_PE
10056 /* print the position in the source file of PC value 'pc' by reading
10057 the stabs debug information */
10058 static void rt_printline(unsigned long wanted_pc
)
10060 Stab_Sym
*sym
, *sym_end
;
10061 char func_name
[128], last_func_name
[128];
10062 unsigned long func_addr
, last_pc
, pc
;
10063 const char *incl_files
[INCLUDE_STACK_SIZE
];
10064 int incl_index
, len
, last_line_num
, i
;
10065 const char *str
, *p
;
10067 fprintf(stderr
, "0x%08lx:", wanted_pc
);
10069 func_name
[0] = '\0';
10072 last_func_name
[0] = '\0';
10073 last_pc
= 0xffffffff;
10075 sym
= (Stab_Sym
*)stab_section
->data
+ 1;
10076 sym_end
= (Stab_Sym
*)(stab_section
->data
+ stab_section
->data_offset
);
10077 while (sym
< sym_end
) {
10078 switch(sym
->n_type
) {
10079 /* function start or end */
10081 if (sym
->n_strx
== 0) {
10082 /* we test if between last line and end of function */
10083 pc
= sym
->n_value
+ func_addr
;
10084 if (wanted_pc
>= last_pc
&& wanted_pc
< pc
)
10086 func_name
[0] = '\0';
10089 str
= stabstr_section
->data
+ sym
->n_strx
;
10090 p
= strchr(str
, ':');
10092 pstrcpy(func_name
, sizeof(func_name
), str
);
10095 if (len
> sizeof(func_name
) - 1)
10096 len
= sizeof(func_name
) - 1;
10097 memcpy(func_name
, str
, len
);
10098 func_name
[len
] = '\0';
10100 func_addr
= sym
->n_value
;
10103 /* line number info */
10105 pc
= sym
->n_value
+ func_addr
;
10106 if (wanted_pc
>= last_pc
&& wanted_pc
< pc
)
10109 last_line_num
= sym
->n_desc
;
10111 strcpy(last_func_name
, func_name
);
10113 /* include files */
10115 str
= stabstr_section
->data
+ sym
->n_strx
;
10117 if (incl_index
< INCLUDE_STACK_SIZE
) {
10118 incl_files
[incl_index
++] = str
;
10122 if (incl_index
> 1)
10126 if (sym
->n_strx
== 0) {
10127 incl_index
= 0; /* end of translation unit */
10129 str
= stabstr_section
->data
+ sym
->n_strx
;
10130 /* do not add path */
10132 if (len
> 0 && str
[len
- 1] != '/')
10140 /* second pass: we try symtab symbols (no line number info) */
10143 ElfW(Sym
) *sym
, *sym_end
;
10146 sym_end
= (ElfW(Sym
) *)(symtab_section
->data
+ symtab_section
->data_offset
);
10147 for(sym
= (ElfW(Sym
) *)symtab_section
->data
+ 1;
10150 type
= ELFW(ST_TYPE
)(sym
->st_info
);
10151 if (type
== STT_FUNC
) {
10152 if (wanted_pc
>= sym
->st_value
&&
10153 wanted_pc
< sym
->st_value
+ sym
->st_size
) {
10154 pstrcpy(last_func_name
, sizeof(last_func_name
),
10155 strtab_section
->data
+ sym
->st_name
);
10161 /* did not find any info: */
10162 fprintf(stderr
, " ???\n");
10165 if (last_func_name
[0] != '\0') {
10166 fprintf(stderr
, " %s()", last_func_name
);
10168 if (incl_index
> 0) {
10169 fprintf(stderr
, " (%s:%d",
10170 incl_files
[incl_index
- 1], last_line_num
);
10171 for(i
= incl_index
- 2; i
>= 0; i
--)
10172 fprintf(stderr
, ", included from %s", incl_files
[i
]);
10173 fprintf(stderr
, ")");
10175 fprintf(stderr
, "\n");
10178 #if !defined(_WIN32) && !defined(CONFIG_TCCBOOT)
10182 /* fix for glibc 2.1 */
10184 #define REG_EIP EIP
10185 #define REG_EBP EBP
10188 /* return the PC at frame level 'level'. Return non zero if not found */
10189 static int rt_get_caller_pc(unsigned long *paddr
,
10190 ucontext_t
*uc
, int level
)
10196 #if defined(__FreeBSD__)
10197 *paddr
= uc
->uc_mcontext
.mc_eip
;
10198 #elif defined(__dietlibc__)
10199 *paddr
= uc
->uc_mcontext
.eip
;
10201 *paddr
= uc
->uc_mcontext
.gregs
[REG_EIP
];
10205 #if defined(__FreeBSD__)
10206 fp
= uc
->uc_mcontext
.mc_ebp
;
10207 #elif defined(__dietlibc__)
10208 fp
= uc
->uc_mcontext
.ebp
;
10210 fp
= uc
->uc_mcontext
.gregs
[REG_EBP
];
10212 for(i
=1;i
<level
;i
++) {
10213 /* XXX: check address validity with program info */
10214 if (fp
<= 0x1000 || fp
>= 0xc0000000)
10216 fp
= ((unsigned long *)fp
)[0];
10218 *paddr
= ((unsigned long *)fp
)[1];
10222 #elif defined(__x86_64__)
10223 /* return the PC at frame level 'level'. Return non zero if not found */
10224 static int rt_get_caller_pc(unsigned long *paddr
,
10225 ucontext_t
*uc
, int level
)
10231 /* XXX: only support linux */
10232 *paddr
= uc
->uc_mcontext
.gregs
[REG_RIP
];
10235 fp
= uc
->uc_mcontext
.gregs
[REG_RBP
];
10236 for(i
=1;i
<level
;i
++) {
10237 /* XXX: check address validity with program info */
10240 fp
= ((unsigned long *)fp
)[0];
10242 *paddr
= ((unsigned long *)fp
)[1];
10248 #warning add arch specific rt_get_caller_pc()
10250 static int rt_get_caller_pc(unsigned long *paddr
,
10251 ucontext_t
*uc
, int level
)
10257 /* emit a run time error at position 'pc' */
10258 void rt_error(ucontext_t
*uc
, const char *fmt
, ...)
10265 fprintf(stderr
, "Runtime error: ");
10266 vfprintf(stderr
, fmt
, ap
);
10267 fprintf(stderr
, "\n");
10268 for(i
=0;i
<num_callers
;i
++) {
10269 if (rt_get_caller_pc(&pc
, uc
, i
) < 0)
10272 fprintf(stderr
, "at ");
10274 fprintf(stderr
, "by ");
10281 /* signal handler for fatal errors */
10282 static void sig_error(int signum
, siginfo_t
*siginf
, void *puc
)
10284 ucontext_t
*uc
= puc
;
10288 switch(siginf
->si_code
) {
10291 rt_error(uc
, "division by zero");
10294 rt_error(uc
, "floating point exception");
10300 if (rt_bound_error_msg
&& *rt_bound_error_msg
)
10301 rt_error(uc
, *rt_bound_error_msg
);
10303 rt_error(uc
, "dereferencing invalid pointer");
10306 rt_error(uc
, "illegal instruction");
10309 rt_error(uc
, "abort() called");
10312 rt_error(uc
, "caught signal %d", signum
);
10319 /* copy code into memory passed in by the caller and do all relocations
10320 (needed before using tcc_get_symbol()).
10321 returns -1 on error and required size if ptr is NULL */
10322 int tcc_relocate(TCCState
*s1
, void *ptr
)
10325 unsigned long offset
, length
, mem
;
10330 if (0 == s1
->runtime_added
) {
10331 #ifdef TCC_TARGET_PE
10332 pe_add_runtime(s1
);
10333 relocate_common_syms();
10334 tcc_add_linker_symbols(s1
);
10336 tcc_add_runtime(s1
);
10337 relocate_common_syms();
10338 tcc_add_linker_symbols(s1
);
10339 build_got_entries(s1
);
10341 s1
->runtime_added
= 1;
10345 mem
= (unsigned long)ptr
;
10346 for(i
= 1; i
< s1
->nb_sections
; i
++) {
10347 s
= s1
->sections
[i
];
10348 if (0 == (s
->sh_flags
& SHF_ALLOC
))
10350 length
= s
->data_offset
;
10353 } else if (1 == mem
) {
10354 /* section are relocated in place.
10355 We also alloc the bss space */
10356 if (s
->sh_type
== SHT_NOBITS
)
10357 s
->data
= tcc_malloc(length
);
10358 s
->sh_addr
= (unsigned long)s
->data
;
10360 /* sections are relocated to new memory */
10361 s
->sh_addr
= (mem
+ offset
+ 15) & ~15;
10363 offset
= (offset
+ length
+ 15) & ~15;
10366 #ifdef TCC_TARGET_X86_64
10367 s1
->runtime_plt_and_got_offset
= 0;
10368 s1
->runtime_plt_and_got
= (char *)(mem
+ offset
);
10369 /* double the size of the buffer for got and plt entries
10370 XXX: calculate exact size for them? */
10375 return offset
+ 15;
10377 /* relocate symbols */
10378 relocate_syms(s1
, 1);
10382 /* relocate each section */
10383 for(i
= 1; i
< s1
->nb_sections
; i
++) {
10384 s
= s1
->sections
[i
];
10386 relocate_section(s1
, s
);
10389 for(i
= 1; i
< s1
->nb_sections
; i
++) {
10390 s
= s1
->sections
[i
];
10391 if (0 == (s
->sh_flags
& SHF_ALLOC
))
10393 length
= s
->data_offset
;
10394 // printf("%-12s %08x %04x\n", s->name, s->sh_addr, length);
10395 ptr
= (void*)s
->sh_addr
;
10396 if (NULL
== s
->data
|| s
->sh_type
== SHT_NOBITS
)
10397 memset(ptr
, 0, length
);
10398 else if (ptr
!= s
->data
)
10399 memcpy(ptr
, s
->data
, length
);
10400 /* mark executable sections as executable in memory */
10401 if (s
->sh_flags
& SHF_EXECINSTR
)
10402 set_pages_executable(ptr
, length
);
10404 #ifdef TCC_TARGET_X86_64
10405 set_pages_executable(s1
->runtime_plt_and_got
,
10406 s1
->runtime_plt_and_got_offset
);
10411 /* launch the compiled program with the given arguments */
10412 int tcc_run(TCCState
*s1
, int argc
, char **argv
)
10414 int (*prog_main
)(int, char **);
10418 ret
= tcc_relocate(s1
, NULL
);
10421 ptr
= tcc_malloc(ret
);
10422 tcc_relocate(s1
, ptr
);
10424 prog_main
= tcc_get_symbol_err(s1
, "main");
10427 #if defined(_WIN32) || defined(CONFIG_TCCBOOT)
10428 error("debug mode currently not available for Windows");
10430 struct sigaction sigact
;
10431 /* install TCC signal handlers to print debug info on fatal
10433 sigact
.sa_flags
= SA_SIGINFO
| SA_RESETHAND
;
10434 sigact
.sa_sigaction
= sig_error
;
10435 sigemptyset(&sigact
.sa_mask
);
10436 sigaction(SIGFPE
, &sigact
, NULL
);
10437 sigaction(SIGILL
, &sigact
, NULL
);
10438 sigaction(SIGSEGV
, &sigact
, NULL
);
10439 sigaction(SIGBUS
, &sigact
, NULL
);
10440 sigaction(SIGABRT
, &sigact
, NULL
);
10444 #ifdef CONFIG_TCC_BCHECK
10445 if (do_bounds_check
) {
10446 void (*bound_init
)(void);
10448 /* set error function */
10449 rt_bound_error_msg
= tcc_get_symbol_err(s1
, "__bound_error_msg");
10451 /* XXX: use .init section so that it also work in binary ? */
10452 bound_init
= (void *)tcc_get_symbol_err(s1
, "__bound_init");
10456 ret
= (*prog_main
)(argc
, argv
);
10461 void tcc_memstats(void)
10464 printf("memory in use: %d\n", mem_cur_size
);
10468 static void tcc_cleanup(void)
10472 if (NULL
== tcc_state
)
10476 /* free -D defines */
10477 free_defines(NULL
);
10480 n
= tok_ident
- TOK_IDENT
;
10481 for(i
= 0; i
< n
; i
++)
10482 tcc_free(table_ident
[i
]);
10483 tcc_free(table_ident
);
10485 /* free sym_pools */
10486 dynarray_reset(&sym_pools
, &nb_sym_pools
);
10487 /* string buffer */
10488 cstr_free(&tokcstr
);
10489 /* reset symbol stack */
10490 sym_free_first
= NULL
;
10491 /* cleanup from error/setjmp */
10495 TCCState
*tcc_new(void)
10504 s
= tcc_mallocz(sizeof(TCCState
));
10508 s
->output_type
= TCC_OUTPUT_MEMORY
;
10510 /* init isid table */
10511 for(i
=CH_EOF
;i
<256;i
++)
10512 isidnum_table
[i
-CH_EOF
] = isid(i
) || isnum(i
);
10514 /* add all tokens */
10515 table_ident
= NULL
;
10516 memset(hash_ident
, 0, TOK_HASH_SIZE
* sizeof(TokenSym
*));
10518 tok_ident
= TOK_IDENT
;
10527 ts
= tok_alloc(p
, r
- p
- 1);
10531 /* we add dummy defines for some special macros to speed up tests
10532 and to have working defined() */
10533 define_push(TOK___LINE__
, MACRO_OBJ
, NULL
, NULL
);
10534 define_push(TOK___FILE__
, MACRO_OBJ
, NULL
, NULL
);
10535 define_push(TOK___DATE__
, MACRO_OBJ
, NULL
, NULL
);
10536 define_push(TOK___TIME__
, MACRO_OBJ
, NULL
, NULL
);
10538 /* standard defines */
10539 tcc_define_symbol(s
, "__STDC__", NULL
);
10540 tcc_define_symbol(s
, "__STDC_VERSION__", "199901L");
10541 #if defined(TCC_TARGET_I386)
10542 tcc_define_symbol(s
, "__i386__", NULL
);
10544 #if defined(TCC_TARGET_X86_64)
10545 tcc_define_symbol(s
, "__x86_64__", NULL
);
10547 #if defined(TCC_TARGET_ARM)
10548 tcc_define_symbol(s
, "__ARM_ARCH_4__", NULL
);
10549 tcc_define_symbol(s
, "__arm_elf__", NULL
);
10550 tcc_define_symbol(s
, "__arm_elf", NULL
);
10551 tcc_define_symbol(s
, "arm_elf", NULL
);
10552 tcc_define_symbol(s
, "__arm__", NULL
);
10553 tcc_define_symbol(s
, "__arm", NULL
);
10554 tcc_define_symbol(s
, "arm", NULL
);
10555 tcc_define_symbol(s
, "__APCS_32__", NULL
);
10557 #ifdef TCC_TARGET_PE
10558 tcc_define_symbol(s
, "_WIN32", NULL
);
10560 tcc_define_symbol(s
, "__unix__", NULL
);
10561 tcc_define_symbol(s
, "__unix", NULL
);
10562 #if defined(__linux)
10563 tcc_define_symbol(s
, "__linux__", NULL
);
10564 tcc_define_symbol(s
, "__linux", NULL
);
10567 /* tiny C specific defines */
10568 tcc_define_symbol(s
, "__TINYC__", NULL
);
10570 /* tiny C & gcc defines */
10571 tcc_define_symbol(s
, "__SIZE_TYPE__", "unsigned int");
10572 tcc_define_symbol(s
, "__PTRDIFF_TYPE__", "int");
10573 #ifdef TCC_TARGET_PE
10574 tcc_define_symbol(s
, "__WCHAR_TYPE__", "unsigned short");
10576 tcc_define_symbol(s
, "__WCHAR_TYPE__", "int");
10579 #ifndef TCC_TARGET_PE
10580 /* default library paths */
10581 tcc_add_library_path(s
, CONFIG_SYSROOT
"/usr/local/lib");
10582 tcc_add_library_path(s
, CONFIG_SYSROOT
"/usr/lib");
10583 tcc_add_library_path(s
, CONFIG_SYSROOT
"/lib");
10586 /* no section zero */
10587 dynarray_add((void ***)&s
->sections
, &s
->nb_sections
, NULL
);
10589 /* create standard sections */
10590 text_section
= new_section(s
, ".text", SHT_PROGBITS
, SHF_ALLOC
| SHF_EXECINSTR
);
10591 data_section
= new_section(s
, ".data", SHT_PROGBITS
, SHF_ALLOC
| SHF_WRITE
);
10592 bss_section
= new_section(s
, ".bss", SHT_NOBITS
, SHF_ALLOC
| SHF_WRITE
);
10594 /* symbols are always generated for linking stage */
10595 symtab_section
= new_symtab(s
, ".symtab", SHT_SYMTAB
, 0,
10597 ".hashtab", SHF_PRIVATE
);
10598 strtab_section
= symtab_section
->link
;
10600 /* private symbol table for dynamic symbols */
10601 s
->dynsymtab_section
= new_symtab(s
, ".dynsymtab", SHT_SYMTAB
, SHF_PRIVATE
,
10603 ".dynhashtab", SHF_PRIVATE
);
10604 s
->alacarte_link
= 1;
10606 #ifdef CHAR_IS_UNSIGNED
10607 s
->char_is_unsigned
= 1;
10609 #if defined(TCC_TARGET_PE) && 0
10610 /* XXX: currently the PE linker is not ready to support that */
10611 s
->leading_underscore
= 1;
10616 void tcc_delete(TCCState
*s1
)
10622 /* free all sections */
10623 for(i
= 1; i
< s1
->nb_sections
; i
++)
10624 free_section(s1
->sections
[i
]);
10625 dynarray_reset(&s1
->sections
, &s1
->nb_sections
);
10627 for(i
= 0; i
< s1
->nb_priv_sections
; i
++)
10628 free_section(s1
->priv_sections
[i
]);
10629 dynarray_reset(&s1
->priv_sections
, &s1
->nb_priv_sections
);
10631 /* free any loaded DLLs */
10632 for ( i
= 0; i
< s1
->nb_loaded_dlls
; i
++) {
10633 DLLReference
*ref
= s1
->loaded_dlls
[i
];
10635 dlclose(ref
->handle
);
10638 /* free loaded dlls array */
10639 dynarray_reset(&s1
->loaded_dlls
, &s1
->nb_loaded_dlls
);
10641 /* free library paths */
10642 dynarray_reset(&s1
->library_paths
, &s1
->nb_library_paths
);
10644 /* free include paths */
10645 dynarray_reset(&s1
->cached_includes
, &s1
->nb_cached_includes
);
10646 dynarray_reset(&s1
->include_paths
, &s1
->nb_include_paths
);
10647 dynarray_reset(&s1
->sysinclude_paths
, &s1
->nb_sysinclude_paths
);
10652 int tcc_add_include_path(TCCState
*s1
, const char *pathname
)
10656 pathname1
= tcc_strdup(pathname
);
10657 dynarray_add((void ***)&s1
->include_paths
, &s1
->nb_include_paths
, pathname1
);
10661 int tcc_add_sysinclude_path(TCCState
*s1
, const char *pathname
)
10665 pathname1
= tcc_strdup(pathname
);
10666 dynarray_add((void ***)&s1
->sysinclude_paths
, &s1
->nb_sysinclude_paths
, pathname1
);
10670 static int tcc_add_file_internal(TCCState
*s1
, const char *filename
, int flags
)
10675 BufferedFile
*saved_file
;
10677 /* find source file type with extension */
10678 ext
= tcc_fileextension(filename
);
10682 /* open the file */
10684 file
= tcc_open(s1
, filename
);
10686 if (flags
& AFF_PRINT_ERROR
) {
10687 error_noabort("file '%s' not found", filename
);
10693 if (flags
& AFF_PREPROCESS
) {
10694 ret
= tcc_preprocess(s1
);
10695 } else if (!ext
[0] || !PATHCMP(ext
, "c")) {
10696 /* C file assumed */
10697 ret
= tcc_compile(s1
);
10699 #ifdef CONFIG_TCC_ASM
10700 if (!strcmp(ext
, "S")) {
10701 /* preprocessed assembler */
10702 ret
= tcc_assemble(s1
, 1);
10703 } else if (!strcmp(ext
, "s")) {
10704 /* non preprocessed assembler */
10705 ret
= tcc_assemble(s1
, 0);
10708 #ifdef TCC_TARGET_PE
10709 if (!PATHCMP(ext
, "def")) {
10710 ret
= pe_load_def_file(s1
, file
->fd
);
10715 /* assume executable format: auto guess file type */
10716 ret
= read(fd
, &ehdr
, sizeof(ehdr
));
10717 lseek(fd
, 0, SEEK_SET
);
10719 error_noabort("could not read header");
10721 } else if (ret
!= sizeof(ehdr
)) {
10722 goto try_load_script
;
10725 if (ehdr
.e_ident
[0] == ELFMAG0
&&
10726 ehdr
.e_ident
[1] == ELFMAG1
&&
10727 ehdr
.e_ident
[2] == ELFMAG2
&&
10728 ehdr
.e_ident
[3] == ELFMAG3
) {
10729 file
->line_num
= 0; /* do not display line number if error */
10730 if (ehdr
.e_type
== ET_REL
) {
10731 ret
= tcc_load_object_file(s1
, fd
, 0);
10732 } else if (ehdr
.e_type
== ET_DYN
) {
10733 if (s1
->output_type
== TCC_OUTPUT_MEMORY
) {
10734 #ifdef TCC_TARGET_PE
10738 h
= dlopen(filename
, RTLD_GLOBAL
| RTLD_LAZY
);
10745 ret
= tcc_load_dll(s1
, fd
, filename
,
10746 (flags
& AFF_REFERENCED_DLL
) != 0);
10749 error_noabort("unrecognized ELF file");
10752 } else if (memcmp((char *)&ehdr
, ARMAG
, 8) == 0) {
10753 file
->line_num
= 0; /* do not display line number if error */
10754 ret
= tcc_load_archive(s1
, fd
);
10756 #ifdef TCC_TARGET_COFF
10757 if (*(uint16_t *)(&ehdr
) == COFF_C67_MAGIC
) {
10758 ret
= tcc_load_coff(s1
, fd
);
10761 #ifdef TCC_TARGET_PE
10762 if (pe_test_res_file(&ehdr
, ret
)) {
10763 ret
= pe_load_res_file(s1
, fd
);
10767 /* as GNU ld, consider it is an ld script if not recognized */
10769 ret
= tcc_load_ldscript(s1
);
10771 error_noabort("unrecognized file type");
10786 int tcc_add_file(TCCState
*s
, const char *filename
)
10788 return tcc_add_file_internal(s
, filename
, AFF_PRINT_ERROR
);
10791 int tcc_add_library_path(TCCState
*s
, const char *pathname
)
10795 pathname1
= tcc_strdup(pathname
);
10796 dynarray_add((void ***)&s
->library_paths
, &s
->nb_library_paths
, pathname1
);
10800 /* find and load a dll. Return non zero if not found */
10801 /* XXX: add '-rpath' option support ? */
10802 static int tcc_add_dll(TCCState
*s
, const char *filename
, int flags
)
10807 for(i
= 0; i
< s
->nb_library_paths
; i
++) {
10808 snprintf(buf
, sizeof(buf
), "%s/%s",
10809 s
->library_paths
[i
], filename
);
10810 if (tcc_add_file_internal(s
, buf
, flags
) == 0)
10816 /* the library name is the same as the argument of the '-l' option */
10817 int tcc_add_library(TCCState
*s
, const char *libraryname
)
10822 /* first we look for the dynamic library if not static linking */
10823 if (!s
->static_link
) {
10824 #ifdef TCC_TARGET_PE
10825 snprintf(buf
, sizeof(buf
), "%s.def", libraryname
);
10827 snprintf(buf
, sizeof(buf
), "lib%s.so", libraryname
);
10829 if (tcc_add_dll(s
, buf
, 0) == 0)
10833 /* then we look for the static library */
10834 for(i
= 0; i
< s
->nb_library_paths
; i
++) {
10835 snprintf(buf
, sizeof(buf
), "%s/lib%s.a",
10836 s
->library_paths
[i
], libraryname
);
10837 if (tcc_add_file_internal(s
, buf
, 0) == 0)
10843 int tcc_add_symbol(TCCState
*s
, const char *name
, void *val
)
10845 add_elf_sym(symtab_section
, (unsigned long)val
, 0,
10846 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
10851 int tcc_set_output_type(TCCState
*s
, int output_type
)
10855 s
->output_type
= output_type
;
10857 if (!s
->nostdinc
) {
10858 /* default include paths */
10859 /* XXX: reverse order needed if -isystem support */
10860 #ifndef TCC_TARGET_PE
10861 tcc_add_sysinclude_path(s
, CONFIG_SYSROOT
"/usr/local/include");
10862 tcc_add_sysinclude_path(s
, CONFIG_SYSROOT
"/usr/include");
10864 snprintf(buf
, sizeof(buf
), "%s/include", tcc_lib_path
);
10865 tcc_add_sysinclude_path(s
, buf
);
10866 #ifdef TCC_TARGET_PE
10867 snprintf(buf
, sizeof(buf
), "%s/include/winapi", tcc_lib_path
);
10868 tcc_add_sysinclude_path(s
, buf
);
10872 /* if bound checking, then add corresponding sections */
10873 #ifdef CONFIG_TCC_BCHECK
10874 if (do_bounds_check
) {
10875 /* define symbol */
10876 tcc_define_symbol(s
, "__BOUNDS_CHECKING_ON", NULL
);
10877 /* create bounds sections */
10878 bounds_section
= new_section(s
, ".bounds",
10879 SHT_PROGBITS
, SHF_ALLOC
);
10880 lbounds_section
= new_section(s
, ".lbounds",
10881 SHT_PROGBITS
, SHF_ALLOC
);
10885 if (s
->char_is_unsigned
) {
10886 tcc_define_symbol(s
, "__CHAR_UNSIGNED__", NULL
);
10889 /* add debug sections */
10892 stab_section
= new_section(s
, ".stab", SHT_PROGBITS
, 0);
10893 stab_section
->sh_entsize
= sizeof(Stab_Sym
);
10894 stabstr_section
= new_section(s
, ".stabstr", SHT_STRTAB
, 0);
10895 put_elf_str(stabstr_section
, "");
10896 stab_section
->link
= stabstr_section
;
10897 /* put first entry */
10898 put_stabs("", 0, 0, 0, 0);
10901 /* add libc crt1/crti objects */
10902 #ifndef TCC_TARGET_PE
10903 if ((output_type
== TCC_OUTPUT_EXE
|| output_type
== TCC_OUTPUT_DLL
) &&
10905 if (output_type
!= TCC_OUTPUT_DLL
)
10906 tcc_add_file(s
, CONFIG_TCC_CRT_PREFIX
"/crt1.o");
10907 tcc_add_file(s
, CONFIG_TCC_CRT_PREFIX
"/crti.o");
10911 #ifdef TCC_TARGET_PE
10912 snprintf(buf
, sizeof(buf
), "%s/lib", tcc_lib_path
);
10913 tcc_add_library_path(s
, buf
);
10919 #define WD_ALL 0x0001 /* warning is activated when using -Wall */
10920 #define FD_INVERT 0x0002 /* invert value before storing */
10922 typedef struct FlagDef
{
10928 static const FlagDef warning_defs
[] = {
10929 { offsetof(TCCState
, warn_unsupported
), 0, "unsupported" },
10930 { offsetof(TCCState
, warn_write_strings
), 0, "write-strings" },
10931 { offsetof(TCCState
, warn_error
), 0, "error" },
10932 { offsetof(TCCState
, warn_implicit_function_declaration
), WD_ALL
,
10933 "implicit-function-declaration" },
10936 static int set_flag(TCCState
*s
, const FlagDef
*flags
, int nb_flags
,
10937 const char *name
, int value
)
10944 if (r
[0] == 'n' && r
[1] == 'o' && r
[2] == '-') {
10948 for(i
= 0, p
= flags
; i
< nb_flags
; i
++, p
++) {
10949 if (!strcmp(r
, p
->name
))
10954 if (p
->flags
& FD_INVERT
)
10956 *(int *)((uint8_t *)s
+ p
->offset
) = value
;
10961 /* set/reset a warning */
10962 int tcc_set_warning(TCCState
*s
, const char *warning_name
, int value
)
10967 if (!strcmp(warning_name
, "all")) {
10968 for(i
= 0, p
= warning_defs
; i
< countof(warning_defs
); i
++, p
++) {
10969 if (p
->flags
& WD_ALL
)
10970 *(int *)((uint8_t *)s
+ p
->offset
) = 1;
10974 return set_flag(s
, warning_defs
, countof(warning_defs
),
10975 warning_name
, value
);
10979 static const FlagDef flag_defs
[] = {
10980 { offsetof(TCCState
, char_is_unsigned
), 0, "unsigned-char" },
10981 { offsetof(TCCState
, char_is_unsigned
), FD_INVERT
, "signed-char" },
10982 { offsetof(TCCState
, nocommon
), FD_INVERT
, "common" },
10983 { offsetof(TCCState
, leading_underscore
), 0, "leading-underscore" },
10986 /* set/reset a flag */
10987 int tcc_set_flag(TCCState
*s
, const char *flag_name
, int value
)
10989 return set_flag(s
, flag_defs
, countof(flag_defs
),
10993 #if !defined(LIBTCC)
10995 static int64_t getclock_us(void)
11000 return (tb
.time
* 1000LL + tb
.millitm
) * 1000LL;
11003 gettimeofday(&tv
, NULL
);
11004 return tv
.tv_sec
* 1000000LL + tv
.tv_usec
;
11010 printf("tcc version " TCC_VERSION
" - Tiny C Compiler - Copyright (C) 2001-2006 Fabrice Bellard\n"
11011 "usage: tcc [-v] [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
11012 " [-Wwarn] [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-soname name]\n"
11013 " [-static] [infile1 infile2...] [-run infile args...]\n"
11015 "General options:\n"
11016 " -v display current version, increase verbosity\n"
11017 " -c compile only - generate an object file\n"
11018 " -o outfile set output filename\n"
11019 " -Bdir set tcc internal library path\n"
11020 " -bench output compilation statistics\n"
11021 " -run run compiled source\n"
11022 " -fflag set or reset (with 'no-' prefix) 'flag' (see man page)\n"
11023 " -Wwarning set or reset (with 'no-' prefix) 'warning' (see man page)\n"
11024 " -w disable all warnings\n"
11025 "Preprocessor options:\n"
11026 " -E preprocess only\n"
11027 " -Idir add include path 'dir'\n"
11028 " -Dsym[=val] define 'sym' with value 'val'\n"
11029 " -Usym undefine 'sym'\n"
11030 "Linker options:\n"
11031 " -Ldir add library path 'dir'\n"
11032 " -llib link with dynamic or static library 'lib'\n"
11033 " -shared generate a shared library\n"
11034 " -soname set name for shared library to be used at runtime\n"
11035 " -static static linking\n"
11036 " -rdynamic export all global symbols to dynamic linker\n"
11037 " -r generate (relocatable) object file\n"
11038 "Debugger options:\n"
11039 " -g generate runtime debug info\n"
11040 #ifdef CONFIG_TCC_BCHECK
11041 " -b compile with built-in memory and bounds checker (implies -g)\n"
11043 " -bt N show N callers in stack traces\n"
11047 #define TCC_OPTION_HAS_ARG 0x0001
11048 #define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
11050 typedef struct TCCOption
{
11079 TCC_OPTION_nostdinc
,
11080 TCC_OPTION_nostdlib
,
11081 TCC_OPTION_print_search_dirs
,
11082 TCC_OPTION_rdynamic
,
11090 static const TCCOption tcc_options
[] = {
11091 { "h", TCC_OPTION_HELP
, 0 },
11092 { "?", TCC_OPTION_HELP
, 0 },
11093 { "I", TCC_OPTION_I
, TCC_OPTION_HAS_ARG
},
11094 { "D", TCC_OPTION_D
, TCC_OPTION_HAS_ARG
},
11095 { "U", TCC_OPTION_U
, TCC_OPTION_HAS_ARG
},
11096 { "L", TCC_OPTION_L
, TCC_OPTION_HAS_ARG
},
11097 { "B", TCC_OPTION_B
, TCC_OPTION_HAS_ARG
},
11098 { "l", TCC_OPTION_l
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
11099 { "bench", TCC_OPTION_bench
, 0 },
11100 { "bt", TCC_OPTION_bt
, TCC_OPTION_HAS_ARG
},
11101 #ifdef CONFIG_TCC_BCHECK
11102 { "b", TCC_OPTION_b
, 0 },
11104 { "g", TCC_OPTION_g
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
11105 { "c", TCC_OPTION_c
, 0 },
11106 { "static", TCC_OPTION_static
, 0 },
11107 { "shared", TCC_OPTION_shared
, 0 },
11108 { "soname", TCC_OPTION_soname
, TCC_OPTION_HAS_ARG
},
11109 { "o", TCC_OPTION_o
, TCC_OPTION_HAS_ARG
},
11110 { "run", TCC_OPTION_run
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
11111 { "rdynamic", TCC_OPTION_rdynamic
, 0 },
11112 { "r", TCC_OPTION_r
, 0 },
11113 { "Wl,", TCC_OPTION_Wl
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
11114 { "W", TCC_OPTION_W
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
11115 { "O", TCC_OPTION_O
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
11116 { "m", TCC_OPTION_m
, TCC_OPTION_HAS_ARG
},
11117 { "f", TCC_OPTION_f
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
11118 { "nostdinc", TCC_OPTION_nostdinc
, 0 },
11119 { "nostdlib", TCC_OPTION_nostdlib
, 0 },
11120 { "print-search-dirs", TCC_OPTION_print_search_dirs
, 0 },
11121 { "v", TCC_OPTION_v
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
11122 { "w", TCC_OPTION_w
, 0 },
11123 { "pipe", TCC_OPTION_pipe
, 0},
11124 { "E", TCC_OPTION_E
, 0},
11128 /* convert 'str' into an array of space separated strings */
11129 static int expand_args(char ***pargv
, const char *str
)
11138 while (is_space(*str
))
11143 while (*str
!= '\0' && !is_space(*str
))
11146 arg
= tcc_malloc(len
+ 1);
11147 memcpy(arg
, s1
, len
);
11149 dynarray_add((void ***)&argv
, &argc
, arg
);
11155 static char **files
;
11156 static int nb_files
, nb_libraries
;
11157 static int multiple_files
;
11158 static int print_search_dirs
;
11159 static int output_type
;
11160 static int reloc_output
;
11161 static const char *outfile
;
11163 int parse_args(TCCState
*s
, int argc
, char **argv
)
11166 const TCCOption
*popt
;
11167 const char *optarg
, *p1
, *r1
;
11171 while (optind
< argc
) {
11173 r
= argv
[optind
++];
11174 if (r
[0] != '-' || r
[1] == '\0') {
11175 /* add a new file */
11176 dynarray_add((void ***)&files
, &nb_files
, r
);
11177 if (!multiple_files
) {
11179 /* argv[0] will be this file */
11183 /* find option in table (match only the first chars */
11184 popt
= tcc_options
;
11188 error("invalid option -- '%s'", r
);
11201 if (popt
->flags
& TCC_OPTION_HAS_ARG
) {
11202 if (*r1
!= '\0' || (popt
->flags
& TCC_OPTION_NOSEP
)) {
11205 if (optind
>= argc
)
11206 error("argument to '%s' is missing", r
);
11207 optarg
= argv
[optind
++];
11215 switch(popt
->index
) {
11216 case TCC_OPTION_HELP
:
11220 if (tcc_add_include_path(s
, optarg
) < 0)
11221 error("too many include paths");
11226 sym
= (char *)optarg
;
11227 value
= strchr(sym
, '=');
11232 tcc_define_symbol(s
, sym
, value
);
11236 tcc_undefine_symbol(s
, optarg
);
11239 tcc_add_library_path(s
, optarg
);
11242 /* set tcc utilities path (mainly for tcc development) */
11243 tcc_lib_path
= optarg
;
11246 dynarray_add((void ***)&files
, &nb_files
, r
);
11249 case TCC_OPTION_bench
:
11252 case TCC_OPTION_bt
:
11253 num_callers
= atoi(optarg
);
11255 #ifdef CONFIG_TCC_BCHECK
11257 do_bounds_check
= 1;
11265 multiple_files
= 1;
11266 output_type
= TCC_OUTPUT_OBJ
;
11268 case TCC_OPTION_static
:
11269 s
->static_link
= 1;
11271 case TCC_OPTION_shared
:
11272 output_type
= TCC_OUTPUT_DLL
;
11274 case TCC_OPTION_soname
:
11275 s
->soname
= optarg
;
11278 multiple_files
= 1;
11282 /* generate a .o merging several output files */
11284 output_type
= TCC_OUTPUT_OBJ
;
11286 case TCC_OPTION_nostdinc
:
11289 case TCC_OPTION_nostdlib
:
11292 case TCC_OPTION_print_search_dirs
:
11293 print_search_dirs
= 1;
11295 case TCC_OPTION_run
:
11299 argc1
= expand_args(&argv1
, optarg
);
11301 parse_args(s
, argc1
, argv1
);
11303 multiple_files
= 0;
11304 output_type
= TCC_OUTPUT_MEMORY
;
11309 if (0 == verbose
++)
11310 printf("tcc version %s\n", TCC_VERSION
);
11311 } while (*optarg
++ == 'v');
11314 if (tcc_set_flag(s
, optarg
, 1) < 0 && s
->warn_unsupported
)
11315 goto unsupported_option
;
11318 if (tcc_set_warning(s
, optarg
, 1) < 0 &&
11319 s
->warn_unsupported
)
11320 goto unsupported_option
;
11325 case TCC_OPTION_rdynamic
:
11328 case TCC_OPTION_Wl
:
11331 if (strstart(optarg
, "-Ttext,", &p
)) {
11332 s
->text_addr
= strtoul(p
, NULL
, 16);
11333 s
->has_text_addr
= 1;
11334 } else if (strstart(optarg
, "--oformat,", &p
)) {
11335 if (strstart(p
, "elf32-", NULL
)) {
11336 s
->output_format
= TCC_OUTPUT_FORMAT_ELF
;
11337 } else if (!strcmp(p
, "binary")) {
11338 s
->output_format
= TCC_OUTPUT_FORMAT_BINARY
;
11340 #ifdef TCC_TARGET_COFF
11341 if (!strcmp(p
, "coff")) {
11342 s
->output_format
= TCC_OUTPUT_FORMAT_COFF
;
11346 error("target %s not found", p
);
11349 error("unsupported linker option '%s'", optarg
);
11354 output_type
= TCC_OUTPUT_PREPROCESS
;
11357 if (s
->warn_unsupported
) {
11358 unsupported_option
:
11359 warning("unsupported option '%s'", r
);
11368 int main(int argc
, char **argv
)
11372 int nb_objfiles
, ret
, optind
;
11373 char objfilename
[1024];
11374 int64_t start_time
= 0;
11377 tcc_lib_path
= w32_tcc_lib_path();
11381 output_type
= TCC_OUTPUT_EXE
;
11383 multiple_files
= 1;
11388 print_search_dirs
= 0;
11391 optind
= parse_args(s
, argc
- 1, argv
+ 1);
11392 if (print_search_dirs
) {
11393 /* enough for Linux kernel */
11394 printf("install: %s/\n", tcc_lib_path
);
11397 if (optind
== 0 || nb_files
== 0) {
11398 if (optind
&& verbose
)
11404 nb_objfiles
= nb_files
- nb_libraries
;
11406 /* if outfile provided without other options, we output an
11408 if (outfile
&& output_type
== TCC_OUTPUT_MEMORY
)
11409 output_type
= TCC_OUTPUT_EXE
;
11411 /* check -c consistency : only single file handled. XXX: checks file type */
11412 if (output_type
== TCC_OUTPUT_OBJ
&& !reloc_output
) {
11413 /* accepts only a single input file */
11414 if (nb_objfiles
!= 1)
11415 error("cannot specify multiple files with -c");
11416 if (nb_libraries
!= 0)
11417 error("cannot specify libraries with -c");
11421 if (output_type
== TCC_OUTPUT_PREPROCESS
) {
11423 s
->outfile
= stdout
;
11425 s
->outfile
= fopen(outfile
, "w");
11427 error("could not open '%s", outfile
);
11429 } else if (output_type
!= TCC_OUTPUT_MEMORY
) {
11431 /* compute default outfile name */
11434 strcmp(files
[0], "-") == 0 ? "a" : tcc_basename(files
[0]);
11435 pstrcpy(objfilename
, sizeof(objfilename
), name
);
11436 ext
= tcc_fileextension(objfilename
);
11437 #ifdef TCC_TARGET_PE
11438 if (output_type
== TCC_OUTPUT_DLL
)
11439 strcpy(ext
, ".dll");
11441 if (output_type
== TCC_OUTPUT_EXE
)
11442 strcpy(ext
, ".exe");
11445 if (output_type
== TCC_OUTPUT_OBJ
&& !reloc_output
&& *ext
)
11448 pstrcpy(objfilename
, sizeof(objfilename
), "a.out");
11449 outfile
= objfilename
;
11454 start_time
= getclock_us();
11457 tcc_set_output_type(s
, output_type
);
11459 /* compile or add each files or library */
11460 for(i
= 0; i
< nb_files
&& ret
== 0; i
++) {
11461 const char *filename
;
11463 filename
= files
[i
];
11464 if (output_type
== TCC_OUTPUT_PREPROCESS
) {
11465 if (tcc_add_file_internal(s
, filename
,
11466 AFF_PRINT_ERROR
| AFF_PREPROCESS
) < 0)
11468 } else if (filename
[0] == '-' && filename
[1]) {
11469 if (tcc_add_library(s
, filename
+ 2) < 0)
11470 error("cannot find %s", filename
);
11473 printf("-> %s\n", filename
);
11474 if (tcc_add_file(s
, filename
) < 0)
11479 /* free all files */
11487 total_time
= (double)(getclock_us() - start_time
) / 1000000.0;
11488 if (total_time
< 0.001)
11489 total_time
= 0.001;
11490 if (total_bytes
< 1)
11492 printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
11493 tok_ident
- TOK_IDENT
, total_lines
, total_bytes
,
11494 total_time
, (int)(total_lines
/ total_time
),
11495 total_bytes
/ total_time
/ 1000000.0);
11498 if (s
->output_type
== TCC_OUTPUT_PREPROCESS
) {
11500 fclose(s
->outfile
);
11501 } else if (s
->output_type
== TCC_OUTPUT_MEMORY
) {
11502 ret
= tcc_run(s
, argc
- optind
, argv
+ optind
);
11504 ret
= tcc_output_file(s
, outfile
) ? 1 : 0;
11506 /* XXX: cannot do it with bound checking because of the malloc hooks */
11507 if (!do_bounds_check
)
11512 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size
, mem_max_size
);